blob: ad1063494efafcddc52ab6ddc07e6cef849755dd [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=...
Piotr Dobrowolski7adc0eb2019-04-09 22:39:42 +02004# kubectl get secrets rook-ceph-object-user-waw-hdd-redundant-1-object-registry -n ceph-waw1 -o yaml --export | kubectl replace -f - -n registry
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +02005
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +02006local kube = import "../../kube/kube.libsonnet";
7local cm = import "../../cluster/kube/lib/cert-manager.libsonnet";
8
9{
10 local app = self,
11 local cfg = app.cfg,
12 cfg:: {
13 namespace: "registry",
14 domain: "k0.hswaw.net",
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +020015 storageClassName: "waw-hdd-redundant-1",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +020016 },
17
18 metadata(component):: {
19 namespace: cfg.namespace,
20 labels: {
21 "app.kubernetes.io/name": "registry",
22 "app.kubernetes.io/managed-by": "kubecfg",
23 "app.kubernetes.io/component": component,
24 },
25 },
26
27 namespace: kube.Namespace(cfg.namespace),
28
29 registryIssuer: cm.Issuer("registry-issuer") {
30 metadata+: app.metadata("registry-issuer"),
31 spec: {
32 selfSigned: {},
33 },
34 },
35 authCertificate: cm.Certificate("auth") {
36 metadata+: app.metadata("auth"),
37 spec: {
38 secretName: "auth-internal",
39 duration: "43800h0m0s", // 5 years
40 issuerRef: {
41 name: app.registryIssuer.metadata.name,
42 },
43 commonName: "auth.registry",
44 },
45 },
46 registryCertificate: cm.Certificate("registry") {
47 metadata+: app.metadata("registry"),
48 spec: {
49 secretName: "registry-internal",
50 duration: "43800h0m0s", // 5 years
51 issuerRef: {
52 name: app.registryIssuer.metadata.name,
53 },
54 commonName: "registry.registry",
55 },
56 },
57
58 registryConfig: kube.ConfigMap("registry-config") {
59 metadata+: app.metadata("registry-config"),
60 data: {
61 "config.yml": std.manifestYamlDoc({
62 version: "0.1",
63 log: {
64 fields: {
65 service: "registry",
66 },
67 },
68 storage: {
69 cache: {
70 blobdescriptor: "inmemory",
71 },
Piotr Dobrowolski7adc0eb2019-04-09 22:39:42 +020072 s3: {
73 regionendpoint: "https://object.ceph-waw1.hswaw.net",
74 bucket: "registry",
75 region: "waw-hdd-redunant-1-object:default-placement",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +020076 },
77 },
78 http: {
79 addr: ":5000",
80 headers: {
81 "X-Content-Type-Options": ["nosniff"],
82 },
83 tls: {
84 certificate: "/certs/tls.crt",
85 key: "/certs/tls.key",
86 },
Piotr Dobrowolski7adc0eb2019-04-09 22:39:42 +020087 debug: {
88 addr: "localhost:5001",
89 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +020090 },
91 health: {
92 storagedriver: {
93 enabled: true,
94 interval: "10s",
95 threshold: 3,
96 },
97 },
98 auth: {
99 token: {
100 realm: "https://registry.%s/auth" % [cfg.domain],
101 service: "my.docker.registry",
102 issuer: "registry.%s auth server" % [cfg.domain],
103 rootcertbundle: "/authcerts/tls.crt",
104 },
105 },
106 }),
107 },
108 },
109
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200110 authVolumeClaim: kube.PersistentVolumeClaim("auth-token-storage") {
111 metadata+: app.metadata("auth-token-storage"),
112 spec+: {
113 storageClassName: cfg.storageClassName,
114 accessModes: [ "ReadWriteOnce" ],
115 resources: {
116 requests: {
117 storage: "1Gi",
118 },
119 },
120 },
121 },
122
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200123 authConfig: kube.ConfigMap("auth-config") {
124 metadata+: app.metadata("auth-config"),
125 data: {
126 "auth_config.yml": std.manifestYamlDoc({
127 server: {
128 addr: ":5001",
129 certificate: "/certs/tls.crt",
130 key: "/certs/tls.key",
131 },
132 token: {
133 issuer: "registry.%s auth server" % [cfg.domain],
134 expiration: 900,
135 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200136 oauth2: {
137 client_id: "registry",
138 client_secret_file: "/secrets/oauth2_secret",
139 authorize_url: "https://sso.hackerspace.pl/oauth/authorize",
140 access_token_url: "https://sso.hackerspace.pl/oauth/token",
141 profile_url: "https://sso.hackerspace.pl/api/1/profile",
142 redirect_url: "https://registry.k0.hswaw.net/oauth2",
143 username_key: "username",
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200144 token_db: "/data/oauth2_tokens.ldb",
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200145 registry_url: "https://registry.k0.hswaw.net",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200146 },
Sergiusz Bazanskib2458652019-04-19 14:41:10 +0200147 users: {
148 [""]: {}, // '' user are anonymous users.
149 },
Sergiusz Bazanski1c825942019-06-30 00:37:34 +0200150 local data = self,
151 pushers:: [
152 { who: ["q3k", "inf"], what: "vms/*" },
153 { who: ["q3k"], what: "app/radio" },
154 { who: ["q3k"], what: "app/factorio" },
155 { who: ["q3k"], what: "app/gerrit" },
Sergiusz Bazanski94f8dbf2019-07-09 13:02:27 +0200156 { who: ["q3k"], what: "app/internet" },
Sergiusz Bazanski1c825942019-06-30 00:37:34 +0200157 { who: ["q3k"], what: "go/svc/egressifier" },
158 ],
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200159 acl: [
160 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200161 match: {account: "/.+/", name: "${account}/*"},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200162 actions: ["*"],
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200163 comment: "Logged in users have full access to images that are in their 'namespace'",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200164 },
165 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200166 match: {account: "/.+/", type: "registry", name: "catalog"},
167 actions: ["*"],
168 comment: "Logged in users can query the catalog.",
169 },
170 {
Sergiusz Bazanskib2458652019-04-19 14:41:10 +0200171 match: {account: ""},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200172 actions: ["pull"],
Sergiusz Bazanskib2458652019-04-19 14:41:10 +0200173 comment: "Anyone can pull all images.",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200174 },
Sergiusz Bazanski1c825942019-06-30 00:37:34 +0200175 ] + [
176 {
177 match: {
178 account: "/(%s)/" % std.join("|", p.who),
179 name: p.what,
180 },
181 actions: ["*"],
182 comment: "%s can push to %s" % [std.join(", ", p.who), p.what],
183 }
184 for p in data.pushers
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200185 ],
186 }),
187 }
188 },
189
190 authDeployment: kube.Deployment("auth") {
191 metadata+: app.metadata("auth"),
192 spec+: {
193 replicas: 1,
194 template+: {
195 spec+: {
196 volumes_: {
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200197 data: kube.PersistentVolumeClaimVolume(app.authVolumeClaim),
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200198 config: kube.ConfigMapVolume(app.authConfig),
199 certs: {
200 secret: { secretName: app.authCertificate.spec.secretName },
201 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200202 secrets: {
203 secret: { secretName: "auth" },
204 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200205 },
206 containers_: {
207 auth: kube.Container("auth") {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200208 image: "informatic/docker_auth:2019040307",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200209 volumeMounts_: {
210 config: { mountPath: "/config" },
211 certs: { mountPath: "/certs" },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200212 secrets: { mountPath: "/secrets" },
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200213 data: { mountPath: "/data" },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200214 },
215 },
216 },
217 },
218 },
219 },
220 },
221 authService: kube.Service("auth") {
222 metadata+: app.metadata("auth"),
223 target_pod:: app.authDeployment.spec.template,
224 spec+: {
225 type: "ClusterIP",
226 ports: [
227 { name: "auth", port: 5001, targetPort: 5001, protocol: "TCP" },
228 ],
229 }
230 },
231 registryDeployment: kube.Deployment("docker-registry") {
232 metadata+: app.metadata("docker-registry"),
233 spec+: {
234 replicas: 1,
235 template+: {
236 spec+: {
237 volumes_: {
238 config: kube.ConfigMapVolume(app.registryConfig),
239 certs: {
240 secret: { secretName: app.registryCertificate.spec.secretName },
241 },
242 authcerts: {
243 secret: { secretName: app.authCertificate.spec.secretName },
244 },
245 },
246 containers_: {
247 registry: kube.Container("docker-registry") {
248 image: "registry:2",
249 args: ["/config/config.yml"],
250 volumeMounts_: {
251 config: { mountPath: "/config" },
252 certs: { mountPath: "/certs" },
253 authcerts: { mountPath: "/authcerts" },
254 },
Piotr Dobrowolski7adc0eb2019-04-09 22:39:42 +0200255 env_: {
256 REGISTRY_STORAGE_S3_ACCESSKEY: { secretKeyRef: {
257 name: "rook-ceph-object-user-waw-hdd-redundant-1-object-registry",
258 key: "AccessKey"
259 }},
260 REGISTRY_STORAGE_S3_SECRETKEY: { secretKeyRef: {
261 name: "rook-ceph-object-user-waw-hdd-redundant-1-object-registry",
262 key: "SecretKey",
263 }},
264 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200265 },
266 },
267 },
268 },
269 },
270 },
271 registryService: kube.Service("docker-registry") {
272 metadata+: app.metadata("docker-registry"),
273 target_pod:: app.registryDeployment.spec.template,
274 spec+: {
275 type: "ClusterIP",
276 ports: [
277 { name: "registry", port: 5000, targetPort: 5000, protocol: "TCP" },
278 ],
279 }
280 },
281 registryIngress: kube.Ingress("registry") {
282 metadata+: app.metadata("registry") {
283 annotations+: {
284 "kubernetes.io/tls-acme": "true",
285 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
286 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200287 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200288 },
289 },
290 spec+: {
291 tls: [
292 {
293 hosts: ["registry.%s" % [cfg.domain]],
294 secretName: "registry-tls",
295 },
296 ],
297 rules: [
298 {
299 host: "registry.%s" % [cfg.domain],
300 http: {
301 paths: [
302 { path: "/auth", backend: app.authService.name_port },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200303 { path: "/", backend: app.authService.name_port },
304 { path: "/v2/", backend: app.registryService.name_port },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200305 ]
306 },
307 }
308 ],
309 },
310 },
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200311
312 registryStorageUser: kube._Object("ceph.rook.io/v1", "CephObjectStoreUser", "registry") {
313 metadata+: {
314 namespace: "ceph-waw1",
315 },
316 spec: {
317 store: "waw-hdd-redundant-1-object",
318 displayName: "docker-registry user",
319 },
320 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200321}