From cc50c3048b6e72c516caf6e73b03c782faa489ff Mon Sep 17 00:00:00 2001 From: Jean-Philippe Evrard Date: Tue, 19 Feb 2019 19:30:16 +0100 Subject: [PATCH] Support self-signed certificates docker registry If you want to run a docker registry for development purposes with self-signed certificates, and use this registry to push your requirements wheel, the loci build process would fail at fetching the wheels. This brings support for self-signed certificates registries by: - Allowing to skip protocol_detection: If protocol_detection happens on a https registry, urllib2 would not throw an HTTPError or URLError, and protocol returned by default would be HTTP, which would then cause issues by not using SSL to fetch data. There is no point to "detect" things if we provide an argument to the users. - If the protocol is correctly given as HTTPs, no certificate is passed into the urllib ssl contexts by default, which would only work with globally valid certificates. This patch also adds an option to bypass the verification of certificates when the user provides `REGISTRY_SSL_NOVERIFY`. Change-Id: Ib00bbc9cc63d70a88dbf8b23a518553d6134d332 --- Dockerfile | 2 ++ README.md | 6 ++++++ scripts/fetch_wheels.py | 29 ++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3d8faf54..7d869341 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,8 @@ ARG PLUGIN=no ARG PYTHON3=no ARG EXTRA_BINDEP="" ARG EXTRA_PYDEP="" +ARG REGISTRY_PROTOCOL="detect" +ARG REGISTRY_INSECURE="False" ARG UID=42424 ARG GID=42424 diff --git a/README.md b/README.md index dac9810a..be7dac11 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,12 @@ For more advanced building you can use docker build arguments to define: be considered next to the default bindep.txt. * `EXTRA_PYDEP` Specify a pydep-* file to add in the container. It would be considered next to the default pydep.txt. + * `REGISTRY_PROTOCOL` Set this to `https` if you are running your own + registry on https, `http` if you are running on http, or leave it as + `detect` if you want to re-use existing protocol detection. + * `REGISTRY_INSECURE` Set this to `True` if your image registry is + running on HTTPS with self-signed certificates to ignore SSL verification. + (defaults to False) This makes it really easy to integrate LOCI images into your development or CI/CD workflow, for example, if you wanted to build an image from [this diff --git a/scripts/fetch_wheels.py b/scripts/fetch_wheels.py index dadc645d..1fe9af65 100755 --- a/scripts/fetch_wheels.py +++ b/scripts/fetch_wheels.py @@ -3,6 +3,8 @@ import json import os import re +import ssl +from distutils.util import strtobool try: import urllib2 @@ -24,7 +26,10 @@ def get_token(protocol, registry, repo): print(url) try: r = urllib2.Request(url=url) - resp = urllib2.urlopen(r) + if strtobool(os.environ.get('REGISTRY_INSECURE', "False")): + resp = urllib2.urlopen(r, context=ssl._create_unverified_context()) + else: + resp = urllib2.urlopen(r) resp_text = resp.read().decode('utf-8').strip() return json.loads(resp_text)['token'] except urllib2.HTTPError as err: @@ -37,7 +42,10 @@ def get_sha(repo, tag, registry, protocol, token): r = urllib2.Request(url=url) if token: r.add_header('Authorization', 'Bearer {}'.format(token)) - resp = urllib2.urlopen(r) + if strtobool(os.environ.get('REGISTRY_INSECURE', "False")): + resp = urllib2.urlopen(r, context=ssl._create_unverified_context()) + else: + resp = urllib2.urlopen(r) resp_text = resp.read().decode('utf-8').strip() return json.loads(resp_text)['fsLayers'][0]['blobSum'] @@ -49,7 +57,10 @@ def get_blob(repo, tag, protocol, registry=DOCKER_REGISTRY, token=None): r = urllib2.Request(url=url) if token: r.add_header('Authorization', 'Bearer {}'.format(token)) - resp = urllib2.urlopen(r) + if strtobool(os.environ.get('REGISTRY_INSECURE', "False")): + resp = urllib2.urlopen(r, context=ssl._create_unverified_context()) + else: + resp = urllib2.urlopen(r) return resp.read() def protocol_detection(registry, protocol='http'): @@ -73,7 +84,10 @@ def protocol_detection(registry, protocol='http'): def get_wheels(url): r = urllib2.Request(url=url) - resp = urllib2.urlopen(r) + if strtobool(os.environ.get('REGISTRY_INSECURE', "False")): + resp = urllib2.urlopen(r, context=ssl._create_unverified_context()) + else: + resp = urllib2.urlopen(r) return resp.read() def parse_image(full_image): @@ -106,7 +120,12 @@ def main(): data = get_wheels(wheels) else: registry, image, tag = parse_image(wheels) - protocol = protocol_detection(registry) + if os.environ.get('REGISTRY_PROTOCOL') in ['http','https']: + protocol = os.environ.get('REGISTRY_PROTOCOL') + elif os.environ.get('REGISTRY_PROTOCOL') == 'detect': + protocol = protocol_detection(registry) + else: + raise ValueError("Unknown protocol given in argument") kwargs = dict() if registry: kwargs.update({'registry': registry})