blob: 5fc21721291da133857ca4e522c7838674756062 [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",
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +020014 storageClassName: "waw-hdd-redundant-1",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +020015 },
16
17 metadata(component):: {
18 namespace: cfg.namespace,
19 labels: {
20 "app.kubernetes.io/name": "registry",
21 "app.kubernetes.io/managed-by": "kubecfg",
22 "app.kubernetes.io/component": component,
23 },
24 },
25
26 namespace: kube.Namespace(cfg.namespace),
27
28 registryIssuer: cm.Issuer("registry-issuer") {
29 metadata+: app.metadata("registry-issuer"),
30 spec: {
31 selfSigned: {},
32 },
33 },
34 authCertificate: cm.Certificate("auth") {
35 metadata+: app.metadata("auth"),
36 spec: {
37 secretName: "auth-internal",
38 duration: "43800h0m0s", // 5 years
39 issuerRef: {
40 name: app.registryIssuer.metadata.name,
41 },
42 commonName: "auth.registry",
43 },
44 },
45 registryCertificate: cm.Certificate("registry") {
46 metadata+: app.metadata("registry"),
47 spec: {
48 secretName: "registry-internal",
49 duration: "43800h0m0s", // 5 years
50 issuerRef: {
51 name: app.registryIssuer.metadata.name,
52 },
53 commonName: "registry.registry",
54 },
55 },
56
57 registryConfig: kube.ConfigMap("registry-config") {
58 metadata+: app.metadata("registry-config"),
59 data: {
60 "config.yml": std.manifestYamlDoc({
61 version: "0.1",
62 log: {
63 fields: {
64 service: "registry",
65 },
66 },
67 storage: {
68 cache: {
69 blobdescriptor: "inmemory",
70 },
71 filesystem: {
72 rootdirectory: "/var/lib/registry",
73 },
74 },
75 http: {
76 addr: ":5000",
77 headers: {
78 "X-Content-Type-Options": ["nosniff"],
79 },
80 tls: {
81 certificate: "/certs/tls.crt",
82 key: "/certs/tls.key",
83 },
84 },
85 health: {
86 storagedriver: {
87 enabled: true,
88 interval: "10s",
89 threshold: 3,
90 },
91 },
92 auth: {
93 token: {
94 realm: "https://registry.%s/auth" % [cfg.domain],
95 service: "my.docker.registry",
96 issuer: "registry.%s auth server" % [cfg.domain],
97 rootcertbundle: "/authcerts/tls.crt",
98 },
99 },
100 }),
101 },
102 },
103
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200104 authVolumeClaim: kube.PersistentVolumeClaim("auth-token-storage") {
105 metadata+: app.metadata("auth-token-storage"),
106 spec+: {
107 storageClassName: cfg.storageClassName,
108 accessModes: [ "ReadWriteOnce" ],
109 resources: {
110 requests: {
111 storage: "1Gi",
112 },
113 },
114 },
115 },
116
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200117 authConfig: kube.ConfigMap("auth-config") {
118 metadata+: app.metadata("auth-config"),
119 data: {
120 "auth_config.yml": std.manifestYamlDoc({
121 server: {
122 addr: ":5001",
123 certificate: "/certs/tls.crt",
124 key: "/certs/tls.key",
125 },
126 token: {
127 issuer: "registry.%s auth server" % [cfg.domain],
128 expiration: 900,
129 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200130 oauth2: {
131 client_id: "registry",
132 client_secret_file: "/secrets/oauth2_secret",
133 authorize_url: "https://sso.hackerspace.pl/oauth/authorize",
134 access_token_url: "https://sso.hackerspace.pl/oauth/token",
135 profile_url: "https://sso.hackerspace.pl/api/1/profile",
136 redirect_url: "https://registry.k0.hswaw.net/oauth2",
137 username_key: "username",
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200138 token_db: "/data/oauth2_tokens.ldb",
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200139 registry_url: "https://registry.k0.hswaw.net",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200140 },
141 acl: [
142 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200143 match: {account: "/.+/", name: "${account}/*"},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200144 actions: ["*"],
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200145 comment: "Logged in users have full access to images that are in their 'namespace'",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200146 },
147 {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200148 match: {account: "/.+/", type: "registry", name: "catalog"},
149 actions: ["*"],
150 comment: "Logged in users can query the catalog.",
151 },
152 {
153 match: {account: "/.+/"},
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200154 actions: ["pull"],
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200155 comment: "Logged in users can pull all images.",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200156 },
157 ],
158 }),
159 }
160 },
161
162 authDeployment: kube.Deployment("auth") {
163 metadata+: app.metadata("auth"),
164 spec+: {
165 replicas: 1,
166 template+: {
167 spec+: {
168 volumes_: {
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200169 data: kube.PersistentVolumeClaimVolume(app.authVolumeClaim),
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200170 config: kube.ConfigMapVolume(app.authConfig),
171 certs: {
172 secret: { secretName: app.authCertificate.spec.secretName },
173 },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200174 secrets: {
175 secret: { secretName: "auth" },
176 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200177 },
178 containers_: {
179 auth: kube.Container("auth") {
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200180 image: "informatic/docker_auth:2019040307",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200181 volumeMounts_: {
182 config: { mountPath: "/config" },
183 certs: { mountPath: "/certs" },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200184 secrets: { mountPath: "/secrets" },
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200185 data: { mountPath: "/data" },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200186 },
187 },
188 },
189 },
190 },
191 },
192 },
193 authService: kube.Service("auth") {
194 metadata+: app.metadata("auth"),
195 target_pod:: app.authDeployment.spec.template,
196 spec+: {
197 type: "ClusterIP",
198 ports: [
199 { name: "auth", port: 5001, targetPort: 5001, protocol: "TCP" },
200 ],
201 }
202 },
203 registryDeployment: kube.Deployment("docker-registry") {
204 metadata+: app.metadata("docker-registry"),
205 spec+: {
206 replicas: 1,
207 template+: {
208 spec+: {
209 volumes_: {
210 config: kube.ConfigMapVolume(app.registryConfig),
211 certs: {
212 secret: { secretName: app.registryCertificate.spec.secretName },
213 },
214 authcerts: {
215 secret: { secretName: app.authCertificate.spec.secretName },
216 },
217 },
218 containers_: {
219 registry: kube.Container("docker-registry") {
220 image: "registry:2",
221 args: ["/config/config.yml"],
222 volumeMounts_: {
223 config: { mountPath: "/config" },
224 certs: { mountPath: "/certs" },
225 authcerts: { mountPath: "/authcerts" },
226 },
227 },
228 },
229 },
230 },
231 },
232 },
233 registryService: kube.Service("docker-registry") {
234 metadata+: app.metadata("docker-registry"),
235 target_pod:: app.registryDeployment.spec.template,
236 spec+: {
237 type: "ClusterIP",
238 ports: [
239 { name: "registry", port: 5000, targetPort: 5000, protocol: "TCP" },
240 ],
241 }
242 },
243 registryIngress: kube.Ingress("registry") {
244 metadata+: app.metadata("registry") {
245 annotations+: {
246 "kubernetes.io/tls-acme": "true",
247 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
248 "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200249 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200250 },
251 },
252 spec+: {
253 tls: [
254 {
255 hosts: ["registry.%s" % [cfg.domain]],
256 secretName: "registry-tls",
257 },
258 ],
259 rules: [
260 {
261 host: "registry.%s" % [cfg.domain],
262 http: {
263 paths: [
264 { path: "/auth", backend: app.authService.name_port },
Piotr Dobrowolskiac38d5a2019-04-03 08:41:20 +0200265 { path: "/", backend: app.authService.name_port },
266 { path: "/v2/", backend: app.registryService.name_port },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200267 ]
268 },
269 }
270 ],
271 },
272 },
Piotr Dobrowolski6da3b282019-04-07 18:49:41 +0200273
274 registryStorageUser: kube._Object("ceph.rook.io/v1", "CephObjectStoreUser", "registry") {
275 metadata+: {
276 namespace: "ceph-waw1",
277 },
278 spec: {
279 store: "waw-hdd-redundant-1-object",
280 displayName: "docker-registry user",
281 },
282 },
Piotr Dobrowolski6dc48392019-04-02 18:07:21 +0200283}