Add note about fork with Proxmox support. #141
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: LXC ssh test | |
# Run this workflow every time a new commit pushed to your repository | |
on: | |
push: | |
#branches: '**' | |
#branches-ignore: 'main' | |
pull_request: | |
#branches: '**' | |
#branches-ignore: 'main' | |
workflow_dispatch: | |
defaults: | |
run: | |
shell: bash | |
jobs: | |
pr-test-ubuntu-user: | |
name: Check the PR (ubuntu user) | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
# also test 'latest', eventually this will be upgraded to a newer version and might fail early | |
# build the matrix manually - not all versions of Ubuntu can do with all Ansible versions, | |
# mostly because the Python version is outdated (20.04 only has Python 3.8) | |
# maybe in the future this can be build with include/exclude | |
#os: [ubuntu-20.04, ubuntu-22.04, ubuntu-latest] | |
#ansible: ["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"] | |
include: | |
- os: ubuntu-20.04 | |
guest: 20.04 | |
#guest-image: 20.04/amd64 | |
ansible: "stable-2.9" | |
- os: ubuntu-20.04 | |
guest: 20.04 | |
ansible: "stable-2.10" | |
- os: ubuntu-20.04 | |
guest: 20.04 | |
ansible: "stable-2.11" | |
- os: ubuntu-20.04 | |
guest: 20.04 | |
ansible: "stable-2.12" | |
- os: ubuntu-20.04 | |
guest: 20.04 | |
ansible: "stable-2.13" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.9" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.10" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.11" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.12" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.13" | |
- os: ubuntu-22.04 | |
guest: 22.04 | |
ansible: "stable-2.14" | |
# build the latest known stable Ansible on the latest known stable Ubuntu | |
- os: ubuntu-latest | |
guest: 22.04 | |
ansible: "stable-2.14" | |
# build the development version of Ansible on latest Ubuntu | |
- os: ubuntu-latest | |
guest: 22.04 | |
ansible: "devel" | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
# check Python syntax | |
- name: Python syntax check | |
run: python3 -m py_compile lxc_ssh.py | |
# prepare container with LXD installation | |
- name: Install basic packages | |
run: sudo apt-get install -y iptables | |
- name: Install LXD (Ubuntu 20.x) | |
run: sudo apt-get install -y lxd lxd-client lxd-tools | |
if: ${{ matrix.guest == '20.04' }} | |
- name: Install LXD (Ubuntu >= 22.x) | |
run: sudo snap install lxd | |
if: ${{ matrix.guest != '20.04' }} | |
# different LXD versions need different init steps | |
- name: Store LXD version | |
run: echo "LXD_Version=$(lxd --version)" >> $GITHUB_OUTPUT | |
id: lxd_version | |
- name: Store LXD major version | |
run: echo "LXD_Major_Version=$(lxd --version | cut -f1 -d'.')" >> $GITHUB_OUTPUT | |
id: lxd__major_version | |
- name: Output version | |
run: echo "${{ steps.lxd_version.outputs.LXD_Version }} - ${{ steps.lxd__major_version.outputs.LXD_Major_Version }}" | |
- name: Fail for unknown older versions | |
run: exit 1 | |
if: steps.lxd__major_version.outputs.LXD_Major_Version < 3 | |
- name: Fail for unknown newer versions | |
run: exit 1 | |
if: steps.lxd__major_version.outputs.LXD_Major_Version > 5 | |
- name: Init LXD version 3 | |
run: sudo lxd init --preseed < $GITHUB_WORKSPACE/.github/resources/lxd3-init.yml | |
if: steps.lxd__major_version.outputs.LXD_Major_Version == 3 | |
- name: Init LXD version 4 | |
run: sudo lxd init --preseed < $GITHUB_WORKSPACE/.github/resources/lxd4-init.yml | |
if: steps.lxd__major_version.outputs.LXD_Major_Version >= 4 | |
- name: Show LXD status | |
run: sudo lxc profile show default | |
- name: Store IPv4 address for lxdbr0 | |
run: echo "IP=$(ip -4 addr show lxdbr0 | grep inet | awk '{print $2}' | cut -d/ -f1)" >> $GITHUB_OUTPUT | |
id: lxdbr0_ipv4 | |
- name: Show lxdbr0 IP address | |
run: echo "${{ steps.lxdbr0_ipv4.outputs.IP }}" | |
- name: Create container-pool for LXD | |
run: sudo lxc storage create container-pool dir | |
- name: Remove default storage pool from LXD | |
run: sudo lxc profile device remove default root | |
- name: Attach container storage pool to default profile | |
run: sudo lxc profile device add default root disk path=/ pool=container-pool | |
# - name: Firewall IPv6 | |
# run: sudo lxc network set lxdbr0 ipv6.firewall false | |
# - name: Firewall IPv4 | |
# run: sudo lxc network set lxdbr0 ipv4.firewall false | |
# - name: Firewall 1 | |
# run: sudo ufw allow in on lxdbr0 | |
# - name: Firewall 2 | |
# run: sudo ufw route allow in on lxdbr0 | |
# - name: Firewall 3 | |
# run: sudo ufw route allow out on lxdbr0 | |
# - name: Docker | |
# run: sudo docker ps | |
# https://linuxcontainers.org/lxd/docs/master/howto/network_bridge_firewalld/#prevent-issues-with-lxd-and-docker | |
- name: Show network configuration | |
run: sudo ip addr | |
- name: Docker Firewall 1 | |
run: sudo iptables -I DOCKER-USER -i lxdbr0 -o eth0 -j ACCEPT | |
- name: Docker Firewall 2 | |
run: sudo iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT | |
# create an actual container, and configure it | |
# Enable container nesting | |
- name: Create container | |
run: sudo lxc launch images:ubuntu/${{ matrix.guest }} test-container -c security.nesting=true | |
- name: Wait for container to start | |
run: sleep 10 | |
- name: Show container | |
run: sudo lxc list | |
- name: Debug | |
run: sudo lxc exec test-container -- ip -4 -o link show | |
- name: Store Container interface name | |
run: echo "IF=$(sudo lxc exec test-container -- ip -4 -o link show | awk '{print $2}' | cut -f1 -d':' | cut -f1 -d'@' | grep '^e[tn]')" >> $GITHUB_OUTPUT | |
id: test_container_interface | |
- name: Request and wait for IPv4 address | |
run: sudo lxc exec test-container -- dhclient -v ${{ steps.test_container_interface.outputs.IF }} | |
- name: Store Container IPv4 address | |
run: echo "IPv4=$(sudo lxc exec test-container -- ip -o -4 addr show ${{ steps.test_container_interface.outputs.IF }} | awk '{print $4}' | cut -d/ -f1)" >> $GITHUB_OUTPUT | |
id: test_container_ipv4 | |
- name: Output container network data | |
run: echo "${{ steps.test_container_interface.outputs.IF }} - ${{ steps.test_container_ipv4.outputs.IPv4 }}" | |
- name: Fail if no network available | |
run: exit 1 | |
if: steps.test_container_ipv4.outputs.IPv4 == '' | |
- name: Ping test if the container is connected | |
run: ping -4 -c 3 -n -v ${{ steps.test_container_ipv4.outputs.IPv4 }} | |
- name: Add container to /etc/hosts | |
run: ls -ld /etc/hosts | |
- name: Add container to /etc/hosts | |
run: echo -e "${{ steps.test_container_ipv4.outputs.IPv4 }}\ttest-container" | sudo tee -a /etc/hosts | |
- name: Show /etc/hosts | |
run: cat /etc/hosts | |
# create ssh key for root | |
- name: Create ssh directory for root | |
run: sudo mkdir -p /root/.ssh/ | |
- name: Update permissions for ssh directory for root | |
run: sudo chmod 0700 /root/.ssh/ | |
- name: Generate OpenSSH key for root | |
#run: sudo ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa -v -N "" -P "" -C "root@host" | |
run: sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -v -N "" -P "" -C "root@host" | |
# create ssh key for runner user | |
- name: Create ssh directory for runner user | |
run: mkdir -p $HOME/.ssh/ | |
- name: Update permissions for ssh directory for runner user | |
run: chmod 0700 $HOME/.ssh/ | |
- name: Generate OpenSSH key for runner user | |
#run: ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/id_rsa -v -N "" -P "" -C "home/runner@host" | |
run: ssh-keygen -t ed25519 -f $HOME/.ssh/id_ed25519 -v -N "" -P "" -C "home/runner@host" | |
# 22.04 can't reach the Ubuntu servers over IPv6 | |
# - name: Disable IPv6 (all) | |
# run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sysctl -w net.ipv6.conf.all.disable_ipv6=1 | |
# - name: Disable IPv6 (default) | |
# run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sysctl -w net.ipv6.conf.default.disable_ipv6=1 | |
# - name: Disable IPv6 (lo) | |
# run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sysctl -w net.ipv6.conf.lo.disable_ipv6=1 | |
- name: Network | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- ip addr | |
- name: Network | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- ip route | |
# install OpenSSH in container | |
- name: Install OpenSSH in container | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- apt-get -y install -y openssh-client openssh-server openssh-sftp-server | |
- name: OpenSSH create root .ssh directory in container | |
run: sudo lxc exec test-container -- mkdir -p /root/.ssh | |
- name: OpenSSH permissions of root .ssh directory in container | |
run: sudo lxc exec test-container -- chmod 0700 /root/.ssh | |
- name: OpenSSH create ubuntu .ssh directory in container | |
run: sudo lxc exec test-container -- mkdir -p /home/ubuntu/.ssh | |
- name: OpenSSH permissions of ubuntu .ssh directory in container | |
run: sudo lxc exec test-container -- chmod 0700 /home/ubuntu/.ssh | |
# install root and user ssh key in container for root and user | |
- name: OpenSSH push authorized_keys for root into container | |
#run: sudo lxc file push /root/.ssh/id_rsa.pub test-container/root/.ssh/authorized_keys | |
run: sudo lxc file push /root/.ssh/id_ed25519.pub test-container/root/.ssh/authorized_keys | |
- name: OpenSSH push authorized_keys for user into container | |
#run: sudo lxc file push $HOME/.ssh/id_rsa.pub test-container/tmp/authorized_keys.user | |
run: sudo lxc file push $HOME/.ssh/id_ed25519.pub test-container/tmp/authorized_keys.user | |
- name: OpenSSH add user key to root authorized_keys in container | |
#run: sudo lxc exec test-container -- bash -c "cat /tmp/authorized_keys.user | sudo tee -a /root/.ssh/authorized_keys" | |
run: sudo lxc exec test-container -- sudo bash -c "cat /tmp/authorized_keys.user >> /root/.ssh/authorized_keys" | |
- name: Install authorized_keys for ubuntu user in container | |
run: sudo lxc exec test-container -- cp -ai /root/.ssh/authorized_keys /home/ubuntu/.ssh | |
- name: OpenSSH ownership of ubuntu .ssh directory in container | |
run: sudo lxc exec test-container -- chown -R ubuntu. /home/ubuntu/.ssh | |
# configure password & other requirements for password authentication | |
- name: Set root user password in container | |
run: sudo lxc exec test-container -- sh -c 'printf "password\npassword\n" | passwd' | |
- name: Set ubuntu user password in container | |
run: sudo lxc exec test-container -- sh -c 'printf "password\npassword\n" | passwd ubuntu' | |
- name: Install sshpass on runner | |
run: sudo apt-get -y install sshpass | |
# update known_hosts for root | |
- name: Create /root/.ssh/known_hosts | |
run: sudo touch /root/.ssh/known_hosts | |
- name: Add container to known_hosts for root | |
run: sudo bash -c "ssh-keyscan -4 test-container >> /root/.ssh/known_hosts" | |
- name: Add container IP to known_hosts for root | |
run: sudo bash -c "ssh-keyscan -4 ${{ steps.test_container_ipv4.outputs.IPv4 }} >> /root/.ssh/known_hosts" | |
# update known_hosts for user | |
- name: Create /user/.ssh/known_hosts | |
run: touch $HOME/.ssh/known_hosts | |
- name: Add container to known_hosts for user | |
run: bash -c "ssh-keyscan -4 test-container >> $HOME/.ssh/known_hosts" | |
- name: Add container IP to known_hosts for user | |
run: bash -c "ssh-keyscan -4 ${{ steps.test_container_ipv4.outputs.IPv4 }} >> $HOME/.ssh/known_hosts" | |
# test ssh connection in all combinations | |
- name: Test ssh connection from root into root | |
run: sudo ssh -i /root/.ssh/id_ed25519 -o PreferredAuthentications=publickey -o PasswordAuthentication=no -l root ${{ steps.test_container_ipv4.outputs.IPv4 }} uptime | |
- name: Test ssh connection from root into ubuntu user | |
run: sudo ssh -i /root/.ssh/id_ed25519 -o PreferredAuthentications=publickey -o PasswordAuthentication=no -l ubuntu ${{ steps.test_container_ipv4.outputs.IPv4 }} uptime | |
- name: Test ssh connection from runner into root user | |
run: ssh -i $HOME/.ssh/id_ed25519 -o PreferredAuthentications=publickey -o PasswordAuthentication=no -l root ${{ steps.test_container_ipv4.outputs.IPv4 }} uptime | |
- name: Test ssh connection from runner into ubuntu user | |
run: ssh -i $HOME/.ssh/id_ed25519 -o PreferredAuthentications=publickey -o PasswordAuthentication=no -l ubuntu ${{ steps.test_container_ipv4.outputs.IPv4 }} uptime | |
- name: Test ssh connection into root user with password authentication | |
run: sshpass -p 'password' ssh -i /dev/null -l ubuntu ${{ steps.test_container_ipv4.outputs.IPv4 }} uptime | |
# copy logfiles from container into log | |
- name: Show logfile in container | |
if: always() | |
run: sudo lxc exec test-container -- tail -n 500 /var/log/syslog | |
- name: Show logfile in container | |
if: always() | |
run: sudo lxc exec test-container -- tail -n 500 /var/log/auth.log | |
# - name: Stop | |
# run: exit 1 | |
# install Python3 in container | |
- name: apt-get update | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- apt-get update | |
# don't upgrade the container to the latest software version | |
# should work out of the box for testing, and saves time | |
#- name: apt-get dist-upgrade | |
# run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- apt-get dist-upgrade -y | |
- name: Ubuntu version | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- lsb_release -a | |
- name: Python3 | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- apt-get -y install -y python3 | |
# Install LXD inside container, it's missing inside container | |
- name: Install LXD inside container (20.04) | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sudo apt-get install -y lxd lxd-client lxd-tools iptables | |
if: ${{ matrix.guest == '20.04' }} | |
- name: Install Snap inside container (>= 22.04) | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sudo apt-get -y install snapd iptables | |
if: ${{ matrix.guest != '20.04' }} | |
- name: Install LXD inside container (>= 22.04) | |
run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- sudo snap install lxd | |
if: ${{ matrix.guest != '20.04' }} | |
# - name: Ping test if the container has connectivity | |
# run: sudo lxc exec test-container --env DEBIAN_FRONTEND=noninteractive -- ping -4 -c 3 -n -v 8.8.8.8 | |
# container is ready | |
# install Ansible | |
- name: Install requested Ansible version using pip | |
run: python -m pip install --user https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz | |
- name: Show Ansible version | |
run: ansible --version | |
- name: Install plugin for tests | |
run: cp -af $GITHUB_WORKSPACE/lxc_ssh.py $GITHUB_WORKSPACE/tests/connection_plugins/lxc_ssh.py | |
- name: Create empty file for tests | |
run: touch $GITHUB_WORKSPACE/tests/test_empty.txt | |
- name: Create a 1000 Bytes file for tests | |
run: dd if=/dev/urandom of=$GITHUB_WORKSPACE/tests/test_1000b.txt bs=1KB count=1 | |
- name: Create a 5MB file for tests | |
run: dd if=/dev/urandom of=$GITHUB_WORKSPACE/tests/test_5mb.txt bs=5MB count=1 | |
- name: Create a 50MB file for tests | |
run: dd if=/dev/urandom of=$GITHUB_WORKSPACE/tests/test_50mb.txt bs=50MB count=1 | |
- name: Show test directory | |
run: bash -c "ls -ld $GITHUB_WORKSPACE/tests/*" | |
# nested LXD configuration | |
- name: Init LXD inside container | |
run: sudo lxc exec test-container -- sudo lxd init --preseed < $GITHUB_WORKSPACE/.github/resources/lxd4-init.yml | |
# Create a nested container for lxc_ssh tests | |
- name: Create a nested container | |
run: sudo lxc exec test-container -- sudo lxc launch images:ubuntu/${{ matrix.guest }} nested-container | |
- name: add container user to lxd group | |
run: sudo lxc exec test-container -- sudo adduser ubuntu lxd | |
- name: Wait for container to start | |
run: sleep 10 | |
- name: Generate ansible inventory | |
run: | | |
cat <<EOF > $GITHUB_WORKSPACE/tests/inventory.yml | |
--- | |
all: | |
hosts: | |
testhost: | |
ansible_host: ${{ steps.test_container_ipv4.outputs.IPv4 }} | |
ansible_ssh_user: 'ubuntu' | |
lxc_host: "nested-container" | |
ansible_connection: lxc_ssh | |
EOF | |
- name: Show inventory file | |
run: cat $GITHUB_WORKSPACE/tests/inventory.yml | |
- name: Run test | |
run: ANSIBLE_CONFIG=$GITHUB_WORKSPACE/tests/ cd tests && ansible-playbook -i $GITHUB_WORKSPACE/tests/inventory.yml $GITHUB_WORKSPACE/tests/test-lxc_ssh.yml | |
# Test password authentication | |
- name: Add a password for the SSH connection | |
run: > | |
printf ' ansible_ssh_pass: "password"\n ansible_ssh_private_key_file: "/dev/null"' >> $GITHUB_WORKSPACE/tests/inventory.yml | |
- name: Run test with password | |
run: > | |
ANSIBLE_CONFIG=$GITHUB_WORKSPACE/tests/ cd tests && ansible-playbook -i $GITHUB_WORKSPACE/tests/inventory.yml $GITHUB_WORKSPACE/tests/test-lxc_ssh.yml -t short | |
- name: Remove sshpass | |
run: sudo apt-get remove -y sshpass | |
- name: Run test with password and without sshpass (expect command failure) | |
run: > | |
set +e; | |
stdout=$(ANSIBLE_CONFIG=$GITHUB_WORKSPACE/tests/ cd tests && ansible-playbook -i $GITHUB_WORKSPACE/tests/inventory.yml $GITHUB_WORKSPACE/tests/test-lxc_ssh.yml -t short); | |
status=$?; | |
set -e; | |
[ $status -eq 2 ] && echo "$stdout" | grep -F "to use the 'ssh' connection type with passwords, you must install the sshpass program" |