Skip to content

Commit 576b896

Browse files
committed
Stop using docker-py for anything
Also properly setup TLS for docker daemon to close security hole
1 parent 9f6fbf7 commit 576b896

File tree

8 files changed

+32
-53
lines changed

8 files changed

+32
-53
lines changed

repo2docker/app.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -750,12 +750,8 @@ def find_image(self):
750750
if self.dry_run:
751751
return False
752752
# check if we already have an image for this content
753-
client = self.get_engine()
754-
for image in client.images():
755-
for tag in image.tags:
756-
if tag == self.output_image_spec + ":latest":
757-
return True
758-
return False
753+
engine = self.get_engine()
754+
return engine.inspect_image(self.output_image_spec) is not None
759755

760756
def build(self):
761757
"""

repo2docker/buildpacks/docker.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
import os
55

6-
import docker
7-
86
from .base import BuildPack
97

108

repo2docker/docker.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Docker container engine for repo2docker
33
"""
44

5+
import json
56
import os
67
import shutil
78
import subprocess
@@ -13,9 +14,7 @@
1314
from iso8601 import parse_date
1415
from traitlets import Dict, List, Unicode
1516

16-
import docker
17-
18-
from .engine import Container, ContainerEngine, ContainerEngineException, Image
17+
from .engine import Container, ContainerEngine, Image
1918
from .utils import execute_cmd
2019

2120

@@ -86,16 +85,6 @@ class DockerEngine(ContainerEngine):
8685
config=True,
8786
)
8887

89-
def __init__(self, *, parent):
90-
super().__init__(parent=parent)
91-
try:
92-
kwargs = docker.utils.kwargs_from_env()
93-
kwargs.update(self.extra_init_args)
94-
kwargs.setdefault("version", "auto")
95-
self._apiclient = docker.APIClient(**kwargs)
96-
except docker.errors.DockerException as e:
97-
raise ContainerEngineException("Check if docker is running on the host.", e)
98-
9988
def build(
10089
self,
10190
*,
@@ -152,13 +141,20 @@ def build(
152141

153142
yield from execute_cmd(args, True)
154143

155-
def images(self):
156-
images = self._apiclient.images()
157-
return [Image(tags=image["RepoTags"]) for image in images]
158144

159145
def inspect_image(self, image):
160-
image = self._apiclient.inspect_image(image)
161-
return Image(tags=image["RepoTags"], config=image["Config"])
146+
"""
147+
Return image configuration if it exists, otherwise None
148+
"""
149+
proc = subprocess.run([
150+
"docker", "image", "inspect", image
151+
], capture_output=True)
152+
153+
if proc.returncode != 0:
154+
return None
155+
156+
config = json.loads(proc.stdout.decode())
157+
return Image(tags=config["RepoTags"], config=config["Config"])
162158

163159
@contextmanager
164160
def docker_login(self, username, password, registry):

repo2docker/engine.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,19 +254,9 @@ def build(
254254
"""
255255
raise NotImplementedError("build not implemented")
256256

257-
def images(self):
258-
"""
259-
List images
260-
261-
Returns
262-
-------
263-
list[Image] : List of Image objects.
264-
"""
265-
raise NotImplementedError("images not implemented")
266-
267257
def inspect_image(self, image):
268258
"""
269-
Get information about an image
259+
Get information about an image, or None if the image does not exist
270260
271261
TODO: This is specific to the engine, can we convert it to a standard format?
272262

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ def get_identifier(json):
5050
version=versioneer.get_version(),
5151
install_requires=[
5252
"chardet",
53-
"docker!=5.0.0",
5453
"entrypoints",
5554
"escapism",
5655
"iso8601",

tests/registry/test_registry.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import shutil
23
import secrets
34
import socket
45
import subprocess
@@ -17,33 +18,36 @@
1718
@pytest.fixture(scope="session")
1819
def dind(registry, host_ip):
1920
port = get_free_port()
21+
22+
# Generate CA certs here so we can securely connect to the docker daemon
23+
cert_dir = HERE / f"tmp-certs-{secrets.token_hex(8)}"
24+
cert_dir.mkdir()
25+
2026
dind_image = "docker:dind"
2127
subprocess.check_call(["docker", "pull", dind_image])
22-
# This is insecure, because I'm disabling all kinds of authentication on the docker daemon.
23-
# FIXME: Use TLS verification.
24-
# but also docker this is your own fucking fault for making technical choices that force dockerhub
25-
# to be the primary registry, so your registry handling sucks and forces these kinds of difficulties.
28+
2629
cmd = [
2730
"docker",
2831
"run",
2932
"-e",
30-
"DOCKER_TLS_CERTDIR=",
33+
"DOCKER_TLS_CERTDIR=/opt/certs",
3134
"--privileged",
35+
"--mount", f"type=bind,src={cert_dir},dst=/opt/certs",
3236
"-p",
3337
f"{port}:2376",
3438
dind_image,
3539
"--host",
3640
"0.0.0.0:2376",
3741
"--insecure-registry",
3842
registry,
39-
"--tls=false",
4043
]
4144
proc = subprocess.Popen(cmd)
4245
time.sleep(5)
4346

4447
try:
45-
yield f"tcp://{host_ip}:{port}"
48+
yield f"tcp://127.0.0.1:{port}", cert_dir
4649
finally:
50+
shutil.rmtree(cert_dir)
4751
proc.terminate()
4852
proc.wait()
4953

@@ -100,7 +104,10 @@ def test_registry(registry, dind):
100104
image_name = f"{registry}/{secrets.token_hex(8)}:latest"
101105
r2d = make_r2d(["--image", image_name, "--push", "--no-run", str(HERE)])
102106

103-
os.environ["DOCKER_HOST"] = dind
107+
docker_host, cert_dir = dind
108+
os.environ["DOCKER_HOST"] = docker_host
109+
os.environ["DOCKER_CERT_PATH"] = str(cert_dir / "client")
110+
os.environ["DOCKER_TLS_VERIFY"] = "1"
104111
r2d.start()
105112

106113
proc = subprocess.run(["docker", "manifest", "inspect", "--insecure", image_name])

tests/unit/test_docker.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
import os
44
from subprocess import check_output
5-
from unittest.mock import Mock, patch
6-
7-
from repo2docker.docker import DockerEngine
85

96
repo_root = os.path.abspath(
107
os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)

tests/unit/test_ports.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import pytest
1212
import requests
1313

14-
import docker
1514
from repo2docker.__main__ import make_r2d
1615
from repo2docker.app import Repo2Docker
1716

@@ -69,10 +68,7 @@ def _cleanup():
6968
container.reload()
7069
if container.status == "running":
7170
container.kill()
72-
try:
7371
container.remove()
74-
except docker.errors.NotFound:
75-
pass
7672

7773
request.addfinalizer(_cleanup)
7874

0 commit comments

Comments
 (0)