Cert-manager DNS providers are integrations with various DNS (Domain Name System) service providers that allow cert-manager, a Kubernetes add-on, to automate the management of SSL/TLS certificates. DNS providers enable cert-manager to automatically perform challenges to prove domain ownership and obtain certificates from certificate authorities like Let's Encrypt.
By configuring cert-manager with the compatible Open Telekom Cloud DNS provider, using this webhook, you can set up automatic certificate issuance and renewal for your Open Telekom Cloud CCE workloads without manual intervention. This automation is crucial for securing web applications and services deployed on CCE clusters.
This webhook is installed exclusively via Helm.
Note
If you dont't have a Kubernetes cluster in place, this project
comes with "batteries included"; a Dev Container (a .devcontainer.json
specifications file that can be
found in the repo and will be discussed in a later chapter) will instruct any IDE that supports Dev Containers, to set up
an isolated containerized Kubernetes environment for you along with all necessary tooling (cert-manager, Helm etc.)
Configure the Chart by setting the following parameters:
groupName
: sets environment variableGROUP_NAME
, defaults toacme.opentelekomcloud.com
debug
: sets environment variableOS_DEBUG
, defaults tofalse
. Whentrue
, raisesklog
verbosity to4
. It must be booleancredentialsSecretRef
: a reference to the KubernetesSecret
that will hold the OTC access & secret keys, defaults tocert-manager-webhook-opentelekomcloud-creds
opentelekomcloud.accessKey
: the access key in plain text, not requiredopentelekomcloud.secretKey
: the secret key in plain text, not required
Note
The remaining chart variables are, besides self-explanatory, the same that used already by cert-manager/webhook-example
If opentelekomcloud.accessKey
and opentelekomcloud.secretKey
are both set, the chart will automatically:
- create the
credentialsSecretRef
secret - encode
opentelekomcloud.accessKey
andopentelekomcloud.secretKey
in base64 - populate secret's
data
with the encoded values ofopentelekomcloud.accessKey
andopentelekomcloud.secretKey
helm repo add cmw-otc https://akyriako.github.io/cert-manager-webhook-opentelekomcloud/
helm repo update
helm upgrade --install $CHART_RELEASE_NAME cmw-otc/cert-manager-webhook-opentelekomcloud \
--set opentelekomcloud.accessKey=$OS_ACCESS_KEY \
--set opentelekomcloud.secretKey=$OS_SECRET_KEY \
--namespace cert-manager
If additionally debug
parameter is set to true
, --set debug=true
, the helm chart will add to the deployment of the
container an additional argument to increase logging verbosity:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- --tls-cert-file=/tls/tls.crt
- --tls-private-key-file=/tls/tls.key
{{- if eq .Values.debug true }}
- --v=4
{{- end }}
or you can alternatively override the values.yaml and set there the parameters.
If for any reason the one-step installation is not fit for your deployment pipeline, you can split the installation in two steps:
First create and deploy a Secret
manifest, that would match the name of credentialsSecretRef
value:
apiVersion: v1
kind: Secret
metadata:
name: cert-manager-webhook-opentelekomcloud-creds
namespace: cert-manager
type: Opaque
data:
accessKey: "<ACCESS_KEY_in_Base64>"
secretKey: "<SECRET_KEY_in_Base64>"
Deploy the secret with kubectl
and then deploy the webhook:
helm repo add cmw-otc https://akyriako.github.io/cert-manager-webhook-opentelekomcloud/
helm repo update
helm upgrade --install $CHART_RELEASE_NAME cmw-otc/cert-manager-webhook-opentelekomcloud \
--namespace cert-manager
Issuers
, and ClusterIssuers
, are Kubernetes resources that represent certificate authorities (CAs) that are able to
generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a
referenced issuer that is in a ready condition to attempt to honor the request. The former is namespaced-scoped while the
latter is cluster-wide.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: opentelekomcloud-letsencrypt-staging
namespace: cert-manager
spec:
acme:
email: [email protected]
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: opentelekomcloud-letsencrypt-staging-tls-key
solvers:
- dns01:
webhook:
groupName: acme.opentelekomcloud.com
solverName: opentelekomcloud
config:
region: "eu-de"
accessKeySecretRef:
name: cert-manager-webhook-opentelekomcloud-creds
key: accessKey
secretKeySecretRef:
name: cert-manager-webhook-opentelekomcloud-creds
key: secretKey
groupName
can be set in the respective chart parameter, otherwise defaults toacme.opentelekomcloud.com
solverName
should beopentelekomcloud
, it is not configurableregion
, although configurable and required, it can only be set toeu-de
accessKeySecretRef
andsecretKeySecretRef
can be set in chart parametercredentialsSecretRef
, if not defaults tocert-manager-webhook-opentelekomcloud-creds
Deploy the manifest above with kubectl
.
In cert-manager, the Certificate
resource represents a human readable definition of a certificate request.
cert-manager uses this input to generate a private key and CertificateRequest
resource in order to obtain a signed
certificate from an Issuer
or ClusterIssuer
. The signed certificate and private key are then stored in the
specified Secret resource. cert-manager will ensure that the certificate is auto-renewed before it expires and re-issued
if requested.
Important
In order to issue any certificates, you'll need to configure an Issuer
or ClusterIssuer
resource first.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: certificate-subdomain-example-com
namespace: cert-manager
spec:
dnsNames:
- '*.subdomain.example.com'
issuerRef:
kind: ClusterIssuer
name: opentelekomcloud-letsencrypt-staging
secretName: certificate-subdomain-example-com-tls
Deploy the manifest above with kubectl
.
As mentioned already in the preface, this project is harnessing the versatilly of Dev Containers to provide to you, on any IDE that supports Dev Containers, an isolated containerized Kubernetes environment along with all necessary tooling (Cert-Manager, Helm, K9s, Dive etc.) so you can start directly developing without wasting time and energy on how to jumpstart yet another project's environment and dependencies.
Note
Although you can use any IDE that supports Dev Containers, the extensions and features added on the base image are tailored for Visual Studio Code.
A Dev Container will be created, with all the necessary prerequisites to get you started developing immediately. A
container, based on mcr.microsoft.com/devcontainers/go:1.21-bullseye
will be spawned with the following features pre-installed:
- Golang 1.21
- Tooltitude for Go (Free License)
- Git, GitHub Actions, GitHub CLI, Git Graph
- Docker in Docker
- Kubectl, Helm, Helmfile, K9s, KinD, Dive
- Bridge to Kubernetes Visual Studio Code Extension
- Resource Monitor
A postCreateCommand
(.devcontainer/setup.sh) will provision:
- A containerized Kubernetes cluster with 1 control and 3 worker nodes and a private registry, using KinD (cluster manifest is in .devcontainer/cluster.yaml)
- A fully functional installation of Cert-Manager
In order to test the changes on a Kubernetes cluster, you need to build a new image, push the image to the container registry of your choice and recreate the manifests that Helm will deploy to the Kubernetes cluster:
For building new image, execute:
make docker-build
For pushing the new image to a container registry, execute:
make docker-push
For creating the manifests out of the helm template, execute:
make rendered-manifest.yaml
Note
Before executing the above target, you have to make sure that you have set the values of the following environment
variables: OS_ACCESS_KEY
and OS_SECRET_KEY
.
The last one will create a yaml file that will contain all required manifests, rendered-manifest.yaml
, in folder _out
:
You can then deploy them in your Kubernetes cluster using kubectl
:
kubectl apply -f _out/rendered-manifest.yaml
If you need to extend the webhook configuration via environment variables, you should extend struct config
which can be found in main.go:
type config struct {
GroupName string `env:"GROUP_NAME" envDefault:"acme.opentelekomcloud.com"`
Debug bool `env:"OS_DEBUG" envDefault:"false"`
}
Caution
No sensitive information (either in plain or encoded text) should be added here for any reason.
Consequently, you might need to change the chart template values so they acknowledge and use the new parameters in the manifests.
If you need to extend the configuration of the solver, extending its API Specs, you should extend struct OpenTelekomCloudDnsProviderConfig
which can be found in config.go:
type OpenTelekomCloudDnsProviderConfig struct {
// These fields will be set by users in the
// `issuer.spec.acme.dns01.providers.webhook.config` field.
Region string `json:"region,required"`
AccessKeySecretRef *corev1.SecretKeySelector `json:"accessKeySecretRef,omitempty"`
SecretKeySecretRef *corev1.SecretKeySelector `json:"secretKeySecretRef,omitempty"`
}
Caution
No sensitive information (either in plain or encoded text) should be added here for any reason.
Consequently, you might need to change the chart template values so they acknowledge and use the new parameters in the manifests.
If you need to extend the secrets & credentials of the solver, you should extend struct OpenTelekomCloudDnsProviderSecrets
which can be found in config.go:
type OpenTelekomCloudDnsProviderSecrets struct {
AccessKey string `env:"OS_ACCESS_KEY,required"`
SecretKey string `env:"OS_SECRET_KEY,required"`
}
Consequently, you might need to change the chart template values so they acknowledge and use the new parameters in the manifests.
Tip
Access & Secret keys are enough to create an Open Telekom Cloud Provider Client and a DNS Service Client. User, Password, Domain or Tenant identifiers are not needed for the DNS Solver to work.
All DNS providers must run the DNS01 provider conformance testing suite, else they will have undetermined behaviour when used with cert-manager.
$ OS_DEBUG=true OS_ACCESS_KEY={AccessKeyinBase64} OS_SECRET_KEY={SecretKeyinBase64} TEST_ZONE_NAME=example.com. make test
Note
Fill in the values of OS_ACCESS_KEY
and OS_SECRET_KEY
. Replace example.com.
with your own (sub)domain.
Make sure not to forget the trailing .
in the TEST_ZONE_NAME
value. You can omit any variable already defined
in your session's environment variables.