Skip to content

Commit

Permalink
ci: run SSH integration tests
Browse files Browse the repository at this point in the history
Fix & enable SSH integration test suite.

This also adds a new test for connecting to unknown hosts when
using the Python SSH implementation (Paramiko). See #2932 for
more info.

Because of the above, some of the config/static key files have been
moved around and adjusted.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
  • Loading branch information
milas committed Jul 27, 2022
1 parent d929864 commit 71a97ba
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
variant: [ "integration-dind", "integration-dind-ssl" ]
variant: [ "integration-dind", "integration-dind-ssl", "integration-dind-ssh" ]

steps:
- uses: actions/checkout@v3
Expand Down
41 changes: 30 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,21 @@ clean:

.PHONY: build-dind-ssh
build-dind-ssh:
docker build -t docker-dind-ssh -f tests/Dockerfile-ssh-dind --build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} --build-arg API_VERSION=${TEST_API_VERSION} --build-arg APT_MIRROR .
docker build \
--pull \
-t docker-dind-ssh \
-f tests/Dockerfile-ssh-dind \
--build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} \
--build-arg API_VERSION=${TEST_API_VERSION} \
--build-arg APT_MIRROR .

.PHONY: build-py3
build-py3:
docker build -t docker-sdk-python3 -f tests/Dockerfile --build-arg APT_MIRROR .
docker build \
--pull \
-t docker-sdk-python3 \
-f tests/Dockerfile \
--build-arg APT_MIRROR .

.PHONY: build-docs
build-docs:
Expand Down Expand Up @@ -61,6 +71,7 @@ integration-dind-py3: build-py3 setup-network
--detach \
--name dpy-dind-py3 \
--network dpy-tests \
--pull=always \
--privileged \
docker:${TEST_ENGINE_VERSION}-dind \
dockerd -H tcp://0.0.0.0:2375 --experimental
Expand All @@ -85,16 +96,23 @@ integration-dind-py3: build-py3 setup-network
docker rm -vf dpy-dind-py3


.PHONY: integration-ssh-py3
integration-ssh-py3: build-dind-ssh build-py3 setup-network
docker rm -vf dpy-dind-py3 || :
docker run -d --network dpy-tests --name dpy-dind-py3 --privileged\
.PHONY: integration-dind-ssh
integration-dind-ssh: build-dind-ssh build-py3 setup-network
docker rm -vf dpy-dind-ssh || :
docker run -d --network dpy-tests --name dpy-dind-ssh --privileged \
docker-dind-ssh dockerd --experimental
# start SSH daemon
docker exec dpy-dind-py3 sh -c "/usr/sbin/sshd"
docker run -t --rm --env="DOCKER_HOST=ssh://dpy-dind-py3" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\
--network dpy-tests docker-sdk-python3 py.test tests/ssh/${file}
docker rm -vf dpy-dind-py3
# start SSH daemon for known key
docker exec dpy-dind-ssh sh -c "/usr/sbin/sshd -h /etc/ssh/known_ed25519 -p 22"
docker exec dpy-dind-ssh sh -c "/usr/sbin/sshd -h /etc/ssh/unknown_ed25519 -p 2222"
docker run \
--tty \
--rm \
--env="DOCKER_HOST=ssh://dpy-dind-ssh" \
--env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}" \
--env="UNKNOWN_DOCKER_SSH_HOST=ssh://dpy-dind-ssh:2222" \
--network dpy-tests \
docker-sdk-python3 py.test tests/ssh/${file}
docker rm -vf dpy-dind-ssh


.PHONY: integration-dind-ssl
Expand All @@ -110,6 +128,7 @@ integration-dind-ssl: build-dind-certs build-py3 setup-network
--name dpy-dind-ssl \
--network dpy-tests \
--network-alias docker \
--pull=always \
--privileged \
--volume /tmp \
--volumes-from dpy-dind-certs \
Expand Down
4 changes: 3 additions & 1 deletion tests/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ RUN apt-get update && apt-get -y install --no-install-recommends \
pass

# Add SSH keys and set permissions
COPY tests/ssh-keys /root/.ssh
COPY tests/ssh/config/client /root/.ssh
COPY tests/ssh/config/server/known_ed25519.pub /root/.ssh/known_hosts
RUN sed -i '1s;^;dpy-dind-ssh ;' /root/.ssh/known_hosts
RUN chmod -R 600 /root/.ssh

COPY ./tests/gpg-keys /gpg-keys
Expand Down
19 changes: 7 additions & 12 deletions tests/Dockerfile-ssh-dind
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
ARG API_VERSION=1.41
ARG ENGINE_VERSION=20.10.17
ARG ENGINE_VERSION=20.10

FROM docker:${ENGINE_VERSION}-dind

RUN apk add --no-cache \
RUN apk add --no-cache --upgrade \
openssh

# Add the keys and set permissions
RUN ssh-keygen -A

# copy the test SSH config
RUN echo "IgnoreUserKnownHosts yes" > /etc/ssh/sshd_config && \
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config && \
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
COPY tests/ssh/config/server /etc/ssh/
RUN chmod -R 600 /etc/ssh

# set authorized keys for client paswordless connection
COPY tests/ssh-keys/authorized_keys /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh/authorized_keys
COPY tests/ssh/config/client/id_rsa.pub /root/.ssh/authorized_keys
RUN chmod -R 600 /root/.ssh

RUN echo "root:root" | chpasswd
# RUN echo "root:root" | chpasswd
RUN ln -s /usr/local/bin/docker /usr/bin/docker
EXPOSE 22
1 change: 0 additions & 1 deletion tests/ssh-keys/authorized_keys

This file was deleted.

3 changes: 0 additions & 3 deletions tests/ssh-keys/config

This file was deleted.

4 changes: 4 additions & 0 deletions tests/ssh/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import shutil
import unittest

import pytest

import docker
from .. import helpers
from docker.utils import kwargs_from_env
Expand Down Expand Up @@ -68,6 +70,8 @@ def tearDown(self):
client.close()


@pytest.mark.skipif(not os.environ.get('DOCKER_HOST', '').startswith('ssh://'),
reason='DOCKER_HOST is not an SSH target')
class BaseAPIIntegrationTest(BaseIntegrationTest):
"""
A test case for `APIClient` integration tests. It sets up an `APIClient`
Expand Down
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions tests/ssh/config/server/known_ed25519
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4QAAAJgIMffcCDH3
3AAAAAtzc2gtZWQyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4Q
AAAEDeXnt5AuNk4oTHjMU1vUsEwh64fuEPu4hXsG6wCVt/6Iax81dU/Xw3tcLohAa67FdB
FtPGU8YuP7n8IHKP16DhAAAAEXJvb3RAMGRkZmQyMWRkYjM3AQIDBA==
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions tests/ssh/config/server/known_ed25519.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIax81dU/Xw3tcLohAa67FdBFtPGU8YuP7n8IHKP16Dh docker-py integration tests known
3 changes: 3 additions & 0 deletions tests/ssh/config/server/sshd_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
IgnoreUserKnownHosts yes
PubkeyAuthentication yes
PermitRootLogin yes
7 changes: 7 additions & 0 deletions tests/ssh/config/server/unknown_ed25519
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4QAAAJgIMffcCDH3
3AAAAAtzc2gtZWQyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4Q
AAAEDeXnt5AuNk4oTHjMU1vUsEwh64fuEPu4hXsG6wCVt/6Iax81dU/Xw3tcLohAa67FdB
FtPGU8YuP7n8IHKP16DhAAAAEXJvb3RAMGRkZmQyMWRkYjM3AQIDBA==
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions tests/ssh/config/server/unknown_ed25519.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIax81dU/Xw3tcLohAa67FdBFtPGU8YuP7n8IHKP16Dh docker-py integration tests unknown
22 changes: 22 additions & 0 deletions tests/ssh/connect_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import unittest

import docker
import paramiko.ssh_exception
import pytest
from .base import TEST_API_VERSION


class SSHConnectionTest(unittest.TestCase):
@pytest.mark.skipif('UNKNOWN_DOCKER_SSH_HOST' not in os.environ,
reason='Unknown Docker SSH host not configured')
def test_ssh_unknown_host(self):
with self.assertRaises(paramiko.ssh_exception.SSHException) as cm:
docker.APIClient(
version=TEST_API_VERSION,
timeout=60,
# test only valid with Paramiko
use_ssh_client=False,
base_url=os.environ['UNKNOWN_DOCKER_SSH_HOST'],
)
self.assertIn('not found in known_hosts', str(cm.exception))

0 comments on commit 71a97ba

Please sign in to comment.