Skip to content

Configuring OpenShift Routes

Once you have installed OpenShift Routes , you need to configure it to get a certificate for OpenShift routes from a cert-manager Issuer or ClusterIssuer.

Configuration requires three steps:

  1. Configure an issuer.
  2. Annotate the routes.
  3. Use the certificate in you workloads (optional).

Prerequisites

You have cert-manager and OpenShift Routes installed in the same namespace. By default, this is in the venafi namespace.

Step 1: Configure an issuer

  1. You can use either a ClusterIssuer or a namespace-based Issuer. The following example creates a Issuer. We will use a self-signed CA for this example. In production, use a Venafi(Cluster)Issuer instead.

    my-ca-issuer.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: demo
    ---
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: selfsigned-issuer
      namespace: demo
    spec:
      selfSigned: {}
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: my-ca-cert
      namespace: demo
    spec:
      isCA: true
      commonName: my-ca
      secretName: my-ca-secret
      privateKey:
        algorithm: ECDSA
        size: 256
      issuerRef:
        name: selfsigned-issuer
        kind: Issuer
        group: cert-manager.io
    ---
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: my-ca-issuer
      namespace: demo
    spec:
      ca:
        secretName: my-ca-secret
    
  2. Apply my-ca-issuer.yaml:

    oc apply -f my-ca-issuer.yaml
    

Step 2: Create an annotated route

  1. If you used the example Issuer above, you can now use the following annotations:

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: example-route
      namespace: demo
      annotations:
        cert-manager.io/issuer-group: cert-manager.io
        cert-manager.io/issuer-kind: Issuer
        cert-manager.io/issuer-name: my-ca-issuer
    spec:
      host: app.service.clustername.domain.com
    
  2. You can now annotate your routes:

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: example-route
      namespace: demo
      annotations:
        cert-manager.io/issuer-name: my-issuer # This is the only required annotation.
        cert-manager.io/issuer-group: cert-manager.io # Optional, defaults to cert-manager.io.
        cert-manager.io/issuer-kind: Issuer # Optional, defaults to Issuer. Other options are ClusterIssuer or an External Issuer
        cert-manager.io/duration: 1h # Optional, defaults to 90 days
        cert-manager.io/renew-before: 30m # Optional, defaults to 1/3 of total certificate duration.
        cert-manager.io/common-name: "My Certificate" # Optional, no default.
        cert-manager.io/alt-names: "mycooldomain.com,mysecondarydomain.com" # Optional, no default.
        cert-manager.io/ip-sans: "10.20.30.40,192.168.192.168" # Optional, no default.
        cert-manager.io/uri-sans: "spiffe://trustdomain/workload" # Optional, no default.
        cert-manager.io/private-key-algorithm: "ECDSA" # Optional, defaults to RSA.
        cert-manager.io/private-key-rotation-policy: "Always" # Optional, valid values are Never and Always. If a rotation policy is unset, it will never be used. Set this to `Always` unless you have a good reason not to.
        cert-manager.io/private-key-size: "384" # Optional, defaults to 265 for ECDSA and 2048 for RSA.
        cert-manager.io/revision-history-limit: "5" # Optional, controls how many CertificateRequests are preserved when certificates are (re-)issued. Set this to a low number to reduce cluster clutter. The minimum value is 1. If unset, all CertificateRequests will be kept.
        cert-manager.io/email-sans: "me@example.com,you@example.com" # Optional, no default.
        cert-manager.io/subject-organizations: "company" # Optional, no default.
        cert-manager.io/subject-organizationalunits: "company division" # Optional, no default.
        cert-manager.io/subject-countries: "My Country" # Optional, no default.
        cert-manager.io/subject-provinces: "My Province" # Optional, no default.
        cert-manager.io/subject-localities: "My City" # Optional, no default.
        cert-manager.io/subject-postalcodes: "123ABC" # Optional, no default.
        cert-manager.io/subject-streetaddresses: "1 Example St" # Optional, no default.
        cert-manager.io/subject-serialnumber: "123456" # Optional, no default.
    spec:
      host: app.service.clustername.domain.com # Will be added to the Subject Alternative Names of the CertificateRequest.
      port:
        targetPort: 8080
      to:
        kind: Service
        name: hello-openshift
    
  3. You should now be able to observe the route.Spec.TLS section of your route being populated automatically by cert-manager.

    The route's TLS certificate will be rotated two-thirds of the way through the certificate's lifetime, or the cert-manager.io/renew-before time, before it expires.

    You should also be able now to call the website: https://app.service.clustername.domain.com. This will be served by the route with a certificate signed by the CA you created in step 1.

Step 3: (Optional) Use the certificate in your workloads

A Certificate resource and Secret will automatically be created. This Secret can mounted to a Pod, and the Certificate is shared between the OpenShift route and the workload.

Note

In the vast majority of cases, The Certificate and Secret naming convention uses the following pattern <route name>-cert and <route name>-tls. For example, for a route called example-route, the Certificate and Secret names will be example-route-cert and example-route-tls.

If, however, the route name exceeds 247 characters (up to a maximum of 253 characters), appending -cert or -tls would exceed the maximum length limit. In such cases, the naming convention will use a trimmed route name at the end, with an appended hash to avoid collisions. The pattern is <trimmed route name>-<hash>-cert or <trimmed route name>-<hash>-tls.

You can use the sample YAML below as an example of how to mount a secret to a Pod:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  volumes:
    - name: secret-volume
      secret:
        secretName: example-route-tls
  containers:
    - name: my-test-container
      image: registry.k8s.io/busybox
      command:
        - ls
        - "-l"
        - "/etc/secret-volume"
      volumeMounts:
        - name: secret-volume
          readOnly: true
          mountPath: "/etc/secret-volume"