From abe5c4a6444250a8a8795940dedf9d22566f5ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 3 Aug 2019 21:40:03 -0500 Subject: [PATCH 1/3] :sparkles: Add support for GCR service account keys and custom delimiters for registry auth strings --- README.md | 21 ++++++++++++++++++--- entrypoint.sh | 29 +++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 13058c0..14ea47e 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,13 @@ for this to work it requires inserting a root CA certificate into system trusted - Map volume `/docker_mirror_cache` for up to 32gb of cached images from all registries - Map volume `/ca`, the proxy will store the CA certificate here across restarts - Env `REGISTRIES`: space separated list of registries to cache; no need to include Docker Hub, its already there. -- Env `AUTH_REGISTRIES`: space separated list of `hostname:username:password` authentication info. +- Env `AUTH_REGISTRIES`: space separated list of `hostname:username:password` authentication info. - `hostname`s listed here should be listed in the REGISTRIES environment as well, so they can be intercepted. - For Docker Hub authentication, `hostname` should be `auth.docker.io`, username should NOT be an email, use the regular username. - For regular registry auth (HTTP Basic), `hostname` here should be the same... unless your registry uses a different auth server. This should work for quay.io also, but I have no way to test. - - For Google Container Registry (GCR), username should be `_json_key` and the password should be the contents of the service account JSON. Check out [GCR docs](https://cloud.google.com/container-registry/docs/advanced-authentication#json_key_file) - + - Env `AUTH_REGISTRIES_DELIMITER` to change the separator between authentication info. By default, a space: "` `". If you use keys that contain spaces (as with Google Cloud Registry), you should update this variable, e.g. setting it to `AUTH_REGISTRIES_DELIMITER=";;;"`. In that case, `AUTH_REGISTRIES` could contain something like `registry1.com:user1:pass1;;;registry2.com:user2:pass2`. + - Env `AUTH_REGISTRY_DELIMITER` to change the separator between authentication info *parts*. By default, a colon: "`:`". If you use keys that contain single colons, you should update this variable, e.g. setting it to `AUTH_REGISTRIES_DELIMITER=":::"`. In that case, `AUTH_REGISTRIES` could contain something like `registry1.com:::user1:::pass1 registry2.com:::user2:::pass2`. + - For Google Container Registry (GCR), username should be `_json_key` and the password should be the contents of the service account JSON. Check out [GCR docs](https://cloud.google.com/container-registry/docs/advanced-authentication#json_key_file). The service account key is in JSON format, it contains spaces ("` `") and colons ("`:`"). To be able to use GCR you should set `AUTH_REGISTRIES_DELIMITER` to something different than space (e.g. `AUTH_REGISTRIES_DELIMITER=";;;"`) and `AUTH_REGISTRY_DELIMITER` to something different than a single colon (e.g. `AUTH_REGISTRY_DELIMITER=":::"`). ```bash docker run --rm --name docker_registry_proxy -it \ @@ -38,6 +39,20 @@ docker run --rm --name docker_registry_proxy -it \ rpardini/docker-registry-proxy:0.2.4 ``` +Example with GCR using credentials from a service account from a key file `servicekey.json`: + +```bash +docker run --rm --name docker_registry_proxy -it \ + -p 0.0.0.0:3128:3128 \ + -v $(pwd)/docker_mirror_cache:/docker_mirror_cache \ + -v $(pwd)/docker_mirror_certs:/ca \ + -e REGISTRIES="k8s.gcr.io gcr.io quay.io your.own.registry another.public.registry" \ + -e AUTH_REGISTRIES_DELIMITER=";;;;" \ + -e AUTH_REGISTRY_DELIMITER="::::" \ + -e AUTH_REGISTRIES="gcr.io::::_json_key::::$(cat servicekey.json);;;auth.docker.io:::dockerhub_username:::dockerhub_password" \ + rpardini/docker-registry-proxy:0.2.4 +``` + Let's say you did this on host `192.168.66.72`, you can then `curl http://192.168.66.72:3128/ca.crt` and get the proxy CA certificate. #### Configuring the Docker clients / Kubernetes nodes diff --git a/entrypoint.sh b/entrypoint.sh index 701f4d4..553b1b8 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -34,12 +34,29 @@ export ALLDOMAINS=${ALLDOMAINS:1} # remove the first comma and export # Now handle the auth part. echo -n "" > /etc/nginx/docker.auth.map -for ONEREGISTRYIN in ${AUTH_REGISTRIES}; do - ONEREGISTRY=$(echo -n ${ONEREGISTRYIN} | xargs) # Remove whitespace - AUTH_HOST=$(echo -n ${ONEREGISTRY} | cut -d ":" -f 1 | xargs) - AUTH_USER=$(echo -n ${ONEREGISTRY} | cut -d ":" -f 2 | xargs) - AUTH_PASS=$(echo -n ${ONEREGISTRY} | cut -d ":" -f 3 | xargs) - AUTH_BASE64=$(echo -n ${AUTH_USER}:${AUTH_PASS} | base64 | xargs) +# Ref: https://stackoverflow.com/a/47633817/219530 +AUTH_REGISTRIES_DELIMITER=${AUTH_REGISTRIES_DELIMITER:-" "} +s=$AUTH_REGISTRIES$AUTH_REGISTRIES_DELIMITER +auth_array=(); +while [[ $s ]]; do + auth_array+=( "${s%%"$AUTH_REGISTRIES_DELIMITER"*}" ); + s=${s#*"$AUTH_REGISTRIES_DELIMITER"}; +done + +AUTH_REGISTRY_DELIMITER=${AUTH_REGISTRY_DELIMITER:-":"} + +for ONEREGISTRY in "${auth_array[@]}"; do + s=$ONEREGISTRY$AUTH_REGISTRY_DELIMITER + registry_array=(); + while [[ $s ]]; do + registry_array+=( "${s%%"$AUTH_REGISTRY_DELIMITER"*}" ); + s=${s#*"$AUTH_REGISTRY_DELIMITER"}; + done + AUTH_HOST="${registry_array[0]}" + AUTH_USER="${registry_array[1]}" + AUTH_PASS="${registry_array[2]}" + # make base64 not wrap lines: https://superuser.com/a/1225334 + AUTH_BASE64=$(echo -n "${AUTH_USER}:${AUTH_PASS}" | base64 | tr -d \\n ) echo "Adding Auth for registry '${AUTH_HOST}' with user '${AUTH_USER}'." echo "\"${AUTH_HOST}\" \"${AUTH_BASE64}\";" >> /etc/nginx/docker.auth.map done From 4e5e75e91d02b1d7c294a156a2c84beaa18c2352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Sat, 3 Aug 2019 22:00:34 -0500 Subject: [PATCH 2/3] :memo: Fix extra colons in example in docs --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14ea47e..76594fa 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ docker run --rm --name docker_registry_proxy -it \ -v $(pwd)/docker_mirror_cache:/docker_mirror_cache \ -v $(pwd)/docker_mirror_certs:/ca \ -e REGISTRIES="k8s.gcr.io gcr.io quay.io your.own.registry another.public.registry" \ - -e AUTH_REGISTRIES_DELIMITER=";;;;" \ - -e AUTH_REGISTRY_DELIMITER="::::" \ - -e AUTH_REGISTRIES="gcr.io::::_json_key::::$(cat servicekey.json);;;auth.docker.io:::dockerhub_username:::dockerhub_password" \ + -e AUTH_REGISTRIES_DELIMITER=";;;" \ + -e AUTH_REGISTRY_DELIMITER=":::" \ + -e AUTH_REGISTRIES="gcr.io:::_json_key:::$(cat servicekey.json);;;auth.docker.io:::dockerhub_username:::dockerhub_password" \ rpardini/docker-registry-proxy:0.2.4 ``` From df8c057855f8c318914a40b2f5b625653c63669d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 9 Aug 2019 18:53:09 -0500 Subject: [PATCH 3/3] :bug: Fix entrypoint when AUTH_REGISTRIES is empty --- entrypoint.sh | 51 +++++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 553b1b8..a661baa 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -34,32 +34,35 @@ export ALLDOMAINS=${ALLDOMAINS:1} # remove the first comma and export # Now handle the auth part. echo -n "" > /etc/nginx/docker.auth.map -# Ref: https://stackoverflow.com/a/47633817/219530 -AUTH_REGISTRIES_DELIMITER=${AUTH_REGISTRIES_DELIMITER:-" "} -s=$AUTH_REGISTRIES$AUTH_REGISTRIES_DELIMITER -auth_array=(); -while [[ $s ]]; do - auth_array+=( "${s%%"$AUTH_REGISTRIES_DELIMITER"*}" ); - s=${s#*"$AUTH_REGISTRIES_DELIMITER"}; -done - -AUTH_REGISTRY_DELIMITER=${AUTH_REGISTRY_DELIMITER:-":"} - -for ONEREGISTRY in "${auth_array[@]}"; do - s=$ONEREGISTRY$AUTH_REGISTRY_DELIMITER - registry_array=(); +# Only configure auth registries if the env var contains values +if [ "$AUTH_REGISTRIES" ]; then + # Ref: https://stackoverflow.com/a/47633817/219530 + AUTH_REGISTRIES_DELIMITER=${AUTH_REGISTRIES_DELIMITER:-" "} + s=$AUTH_REGISTRIES$AUTH_REGISTRIES_DELIMITER + auth_array=(); while [[ $s ]]; do - registry_array+=( "${s%%"$AUTH_REGISTRY_DELIMITER"*}" ); - s=${s#*"$AUTH_REGISTRY_DELIMITER"}; + auth_array+=( "${s%%"$AUTH_REGISTRIES_DELIMITER"*}" ); + s=${s#*"$AUTH_REGISTRIES_DELIMITER"}; done - AUTH_HOST="${registry_array[0]}" - AUTH_USER="${registry_array[1]}" - AUTH_PASS="${registry_array[2]}" - # make base64 not wrap lines: https://superuser.com/a/1225334 - AUTH_BASE64=$(echo -n "${AUTH_USER}:${AUTH_PASS}" | base64 | tr -d \\n ) - echo "Adding Auth for registry '${AUTH_HOST}' with user '${AUTH_USER}'." - echo "\"${AUTH_HOST}\" \"${AUTH_BASE64}\";" >> /etc/nginx/docker.auth.map -done + + AUTH_REGISTRY_DELIMITER=${AUTH_REGISTRY_DELIMITER:-":"} + + for ONEREGISTRY in "${auth_array[@]}"; do + s=$ONEREGISTRY$AUTH_REGISTRY_DELIMITER + registry_array=(); + while [[ $s ]]; do + registry_array+=( "${s%%"$AUTH_REGISTRY_DELIMITER"*}" ); + s=${s#*"$AUTH_REGISTRY_DELIMITER"}; + done + AUTH_HOST="${registry_array[0]}" + AUTH_USER="${registry_array[1]}" + AUTH_PASS="${registry_array[2]}" + # make base64 not wrap lines: https://superuser.com/a/1225334 + AUTH_BASE64=$(echo -n "${AUTH_USER}:${AUTH_PASS}" | base64 | tr -d \\n ) + echo "Adding Auth for registry '${AUTH_HOST}' with user '${AUTH_USER}'." + echo "\"${AUTH_HOST}\" \"${AUTH_BASE64}\";" >> /etc/nginx/docker.auth.map + done +fi echo "" > /etc/nginx/docker.verify.ssl.conf if [[ "a${VERIFY_SSL}" == "atrue" ]]; then