SSH test using GitHub Action

I have a code that wraps around some SSH operations. I would like to build CI for this code. Is there a way to generate two virtual machine and SSH between them?


Technically you should be able to use Qemu (possibly with libvirt) on an Ubuntu runner, maybe with Vagrant or something to set them up automatically.

However I’d recommend using containers instead if possible, because the performance is much better. I have a Dockerfile that starts an SSH server inside a container for a project of mine. In that project a script creates the necessary authorized_keys file after the container has been started, but you could also do that with a volume or in the Dockerfile. Maybe that example can help you get started. :slightly_smiling_face:

1 Like

It’s actually a good idea to use an ssh server! I’ll try to get started based on your example, thanks.


@airtower-luna I’ve been trying your suggestion. Here is what I have in my action:

    - name: Install SSH server
      if: runner.os == 'Linux'
      run: |
        sudo apt-get install openssh-server
        sudo systemctl enable ssh
        sudo systemctl start ssh
        mkdir -p "$HOME/.ssh"
        chmod 0700 "$HOME/.ssh"
        ssh-keygen -t rsa -q -f "$HOME/.ssh/id_rsa" -N ""
        cat "$HOME/.ssh/" >> "$HOME/.ssh/authorized_keys"
        chmod 640 "$HOME/.ssh/authorized_keys"
        echo "NoHostAuthenticationForLocalhost yes" >> ~/.ssh/config
        sudo systemctl restart ssh
        ssh localhost "uname"

However, I’m getting permission issues:

Reading package lists...
Building dependency tree...
Reading state information...
openssh-server is already the newest version (1:8.2p1-4ubuntu0.1).
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
Permission denied, please try again.
Permission denied, please try again.
runner@localhost: Permission denied (publickey,password).

would you happen to know how to solve these issues?

At a glance, no. To get more information try running ssh with the -v option, and check /var/log/auth.log (as in, cat to the log or upload as artifact) for the server side.

Thanks @airtower-luna ! I’m not too good at reading the verbose output of ssh, but it seems to me that ssh wants to read a passphrase that I set to be empty:

debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug1: Connecting to localhost [::1] port 22.
debug1: Connection established.
debug1: identity file /home/runner/.ssh/id_rsa type 0
debug1: identity file /home/runner/.ssh/id_rsa-cert type -1
debug1: identity file /home/runner/.ssh/id_dsa type -1
debug1: identity file /home/runner/.ssh/id_dsa-cert type -1
debug1: identity file /home/runner/.ssh/id_ecdsa type -1
debug1: identity file /home/runner/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/runner/.ssh/id_ecdsa_sk type -1
debug1: identity file /home/runner/.ssh/id_ecdsa_sk-cert type -1
debug1: identity file /home/runner/.ssh/id_ed25519 type -1
debug1: identity file /home/runner/.ssh/id_ed25519-cert type -1
debug1: identity file /home/runner/.ssh/id_ed25519_sk type -1
debug1: identity file /home/runner/.ssh/id_ed25519_sk-cert type -1
debug1: identity file /home/runner/.ssh/id_xmss type -1
debug1: identity file /home/runner/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.2p1 Ubuntu-4ubuntu0.1
debug1: match: OpenSSH_8.2p1 Ubuntu-4ubuntu0.1 pat OpenSSH* compat 0x04000000
debug1: Authenticating to localhost:22 as 'runner'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: MAC: <implicit> compression: none
debug1: kex: client->server cipher: MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:NFnWPH2boToKCX0yq1K33LY0K3EwK810f599LpwoXJI
debug1: read_passphrase: can't open /dev/tty: No such device or address
Host key verification failed.

This looks like the key issue, not the passphrase:

You need to either import the host key for localhost into authorized_keys, or (if you’re only going to make test connections to localhost, nothing critical) you can write StrictHostKeyChecking accept-new to automatically accept the new key.

Thanks once more @airtower-luna .

The thing that confuses me is that I did import the key:

ssh-keygen -t rsa -q -f "$HOME/.ssh/id_rsa" -N ""
cat "$HOME/.ssh/" >> "$HOME/.ssh/authorized_keys"

and that it did find it:

debug1: identity file /home/runner/.ssh/id_rsa type 0

Sorry, writing authorized_keys in the previous post was a mistake. The issue is with known_hosts. The rest still applies, though. :wink: The key missing from known_hosts is not your login key, but the host key, which the SSH client uses to ensure it’s talking to the right server.

Thanks! Indeed that was one issue in adding myself to know_hosts. However, even with this fixed, ssh seems to really now want to take my rsa key.

debug1: Offering public key: /home/runner/.ssh/id_rsa RSA SHA256:ivLPhVUx8LHGGeIQkIdDwBJVzp9wQBkRiFRkXXN5HwE agent
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/runner/.ssh/id_dsa

(Not to worry about publishing the key here, it is generated in a virtual machine in CI).

For reference:

It looks like the SSH server rejected the key. To figure out why you’ll need to check /var/log/auth.log as I mentioned above, it should contain information on login attempts.

Thanks for all your help. The solution was in the end very simple. My $HOME has permissions 777, which is too much for SSH. So what solved it was

chmod g-w $HOME
chmod o-w $HOME
1 Like

I have lost a lot of time debugging users ssh incidents only to find out it was a simple file permission. I wrote a few bash scripts that allow users and administrators to make sure that the ssh files and directory permissions are correct on each system. The script names are and which can be found at docker-security-infrastructure/ssh at master · BradleyA/docker-security-infrastructure · GitHub

Thanks nice @bradleya . Did you consider making this an GitHub Action?