blob: 28d706d771e850edb3e28943ddc5e7d6758801e5 [file] [log] [blame]
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +02001# registry.k0.hswaw.net, a private docker registry
2# This needs an oauth2 secret provisioned, create with:
3# kubectl -n registry create secret generic auth --from-literal=oauth2_secret=...
4
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +02005local kube = import "../../kube/kube.libsonnet";
6local cm = import "../../cluster/kube/lib/cert-manager.libsonnet";
7
8{
9 local app = self,
10 local cfg = app.cfg,
11 cfg:: {
12 namespace: "registry",
13 domain: "k0.hswaw.net",
14 },
15
16 metadata(component):: {
17 namespace: cfg.namespace,
18 labels: {
19 "app.kubernetes.io/name": "registry",
20 "app.kubernetes.io/managed-by": "kubecfg",
21 "app.kubernetes.io/component": component,
22 },
23 },
24
25 namespace: kube.Namespace(cfg.namespace),
26
27 registryIssuer: cm.Issuer("registry-issuer") {
28 metadata+: app.metadata("registry-issuer"),
29 spec: {
30 selfSigned: {},
31 },
32 },
33 authCertificate: cm.Certificate("auth") {
34 metadata+: app.metadata("auth"),
35 spec: {
36 secretName: "auth-internal",
37 duration: "43800h0m0s", // 5 years
38 issuerRef: {
39 name: app.registryIssuer.metadata.name,
40 },
41 commonName: "auth.registry",
42 },
43 },
44 registryCertificate: cm.Certificate("registry") {
45 metadata+: app.metadata("registry"),
46 spec: {
47 secretName: "registry-internal",
48 duration: "43800h0m0s", // 5 years
49 issuerRef: {
50 name: app.registryIssuer.metadata.name,
51 },
52 commonName: "registry.registry",
53 },
54 },
55
56 registryConfig: kube.ConfigMap("registry-config") {
57 metadata+: app.metadata("registry-config"),
58 data: {
59 "config.yml": std.manifestYamlDoc({
60 version: "0.1",
61 log: {
62 fields: {
63 service: "registry",
64 },
65 },
66 storage: {
67 cache: {
68 blobdescriptor: "inmemory",
69 },
70 filesystem: {
71 rootdirectory: "/var/lib/registry",
72 },
73 },
74 http: {
75 addr: ":5000",
76 headers: {
77 "X-Content-Type-Options": ["nosniff"],
78 },
79 tls: {
80 certificate: "/certs/tls.crt",
81 key: "/certs/tls.key",
82 },
83 },
84 health: {
85 storagedriver: {
86 enabled: true,
87 interval: "10s",
88 threshold: 3,
89 },
90 },
91 auth: {
92 token: {
93 realm: "https://registry.%s/auth" % [cfg.domain],
94 service: "my.docker.registry",
95 issuer: "registry.%s auth server" % [cfg.domain],
96 rootcertbundle: "/authcerts/tls.crt",
97 },
98 },
99 }),
100 },
101 },
102
103 authConfig: kube.ConfigMap("auth-config") {
104 metadata+: app.metadata("auth-config"),
105 data: {
106 "auth_config.yml": std.manifestYamlDoc({
107 server: {
108 addr: ":5001",
109 certificate: "/certs/tls.crt",
110 key: "/certs/tls.key",
111 },
112 token: {
113 issuer: "registry.%s auth server" % [cfg.domain],
114 expiration: 900,
115 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200116 oauth2: {
117 client_id: "registry",
118 client_secret_file: "/secrets/oauth2_secret",
119 authorize_url: "https://sso.hackerspace.pl/oauth/authorize",
120 access_token_url: "https://sso.hackerspace.pl/oauth/token",
121 profile_url: "https://sso.hackerspace.pl/api/1/profile",
122 redirect_url: "https://registry.k0.hswaw.net/oauth2",
123 username_key: "username",
124 token_db: "/tmp/oauth2_tokens.ldb",
125 registry_url: "https://registry.k0.hswaw.net",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200126 },
127 acl: [
128 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200129 match: {account: "/.+/", name: "${account}/*"},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200130 actions: ["*"],
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200131 comment: "Logged in users have full access to images that are in their 'namespace'",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200132 },
133 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200134 match: {account: "/.+/", type: "registry", name: "catalog"},
135 actions: ["*"],
136 comment: "Logged in users can query the catalog.",
137 },
138 {
139 match: {account: "/.+/"},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200140 actions: ["pull"],
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200141 comment: "Logged in users can pull all images.",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200142 },
143 ],
144 }),
145 }
146 },
147
148 authDeployment: kube.Deployment("auth") {
149 metadata+: app.metadata("auth"),
150 spec+: {
151 replicas: 1,
152 template+: {
153 spec+: {
154 volumes_: {
155 config: kube.ConfigMapVolume(app.authConfig),
156 certs: {
157 secret: { secretName: app.authCertificate.spec.secretName },
158 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200159 secrets: {
160 secret: { secretName: "auth" },
161 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200162 },
163 containers_: {
164 auth: kube.Container("auth") {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200165 image: "informatic/docker_auth:2019040307",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200166 volumeMounts_: {
167 config: { mountPath: "/config" },
168 certs: { mountPath: "/certs" },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200169 secrets: { mountPath: "/secrets" },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200170 },
171 },
172 },
173 },
174 },
175 },
176 },
177 authService: kube.Service("auth") {
178 metadata+: app.metadata("auth"),
179 target_pod:: app.authDeployment.spec.template,
180 spec+: {
181 type: "ClusterIP",
182 ports: [
183 { name: "auth", port: 5001, targetPort: 5001, protocol: "TCP" },
184 ],
185 }
186 },
187 registryDeployment: kube.Deployment("docker-registry") {
188 metadata+: app.metadata("docker-registry"),
189 spec+: {
190 replicas: 1,
191 template+: {
192 spec+: {
193 volumes_: {
194 config: kube.ConfigMapVolume(app.registryConfig),
195 certs: {
196 secret: { secretName: app.registryCertificate.spec.secretName },
197 },
198 authcerts: {
199 secret: { secretName: app.authCertificate.spec.secretName },
200 },
201 },
202 containers_: {
203 registry: kube.Container("docker-registry") {
204 image: "registry:2",
205 args: ["/config/config.yml"],
206 volumeMounts_: {
207 config: { mountPath: "/config" },
208 certs: { mountPath: "/certs" },
209 authcerts: { mountPath: "/authcerts" },
210 },
211 },
212 },
213 },
214 },
215 },
216 },
217 registryService: kube.Service("docker-registry") {
218 metadata+: app.metadata("docker-registry"),
219 target_pod:: app.registryDeployment.spec.template,
220 spec+: {
221 type: "ClusterIP",
222 ports: [
223 { name: "registry", port: 5000, targetPort: 5000, protocol: "TCP" },
224 ],
225 }
226 },
227 registryIngress: kube.Ingress("registry") {
228 metadata+: app.metadata("registry") {
229 annotations+: {
230 "kubernetes.io/tls-acme": "true",
231 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
232 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200233 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200234 },
235 },
236 spec+: {
237 tls: [
238 {
239 hosts: ["registry.%s" % [cfg.domain]],
240 secretName: "registry-tls",
241 },
242 ],
243 rules: [
244 {
245 host: "registry.%s" % [cfg.domain],
246 http: {
247 paths: [
248 { path: "/auth", backend: app.authService.name_port },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200249 { path: "/", backend: app.authService.name_port },
250 { path: "/v2/", backend: app.registryService.name_port },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200251 ]
252 },
253 }
254 ],
255 },
256 },
257}