Creating certificates

IBM® Cloud Private cert-manager is the Kubernetes certificate manager controller shared service that is used to generate and manage certificates based on the jetstack/cert-manager project Opens in a new tab.

About cert-manager

You can use the IBM Cloud Private cert-manager to create and mount a certificate to a Kubernetes Deployment, StatefulSet, or DaemonSet. You can also create and add a certificate to a Kubernetes Ingress.

Issuer, ClusterIssuer, and Certificate are Kubernetes resource types that were introduced to support certificate generation and lifecycle management.

IBM Cloud Private has one ClusterIssuer, icp-ca-issuer, that holds an IBM Cloud Private self-signed CA certificate and key pair. The certificate and key pair are stored as a Secret, cluster-ca-cert, within the kube-system namespace and are generated when you install IBM Cloud Private. You can create your own issuers for your own workloads after installation.

See the following list to learn how IBM Cloud Private cert-manager works:

Adding a certificate to a Kubernetes workload

An icp-ca-issuer is automatically created as a ClusterIssuer for each IBM Cloud Private installation. This Issuer contains the self-signed IBM Cloud Private cluster CA and is accessible from all namespaces. More Issuers (namespace-scoped) or ClusterIssuers (cluster-scoped) can be defined.

  1. Define the Issuer.

    See the following example of a Secret that contains a CA certificate and key pair:

    apiVersion: v1
    data:
     # base64 encoded PEM
     tls.crt: LS0tLS...tLS0tCg==
     tls.key: LS0tLS...tLS0tLQo=
    kind: Secret
    metadata:
     name: hello-deployment-tls-ca-key-pair
     namespace: default
    type: kubernetes.io/tls
    

    See the following example of an Issuer that references the previous Secret:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Issuer
    metadata:
     name: hello-deployment-tls
     namespace: foobar
    spec:
     ca:
       secretName: hello-deployment-tls-ca-key-pair
    
  2. Define the certificate.

    The following example defines a certificate that uses the Issuer, which is referenced in the previous step:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Certificate
    metadata:
     name: hello-deployment-tls-1
     namespace: foobar
    spec:
     # name of the tls secret to store
     # the generated certificate/key pair
     secretName: hello-deployment-tls-1
     issuerRef:
       # issuer created in step 1
       name: hello-deployment-tls
       # ClusterIssuers can be referenced
       # by changing the kind here.
       # the default value is Issuer (i.e.
       # a locally namespaced Issuer)
       kind: Issuer
     commonName: "foo1.bar1"
     dnsNames:
       # one more fully-qualified domain name
       # can be defined here
     - foo1.bar1
    

    The following code example defines a certificate that uses the icp-ca-issuer that was created during installation.

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Certificate
    metadata:
     name: hello-deployment-tls-1
     namespace: foobar
    spec:
     # name of the tls secret to store
     # the generated certificate/key pair
     secretName: hello-deployment-tls-1
     issuerRef:
       # issuer created in step 1
       name: icp-ca-issuer
       # ClusterIssuers can be referenced
       # by changing the kind here.
       # the default value is Issuer (i.e.
       # a locally namespaced Issuer)
       kind: ClusterIssuer
     commonName: "foo1.bar1"
     dnsNames:
       # one more fully-qualified domain name
       # can be defined here
     - foo1.bar1
    
  3. Mount the Secret to the Deployment, DaemonSet, or StatefulSet.

    The Kubernetes Secret that contains the certificate is mounted to the file system in the same manner as any other secret. For more information, see the Kubernetes documentation Opens in a new tab.

Adding a certificate to Kubernetes Ingress

The Ingress Kubernetes resource type is used to expose services to an external network. Cert-manager generated certificates can be added to Ingress resources. IBM Cloud Private provides a NGINX Kubernetes Ingress point out-of-the-box.

Handling Multiple Domain Names

Requests to multiple virtual hosts can be handled by the same Ingress. Each virtual host can be terminated with its own certificates. In this case, the fully-qualified domain name in the TLS/HTTPS request is used to identify the requested virtual host. The TLS-SNI protocol extension defines this process.

Complete the following procedure to secure the Kubernetes Ingress:

  1. Define the Issuer.

    An icp-ca-issuer is automatically created as a ClusterIssuer for each IBM Cloud Private installation. This issuer contains the self-signed IBM Cloud Private cluster CA and is accessible from all namespaces.

    More Issuers (namespace-scoped) or ClusterIssuers (cluster-scoped) can be defined with the following examples.

    For the CA certificate and key pair, see the following example:

    apiVersion: v1
    data:
     # base64 encoded PEM
     tls.crt: LS0tLS...tLS0tCg==
     tls.key: LS0tLS...tLS0tLQo=
    kind: Secret
    metadata:
     name: hello-deployment-tls-ca-key-pair
     namespace: default
    type: kubernetes.io/tls
    

    For the Issuer, see the following example:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Issuer
    metadata:
     name: hello-deployment-tls
     namespace: foobar
    spec:
     ca:
       secretName: hello-deployment-tls-ca-key-pair
    
  2. Define the certificate.

    The following example defines a certificate that uses the Issuer in the previous step:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Certificate
    metadata:
     name: hello-deployment-tls-1
     namespace: foobar
    spec:
     # name of the tls secret to store
     # the generated certificate/key pair
     secretName: hello-deployment-tls-1
     issuerRef:
       # issuer created in step 1
       name: hello-deployment-tls
       # ClusterIssuers can be referenced
       # by changing the kind here.
       # the default value is Issuer (i.e.
       # a locally namespaced Issuer)
       kind: Issuer
     commonName: "foo1.bar1"
     dnsNames:
       # one more fully-qualified domain name
       # can be defined here
     - foo1.bar1
    

    Cert-manager creates the certificate based on the certificate resource definition and stores it as a Kubernetes secret.

    The following example defines a certificate that uses the icp-ca-issuer that was created during installation:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: Certificate
    metadata:
     name: hello-deployment-tls-1
     namespace: foobar
    spec:
     # name of the tls secret to store
     # the generated certificate/key pair
     secretName: hello-deployment-tls-1
     issuerRef:
       # issuer created in step 1
       name: icp-ca-issuer
       # ClusterIssuers can be referenced
       # by changing the kind here.
       # the default value is Issuer (i.e.
       # a locally namespaced Issuer)
       kind: ClusterIssuer
     commonName: "foo1.bar1"
     dnsNames:
       # one more fully-qualified domain name
       # can be defined here
     - foo1.bar1
    
  3. Add the secret to the Kubernetes Ingress.

    The following example defines a TLS-enabled Kubernetes Ingress that is integrated with cert-manager:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
     name: hello-k8s-ingress-tls
     annotations:
       kubernetes.io/ingress.class: "nginx"
       ingress.kubernetes.io/rewrite-target: "/"
    spec:
     tls:
     # k8s ingress defines different tls certificates
     # for each nginx server blocks.
     # k8s ingress default cert is used if
     # no host-specific secret specified
     - hosts:
       # this is the fully-qualified domain name
       # of the first server block
       - foo1.bar1
       # certificate hello-k8s-ingress-tls-1
       # is only used by foo1.bar1
       secretName: hello-k8s-ingress-tls-1
     - hosts:
       # this is the fully-qualified domain name
       # of the second server block
       - foo2.bar2
       # certificate hello-k8s-ingress-tls-2
       # is only used by foo2.bar2
       secretName: hello-k8s-ingress-tls-2
     rules:
       # each server block redirects request
       # to its own backend service
     - host: foo1.bar1
       http:
         paths:
         - backend:
             serviceName: hello-world-svc
             servicePort: 80
           path: /fb
     - host: foo2.bar2
       http:
         paths:
         - backend:
             serviceName: hello-world-svc
             servicePort: 80
           path: /fb
    

Note: Certificates that are created by cert-manager are automatically renewed before expiration. Workloads must pick up the new certificates.