Deckhouse Virtualization Platform (DVP) provides built-in tools for managing TLS certificates, simplifying setup and management of traffic encryption for applications running in the cluster.
This page covers the following aspects of certificate usage in DVP:
- Manually requesting TLS certificates using the Certificate and ClusterIssuer resources.
- Securely storing and using credentials for accessing certificate authorities (CAs).
- Automatically obtaining certificates using the
tls-acmeannotation in Ingress resources.
For a general overview of certificate management in DVP, the list of supported issuers, and setup recommendations, refer to Certificate management.
Working with certificates
Viewing certificate details
-
To list all certificates in the cluster, use the following command:
d8 k get certificate --all-namespaces -
To check the status of a specific certificate, run:
d8 k -n <NAMESPACE> describe certificate <CERTIFICATE-NAME>
Automatic certificate requesting
To request a letsencrypt certificate, follow these steps:
-
Create a Certificate resource as described in the
cert-managerdocumentation. Use the following example as a reference:apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-com # Certificate name. namespace: default spec: secretName: example-com-tls # Name of the Secret that will store the private key and the certificate. issuerRef: kind: ClusterIssuer # Certificate issuer details. name: letsencrypt commonName: example.com # Certificate main domain. dnsNames: # Optional additional certificate domains (at least one DNS name or IP address). - www.example.com - admin.example.com - The
cert-managermodule will automatically run a domain ownership challenge using the method defined in the ClusterIssuer resource (for example,HTTP-01orDNS-01). - The
cert-managermodule will automatically create a temporary Ingress resource for the challenge. This temporary Ingress will not affect your existing Ingress configuration. - Once validated, the issued certificate will be stored in the Secret specified in the
secretNamefield.
If you see a CAA record does not match issuer error during certificate issuance, check the DNS records for the domain.
To use letsencrypt, your domain must have the following CAA record: issue "letsencrypt.org".
For mode details on CAA records, refer to Let’s Encrypt documentation.
Requesting a wildcard certificate using DNS in Cloudflare
- Obtain your
GlobalAPIKeyandEmail:- Go to
dash.cloudflare.com/profile. - Your email is shown at the top under Email Address.
- To view the key, click View next to Global API Key at the bottom.
- Go to
-
Edit the
cert-managermodule settings, adding the following section:settings: cloudflareGlobalAPIKey: APIkey cloudflareEmail: some@mail.somedomainOr, use an API token instead (recommended):
settings: cloudflareAPIToken: some-token cloudflareEmail: some@mail.somedomainDVP will automatically create a ClusterIssuer and Secret for Cloudflare in the
d8-cert-managernamespace. -
Create a Certificate resource using Cloudflare for DNS validation. This option becomes available only after the
cloudflareGlobalAPIKeyandcloudflareEmailparameters are configured:apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: domain-wildcard namespace: app-namespace spec: secretName: tls-wildcard issuerRef: name: cloudflare kind: ClusterIssuer commonName: "*.domain.com" dnsNames: - "*.domain.com" -
Create the Ingress resource:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: domain-wildcard namespace: app-namespace spec: ingressClassName: nginx rules: - host: "*.domain.com" http: paths: - backend: service: name: svc-web port: number: 80 path: / tls: - hosts: - "*.domain.com" secretName: tls-wildcard
Requesting a wildcard certificate using DNS in AWS Route53
-
Create a user with the required permissions:
-
On the policy management page, create a policy with the following permissions:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "route53:GetChange", "Resource": "arn:aws:route53:::change/*" }, { "Effect": "Allow", "Action": "route53:ChangeResourceRecordSets", "Resource": "arn:aws:route53:::hostedzone/*" }, { "Effect": "Allow", "Action": "route53:ListHostedZonesByName", "Resource": "*" } ] } -
Open the user management page and create a user with the above policy.
-
-
Edit the
cert-managermodule settings to add the following section:settings: route53AccessKeyID: <ACCESS_KEY_ID> route53SecretAccessKey: <SECRET_ACCESS_KEY>DVP will automatically create a ClusterIssuer and Secret for Route53 in the
d8-cert-managernamespace. -
Create a Certificate resource for validation with Route53. This option becomes available only after the
route53AccessKeyIDandroute53SecretAccessKeyparameters are configured:apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: domain-wildcard namespace: app-namespace spec: secretName: tls-wildcard issuerRef: name: route53 kind: ClusterIssuer commonName: "*.domain.com" dnsNames: - "*.domain.com"
Requesting a wildcard certificate using DNS in Google
-
Create a ServiceAccount with the required role:
- Open the policy management page.
- Choose the target project and create a ServiceAccount under any name (for example,
dns01-solver). - In the created account, create a key by clicking Add key. A JSON file with the key data will be downloaded.
-
Encode the JSON file as a Base64 string:
base64 project-209317-556c656b81c4.json
-
Save the Base64 string in the
cloudDNSServiceAccountparameter.DVP will automatically create a ClusterIssuer and Secret for CloudDNS in the
d8-cert-managernamespace. -
Create a Certificate resource using CloudDNS for validation:
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: domain-wildcard namespace: app-namespace spec: secretName: tls-wildcard issuerRef: name: clouddns kind: ClusterIssuer dnsNames: - "*.domain.com"
Requesting a self-signed certificate
To issue a self-signed certificate, specify selfsigned as the value for issuerRef.name:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com # Certificate name.
namespace: default
spec:
secretName: example-com-tls # Name of the Secret that will store the private key and the certificate.
issuerRef:
kind: ClusterIssuer # Certificate issuer details.
name: selfsigned
commonName: example.com # Certificate main domain.
dnsNames: # Optional additional certificate domains (at least one DNS name or IP address).
- www.example.com
- admin.example.com
Generating a self-signed certificate
When generating certificates manually, it is important to fill out all fields of the certificate request correctly to ensure that the final certificate is issued properly and can be validated across various services.
It is important to follow these guidelines:
-
Specify domain names in the
SAN(Subject Alternative Name) field.The
SANfield is a more modern and commonly used method for specifying the domain names covered by the certificate. Some services no longer consider theCN(Common Name) field as the source for domain names. -
Correctly fill out the
keyUsage,basicConstraints,extendedKeyUsagefields, specifically:-
basicConstraints = CA:FALSEThis field determines whether the certificate is an end-entity certificate or a certification authority (CA) certificate. CA certificates cannot be used as service certificates.
-
keyUsage = digitalSignature, keyEnciphermentThe
keyUsagefield limits the permissible usage scenarios of this key:digitalSignature: Allows the key to be used for signing digital messages and ensuring data integrity.keyEncipherment: Allows the key to be used for encrypting other keys, which is necessary for secure data exchange using TLS (Transport Layer Security).
-
extendedKeyUsage = serverAuthThe
extendedKeyUsagefield specifies additional key usage scenarios required by specific protocols or applications:serverAuth: Indicates that the certificate is intended for server use, authenticating the server to the client during the establishment of a secure connection.
-
It is also recommended to:
-
Issue the certificate for no more than 1 year (365 days).
The validity period of the certificate affects its security. A one-year validity ensures the cryptographic methods remain current and allows for timely certificate updates in case of threats. Furthermore, some modern browsers now reject certificates with a validity period longer than 1 year.
-
Use robust cryptographic algorithms, such as elliptic curve algorithms (including
prime256v1).Elliptic curve algorithms (ECC) provide a high level of security with a smaller key size compared to traditional methods like RSA. This makes the certificates more efficient in terms of performance and secure in the long term.
-
Do not specify domains in the
CN(Common Name) field.Historically, the
CNfield was used to specify the primary domain name for which the certificate was issued. However, modern standards, such as RFC 2818, recommend using theSAN(Subject Alternative Name) field for this purpose. If the certificate is intended for multiple domain names listed in theSANfield, specifying one of the domains additionally inCNcan cause a validation error in some services when accessing domains not listed inCN. If non-domain-related information is specified inCN(for example, an identifier or service name), the certificate will also extend to these names, which could be exploited for malicious purposes.
Certificate generation example
To generate a certificate, we’ll use the openssl utility.
-
Fill in the
cert.cnfconfiguration file:[ req ] default_bits = 2048 default_md = sha256 prompt = no distinguished_name = dn req_extensions = req_ext [ dn ] C = GB ST = London L = London O = Example Company OU = IT Department # CN = Do not specify the CN field. [ req_ext ] subjectAltName = @alt_names [ alt_names ] # Specify all domain names. DNS.1 = example.co.uk DNS.2 = www.example.co.uk DNS.3 = api.example.co.uk # Specify IP addresses (if required). IP.1 = 192.0.2.1 IP.2 = 192.0.4.1 [ v3_ca ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth [ v3_req ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names # Elliptic curve parameters. [ ec_params ] name = prime256v1 -
Generate an elliptic curve key:
openssl ecparam -genkey -name prime256v1 -noout -out ec_private_key.pem -
Create a certificate signing request:
openssl req -new -key ec_private_key.pem -out example.csr -config cert.cnf -
Generate a self-signed certificate:
openssl x509 -req -in example.csr -signkey ec_private_key.pem -out example.crt -days 365 -extensions v3_req -extfile cert.cnf
Protecting credentials
If you prefer not to store credentials in the DVP configuration, you can create a separate Secret and reference it in the ClusterIssuer resource.
To do this, follow these steps:
-
Create a Secret with the access key:
d8 k apply -f - <<EOF apiVersion: v1 kind: Secret type: Opaque metadata: name: route53 namespace: default data: secret-access-key: MY-AWS-ACCESS-KEY-TOKEN EOF -
Create a ClusterIssuer that references the Secret:
d8 k apply -f - <<EOF apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: route53 namespace: default spec: acme: server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: route53-tls-key solvers: - dns01: route53: region: us-east-1 accessKeyID: MY-AWS-ACCESS-KEY-ID secretAccessKeySecretRef: name: route53 key: secret-access-key EOF -
Request certificates as usual, using the created ClusterIssuer:
d8 k apply -f - <<EOF apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-com namespace: default spec: secretName: example-com-tls issuerRef: name: route53 commonName: www.example.com dnsNames: - www.example.com EOF
Support for tls-acme annotation
DVP supports the annotation kubernetes.io/tls-acme: "true" in Ingress resources.
The cert-manager-ingress-shim component watches for this annotation
and automatically creates Certificate resources in the same namespace as the Ingress.
When using the annotation, the Certificate resource is linked to the existing Ingress. No separate Ingress is created for domain validation; instead, additional records are added to the existing Ingress. If the Ingress has authentication or a whitelist configured, the validation will fail. Therefore, it’s recommended that you use a Certificate resource directly instead.
If switching from annotation to a manual Certificate, make sure to delete the automatically generated Certificate first. Otherwise, both will try to update the same Secret, potentially exceeding Let’s Encrypt rate limits.
Example Ingress configuration with the annotation:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/tls-acme: "true" # Annotation.
name: example-com
namespace: default
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- backend:
service:
name: site
port:
number: 80
path: /
pathType: ImplementationSpecific
- host: www.example.com # Additional domain.
http:
paths:
- backend:
service:
name: site
port:
number: 80
path: /
pathType: ImplementationSpecific
- host: admin.example.com # Another additional domain.
http:
paths:
- backend:
service:
name: site
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- example.com
- www.example.com # Additional domain.
- admin.example.com # Another additional domain.
secretName: example-com-tls # Name of the Certificate and Secret.