├── .gitignore
├── LICENSE
├── README.md
├── auth
├── config
│ ├── auth_config.yml
│ ├── ldap_certificates
│ │ └── COPY_CERTIFICATES_HERE_THAT_ARE_NEEDED_FOR_AUTHENTICATION_AGAINST_LDAP
│ ├── ldap_password.txt
│ └── reference.yml
└── start.sh
├── certs
├── README.md
├── auth.crt
├── auth.key
├── registry.crt
└── registry.key
├── docker-compose.yml
├── docs
├── setup.graphml
└── setup.png
├── ldap
├── Dockerfile
├── setup-ldap-schema.ldif
├── setup-ldap-schema.sh
├── slapd.sh
└── supervisord.conf
└── registry
└── conf
└── config.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | registry/storage/*
2 | auth/logs
3 | auth/config/ldap_certificates/*
4 | auth/config/config.yml.custom
5 | *~
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Docker Registry Setup
2 |
3 | This project is intended for people like me who need to get their hands on a
4 | piece of technology before they can fully grasp it.
5 |
6 | The purpose of this project is rather educational. I'll show you how you can
7 | setup a docker registry v2 and an authorization server with an LDAP backend.
8 | In fact, everything is already setup for you to run. There's a docker container
9 | for the registry, the JWT auth server and the LDAP server. Feel free to connect
10 | to your company LDAP if you want by making adjustments to the auth server's
11 | config file (`auth/config/config.yml`). Just like that you can replace this
12 | setup piece by piece to suite your needs.
13 |
14 | Here's a graphic showing all the containers and how they talk to each other:
15 |
16 | 
17 |
18 | 1. Attempt to begin a push/pull operation with the registry.
19 | 2. If the registry requires authorization it will return a 401 Unauthorized HTTP response with information on how to authenticate.
20 | 3. The registry client makes a request to the authorization service for a Bearer token.
21 | 4. The authorization server makes a request to the LDAP server to check if a user exists. We use a service account to connect to the LDAP server.
22 | 5. The LDAP server returns an answer to the user lookup.
23 | 6. The authorization service returns an opaque Bearer token representing the client's authorized access.
24 | 7. The client retries the original request with the Bearer token embedded in the request's Authorization header.
25 | 8. The Registry authorizes the client by validating the Bearer token and the claim set embedded within it and begins the push/pull session as usual.
26 |
27 | [Here](https://github.com/docker/distribution/blob/master/docs/spec/auth/token.md)
28 | you can read more about the Docker v2 registry authorization process.
29 |
30 | # How are authentication and authorization configured
31 |
32 | **NOTE** Remember, that *authentication* ensures that you are who you claim t
33 | be. *Authorization* on the other hand defines rules of what somebody is
34 | (dis)allowed to do.
35 |
36 | The auth server is configured to try all authentication methods that
37 | have been specified in `auth/config/config.yml`. Currently LDAP and a static
38 | list of users/passwords are configured
39 |
40 | These password combinations are defined statically:
41 |
42 | * admin:badmin (can push and pull)
43 | * test:123 (can only pull)
44 |
45 | I've included an LDAP server in the `docker-compose.yml` that is also used for
46 | authentication. This is the LDAP hierarchy:
47 |
48 | ```
49 | com
50 | |_example
51 | |
52 | |_philosophs
53 | | |_schopenhauer
54 | | |_kant
55 | |_musicians
56 | | |_mozart
57 | | |_bach
58 | |_it
59 | |_serviceaccount
60 | ```
61 |
62 | (This hierarchy is described here: `ldap/setup-ldap-schema.ldif`.)
63 |
64 | All musicians (`mozart` and `bach`) are usernames that are authorized to login
65 | using the password `password` and they can all push and pull images to or from
66 | the registry. The philosophs (`schopenhauer` and `kant`) are not used and will
67 | not function with the current LDAP search base (see
68 | `base: "ou=musicians,dc=example,dc=com"` in `auth/config/config.yml`).
69 |
70 | I use the `serviceaccount` username to connect to bind to LDAP from the auth
71 | server. It
72 |
73 | **Notice** that on a successful second pull or push you won't have to enter your
74 | credentials again because they have been saved here: `~/.docker/config.json`.
75 | Remove this file if you want to force another prompt for username and password.
76 |
77 | # Preparation
78 |
79 | **IMPORTANT** Read these instructions to get up and running with your own
80 | already configured docker registry v2 deployment.
81 |
82 | ## Configure docker deamon
83 |
84 | These instructions only need to be executed once. For the purpose of demonstation we
85 | will be running a registry on `localhost` and by default we must inform our
86 | docker client about any insecure registry that we want to be using. Here's how
87 | it works:
88 |
89 | * Make sure you have docker > 1.8 as well as docker-compose installed.
90 | * Ensure your `DOCKER_OPTS` contains this option: `--insecure-registry 0.0.0.0:5000`.
91 | On an Ubuntu 14.04 you can find this option in your `/etc/default/docker` file.
92 | * Restart your docker service: `service docker restart`.
93 |
94 | # How to run
95 |
96 | ```bash
97 | # Clone the repository
98 | git clone https://github.com/kwk/docker-registry-setup.git
99 |
100 | # Navigate inside
101 | cd docker-registry-setup
102 |
103 | # Fire up the registry and the auth server as containers
104 | # Notice that the docker registry is configured with a persistent storage volume
105 | # from the docker host, hence --force-recreate will not wipe this storage for you.
106 | docker-compose up -d --force-recreate
107 |
108 | # Pull an image from the offical docker hub that we want push to our own secured registry
109 | docker pull busybox
110 |
111 | # Tag the image so that it can be pushed to our local registry
112 | docker tag busybox 0.0.0.0:5000/anyuser/busybox
113 | ```
114 |
115 | Okay, up until know we haven't pushed or pulled from our local registry. It is
116 | now time to change this:
117 |
118 | ```bash
119 | # First ensure we haven't stored any credentials:
120 | mv -b ~/.docker/config.json ~/.docker/config.json.orig
121 |
122 | # Push the image
123 | docker push 0.0.0.0:5000/anyuser/busybox
124 | ```
125 |
126 | And voila, you'll be prompted for a username and a password. Let's use the
127 | username `mozart` (from the *musicians* organization unit in LDAP) and the
128 | password `password`. The email address doesn't matter this much.
129 |
130 | ```
131 | The push refers to a repository [0.0.0.0:5000/anyuser/busybox] (len: 1)
132 | d7057cb02084: Image push failed
133 |
134 | Please login prior to push:
135 | Username: mozart
136 | Password:
137 | Email: mozart@example.com
138 | WARNING: login credentials saved in /home/YOU/.docker/config.json
139 | Login Succeeded
140 | The push refers to a repository [0.0.0.0:5000/anyuser/busybox] (len: 1)
141 | d7057cb02084: Image successfully pushed
142 | cfa753dfea5e: Image successfully pushed
143 | latest: digest: sha256:15eda5ab78f31658ab922650eebe9da9ccc6c16462d5ef0bfd6d9f29b8800569 size: 2743
144 | ```
145 |
146 | ## Test that LDAP auth is working
147 |
148 | This will connect to the LDAP and query all information below the base (`-b`).
149 | The user that is used to authenticate is called `YOUR_SERVICE_ACCOUNT`
150 | and the password is taken from the file `./auth/config/ldap_password.txt`. But
151 | since most editors append a newline (`\n`) or carriage return (`\r`) we first
152 | remove those characters. The user `YOUR_SERVICE_ACCOUNT` is a service account,
153 | but if you don't have one you can also try to login with your own email address
154 | (`-D FIRSTNAME.LASTNAME@YOUR_COMPANY.com`).
155 |
156 | ```bash
157 | LDAP_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' dockerregistrysetup_ldap_1)
158 | ldapsearch -v \
159 | -H ldap://$LDAP_IP:389 \
160 | -x \
161 | -D "uid=serviceaccount,ou=it,dc=example,dc=com" \
162 | -b "ou=musicians,dc=example,dc=com" \
163 | -w password
164 | ```
165 |
166 | To find an entry based on a user's email address execute this command:
167 |
168 | ```bash
169 | LDAP_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' dockerregistrysetup_ldap_1)
170 | ldapsearch -v \
171 | -H ldap://$LDAP_IP:389 \
172 | -x \
173 | -D "uid=serviceaccount,ou=it,dc=example,dc=com" \
174 | -b "ou=musicians,dc=example,dc=com" \
175 | -w password \
176 | "(&(mail=mozart@example.com)(objectClass=person))"
177 | ```
178 |
179 | and appropriately replace `FIRSTNAME.LASTNAME@YOUR_COMPANY.com` with your own
180 | email address.
181 |
182 | ## How to use your own LDAP as your authentication backend...
183 |
184 | 1. Chances are that your own LDAP server requires you to have certificates
185 | installed on the machine that binds to LDAP. Simply copy those certificates to
186 | `auth/config/ldap_certificates/`. I've [modified the auth container](https://github.com/kwk/docker-registry-setup/blob/master/auth/start.sh#L4) a bit by
187 | introducing a start script that automatically searches for files in that
188 | that directory and updates the cert store of the container on every start.
189 | 2. Copy the `auth/config/auth_config.yml` to `auth/config/auth_config.yml.custom` and
190 | adjust all the settings inside to match the LDAP configuration that you have
191 | validated above. The file `auth/config/auth_config.yml.custom` will be loaded instead
192 | of `auth/config/auth_config.yml` whenever it is present.
193 | 3. Put the password for the service account in this file:
194 | `auth/config/ldap_password.txt`.
195 | 4. Restart the registry and auth server: `docker-compose up -d --force-recreate`
196 | 5. Try pushing an image to the registry and login with your LDAP credentials.
197 |
198 | # Test the auth server
199 |
200 | Replace `USERNAME` and `PASSWORD` below with credentials of somebody who wants
201 | to authenticate against LDAP (eg. `mozart` and `password`). You should get an
202 | `HTTP 200 OK` response containing a JSON Web `token` if everything worked
203 | correctly.
204 |
205 | ```
206 | curl -H "Authorization: Basic $(echo "USERNAME:PASSWORD" | base64)" -vk "https://127.0.0.1:5001/auth?service=Docker%20registry&scope=registry:catalog:*"
207 | ```
208 |
209 | # Manual token-based workflow to list repositories
210 |
211 | You can skip this section if you're not interested in how a token can be
212 | requested manually to list the repositories inside a registry.
213 |
214 | ```bash
215 | # This is the operation we want to perform on the registry
216 | registryURL=https://127.0.0.1:5000/v2/_catalog
217 |
218 | # Save the response headers of our first request to the registry to get the Www-Authenticate header
219 | respHeader=$(tempfile);
220 | curl -k --dump-header $respHeader $registryURL
221 |
222 | # Extract the realm, the service, and the scope from the Www-Authenticate header
223 | wwwAuth=$(cat $respHeader | grep "Www-Authenticate")
224 | realm=$(echo $wwwAuth | grep -o '\(realm\)="[^"]*"' | cut -d '"' -f 2)
225 | service=$(echo $wwwAuth | grep -o '\(service\)="[^"]*"' | cut -d '"' -f 2)
226 | scope=$(echo $wwwAuth | grep -o '\(scope\)="[^"]*"' | cut -d '"' -f 2)
227 |
228 | # Build the URL to query the auth server
229 | authURL="$realm?service=$service&scope=$scope"
230 |
231 | # Query the auth server to get a token
232 | token=$(curl -ks -H "Authorization: Basic $(echo -n "mozart:password" | base64)" "$authURL")
233 |
234 | # Get the bare token from the JSON string: {"token": "...."}
235 | token=$(echo $token | jq .token | tr -d '"')
236 |
237 | # Query the registry again, but this time with a bearer token
238 | curl -vk -H "Authorization: Bearer $token" $registryURL
239 | ```
240 |
241 | As a result you should get a list of repositories in your registry. If you have
242 | pushed only the busybox image from above to your registry you should see an HTTP
243 | body like this:
244 |
245 | ```json
246 | {"repositories":["anyuser/busybox"]}
247 | ```
248 |
249 | # Plans
250 |
251 | - [ ] Integrate a frontend
252 |
253 | Have fun!
254 |
--------------------------------------------------------------------------------
/auth/config/auth_config.yml:
--------------------------------------------------------------------------------
1 | # . See reference.yml for explanation for explanation of all options.
2 | #
3 | # auth:
4 | # token:
5 | # realm: "https://127.0.0.1:5001/auth"
6 | # service: "Docker registry"
7 | # issuer: "Acme auth server"
8 | # rootcertbundle: "/path/to/server.pem"
9 |
10 | server:
11 | addr: ":5001"
12 | certificate: "/certs/auth.crt"
13 | key: "/certs/auth.key"
14 |
15 | token:
16 | issuer: "Acme auth server" # Must match issuer in the Registry config.
17 | expiration: 900
18 |
19 | # LDAP authentication.
20 | # Authentication is performed by first binding to the server, looking up the user entry
21 | # by using the specified filter, and then re-binding using the matched DN and the password provided.
22 | ldap_auth:
23 | addr: "ldap:389"
24 | #tls: true
25 | # In case bind DN and password is required for querying user information,
26 | # specify them here. Plain text password is read from the file.
27 | bind_dn: "uid=serviceaccount,ou=it,dc=example,dc=com"
28 | # Make sure you remove newlines and carriage returns from the password file.
29 | bind_password_file: /tmp/ldap_password.txt.clean
30 | # User query settings. ${account} is expanded from auth request
31 | base: "ou=musicians,dc=example,dc=com"
32 | filter: "(&(uid=${account})(objectClass=organizationalPerson))"
33 |
34 | users:
35 | # Password is specified as a BCrypt hash. Use htpasswd -B to generate.
36 | "admin":
37 | password: "$2y$05$LO.vzwpWC5LZGqThvEfznu8qhb5SGqvBSWY1J3yZ4AxtMRZ3kN5jC" # badmin
38 | "test":
39 | password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya" # 123
40 |
41 | acl:
42 | # Admin has full access to everything.
43 | - match: {account: "admin"}
44 | actions: ["*"]
45 |
46 | # User "user" can pull stuff.
47 | - match: {account: "test"}
48 | actions: ["pull"]
49 |
50 | # This will allow authenticated users to pull/push
51 | - match:
52 | account: /.+/
53 | actions: ['*']
54 |
55 | # The user "serviceaccount" (from LDAP) may not perform any docker actions
56 | # like push or pull.
57 | - match: {account: "serviceaccount"}
58 | actions: []
59 |
--------------------------------------------------------------------------------
/auth/config/ldap_certificates/COPY_CERTIFICATES_HERE_THAT_ARE_NEEDED_FOR_AUTHENTICATION_AGAINST_LDAP:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwk/docker-registry-setup/101aa6e8cba1c58174cceee549383efcdfb0fb15/auth/config/ldap_certificates/COPY_CERTIFICATES_HERE_THAT_ARE_NEEDED_FOR_AUTHENTICATION_AGAINST_LDAP
--------------------------------------------------------------------------------
/auth/config/ldap_password.txt:
--------------------------------------------------------------------------------
1 | password
2 |
--------------------------------------------------------------------------------
/auth/config/reference.yml:
--------------------------------------------------------------------------------
1 | # This config lists all the possible config options.
2 | #
3 | # To configure Docker Registry to talk to this server, put the following in the registry config file:
4 | #
5 | # auth:
6 | # token:
7 | # realm: "https://127.0.0.1:5001/auth"
8 | # service: "Docker registry"
9 | # issuer: "Acme auth server"
10 | # rootcertbundle: "/path/to/server.pem"
11 |
12 | server: # Server settings.
13 | # Address to listen on.
14 | addr: ":5001"
15 | # TLS certificate and key.
16 | certificate: "/path/to/server.pem"
17 | key: "/path/to/server.key"
18 |
19 | token: # Settings for the tokens.
20 | issuer: "Acme auth server" # Must match issuer in the Registry config.
21 | expiration: 900
22 | # It is possible configure a different certificate for tokens.
23 | # If not specified, server certificate is used.
24 | # certificate: "..."
25 | # key: "..."
26 |
27 | # Authentication methods. All are tried, any one returning success is sufficient.
28 | # At least one must be configured. If you want an unauthenticated public setup,
29 | # configure static user map with anonymous access.
30 |
31 | # Static user map.
32 | users:
33 | # Password is specified as a BCrypt hash. Use htpasswd -B to generate.
34 | "admin":
35 | password: "$2y$05$LO.vzwpWC5LZGqThvEfznu8qhb5SGqvBSWY1J3yZ4AxtMRZ3kN5jC" # badmin
36 | "test":
37 | password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya" # 123
38 | "": {} # Allow anonymous (no "docker login") access.
39 |
40 | # Google authentication.
41 | # ==! NB: DO NOT ENTER YOUR GOOGLE PASSWORD AT "docker login". IT WILL NOT WORK.
42 | # Instead, Auth server maintains a database of Google authentication tokens.
43 | # Go to the server's port with you browser and follow the "Login with Google account" link.
44 | # Once signed in, you will get a throw-away password which you can use for Docker login.
45 | google_auth:
46 | domain: "example.com" # Optional. If set, only logins fromt his domain are accepted.
47 | # client_id and client_secret for API access. Required.
48 | # Follow instructions here: https://developers.google.com/identity/sign-in/web/devconsole-project
49 | # NB: Make sure JavaScript origins are configured correcly.
50 | client_id: "1223123456-somethingsomething.apps.googleusercontent.com"
51 | # Either client_secret or client_secret_file is required. Use client_secret_file if you don't
52 | # want to have sensitive information checked in.
53 | # client_secret: "verysecret"
54 | client_secret_file: "/path/to/client_secret.txt"
55 | # Where to store server tokens. Required.
56 | token_db: "/somewhere/to/put/google_tokens.ldb"
57 | # How long to wait when talking to Google servers. Optional.
58 | http_timeout: 10
59 |
60 | # LDAP authentication.
61 | # Authentication is performed by first binding to the server, looking up the user entry
62 | # by using the specified filter, and then re-binding using the matched DN and the password provided.
63 | ldap_auth:
64 | addr: "ldap.example.com:389"
65 | tls: true
66 | # In case bind DN and password is required for querying user information,
67 | # specify them here. Plain text password is read from the file.
68 | bind_dn:
69 | bind_password_file:
70 | # User query settings. ${account} is expanded from auth request
71 | base: "o=example.com"
72 | filter: "(&(uid=${account})(objectClass=person))"
73 |
74 | # ACL specifies who can do what. If the match section of an entry matches the
75 | # request, the set of allowed actions will be applied to the token request
76 | # and a ticket will be issued only for those of the requested actions that are
77 | # allowed by the rule.
78 | # * It is possible to match on user's name ("account"), subject type ("type")
79 | # and name ("name"; for type=repository which, at the timeof writing, is the
80 | # only known subject type, this is the image name).
81 | # * Matches are evaluated as shell file name patterns ("globs") by default,
82 | # so "foobar", "f??bar", "f*bar" are all valid. For even more flexibility
83 | # match patterns can be evaluated as regexes by enclosing them in //, e.g.
84 | # "/(foo|bar)/".
85 | # * ACL is evaluated in the order it is defined until a match is found.
86 | # * Empty match clause matches anything, it only makes sense at the end of the
87 | # list and can be used as a way of specifying default permissions.
88 | # * Empty actions set means "deny everything". Thus, a rule with `actions: []`
89 | # is in effect a "deny" rule.
90 | # * A special set consisting of a single "*" action means "allow everything".
91 | # * If no match is found the default is to deny the request.
92 | #
93 | # You can use the following variables from the ticket request in any field:
94 | # * ${account} - the account name, currently the same as authenticated user's name.
95 | # * ${service} - the service name, specified by auth.token.service in the registry config.
96 | # * ${type} - the type of the entity, normally "repository".
97 | # * ${name} - the name of the repository (i.e. image), e.g. centos.
98 | acl:
99 | # Admin has full access to everything.
100 | - match: {account: "admin"}
101 | actions: ["*"]
102 | # User "test" has full access to test-* images but nothing else.
103 | - match: {account: "test", name: "test-*"}
104 | actions: ["*"]
105 | - match: {account: "test"}
106 | actions: []
107 | # All logged in users can pull all images.
108 | - match: {account: "/.+/"}
109 | actions: ["pull"]
110 | # All logged in users can push all images that are in a namespace beginning with their name
111 | - match: {account: "/.+/", name: "${account}/*"}
112 | actions: ["*"]
113 | # Anonymous users can pull "hello-world".
114 | - match: {account: "", name: "hello-world"}
115 | actions: ["pull"]
116 | # Access is denied by default.
117 |
--------------------------------------------------------------------------------
/auth/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Copy over certificates to correct place and update certificate storage
4 | find "/config/ldap_certificates" -type f -exec cp -fv {} /usr/local/share/ca-certificates/ \;
5 | update-ca-certificates
6 |
7 | # Replace newline and carriage returns in password file
8 | cat /config/ldap_password.txt | tr -d '\r\n' > /tmp/ldap_password.txt.clean
9 |
10 | # If we see a custom config file, we load that instead of the default one
11 | CONF_PATH=/config/auth_config.yml
12 | if [ -f $CONF_PATH.custom ]; then
13 | CONF_PATH=$CONF_PATH.custom
14 | fi
15 |
16 | # Start the auth server
17 | /auth_server -v=5 -alsologtostderr=true -log_dir=/logs $CONF_PATH
18 |
--------------------------------------------------------------------------------
/certs/README.md:
--------------------------------------------------------------------------------
1 | # Creation of example certificates
2 |
3 | **NOTE:** You should replace these files with your own!!!
4 |
5 | # Certificate and key for the registry
6 |
7 | The `registry.crt` and `registry.key` files have been created using this command:
8 |
9 | ```
10 | openssl req -newkey rsa:4096 -nodes -sha256 -keyout registry.key -x509 -days 365 -out registry.crt
11 | Generating a 4096 bit RSA private key
12 | ............................................................................................++
13 | ........................................................................................++
14 | writing new private key to 'registry.key'
15 | -----
16 | You are about to be asked to enter information that will be incorporated
17 | into your certificate request.
18 | What you are about to enter is what is called a Distinguished Name or a DN.
19 | There are quite a few fields but you can leave some blank
20 | For some fields there will be a default value,
21 | If you enter '.', the field will be left blank.
22 | -----
23 | Country Name (2 letter code) [AU]:DE
24 | State or Province Name (full name) [Some-State]:Example State
25 | Locality Name (eg, city) []:Example City
26 | Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company
27 | Organizational Unit Name (eg, section) []:Example Organization Unit
28 | Common Name (e.g. server FQDN or YOUR name) []:registry.example.com
29 | Email Address []:admin@registry.example.com
30 | ```
31 |
32 | # Certificate and key for the auth server
33 |
34 | The `auth.crt` and `auth.key` files have been created using this command:
35 |
36 | ```
37 | openssl req -newkey rsa:4096 -nodes -sha256 -keyout auth.key -x509 -days 365 -out auth.crt
38 | Generating a 4096 bit RSA private key
39 | ................................................................................................................................................................................................................++
40 | ........................................................................++
41 | writing new private key to 'auth.key'
42 | -----
43 | You are about to be asked to enter information that will be incorporated
44 | into your certificate request.
45 | What you are about to enter is what is called a Distinguished Name or a DN.
46 | There are quite a few fields but you can leave some blank
47 | For some fields there will be a default value,
48 | If you enter '.', the field will be left blank.
49 | -----
50 | Country Name (2 letter code) [AU]:DE
51 | State or Province Name (full name) [Some-State]:Example State
52 | Locality Name (eg, city) []:Example City
53 | Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company
54 | Organizational Unit Name (eg, section) []:Example Organizational Unit
55 | Common Name (e.g. server FQDN or YOUR name) []:auth.example.com
56 | Email Address []:admin@auth.example.com
57 | ```
58 |
59 | # How to list the contents of one of the certificates
60 |
61 | ```bash
62 | openssl x509 -in registry.crt -text
63 | ```
64 |
65 | Output
66 |
67 | ```
68 | Certificate:
69 | Data:
70 | Version: 3 (0x2)
71 | Serial Number: 15377324996609959013 (0xd5673b9ca2abe465)
72 | Signature Algorithm: sha256WithRSAEncryption
73 | Issuer: C=DE, ST=Example State, L=Example City, O=Example Company, OU=Example Organization Unit, CN=registry.example.com/emailAddress=admin@registry.example.com
74 | Validity
75 | Not Before: Oct 26 11:02:58 2015 GMT
76 | Not After : Oct 25 11:02:58 2016 GMT
77 | Subject: C=DE, ST=Example State, L=Example City, O=Example Company, OU=Example Organization Unit, CN=registry.example.com/emailAddress=admin@registry.example.com
78 | Subject Public Key Info:
79 | Public Key Algorithm: rsaEncryption
80 | Public-Key: (4096 bit)
81 | Modulus:
82 | 00:b3:90:24:96:67:de:56:aa:e3:b5:7d:27:5d:34:
83 | 4d:ce:60:bd:cf:9b:68:9e:af:e6:89:6d:95:74:9e:
84 | 3e:c6:27:8f:b6:34:52:ba:8b:9e:02:dc:a6:7c:a9:
85 | 84:6b:40:e1:ad:5b:c0:19:f4:8d:3d:81:76:2d:e9:
86 | f1:2f:d4:20:7d:50:15:6d:cb:b6:cd:93:eb:f7:d2:
87 | 9c:99:90:1b:b6:99:d8:ad:a5:7a:df:92:2f:ab:8e:
88 | b8:04:a9:cc:34:7f:d0:21:6a:46:89:a0:d5:2b:46:
89 | f8:41:4a:ee:2a:d7:57:04:a1:33:c8:3f:fd:a4:10:
90 | 81:1b:5b:5b:91:c9:0e:0c:91:0e:ea:fe:36:2e:f3:
91 | c7:be:01:2f:f4:fc:b0:ac:57:3b:d2:93:a8:0c:ad:
92 | 23:81:07:71:ef:3a:7e:6f:a4:52:c3:dc:ba:7e:db:
93 | 99:3c:c5:e0:66:88:8d:d2:f6:29:6c:a5:ac:9c:ba:
94 | a7:dd:2d:a0:8b:ad:54:b2:ff:a0:c6:26:90:15:0c:
95 | f9:2f:f8:d9:80:27:5a:52:08:8e:eb:84:5d:24:fe:
96 | ad:05:e9:c2:6e:e2:f2:03:ce:fc:2d:37:7e:cf:c5:
97 | ec:6d:45:d1:05:ed:97:11:f9:6b:89:66:dd:cc:4c:
98 | fd:b7:18:71:be:f5:c7:ac:e1:6a:a5:6a:78:ab:66:
99 | 15:0e:65:6b:08:47:8b:06:31:99:ab:bb:70:50:8e:
100 | 2f:a9:d6:9a:86:39:c8:79:ef:b6:64:d6:00:2b:8d:
101 | 79:c2:c5:c6:6f:02:5b:50:56:64:4e:7e:f4:74:63:
102 | 4f:80:6d:b2:55:13:4e:95:93:1e:66:1b:28:9c:6c:
103 | 6b:1c:62:63:fb:9a:8a:ed:08:c8:e0:5c:04:f3:dd:
104 | bb:c0:c5:d2:54:23:b8:bd:aa:95:30:62:ff:27:68:
105 | 41:bb:68:be:5b:f8:69:ef:3e:6f:81:fb:08:a4:f7:
106 | fb:07:82:c9:53:09:d3:ae:48:02:47:db:ef:60:b1:
107 | d7:be:6d:c1:d1:2d:ec:50:27:b2:29:9e:43:b4:e6:
108 | 2a:bb:99:23:1b:4b:27:89:c4:b8:64:30:33:a4:3b:
109 | b4:a1:fb:65:7b:ff:50:32:0e:68:ea:de:e2:5f:b1:
110 | 11:e3:3c:e9:b2:70:aa:7f:6e:7c:01:0d:00:f9:f9:
111 | 02:65:fc:84:03:aa:78:66:16:04:ae:31:ba:02:bf:
112 | 3c:8c:f6:2b:0b:ec:a5:e2:f9:eb:9a:ce:31:cc:17:
113 | 3e:49:65:39:77:94:68:60:d8:56:5e:61:4d:5b:af:
114 | 12:1d:f8:b8:7b:a5:32:0b:99:c4:ba:cb:d3:b4:2c:
115 | 93:97:b9:fc:96:85:d8:27:0c:d2:9c:81:4e:85:70:
116 | f0:a0:69
117 | Exponent: 65537 (0x10001)
118 | X509v3 extensions:
119 | X509v3 Subject Key Identifier:
120 | 1C:1B:FC:0C:39:36:72:76:48:06:B0:90:26:F7:E3:E4:5D:1C:3D:14
121 | X509v3 Authority Key Identifier:
122 | keyid:1C:1B:FC:0C:39:36:72:76:48:06:B0:90:26:F7:E3:E4:5D:1C:3D:14
123 |
124 | X509v3 Basic Constraints:
125 | CA:TRUE
126 | Signature Algorithm: sha256WithRSAEncryption
127 | 8e:d2:18:07:b1:f9:f1:4d:60:45:98:e0:a5:64:8e:77:4d:3d:
128 | fd:31:3f:14:2a:bd:35:c9:f5:93:a8:00:63:05:54:41:44:6c:
129 | fe:f0:ab:e8:04:b8:b3:58:e2:6f:dc:63:58:92:63:bb:6a:cc:
130 | 2d:83:71:00:17:87:91:d5:24:88:11:8e:47:d0:65:e9:16:c1:
131 | fe:92:e2:89:6d:56:f0:69:33:34:c3:e2:1f:57:00:6f:58:3c:
132 | 61:2f:a4:bf:74:93:5f:f4:72:2e:59:61:19:58:00:0c:13:0c:
133 | a4:ad:2a:81:b5:78:4f:d2:ed:3d:4c:80:a8:65:66:66:95:9f:
134 | 5a:9f:a9:85:05:2c:4b:e5:cb:74:e6:a3:4c:3f:2b:4f:cf:f9:
135 | 53:b2:a0:11:b0:55:d4:7a:55:30:00:d8:a9:30:95:f1:06:58:
136 | 00:03:96:c5:cc:d1:4e:b1:f8:57:87:79:d0:b1:ce:bb:95:27:
137 | 5a:96:d1:fb:4b:15:5e:60:37:ab:1d:41:4b:c2:f7:13:2a:c0:
138 | bb:0f:b8:b9:1f:16:28:80:76:96:1f:7c:da:b4:d8:9e:ed:2f:
139 | e7:80:e7:63:bc:4d:e4:2a:20:3c:c4:cc:34:8a:cc:8f:c5:0a:
140 | c4:ca:90:e6:32:af:b6:bd:2a:74:86:ce:72:3c:f0:01:69:15:
141 | 57:41:11:4e:55:d1:26:83:9b:7c:f4:ad:67:bb:af:4a:43:37:
142 | 4f:94:93:92:00:f2:08:b8:65:18:4a:db:0f:06:2a:b7:e2:4d:
143 | 2d:b0:62:9c:45:4a:9d:8d:b3:25:d0:99:c7:ed:21:e0:33:4b:
144 | dc:3e:15:77:79:54:ae:0c:31:1b:1d:d6:8f:7c:1e:0f:70:6c:
145 | 96:6f:3d:fa:60:db:a5:3e:a9:3a:bd:ec:2e:d1:49:8f:ec:d2:
146 | 2c:05:e6:55:8d:55:57:b8:a6:b3:7c:8a:a8:a1:b5:11:50:21:
147 | db:7d:f9:cb:24:db:e8:20:03:eb:ca:ac:5f:14:79:ad:e6:ff:
148 | 1e:d4:1e:35:6c:0f:15:b4:b8:c2:ab:40:2b:e6:25:a4:14:1b:
149 | 02:e7:16:27:a8:3a:6f:5f:79:96:11:b3:4a:77:6d:fc:cd:4d:
150 | d0:16:7f:c3:0b:9e:fa:d6:0c:4d:bd:92:dd:43:54:7f:b7:28:
151 | 27:5b:14:26:72:d2:55:66:6c:1c:e0:ac:1e:11:41:d2:8b:8c:
152 | 0e:c6:97:d8:b2:c1:5e:05:8f:66:55:d5:d0:b0:38:de:16:a4:
153 | 38:d4:65:ef:db:ba:62:44:8d:88:18:93:72:a7:5c:14:d6:ed:
154 | 0e:a2:25:e8:45:d1:0a:3b:2c:1d:21:94:be:1e:3c:e2:be:6c:
155 | e3:c3:26:41:5f:f0:6b:5b
156 | -----BEGIN CERTIFICATE-----
157 | MIIGXTCCBEWgAwIBAgIJANVnO5yiq+RlMA0GCSqGSIb3DQEBCwUAMIHEMQswCQYD
158 | VQQGEwJERTEWMBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBs
159 | ZSBDaXR5MRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxIjAgBgNVBAsMGUV4YW1w
160 | bGUgT3JnYW5pemF0aW9uIFVuaXQxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUu
161 | Y29tMSkwJwYJKoZIhvcNAQkBFhphZG1pbkByZWdpc3RyeS5leGFtcGxlLmNvbTAe
162 | Fw0xNTEwMjYxMTAyNThaFw0xNjEwMjUxMTAyNThaMIHEMQswCQYDVQQGEwJERTEW
163 | MBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBsZSBDaXR5MRgw
164 | FgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxIjAgBgNVBAsMGUV4YW1wbGUgT3JnYW5p
165 | emF0aW9uIFVuaXQxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUuY29tMSkwJwYJ
166 | KoZIhvcNAQkBFhphZG1pbkByZWdpc3RyeS5leGFtcGxlLmNvbTCCAiIwDQYJKoZI
167 | hvcNAQEBBQADggIPADCCAgoCggIBALOQJJZn3laq47V9J100Tc5gvc+baJ6v5olt
168 | lXSePsYnj7Y0UrqLngLcpnyphGtA4a1bwBn0jT2Bdi3p8S/UIH1QFW3Lts2T6/fS
169 | nJmQG7aZ2K2let+SL6uOuASpzDR/0CFqRomg1StG+EFK7irXVwShM8g//aQQgRtb
170 | W5HJDgyRDur+Ni7zx74BL/T8sKxXO9KTqAytI4EHce86fm+kUsPcun7bmTzF4GaI
171 | jdL2KWylrJy6p90toIutVLL/oMYmkBUM+S/42YAnWlIIjuuEXST+rQXpwm7i8gPO
172 | /C03fs/F7G1F0QXtlxH5a4lm3cxM/bcYcb71x6zhaqVqeKtmFQ5lawhHiwYxmau7
173 | cFCOL6nWmoY5yHnvtmTWACuNecLFxm8CW1BWZE5+9HRjT4BtslUTTpWTHmYbKJxs
174 | axxiY/uaiu0IyOBcBPPdu8DF0lQjuL2qlTBi/ydoQbtovlv4ae8+b4H7CKT3+weC
175 | yVMJ065IAkfb72Cx175twdEt7FAnsimeQ7TmKruZIxtLJ4nEuGQwM6Q7tKH7ZXv/
176 | UDIOaOre4l+xEeM86bJwqn9ufAENAPn5AmX8hAOqeGYWBK4xugK/PIz2KwvspeL5
177 | 65rOMcwXPkllOXeUaGDYVl5hTVuvEh34uHulMguZxLrL07Qsk5e5/JaF2CcM0pyB
178 | ToVw8KBpAgMBAAGjUDBOMB0GA1UdDgQWBBQcG/wMOTZydkgGsJAm9+PkXRw9FDAf
179 | BgNVHSMEGDAWgBQcG/wMOTZydkgGsJAm9+PkXRw9FDAMBgNVHRMEBTADAQH/MA0G
180 | CSqGSIb3DQEBCwUAA4ICAQCO0hgHsfnxTWBFmOClZI53TT39MT8UKr01yfWTqABj
181 | BVRBRGz+8KvoBLizWOJv3GNYkmO7aswtg3EAF4eR1SSIEY5H0GXpFsH+kuKJbVbw
182 | aTM0w+IfVwBvWDxhL6S/dJNf9HIuWWEZWAAMEwykrSqBtXhP0u09TICoZWZmlZ9a
183 | n6mFBSxL5ct05qNMPytPz/lTsqARsFXUelUwANipMJXxBlgAA5bFzNFOsfhXh3nQ
184 | sc67lSdaltH7SxVeYDerHUFLwvcTKsC7D7i5HxYogHaWH3zatNie7S/ngOdjvE3k
185 | KiA8xMw0isyPxQrEypDmMq+2vSp0hs5yPPABaRVXQRFOVdEmg5t89K1nu69KQzdP
186 | lJOSAPIIuGUYStsPBiq34k0tsGKcRUqdjbMl0JnH7SHgM0vcPhV3eVSuDDEbHdaP
187 | fB4PcGyWbz36YNulPqk6vewu0UmP7NIsBeZVjVVXuKazfIqoobURUCHbffnLJNvo
188 | IAPryqxfFHmt5v8e1B41bA8VtLjCq0Ar5iWkFBsC5xYnqDpvX3mWEbNKd238zU3Q
189 | Fn/DC5761gxNvZLdQ1R/tygnWxQmctJVZmwc4KweEUHSi4wOxpfYssFeBY9mVdXQ
190 | sDjeFqQ41GXv27piRI2IGJNyp1wU1u0OoiXoRdEKOywdIZS+HjzivmzjwyZBX/Br
191 | Ww==
192 | -----END CERTIFICATE-----
193 |
194 | ```
195 |
--------------------------------------------------------------------------------
/certs/auth.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIGUTCCBDmgAwIBAgIJAIg5BM++T0GHMA0GCSqGSIb3DQEBCwUAMIG+MQswCQYD
3 | VQQGEwJERTEWMBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBs
4 | ZSBDaXR5MRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxJDAiBgNVBAsMG0V4YW1w
5 | bGUgT3JnYW5pemF0aW9uYWwgVW5pdDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNv
6 | bTElMCMGCSqGSIb3DQEJARYWYWRtaW5AYXV0aC5leGFtcGxlLmNvbTAeFw0xNTEw
7 | MjYxMTAzNDhaFw0xNjEwMjUxMTAzNDhaMIG+MQswCQYDVQQGEwJERTEWMBQGA1UE
8 | CAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBsZSBDaXR5MRgwFgYDVQQK
9 | DA9FeGFtcGxlIENvbXBhbnkxJDAiBgNVBAsMG0V4YW1wbGUgT3JnYW5pemF0aW9u
10 | YWwgVW5pdDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNvbTElMCMGCSqGSIb3DQEJ
11 | ARYWYWRtaW5AYXV0aC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
12 | ADCCAgoCggIBANv6wuZ8U9iW8/+RFZOwNC5mrjWdQcAGHHTebrOj0PZDfyDSbOQ6
13 | N+/B06dKgkJe70hDXrKqQV2ABnopJjFumqJAcczVfOEcT7dQJYcRav5OGxPl6c5m
14 | 5KyBMoyFfkclrSrt553ZqbJ90rzbdkXSWobSwZ7y2zORtS91lArRwf4K4ZJWjLC0
15 | 1WUwcpXOeuez+vymhwi4c3d0RT48HLZhdy3t+S3ANE3B0jqwMsWvkfUp3uO8kOHo
16 | ruc1XWdChxj+LfsrNsoQk11iy2OBMmk55usFQbikBRvuNvvWCSmyh5SllOEyM017
17 | E+qqkdEE/bo68EvqLurgzo0BnsW9YaQWblr8Qg38V6pR5ny2WJdW+rI/0cqmSP1r
18 | uOLd0JvrJIUhV1CV1EpJotlgpmxSNMWuxT8T1aWkd4LSt6VHYxySV76CcQ5BkuQ0
19 | JFg3ynfT+M39hniXmA+XTqAb9fg13aBtnJ7wBb5+PzxxDnsGdVtefbVQdIyo/W5V
20 | EK7XRRk3cfrH+0TNI73r4eRN+n4rYwQXiEiT86KIull+XrDVaW4noC6hxDZQuzay
21 | 42CcVnpDdnU1FPby6+GgKBzKrXrvq6jXtuOOMEOToXpjbsE2kyGiGPofcksRhEQv
22 | bwlV8mpBB8zoHWekSMOc59KsUtk9tz7Ud6c3B+mjOEozx/7HJhYIfH4HAgMBAAGj
23 | UDBOMB0GA1UdDgQWBBTbQYvhJfcSfEl2FC+JweoZs5KtiTAfBgNVHSMEGDAWgBTb
24 | QYvhJfcSfEl2FC+JweoZs5KtiTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA
25 | A4ICAQC6IOLZW7rnHt1vgyUsxVcNrJZvQmWyctOyMfMYGsB5OC/LUtwOJWHc1B9v
26 | RCwdnsZi1/TGDQrgfnE5TgROb4ysbOtPNtk9VeDS1OoJuunK8WZl2xgjyscs24Id
27 | jJOrgMHvNvAtEIfmcjnBuqInpysh+fP3eJgcO/61iVU0bxilkeN2zRhnWGr9mIi4
28 | IOyOh3q5tmF/6nHncgrkg1qlozzXIEcJw5X/IKcOJWJlDwWse4lXj3fjK8SvPxz6
29 | JNuLgoVtcT75ZbjHzRrY3n6m2jj+LFuclDs1tLRImMvGrtNleW5ZwUgnMK8367hH
30 | r7GpnVAnnSuKQz7n7efHnHXNet0fakT/4Ie9IbLnvREefBeYNA+P/ugi5MWKIJuR
31 | ALQASAcq/wiMnZ0aWUj2qN5KLM0u+9tRe+GPHF9+ii9McIo+kcPH0opZCLUIx8uw
32 | MwNoaA11xu21+kLgyvMGk2InDgazjiyDSuNbGx9mUH0cGttl+4VtmmMQMkZ0uhf9
33 | fKQb9Fyen+yXPRdrtW+atfnIHa8IM7pm36yQ926JM4cEroqYplXSkOfx9mjEzKWv
34 | YlfEbz3AHB/QG0Kq5lMSOw7fPgNS2iwnwKPwDh0qvyQTIfA/pPQ6qPmr5OOO1+PT
35 | QrWHAjG3qbI3vgzDab32kwevjChelqmfoQyqT0wMypMYmD2L6Q==
36 | -----END CERTIFICATE-----
37 |
--------------------------------------------------------------------------------
/certs/auth.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | my7FsXDuRNUL8epD5iO7hhddN53Yig==
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/certs/registry.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIGXTCCBEWgAwIBAgIJANVnO5yiq+RlMA0GCSqGSIb3DQEBCwUAMIHEMQswCQYD
3 | VQQGEwJERTEWMBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBs
4 | ZSBDaXR5MRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxIjAgBgNVBAsMGUV4YW1w
5 | bGUgT3JnYW5pemF0aW9uIFVuaXQxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUu
6 | Y29tMSkwJwYJKoZIhvcNAQkBFhphZG1pbkByZWdpc3RyeS5leGFtcGxlLmNvbTAe
7 | Fw0xNTEwMjYxMTAyNThaFw0xNjEwMjUxMTAyNThaMIHEMQswCQYDVQQGEwJERTEW
8 | MBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBsZSBDaXR5MRgw
9 | FgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxIjAgBgNVBAsMGUV4YW1wbGUgT3JnYW5p
10 | emF0aW9uIFVuaXQxHTAbBgNVBAMMFHJlZ2lzdHJ5LmV4YW1wbGUuY29tMSkwJwYJ
11 | KoZIhvcNAQkBFhphZG1pbkByZWdpc3RyeS5leGFtcGxlLmNvbTCCAiIwDQYJKoZI
12 | hvcNAQEBBQADggIPADCCAgoCggIBALOQJJZn3laq47V9J100Tc5gvc+baJ6v5olt
13 | lXSePsYnj7Y0UrqLngLcpnyphGtA4a1bwBn0jT2Bdi3p8S/UIH1QFW3Lts2T6/fS
14 | nJmQG7aZ2K2let+SL6uOuASpzDR/0CFqRomg1StG+EFK7irXVwShM8g//aQQgRtb
15 | W5HJDgyRDur+Ni7zx74BL/T8sKxXO9KTqAytI4EHce86fm+kUsPcun7bmTzF4GaI
16 | jdL2KWylrJy6p90toIutVLL/oMYmkBUM+S/42YAnWlIIjuuEXST+rQXpwm7i8gPO
17 | /C03fs/F7G1F0QXtlxH5a4lm3cxM/bcYcb71x6zhaqVqeKtmFQ5lawhHiwYxmau7
18 | cFCOL6nWmoY5yHnvtmTWACuNecLFxm8CW1BWZE5+9HRjT4BtslUTTpWTHmYbKJxs
19 | axxiY/uaiu0IyOBcBPPdu8DF0lQjuL2qlTBi/ydoQbtovlv4ae8+b4H7CKT3+weC
20 | yVMJ065IAkfb72Cx175twdEt7FAnsimeQ7TmKruZIxtLJ4nEuGQwM6Q7tKH7ZXv/
21 | UDIOaOre4l+xEeM86bJwqn9ufAENAPn5AmX8hAOqeGYWBK4xugK/PIz2KwvspeL5
22 | 65rOMcwXPkllOXeUaGDYVl5hTVuvEh34uHulMguZxLrL07Qsk5e5/JaF2CcM0pyB
23 | ToVw8KBpAgMBAAGjUDBOMB0GA1UdDgQWBBQcG/wMOTZydkgGsJAm9+PkXRw9FDAf
24 | BgNVHSMEGDAWgBQcG/wMOTZydkgGsJAm9+PkXRw9FDAMBgNVHRMEBTADAQH/MA0G
25 | CSqGSIb3DQEBCwUAA4ICAQCO0hgHsfnxTWBFmOClZI53TT39MT8UKr01yfWTqABj
26 | BVRBRGz+8KvoBLizWOJv3GNYkmO7aswtg3EAF4eR1SSIEY5H0GXpFsH+kuKJbVbw
27 | aTM0w+IfVwBvWDxhL6S/dJNf9HIuWWEZWAAMEwykrSqBtXhP0u09TICoZWZmlZ9a
28 | n6mFBSxL5ct05qNMPytPz/lTsqARsFXUelUwANipMJXxBlgAA5bFzNFOsfhXh3nQ
29 | sc67lSdaltH7SxVeYDerHUFLwvcTKsC7D7i5HxYogHaWH3zatNie7S/ngOdjvE3k
30 | KiA8xMw0isyPxQrEypDmMq+2vSp0hs5yPPABaRVXQRFOVdEmg5t89K1nu69KQzdP
31 | lJOSAPIIuGUYStsPBiq34k0tsGKcRUqdjbMl0JnH7SHgM0vcPhV3eVSuDDEbHdaP
32 | fB4PcGyWbz36YNulPqk6vewu0UmP7NIsBeZVjVVXuKazfIqoobURUCHbffnLJNvo
33 | IAPryqxfFHmt5v8e1B41bA8VtLjCq0Ar5iWkFBsC5xYnqDpvX3mWEbNKd238zU3Q
34 | Fn/DC5761gxNvZLdQ1R/tygnWxQmctJVZmwc4KweEUHSi4wOxpfYssFeBY9mVdXQ
35 | sDjeFqQ41GXv27piRI2IGJNyp1wU1u0OoiXoRdEKOywdIZS+HjzivmzjwyZBX/Br
36 | Ww==
37 | -----END CERTIFICATE-----
38 |
--------------------------------------------------------------------------------
/certs/registry.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCzkCSWZ95WquO1
3 | fSddNE3OYL3Pm2ier+aJbZV0nj7GJ4+2NFK6i54C3KZ8qYRrQOGtW8AZ9I09gXYt
4 | 6fEv1CB9UBVty7bNk+v30pyZkBu2mditpXrfki+rjrgEqcw0f9AhakaJoNUrRvhB
5 | Su4q11cEoTPIP/2kEIEbW1uRyQ4MkQ7q/jYu88e+AS/0/LCsVzvSk6gMrSOBB3Hv
6 | On5vpFLD3Lp+25k8xeBmiI3S9ilspaycuqfdLaCLrVSy/6DGJpAVDPkv+NmAJ1pS
7 | CI7rhF0k/q0F6cJu4vIDzvwtN37PxextRdEF7ZcR+WuJZt3MTP23GHG+9ces4Wql
8 | anirZhUOZWsIR4sGMZmru3BQji+p1pqGOch577Zk1gArjXnCxcZvAltQVmROfvR0
9 | Y0+AbbJVE06Vkx5mGyicbGscYmP7mortCMjgXATz3bvAxdJUI7i9qpUwYv8naEG7
10 | aL5b+GnvPm+B+wik9/sHgslTCdOuSAJH2+9gsde+bcHRLexQJ7IpnkO05iq7mSMb
11 | SyeJxLhkMDOkO7Sh+2V7/1AyDmjq3uJfsRHjPOmycKp/bnwBDQD5+QJl/IQDqnhm
12 | FgSuMboCvzyM9isL7KXi+euazjHMFz5JZTl3lGhg2FZeYU1brxId+Lh7pTILmcS6
13 | y9O0LJOXufyWhdgnDNKcgU6FcPCgaQIDAQABAoICAAJlu0dSzbIkh/PFXwAskZle
14 | y0n5TjVILfDJyMQM1NO6dX2+Rxh8griRD5v8e2sfK6Qv5Gm0TSp0Dwrf47t6vpBN
15 | wGt928v03KKrajHWrbgLZ8wxuGlBv2cv+Z7+UV6mEjZP/+8YeaAhS3E7ueBSjbPf
16 | HxzeVdmZ6s9dseRJZemfCi7zA/Auiw0rYOOJeCZk58SQ+h5pNV8kpU3HXybIb95z
17 | lP3amron/i4ARrx5UuZDdAGHsHQQhuM2hjn5lcDvhN7zFGSikuzWGauct6PHWaMD
18 | z3WTwGfQmeCZI97KrePCRbzTwM2udWTlCp2EBRQUNxL5vZMKHwdc3xqkSEYpj8Bi
19 | so0NXjAz+nR+8FomGVGHtPWe9+Lcz+B+4HJx61KilZ/Uav6O2pwBA6DIJVmj6Nem
20 | 8ZZicgXcDHDLSWWwoG6X0pzI4h8ohV+Gs/422iAMrLiZW3eWiqA+tjgnjas/g39j
21 | B2mohWLtNEEMt53SPTGMZC9tJh8JFPHxqxIgmZ+JTt8ZxJhhqI8pprbSlQW4O+JJ
22 | jMcnMRKFUAEPF0ZPWTjU87u8B2v0NquTxn293+Su9h6jutGaGPxxOn2H/0FjX3t6
23 | EliofDL+etCLBGzR7jySfV0Sxk6QdIMcGIO6S7GLf+QcV82SoLdMlc7oeiJBtg8E
24 | T3et6KEmWje9YQ5+CKgdAoIBAQDuHL/zSs/eo3RR1Axq1trAXQbzi5hhdk/qqYmh
25 | fbJoXmCFPYnM68XyfdcnMHJL3pOWSFQGbH4MTrzK5Qmfu/S6k2Ox0L4dVDUY+9r1
26 | ksA6eXngmbA610ch8IR21XWt4crt2q7VVhUdKFUhjyKwHpBpNHwwBzG1IrEzq9Dd
27 | PKX+XEDHv8YXm4bdYCzI+07u4Dn4LKBpfKt838OP4bovJuzwCuDPkQiwOswnuIr+
28 | nSl6Nr/MtlxG3xqhAlxWZKjcLfNISNqCTXRTzoNt5pLaLhwGILkiE0HaJf+MK6x1
29 | 2/IGlXOLfB4s4onv1DsoxmOH9ke4yURjZfJeyB0e1shRh3DvAoIBAQDBDWeocOeS
30 | 16Z5dCiBICibN4zA+C0gnLyigUD5N+D+1Hq6ULCjdfEbWIn9w9Xh58dnAvEVNOOm
31 | Bc4oDPSeV4FjRXmwOx7WrAzc4ZFOP1BiuzwowZZjxxjvSaWae4kzM1NDxFAYOeQ8
32 | MkscRzJw0PkgtduqSK2cdPiRRJRz3iTE3UAhNcXFzLLFKOaFup+yjymBvH8Aq+fA
33 | yFFsHZnrrsaWBvvg31v5C2nPzPCGzD8vqnQlbwyo5D2G/nJYs82PzoSfq822B0oo
34 | 16i9LlTLn3sxBkkgg7vLf6ehH1YbmBQruVePfez/Gfy/ju2Pb/1ONrMUE279Mv5E
35 | ULARxxAvwFQnAoIBAQCoyjaDh1/NSf811mQrBD0zKX64/Ba71/uUtDO9B3aFp4ky
36 | Sko5ulSqrevrets6zv++A22U1CmSHeqUxUFKOxmjfMGqFff+oGe3Wyl+9VVQ3jW4
37 | MhoLy/k/pNixyGVQKoQIkgFnd0smTSXz0Rxczn2+Jhd2kFL7PSlyIHTBr7FXmxvM
38 | vTP2Hii/GuMEYak1ijttomzf+iEyNwjRIMkzjZteGcf9O6l2C2gXLClTjiMN4Gub
39 | +RV2o8ajpiHAmEBfPC996S8EOVWh5v2h1VX6Vb9F1MKH1jDTLCZ3vanWLmDlq+Gp
40 | WgWl+bygBskdAW0iv0FeS0YwU984sxB5gPWlXaZ/AoIBAG/BBMqbYVK+B56zQWdO
41 | aHNB+vcSM313fjNMQ4KBeHvMIKeOYlKdyc8ct/Tw0vWNKP9W0pyGG2pWXfsNVOX8
42 | negLpeAAuV9oBaIv6d+0AyLEZJTrS9XCwYpzxavh65B6G69VC1Ca4qZ+LsDV7jsk
43 | nbLz04+FtwqlI+dkHdPdOsfDlIYlDLHuR2aewKOVXzEMcuipZ5PJ78THsWq20A2B
44 | BXB/5ntMkX9fvgcPCgXeYo2DTO0GlfuG9J8a2LLEkzC2SkvsNo8zNRjjjsjE801U
45 | qwm8K8TovWOWKEG7VCtxI+wTxL5KFVGvh4KUiKzKFYabX5s1jMCCLnL5ipMf+xzJ
46 | Z20CggEBAOJ994I3GQcwuA2EOvIpGYgNlfq5q72Jc+KS2CbIJWvjjIa5j2q1r1c1
47 | AyprFTrh6UC6ekNEGhj5TDs1Lfc5LMy1UjanglcOmG4AUwtknIQG1WqDbKVQ9ucz
48 | OWVRz3qYgw0abIuzQka46P0/QKzSuLoKuqt7LEvwAUd4oMQqFJRsdnpxeX9ovlQi
49 | CzmceYk0i8fKiFPA4tDqSY+8wTWgCUPkT/Wb4Eha6Dg9j6yphskfMj2MwxamhpId
50 | 1hh0Y8sBp/cVVtnUtKhcFySyhv5LOKOAPrtrcjnOjUuJs4xMX7elpfY9BSLCMX8I
51 | GDJ0k/7Jc0+g7M8Gof7SKU2ItNBjxxQ=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | registry:
2 | image: registry:2
3 | restart: always
4 | ports:
5 | - "5000:5000"
6 | volumes:
7 | - "./certs:/certs:ro"
8 | - "./registry/conf:/etc/docker/registry:ro"
9 | - "./registry/storage:/var/lib/registry:rw"
10 |
11 | auth:
12 | image: cesanta/docker_auth
13 | entrypoint: /start.sh
14 | ports:
15 | - "5001:5001"
16 | links:
17 | - ldap:ldap
18 | volumes:
19 | - "./auth/start.sh:/start.sh:ro"
20 | - "./auth/config:/config:ro"
21 | - "./auth/logs:/logs:rw"
22 | - "./certs:/certs:ro"
23 |
24 | ldap:
25 | build: ./ldap
26 | expose:
27 | - "389"
28 |
--------------------------------------------------------------------------------
/docs/setup.graphml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Client
25 | Computer
26 | (Talks HTTPs to registry
27 | and the auth server)
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Docker registry
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | JSON Web Token (JWT)
65 | Auth Server
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | LDAP Server
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Docker Daemon
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | Docker Client
123 |
124 | docker push your.registry.com/anyuser/busybox
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | docker-compose.yml
144 | configures these containers
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | 1
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | 2
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 | 3
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 | 4
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | 5
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 | 6
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 | 7
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 | 8
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
--------------------------------------------------------------------------------
/docs/setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kwk/docker-registry-setup/101aa6e8cba1c58174cceee549383efcdfb0fb15/docs/setup.png
--------------------------------------------------------------------------------
/ldap/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:jessie
2 | MAINTAINER "Konrad Kleine"
3 |
4 | ############################################################
5 | # Speedup DPKG and don't use cache for packages
6 | ############################################################
7 |
8 | # Taken from here: https://gist.github.com/kwk/55bb5b6a4b7457bef38d
9 | #
10 | # this forces dpkg not to call sync() after package extraction and speeds up
11 | # install
12 | RUN echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/02apt-speedup
13 | # # we don't need and apt cache in a container
14 | RUN echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache
15 |
16 | ############################################################
17 | # Install slapd, LDAP utils, and supervisor
18 | ############################################################
19 |
20 | RUN export LC_ALL=C \
21 | && export DEBIAN_FRONTEND=noninteractive \
22 | && apt-get -y update \
23 | && apt-get -y install \
24 | slapd \
25 | ldap-utils \
26 | supervisor \
27 | netcat-openbsd \
28 | --no-install-recommends \
29 | && apt-get -y autoremove \
30 | && apt-get -y clean \
31 | && rm -rf /var/lib/apt/lists/*
32 |
33 | # LDAP configuration
34 | ENV LDAP_ROOTPASS password
35 | ENV LDAP_ORGANISATION My Example Organization
36 | ENV LDAP_DOMAIN example.com
37 |
38 | ADD ./setup-ldap-schema.ldif /setup-ldap-schema.ldif
39 | ADD ./setup-ldap-schema.sh /setup-ldap-schema.sh
40 | ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
41 | ADD slapd.sh /slapd.sh
42 |
43 | # Supervisor manager slapd and the schema setup
44 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
45 |
46 | EXPOSE 389
47 |
--------------------------------------------------------------------------------
/ldap/setup-ldap-schema.ldif:
--------------------------------------------------------------------------------
1 | ## # The Organization
2 | ## dn: dc=example,dc=com
3 | ## objectClass: dcObject
4 | ## objectClass: organization
5 | ## o: Example dc: example
6 |
7 | # The organizational unit philosophs
8 | dn: ou=philosophs,dc=example,dc=com
9 | objectClass: organizationalUnit
10 | ou: philosophs
11 |
12 | # The organizational unit musicians
13 | dn: ou=musicians,dc=example,dc=com
14 | objectClass: organizationalUnit
15 | ou: musicians
16 |
17 | # The organizational unit it
18 | dn: ou=it,dc=example,dc=com
19 | objectClass: organizationalUnit
20 | ou: it
21 |
22 | # User account Immanuel Kant
23 | dn: uid=kant,ou=philosophs,dc=example,dc=com
24 | cn: Immanuel Kant
25 | givenName: Immanuel
26 | sn: Kant
27 | uid: kant
28 | uidNumber: 10001
29 | gidNumber: 10001
30 | homeDirectory: /home/kant
31 | mail: kant@example.com
32 | objectClass: top
33 | objectClass: posixAccount
34 | objectClass: shadowAccount
35 | objectClass: inetOrgPerson
36 | objectClass: organizationalPerson
37 | objectClass: person
38 | loginShell: /bin/bash
39 | userPassword: {CRYPT}*
40 |
41 | # User account Arthur Schopenhauer
42 | dn: uid=schopenhauer,ou=philosophs,dc=example,dc=com
43 | cn: Arthur Schopenhauer
44 | givenName: Arthur
45 | sn: Schopenhauer
46 | uid: schopenhauer
47 | uidNumber: 10002
48 | gidNumber: 10002
49 | homeDirectory: /home/schopenhauer
50 | mail: schopenhauer@example.com
51 | objectClass: top
52 | objectClass: posixAccount
53 | objectClass: shadowAccount
54 | objectClass: inetOrgPerson
55 | objectClass: organizationalPerson
56 | objectClass: person
57 | loginShell: /bin/bash
58 | userPassword: {CRYPT}*
59 |
60 | # User account Wolfgang Amadeus Mozart
61 | dn: uid=mozart,ou=musicians,dc=example,dc=com
62 | cn: Wolfgang Amadeus Mozart
63 | givenName: Wolfgang Amadeus
64 | sn: Mozart
65 | uid: mozart
66 | uidNumber: 10003
67 | gidNumber: 10003
68 | homeDirectory: /home/mozart
69 | mail: mozart@example.com
70 | objectClass: top
71 | objectClass: posixAccount
72 | objectClass: shadowAccount
73 | objectClass: inetOrgPerson
74 | objectClass: organizationalPerson
75 | objectClass: person
76 | loginShell: /bin/bash
77 | userPassword: {CRYPT}*
78 |
79 | # User account Johann Sebastian Bach
80 | dn: uid=bach,ou=musicians,dc=example,dc=com
81 | cn: Johann Sebastian Bach
82 | givenName: Johann Sebastian
83 | sn: Bach
84 | uid: bach
85 | uidNumber: 10004
86 | gidNumber: 10004
87 | homeDirectory: /home/bach
88 | mail: bach@example.com
89 | objectClass: top
90 | objectClass: posixAccount
91 | objectClass: shadowAccount
92 | objectClass: inetOrgPerson
93 | objectClass: organizationalPerson
94 | objectClass: person
95 | loginShell: /bin/bash
96 | userPassword: {CRYPT}*
97 |
98 | # Service account
99 | dn: uid=serviceaccount,ou=it,dc=example,dc=com
100 | cn: Service Account
101 | givenName: Service
102 | sn: Account
103 | uid: serviceaccount
104 | uidNumber: 10005
105 | gidNumber: 10005
106 | homeDirectory: /home/serviceaccount
107 | mail: serviceaccount@example.com
108 | objectClass: top
109 | objectClass: posixAccount
110 | objectClass: shadowAccount
111 | objectClass: inetOrgPerson
112 | objectClass: organizationalPerson
113 | objectClass: person
114 | loginShell: /bin/bash
115 | userPassword: {CRYPT}*
116 |
--------------------------------------------------------------------------------
/ldap/setup-ldap-schema.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -exu
4 |
5 | while ! netcat -z localhost 389; do
6 | sleep 1
7 | done
8 |
9 | # Create the schema
10 | ldapadd -c -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -f /setup-ldap-schema.ldif
11 |
12 | # Set user passwords to "password"
13 |
14 | ldappasswd -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -s password "uid=kant,ou=philosophs,dc=example,dc=com"
15 | ldappasswd -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -s password "uid=schopenhauer,ou=philosophs,dc=example,dc=com"
16 | ldappasswd -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -s password "uid=mozart,ou=musicians,dc=example,dc=com"
17 | ldappasswd -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -s password "uid=bach,ou=musicians,dc=example,dc=com"
18 | ldappasswd -H ldap://localhost:389 -x -D "cn=admin,dc=example,dc=com" -w password -s password "uid=serviceaccount,ou=it,dc=example,dc=com"
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ldap/slapd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -eu
4 |
5 | status () {
6 | echo "---> ${@}" >&2
7 | }
8 |
9 | set -x
10 | : LDAP_ROOTPASS=${LDAP_ROOTPASS}
11 | : LDAP_DOMAIN=${LDAP_DOMAIN}
12 | : LDAP_ORGANISATION=${LDAP_ORGANISATION}
13 |
14 | if [ ! -e /var/lib/ldap/docker_bootstrapped ]; then
15 | status "configuring slapd for first run"
16 |
17 | cat <