ci: run SSH integration tests (#3012)

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>
This commit is contained in:
Milas Bowman 2022-07-27 16:25:27 -04:00 committed by GitHub
parent ea4cefe4fd
commit acdafbc116
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 86 additions and 29 deletions

View File

@ -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

View File

@ -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:
@ -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
@ -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
@ -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 \

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/BiXkbL9oEbE3PJv1S2p12XK5BHW3qQT5Rf+CYG0ATYyMPIVM6+IXVyf3QNxpnvPXvbPBQJCs0qHeuPwZy2Gsbt35QnmlgrczFPiXXosCD2N+wrcOQPZGuLjQyUUP2yJRVSTLpp8zk2F8w3laGIB3Jk1hUcMUExemKxQYk/L40b5rXKkarLk5awBuicjRStMrchPRHZ2n715TG+zSvf8tB/UHRXKYPqai/Je5eiH3yGUzCY4zn+uEoqAFb4V8lpIj8Rw3EXmCYVwG0vg+44QIQ2gJnIhTlcmxwkynvZn97nug4NLlGJQ+sDCnIvMapycHfGkNlBz3fFtu/ORsxPpZbTNg/9noa3Zf8OpIwvE/FHNPqDctGltwxEgQxj5fE34x0fYnF08tejAUJJCZE3YsGgNabsS4pD+kRhI83eFZvgj3Q1AeTK0V9bRM7jujcc9Rz+V9Gb5zYEHN/l8PxEVlj0OlURf9ZlknNQK8xRh597jDXTfVQKCMO/nRaWH2bq0=

View File

@ -1,3 +0,0 @@
Host *
StrictHostKeyChecking no
UserKnownHostsFile=/dev/null

View File

@ -2,6 +2,8 @@ import os
import shutil
import unittest
import pytest
import docker
from .. import helpers
from docker.utils import kwargs_from_env
@ -68,6 +70,8 @@ class BaseIntegrationTest(unittest.TestCase):
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`

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4QAAAJgIMffcCDH3
3AAAAAtzc2gtZWQyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4Q
AAAEDeXnt5AuNk4oTHjMU1vUsEwh64fuEPu4hXsG6wCVt/6Iax81dU/Xw3tcLohAa67FdB
FtPGU8YuP7n8IHKP16DhAAAAEXJvb3RAMGRkZmQyMWRkYjM3AQIDBA==
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIax81dU/Xw3tcLohAa67FdBFtPGU8YuP7n8IHKP16Dh docker-py integration tests known

View File

@ -0,0 +1,3 @@
IgnoreUserKnownHosts yes
PubkeyAuthentication yes
PermitRootLogin yes

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4QAAAJgIMffcCDH3
3AAAAAtzc2gtZWQyNTUxOQAAACCGsfNXVP18N7XC6IQGuuxXQRbTxlPGLj+5/CByj9eg4Q
AAAEDeXnt5AuNk4oTHjMU1vUsEwh64fuEPu4hXsG6wCVt/6Iax81dU/Xw3tcLohAa67FdB
FtPGU8YuP7n8IHKP16DhAAAAEXJvb3RAMGRkZmQyMWRkYjM3AQIDBA==
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIax81dU/Xw3tcLohAa67FdBFtPGU8YuP7n8IHKP16Dh docker-py integration tests unknown

22
tests/ssh/connect_test.py Normal file
View File

@ -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))