Skip to content

Using the Private PKI for Internal Certificates

While the automated Let's Encrypt integration is perfect for public-facing services, you may have internal applications that also need to communicate securely over TLS. For this purpose, the platform provides a private Public Key Infrastructure (PKI) service, powered by OpenBao, which can issue trusted certificates for your internal services.

When to Use the Private PKI

You should use the private PKI for issuing certificates in scenarios such as:

  • Securing Service-to-Service Communication: Encrypting traffic between your internal microservices (mTLS).
  • Internal APIs: For services that are only accessible within the cluster or via a VPN and do not have a public DNS record.
  • Database Connections: Securing connections between your application and a database.

These certificates are trusted within the platform's ecosystem but are not trusted by default by end-user web browsers or operating systems.

How It Works

The process is very similar to requesting a public certificate. The main difference is that you will reference a different ClusterIssuer that is configured to get certificates from our internal PKI engine.

Because the PKI is internal, it doesn't need to perform public domain validation challenges like the Let's Encrypt issuer does.

Example: Securing an Internal gRPC Service

A common use case is securing a gRPC service that communicates with other services inside the cluster. Unlike web applications, these services often don't have an HTTPProxy or Ingress resource. In this case, you can create a Certificate resource directly.

Let's say you have a service named user-database in the backend-services namespace. You want to issue a TLS certificate for it so other pods can connect securely to its FQDN: user-database.backend-services.svc.cluster.local.

1. Create a Certificate Resource

Create the following manifest in your GitOps repository:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: user-db-internal-tls
  namespace: backend-services
spec:
  # The name of the secret where the certificate will be stored.
  secretName: user-db-internal-tls-secret

  # The internal FQDNs the certificate will be valid for.
  dnsNames:
  - user-database.backend-services.svc.cluster.local
  - user-database.backend-services.svc
  - user-database.backend-services
  - user-database

  # Reference our pre-configured internal PKI issuer.
  issuerRef:
    name: openbao-pki
    kind: ClusterIssuer
  • spec.secretName: You define the name of the Secret that cert-manager will create to hold the tls.crt, tls.key, and ca.crt.
  • spec.dnsNames: A list of all the internal DNS names that clients might use to connect to your service. It's a good practice to include the fully qualified name as well as shorter versions.
  • spec.issuerRef: This points to the openbao-pki ClusterIssuer, telling the Certificates service to use our internal PKI instead of Let's Encrypt.

2. Consume the Certificate in Your Application

Once you push the manifest, the Certificates service will create the user-db-internal-tls-secret. You can now mount this secret as a volume in your application's Deployment and configure your application to use the certificate and key.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-database
  namespace: backend-services
spec:
  # ... other deployment specs
  template:
    # ... other pod specs
    spec:
      containers:
      - name: user-database-container
        image: your-image/user-db
        ports:
        - containerPort: 50051
        volumeMounts:
        - name: tls-certs
          mountPath: /etc/tls
          readOnly: true
      volumes:
      - name: tls-certs
        secret:
          secretName: user-db-internal-tls-secret # Mount the secret created by cert-manager

Your application can now load the certificate from /etc/tls/tls.crt and the private key from /etc/tls/tls.key to start its secure gRPC server.

Next Steps

  • You can now issue certificates for any internal service, enhancing your security posture.
  • For more complex configurations, refer to the official cert-manager documentation.