blob: 12056cf185690eafb049519722a232c7d031e26e [file] [log] [blame]
// Deploys admitomatic, a validating admission webhook. It is used in
// conjunction with Kubernetes' RBAC to provide a level of multitenancy to the
// cluster, adding extra restrictions to resources created by non-administrative
// users.
//
// For more information about admitomatic , see //cluster/admitomatic .
//
// As with every Kubernetes admission webhook, the Kubernetes control plane
// (ie. apiserver) needs to be able to dial the deployed admitomatic service.
// The authentication story for this is unfortunately quite sad and requires
// the use of a pre-generated one-shot CA and certificate.
//
// .---- self-signed -.
// v |
// Admitomatic CA ----------' <-- caBundle used by apiserver,
// | set in ValidatingWebhookConfiguration
// v
// Admitomatic Cert <-- admitomatic_tls_cert used by admitomatic
//
// This CA needs to be provisioned ahead of time by ourselves. In order to keep
// things simple (as admitomatic being an admission webhook becomes a core
// component of the k8s control plane), we generate this CA as plain text
// secrets, and store them with secretstore in git. This is done via clustercfg.
local kube = import "../../../kube/kube.libsonnet";
local prototext = import "../../../kube/prototext.libsonnet";
{
Environment: {
local env = self,
local cfg = env.cfg,
cfg:: {
namespace: "admitomatic",
image: "registry.k0.hswaw.net/cluster/admitomatic@sha256:f7f0c007b2e12ca564282dd55c9334947854d58ebb5b305cf6e9e0060382d81d",
proto: {},
},
namespace: kube.Namespace(cfg.namespace),
local ns = self.namespace,
config: ns.Contain(kube.ConfigMap("admitomatic")) {
data: {
"config.pb.text": prototext.manifestProtoText(cfg.proto),
},
},
secret: ns.Contain(kube.Secret("admitomatic")) {
data_: {
"webhook.key": importstr "../../secrets/plain/admitomatic-webhook.key",
"webhook.crt": importstr "../../certs/admitomatic-webhook.cert",
},
},
daemonset: ns.Contain(kube.DaemonSet("admitomatic")) {
spec+: {
template+: {
spec+: {
containers_: {
default: kube.Container("default") {
image: cfg.image,
args: [
"/cluster/admitomatic/admitomatic",
"-admitomatic_config", "/admitomatic/config/config.pb.text",
"-admitomatic_listen", "0.0.0.0:8443",
"-admitomatic_tls_cert", "/admitomatic/secret/webhook.crt",
"-admitomatic_tls_key", "/admitomatic/secret/webhook.key",
// doesn't serve anything over gRPC.
"-hspki_disable"
],
volumeMounts_: {
config: { mountPath: "/admitomatic/config" },
secret: { mountPath: "/admitomatic/secret" },
},
ports_: {
public: { containerPort: 8443 },
},
},
},
volumes_: {
config: env.config.volume,
secret: kube.SecretVolume(env.secret),
},
},
},
},
},
svc: ns.Contain(kube.Service("admitomatic")) {
target:: env.daemonset,
},
webhook: kube.ValidatingWebhookConfiguration("admitomatic") {
webhooks_: {
"admitomatic.hswaw.net": {
rules: [
{
apiGroups: ["networking.k8s.io"],
apiVersions: ["v1", "v1beta1"],
operations: ["CREATE", "UPDATE"],
resources: ["ingresses"],
scope: "Namespaced",
}
],
clientConfig: {
service: {
namespace: env.svc.metadata.namespace,
name: env.svc.metadata.name,
port: 8443,
path: "/webhook",
},
caBundle: std.base64(importstr "../../certs/ca-admitomatic.crt"),
},
failurePolicy: "Ignore",
matchPolicy: "Equivalent",
admissionReviewVersions: ["v1", "v1beta1"],
sideEffects: "None",
timeoutSeconds: 5,
},
},
},
},
}