View Source K8sWebhoox (k8s_webhoox v0.1.0)
Kubernetes webhook endpoints need to be TLS terminated. This
module and the only exported functions ensure_certificates/5
,
update_admission_webhook_configs/3
and update_crd_conversion_configs/3
help initializing TLS termination for your webhook endpoint.
how-it-works
How it works
The function ensure_certificates/5
generates a CA and a SSL certificate and
stores them in a secret, together with their private keys. If the secret
already exists, it reads the certificates from that secret and doesn't
generate them again.
update_admission_webhook_configs/3
searches the cluster for resources of
type admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration
and
admissionregistration.k8s.io/v1/MutatingWebhookConfiguration
and updates
them in place, setting the caBundle
entry to the value of the generated CA
certificate.
update_crd_conversion_configs/3
searches the cluster for resources of
type apiextensions.k8s.io/v1/CustomResourceDefinition
and updates
them in place, setting the caBundle
entry to the value of the generated CA
certificate.
usage
Usage
rbac
RBAC
I assume you already have a Kubernetes deployment running your applicaiton bundled with this library. Make sure the service account used by the pods can read and patch secrets and webhook configurations. You can create and assign it the following RBAC role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: your-operator
namespace: default
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
- mutatingwebhookconfigurations
verbs: ["*"]
- apiGroups: [""]
resources: ["secrets", "customresourcedefinitions"]
verbs: ["*"]
mounting-the-certificates
Mounting the certificates
In the main container of your deployment, mount a secret as volume. In the
example below, the secret is called admission-webhook-cert
and is mounted to
/mnt/cert
. The path should correlate to where you load the certificate from
in your HTTP Server configuration (see K8sWebhoox.Plug
).
The secret does not exist at this moment which is why we set optional: true
:
apiVersion: apps/v1
kind: Deployment
...
spec:
template:
spec:
containers:
- name: your-operator
...
volumeMounts:
- name: cert
mountPath: "/mnt/cert"
readOnly: true
volumes:
- name: cert
secret:
secretName: admission-webhook-cert
optional: true
use-init-container-to-create-certificates
Use Init Container to Create Certificates
In your code base, implement a function that calls the functions of this module in order to initialize the TLS configuration:
defmodule MyOperator.K8sWebhooxTLS do
def bootstrap_tls() do
# Initialize connection to Kubernetes
conn = ...
# Create certificates if necessary
{:ok, ca_bundle_base_64} =
K8sWebhoox.ensure_certificates(
conn,
"default",
"my-operator",
"default",
"webhook-tls-certificate"
)
# Patch admission webhook configurations
:ok = K8sWebhoox.update_admission_webhook_configs(conn, "my-operator", ca_bundle_base_64)
# Patch conversion webhook configurations in CRDs
:ok = K8sWebhoox.update_crd_conversion_configs(conn, "myoperator.com", ca_bundle_base_64)
end
end
In your deployment, add an init container with the same image
as the main
container and call your TLS bootstrap function using eval
:
...
initContainers:
- name: bootstrap-tls
image: SAME_AS_MAIN_CONTAINER
args: ["eval", "MyOperator.K8sWebhooxTLS.bootstrap_tls()"]
...
Link to this section Summary
Functions
Gets the certificate bundle from the Kubernetes Secret. Creates new CA and certificate if necessary. Returns the CA bundle Base64 encoded.
Searches the cluster for ValidatingWebhookConfiguration
and
MutatingWebhookConfiguration
resources with the given
admission_config_name
and sets the .webhooks[*].clientConfig.caBundle
fields to ca_bundle_base_64
Searches the cluster for CustomResourceDefinition
resources for the given
group
and sets the .spec.conversion.webhook.clientConfig.caBundle
fields
to ca_bundle_base_64
.
Link to this section Functions
ensure_certificates(conn, service_namespace, service_name, secret_namespace, secret_name, opts \\ [])
View Source@spec ensure_certificates( conn :: K8s.Conn.t(), service_namespace :: binary(), service_name :: binary(), secret_namespace :: binary(), secret_name :: binary(), opts :: keyword() ) :: :error | {:ok, binary()}
Gets the certificate bundle from the Kubernetes Secret. Creates new CA and certificate if necessary. Returns the CA bundle Base64 encoded.
update_admission_webhook_configs(conn, admission_config_name, ca_bundle_base_64)
View Source@spec update_admission_webhook_configs( conn :: K8s.Conn.t(), admission_config_name :: binary(), ca_bundle_base_64 :: binary() ) :: :ok | :error
Searches the cluster for ValidatingWebhookConfiguration
and
MutatingWebhookConfiguration
resources with the given
admission_config_name
and sets the .webhooks[*].clientConfig.caBundle
fields to ca_bundle_base_64
@spec update_crd_conversion_configs( conn :: K8s.Conn.t(), group :: binary(), ca_bundle_base_64 :: binary() ) :: :ok | :error
Searches the cluster for CustomResourceDefinition
resources for the given
group
and sets the .spec.conversion.webhook.clientConfig.caBundle
fields
to ca_bundle_base_64
.