prod{access,vider}: implement

Prodaccess/Prodvider allow issuing short-lived certificates for all SSO
users to access the kubernetes cluster.

Currently, all users get a personal-$username namespace in which they
have adminitrative rights. Otherwise, they get no access.

In addition, we define a static CRB to allow some admins access to
everything. In the future, this will be more granular.

We also update relevant documentation.

Change-Id: Ia18594eea8a9e5efbb3e9a25a04a28bbd6a42153
diff --git a/cluster/kube/lib/cockroachdb.libsonnet b/cluster/kube/lib/cockroachdb.libsonnet
index ac4c965..212104d 100644
--- a/cluster/kube/lib/cockroachdb.libsonnet
+++ b/cluster/kube/lib/cockroachdb.libsonnet
@@ -36,6 +36,7 @@
 
 local kube = import "../../../kube/kube.libsonnet";
 local cm = import "cert-manager.libsonnet";
+local policies = import "../../../kube/policies.libsonnet";
 
 {
     Cluster(name): {
@@ -70,6 +71,8 @@
             [if cluster.cfg.ownNamespace then "ns"]: kube.Namespace(cluster.namespaceName),
         },
 
+        insecurePolicy: policies.AllowNamespaceInsecure(cluster.namespaceName),
+
         name(suffix):: if cluster.cfg.ownNamespace then suffix else name + "-" + suffix,
 
         pki: {
diff --git a/cluster/kube/lib/metallb.libsonnet b/cluster/kube/lib/metallb.libsonnet
index a56fc90..7f3d746 100644
--- a/cluster/kube/lib/metallb.libsonnet
+++ b/cluster/kube/lib/metallb.libsonnet
@@ -1,6 +1,7 @@
 # Deploy MetalLB
 
 local kube = import "../../../kube/kube.libsonnet";
+local policies = import "../../../kube/policies.libsonnet";
 
 local bindServiceAccountClusterRole(sa, cr) = kube.ClusterRoleBinding(cr.metadata.name) {
     roleRef: {
@@ -32,6 +33,8 @@
 
         ns: if cfg.namespaceCreate then kube.Namespace(cfg.namespace),
 
+        insecurePolicy: policies.AllowNamespaceInsecure(cfg.namespace),
+
         saController: kube.ServiceAccount("controller") {
             metadata+: {
                 namespace: cfg.namespace,
diff --git a/cluster/kube/lib/nginx.libsonnet b/cluster/kube/lib/nginx.libsonnet
index a871b96..ab7bbc2 100644
--- a/cluster/kube/lib/nginx.libsonnet
+++ b/cluster/kube/lib/nginx.libsonnet
@@ -1,6 +1,7 @@
 # Deploy a per-cluster Nginx Ingress Controller
 
 local kube = import "../../../kube/kube.libsonnet";
+local policies = import "../../../kube/policies.libsonnet";
 
 {
     Environment: {
@@ -21,6 +22,8 @@
 
         namespace: kube.Namespace(cfg.namespace),
 
+        allowInsecure: policies.AllowNamespaceInsecure(cfg.namespace),
+
         maps: {
             make(name):: kube.ConfigMap(name) {
                 metadata+: env.metadata,
diff --git a/cluster/kube/lib/prodvider.libsonnet b/cluster/kube/lib/prodvider.libsonnet
new file mode 100644
index 0000000..5b75c79
--- /dev/null
+++ b/cluster/kube/lib/prodvider.libsonnet
@@ -0,0 +1,85 @@
+# Deploy prodvider (prodaccess server) in cluster.
+
+local kube = import "../../../kube/kube.libsonnet";
+
+{
+    Environment: {
+        local env = self,
+        local cfg = env.cfg,
+
+        cfg:: {
+            namespace: "prodvider",
+            image: "registry.k0.hswaw.net/cluster/prodvider:1567199084-2e1c08fa7a41faac2ef3f79a1bb82f8841a68016",
+
+            pki: {
+                intermediate: {
+                    cert: importstr "../../certs/ca-kube-prodvider.cert",
+                    key: importstr "../../secrets/plain/ca-kube-prodvider.key",
+                },
+                kube: {
+                    cert: importstr "../../certs/ca-kube.crt",
+                },
+            }
+        },
+
+        namespace: kube.Namespace(cfg.namespace),
+
+        metadata(component):: {
+            namespace: cfg.namespace,
+            labels: {
+                "app.kubernetes.io/name": "prodvider",
+                "app.kubernetes.io/managed-by": "kubecfg",
+                "app.kubernetes.io/component": component,
+            },
+        },
+
+        secret: kube.Secret("ca") {
+            metadata+: env.metadata("prodvider"),
+            data_: {
+                "intermediate-ca.crt": cfg.pki.intermediate.cert,
+                "intermediate-ca.key": cfg.pki.intermediate.key,
+                "ca.crt": cfg.pki.kube.cert,
+            },
+        },
+
+        deployment: kube.Deployment("prodvider") {
+            metadata+: env.metadata("prodvider"),
+            spec+: {
+                replicas: 3,
+                template+: {
+                    spec+: {
+                        volumes_: {
+                            ca: kube.SecretVolume(env.secret),
+                        },
+                        containers_: {
+                            prodvider: kube.Container("prodvider") {
+                                image: cfg.image,
+                                args: [
+                                    "/cluster/prodvider/prodvider",
+                                    "-listen_address", "0.0.0.0:8080",
+                                    "-ca_key_path", "/opt/ca/intermediate-ca.key",
+                                    "-ca_certificate_path", "/opt/ca/intermediate-ca.crt",
+                                    "-kube_ca_certificate_path", "/opt/ca/ca.crt",
+                                ],
+                                volumeMounts_: {
+                                    ca: { mountPath: "/opt/ca" },
+                                }
+                            },
+                        },
+                    },
+                },
+            },
+        },
+
+        svc: kube.Service("prodvider") {
+            metadata+: env.metadata("prodvider"),
+            target_pod:: env.deployment.spec.template,
+            spec+: {
+                type: "LoadBalancer",
+                ports: [
+                    { name: "public", port: 443, targetPort: 8080, protocol: "TCP" },
+                ],
+            },
+        },
+    },
+}
diff --git a/cluster/kube/lib/registry.libsonnet b/cluster/kube/lib/registry.libsonnet
index 1ce022d..a791acf 100644
--- a/cluster/kube/lib/registry.libsonnet
+++ b/cluster/kube/lib/registry.libsonnet
@@ -152,11 +152,12 @@
                     },
                     local data = self,
                     pushers:: [
-                            { who: ["q3k", "inf"], what: "vms/*" },
-                            { who: ["q3k", "inf"], what: "app/*" },
-                            { who: ["q3k", "inf"], what: "go/svc/*" },
+                            { who: ["q3k", "informatic"], what: "vms/*" },
+                            { who: ["q3k", "informatic"], what: "app/*" },
+                            { who: ["q3k", "informatic"], what: "go/svc/*" },
                             { who: ["q3k"], what: "bgpwtf/*" },
                             { who: ["q3k"], what: "devtools/*" },
+                            { who: ["q3k", "informatic"], what: "cluster/*" },
                     ],
                     acl: [
                         {