app/matrix: add wellKnown server integration

Exposes /.well-known/matrix/ metadata endpoints on cfg.webDomain that
are required for federation to work properly. This can be enabled using
cfg.wellKnown flag set to true.

Change-Id: I097b58efc7442b904a135d4519999e36d155c197
diff --git a/app/matrix/lib/matrix.libsonnet b/app/matrix/lib/matrix.libsonnet
index 7b10f6f..87eefb1 100644
--- a/app/matrix/lib/matrix.libsonnet
+++ b/app/matrix/lib/matrix.libsonnet
@@ -49,6 +49,7 @@
             appserviceIRC: "matrixdotorg/matrix-appservice-irc:release-0.17.1",
             # That's v0.8.2 - we just don't trust that host to not re-tag images.
             appserviceTelegram: "dock.mau.dev/tulir/mautrix-telegram@sha256:9e68eaa80c9e4a75d9a09ec92dc4898b12d48390e01efa4de40ce882a6f7e330",
+            wellKnown: "registry.k0.hswaw.net/q3k/wellknown:1611960794-adbf560851a46ad0e58b42f0daad7ef19535687c",
         },
 
         # Central Authentication Scheme, a single-sign-on system. Note: this flow is now called 'SSO' in Matrix, we keep this name for legacy reasons.
@@ -66,6 +67,8 @@
                 userinfoURL:    error "cas.oauth2.userinfoURL must be set",
             },
         },
+
+        wellKnown: false,
     },
 
     metadata(component):: {
@@ -351,6 +354,37 @@
         target_pod:: app.riotDeployment.spec.template,
     },
 
+    wellKnown: if cfg.wellKnown then {
+        deployment: kube.Deployment("wellknown") {
+            metadata+: app.metadata("wellknown"),
+            spec+: {
+                replicas: 1,
+                template+: {
+                    spec+: {
+                        containers_: {
+                            web: kube.Container("wellknown") {
+                                image: cfg.images.wellKnown,
+                                ports_: {
+                                    http: { containerPort: 8080 },
+                                },
+                                command: ["/app/matrix/wellknown"],
+                                args: ["-hspki_disable", "-domain", cfg.webDomain],
+                            },
+                        },
+                        securityContext: {
+                            runAsUser: 101,
+                            runAsGroup: 101,
+                        },
+                    },
+                },
+            },
+        },
+        svc: kube.Service("wellknown") {
+            metadata+: app.metadata("wellknown"),
+            target_pod:: app.wellKnown.deployment.spec.template,
+        },
+    } else {},
+
     // Any appservice you add here will require an appservice-X-registration
     // secret containing a registration.yaml file. Adding something to this
     // dictionary will cause Synapse to not start until that secret is
@@ -383,6 +417,8 @@
                             { path: "/_matrix", backend: app.synapseSvc.name_port },
                         ] + (if cfg.cas.enable then [
                             { path: "/_cas", backend: app.casSvc.name_port },
+                        ] else []) + (if cfg.wellKnown then [
+                            { path: "/.well-known/matrix", backend: app.wellKnown.svc.name_port },
                         ] else [])
                     },
                 }