Difference between revisions of "Docker: Docker registry"

From Define Wiki
Jump to navigation Jump to search
(Created page with "== Secure Docker registry with user authentication == <code>docker-compose.yaml</code> <nowiki> dockerauth: container_name: dockerauth image: cesanta/docker_auth port...")
 
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
 
== Secure Docker registry with user authentication ==
 
== Secure Docker registry with user authentication ==
 +
For this to work, there are 2 things required:
  
<code>docker-compose.yaml</code>
+
# the registry to store images in
 +
# an authentication service to authenticate users
  
 +
[[File:V2-registry-auth.png]]
 +
 +
Here Token Authentication[2] is used with <code>cesanta/docker_auth</code>[4] playing a role of a token issuer.
 +
 +
File: <code>docker-compose.yaml</code>
 
  <nowiki>
 
  <nowiki>
 
dockerauth:
 
dockerauth:
Line 35: Line 42:
 
</nowiki>
 
</nowiki>
  
<code>auth_config.yml</code>
+
<code>docker_auth</code> provides an implementation of the Token Auth specification [2] that supports multiple authentication methods (see README in the GitHub repo). The simplest of them is a static list of users who's credentials (hashed) have to be added to the service's config file:
  
 +
File: <code>auth_config.yml</code>
 
  <nowiki>
 
  <nowiki>
 
# Server settings
 
# Server settings
Line 67: Line 75:
 
   # Access is denied by default
 
   # Access is denied by default
 
</nowiki>
 
</nowiki>
(admin's password is "admin" - without quotes)
+
On the above admin's password is "admin" - without quotes. To hash a passwords, run <code>docker run --rm -it httpd htpasswd -nB <username></code>.
 +
 
 +
Both containers encrypt client traffic by using the wildcard vscaler.com SSL certificate located in <code>/etc/pki/docker-registry</code>.
 +
 
 +
ACLs allow to control user actions or even restrict access to certain images[5].
 +
 
 +
TODO: Add a private namespace with images only available after logging in.
  
 
To create containers, run:
 
To create containers, run:
Line 76: Line 90:
  
  
=== Usage ===
+
=== Usage (testing) ===
 +
For testing purposes a clone of the real registry.vscaler.com instance has been created in the Labs and authentication has been set up there using the method from the previous section. In order to interact with the clone, the host entry for registry.vscaler.com has to be set to point to the clone's IP. A clean method for doing this is to use a Docker-in-Docker container run with the <code>--add-host</code> flag:
 +
<nowiki>
 +
[root@vscaler-vgpu ~]# docker run -d --privileged --name dind --add-host registry.vscaler.com:172.28.139.124 docker:stable-dind
 +
[root@vscaler-vgpu ~]# docker exec -it dind /bin/sh
 +
</nowiki>
 +
 
 
As an anonymous user (without logging in):
 
As an anonymous user (without logging in):
  
 
  <nowiki>
 
  <nowiki>
[root@vscaler-vgpu ~]# docker run -d --privileged --name dind --add-host registry.vscaler.com:172.28.139.124 docker:stable-dind
 
[root@vscaler-vgpu ~]# docker exec -it dind /bin/sh
 
 
/ # docker pull registry.vscaler.com:5000/alpine:latest
 
/ # docker pull registry.vscaler.com:5000/alpine:latest
 
latest: Pulling from alpine
 
latest: Pulling from alpine
Line 99: Line 117:
 
denied: requested access to the resource is denied
 
denied: requested access to the resource is denied
 
</nowiki>
 
</nowiki>
 +
Anonymous users can pull images from the registry, but can't push them.
 +
 
Log in as an admin:
 
Log in as an admin:
 
  <nowiki>
 
  <nowiki>
Line 124: Line 144:
 
Status: Downloaded newer image for registry.vscaler.com:5000/alpine:latest
 
Status: Downloaded newer image for registry.vscaler.com:5000/alpine:latest
 
</nowiki>
 
</nowiki>
 +
 +
=== Resources ===
 +
# https://github.com/docker/docker.github.io/blob/b0f67bf/registry/deploying.md
 +
# https://docs.docker.com/registry/spec/auth/token/
 +
# https://the.binbashtheory.com/creating-private-docker-registry-2-0-with-token-authentication-service/
 +
# https://github.com/cesanta/docker_auth
 +
# https://github.com/cesanta/docker_auth/blob/b89dec9a4f0098fb0f71d9b94e44d1710c1fe5cf/docs/Backend_MongoDB.md
 +
# https://docs.docker.com/compose/compose-file/compose-file-v2/

Latest revision as of 10:44, 15 March 2019

Secure Docker registry with user authentication

For this to work, there are 2 things required:

  1. the registry to store images in
  2. an authentication service to authenticate users

V2-registry-auth.png

Here Token Authentication[2] is used with cesanta/docker_auth[4] playing a role of a token issuer.

File: docker-compose.yaml

dockerauth:
  container_name: dockerauth
  image: cesanta/docker_auth
  ports:
    - 5001:5001
  volumes:
    - /root/registry:/config:ro
    - /var/log/docker_auth:/logs
    - /etc/pki/docker-registry:/ssl:ro
  command: /config/auth_config.yml
  restart: always

registry:
  container_name: registry
  restart: always
  image: registry:2
  ports:
    - 5000:5000
  environment:
    REGISTRY_HTTP_TLS_CERTIFICATE: /certs/vscaler.com.crt
    REGISTRY_HTTP_TLS_KEY: /certs/vscaler.com.key
    REGISTRY_AUTH: token
    REGISTRY_AUTH_TOKEN_REALM: https://registry.vscaler.com:5001/auth
    REGISTRY_AUTH_TOKEN_SERVICE: "Docker registry"
    REGISTRY_AUTH_TOKEN_ISSUER: "Auth Service"
    REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE: /certs/vscaler.com.crt
  volumes:
    - registry:/var/lib/registry
    - /etc/pki/docker-registry:/certs:ro

docker_auth provides an implementation of the Token Auth specification [2] that supports multiple authentication methods (see README in the GitHub repo). The simplest of them is a static list of users who's credentials (hashed) have to be added to the service's config file:

File: auth_config.yml

# Server settings
server:
  # Address to listen on
  addr: ":5001"
  # TLS certificate and key
  certificate: "/ssl/vscaler.com.crt"
  key: "/ssl/vscaler.com.key"

# Settings for the token
token:
  issuer: "Auth Service"  # Must match issuer in the Registry config.
  expiration: 900

# Static user map
users:
  # Password is specified as a BCrypt hash. Use `htpasswd -nB username` to generate.
  "admin":
    password: "$2y$05$3XbRMkU1lavzRK7HSO4x..9MuRGwVMphjXqX/z2krxgflr8JB9lM."
  "": {}  # Allow anonymous (no "docker login") access

acl:
  # Admin has full access to everything
  - match: {account: "admin"}
    actions: ["*"]
  # Anonymous users can pull all images
  - match: {account: ""}
    actions: ["pull"]
  # Access is denied by default

On the above admin's password is "admin" - without quotes. To hash a passwords, run docker run --rm -it httpd htpasswd -nB <username>.

Both containers encrypt client traffic by using the wildcard vscaler.com SSL certificate located in /etc/pki/docker-registry.

ACLs allow to control user actions or even restrict access to certain images[5].

TODO: Add a private namespace with images only available after logging in.

To create containers, run:

docker-compose up -d

as root in the directory with docker-compose.yaml (currently /root/registry/).


Usage (testing)

For testing purposes a clone of the real registry.vscaler.com instance has been created in the Labs and authentication has been set up there using the method from the previous section. In order to interact with the clone, the host entry for registry.vscaler.com has to be set to point to the clone's IP. A clean method for doing this is to use a Docker-in-Docker container run with the --add-host flag:

[root@vscaler-vgpu ~]# docker run -d --privileged --name dind --add-host registry.vscaler.com:172.28.139.124 docker:stable-dind
[root@vscaler-vgpu ~]# docker exec -it dind /bin/sh

As an anonymous user (without logging in):

/ # docker pull registry.vscaler.com:5000/alpine:latest
latest: Pulling from alpine
8e402f1a9c57: Pull complete
Digest: sha256:d05ecd4520cab5d9e5d877595fb0532aadcd6c90f4bbc837bc11679f704c4c82
Status: Downloaded newer image for registry.vscaler.com:5000/alpine:latest
/ # docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest
/ # docker tag hello-world registry.vscaler.com:5000/hello-world:mariusz
/ # docker push registry.vscaler.com:5000/hello-world:mariusz
The push refers to repository [registry.vscaler.com:5000/hello-world]
af0b15c8625b: Preparing
denied: requested access to the resource is denied

Anonymous users can pull images from the registry, but can't push them.

Log in as an admin:

/ # docker login registry.vscaler.com:5000
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
/ # docker push registry.vscaler.com:5000/hello-world:mariusz
The push refers to repository [registry.vscaler.com:5000/hello-world]
af0b15c8625b: Pushed
mariusz: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524
/ # docker rmi registry.vscaler.com:5000/alpine:latest
Untagged: registry.vscaler.com:5000/alpine:latest
Untagged: registry.vscaler.com:5000/alpine@sha256:d05ecd4520cab5d9e5d877595fb0532aadcd6c90f4bbc837bc11679f704c4c82
Deleted: sha256:5cb3aa00f89934411ffba5c063a9bc98ace875d8f92e77d0029543d9f2ef4ad0
Deleted: sha256:bcf2f368fe234217249e00ad9d762d8f1a3156d60c442ed92079fa5b120634a1
/ # docker pull registry.vscaler.com:5000/alpine:latest
latest: Pulling from alpine
8e402f1a9c57: Pull complete
Digest: sha256:d05ecd4520cab5d9e5d877595fb0532aadcd6c90f4bbc837bc11679f704c4c82
Status: Downloaded newer image for registry.vscaler.com:5000/alpine:latest

Resources

  1. https://github.com/docker/docker.github.io/blob/b0f67bf/registry/deploying.md
  2. https://docs.docker.com/registry/spec/auth/token/
  3. https://the.binbashtheory.com/creating-private-docker-registry-2-0-with-token-authentication-service/
  4. https://github.com/cesanta/docker_auth
  5. https://github.com/cesanta/docker_auth/blob/b89dec9a4f0098fb0f71d9b94e44d1710c1fe5cf/docs/Backend_MongoDB.md
  6. https://docs.docker.com/compose/compose-file/compose-file-v2/