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 theSecretthat cert-manager will create to hold thetls.crt,tls.key, andca.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 theopenbao-pkiClusterIssuer, 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.