| name | manage-certificates |
| description | Request and manage x509 certificates in a Kube-DC project — ManagedCertificate resources backed by either the Organization's private intermediate CA (mTLS, internal services, code signing) or a public ACME issuer (Let's Encrypt by default). Certificates auto-renew before expiry; the result lands in a Kubernetes Secret your workloads mount. For HTTPS via Gateway / HTTPRoute use the expose-service skill — it auto-creates the ManagedCertificate. Use this skill directly only for mTLS, client certs, code signing, or custom durations. |
Prerequisites
- Target project must exist and be Ready
- Project namespace:
{org}-{project}
- For
type: public — the requested dnsNames must resolve to your project's external IP and be on the Organization's allowed-domains list (admission webhook enforces)
- For
type: private — the Organization's intermediate CA must be provisioned (auto-done at first request)
Key Concepts
- ManagedCertificate — Project-scoped CRD that wraps cert-manager + the OpenBao PKI engine. You name a target Kubernetes Secret and a SAN list; the platform issues + renews + writes
tls.crt / tls.key / ca.crt into the Secret.
- type —
private (Org intermediate CA — trusted inside the platform) or public (ACME — trusted by browsers).
- purpose —
server (server TLS auth, the default), client (client TLS auth for mTLS), mtls (both), code-signing (code-signing EKU).
- Auto-renewal — Renews
renewBefore ahead of expiry (default 15d for a 90d cert). No tenant action required.
Decide: type=private or type=public?
| Need | Pick |
|---|
| HTTPS endpoint reachable from the internet | public |
| Internal service mTLS (service-to-service in the project / org) | private |
| Client certs you ship to partners or workloads | private |
| Code signing (signing images, OCI artifacts) | private |
| Short-lived certs (< 90d) for batch jobs | private |
public certs cost an ACME issuance — don't churn them. private is free + fast (< 10s issuance) but not internet-trusted.
Request a Certificate
apiVersion: security.kube-dc.com/v1alpha1
kind: ManagedCertificate
metadata:
name: {cert-name}
namespace: {project-namespace}
spec:
type: private
purpose: server
dnsNames:
- {hostname-or-san-1}
- {hostname-or-san-2}
duration: 90d
renewBefore: 15d
targetSecretName: {cert-name}
See @managed-certificate-template.yaml for a fully-annotated template.
Common shapes
kube-dc certificates request {api-name} \
--type=public \
--dns={api.your-domain.com}
kube-dc certificates request {svc-name} \
--type=private --purpose=mtls \
--dns={svc.internal} \
--dns={svc.{project-namespace}.svc.cluster.local}
kube-dc certificates request {partner-name} \
--type=private --purpose=client \
--dns={partner-name}.partners.internal
kube-dc certificates request {batch-name} \
--type=private \
--dns={batch-job.internal} \
--duration=30d --renew-before=5d
Use the Certificate
The platform writes a standard kubernetes.io/tls Secret with tls.crt, tls.key, and (for type: private) ca.crt containing the Org intermediate CA chain.
spec:
containers:
- name: app
image: my-app
volumeMounts:
- name: tls
mountPath: /etc/tls
readOnly: true
volumes:
- name: tls
secret:
secretName: {cert-name}
For Gateway / HTTPRoute use the secret directly in certificateRefs:
spec:
listeners:
- name: https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- kind: Secret
name: {cert-name}
Inspect / Renew / Delete
kube-dc certificates list
kube-dc certificates get {cert-name}
kube-dc certificates renew {cert-name}
kube-dc certificates delete {cert-name} --yes
kubectl short name is mcert:
kubectl get mcert -n {project-namespace}
kubectl describe mcert {cert-name} -n {project-namespace}
Verification
After requesting a certificate:
kubectl get managedcertificate {name} -n {project-namespace} \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'
kubectl get secret {targetSecretName} -n {project-namespace} \
-o jsonpath='{.type}'
kubectl get managedcertificate {name} -n {project-namespace} \
-o jsonpath='{.status.notAfter}'
kubectl get managedcertificate {name} -n {project-namespace} \
-o jsonpath='{.status.renewalTime}'
Success: Ready=True, target Secret has tls.crt/tls.key, notAfter in the future.
Failure:
- Stuck
CertificateRequested for type=public: ACME HTTP-01 challenge can't complete — check DNS points at the cluster's ingress IP, and that the project's HTTPRoute / Gateway is up.
- Stuck
CertificateRequested for type=private: PKI engine missing for the Org — check the cluster admin enabled OpenBao.
dnsNames not allowed: an admission webhook rejected one of the SANs. Verify against the Org's allowed-domains list.
Safety
dnsNames are validated against the Organization's allowed-domains list. Don't try to issue for a domain you don't control — the request will be admission-rejected.
type: public issuance hits Let's Encrypt rate limits (50 certs / domain / week by default). Don't churn them.
- Deleting a ManagedCertificate also deletes the target Kubernetes Secret. Workloads currently mounting it will fail to restart until you fix references. Run
kubectl get pods -n {project-namespace} -o yaml | grep -A2 secretName.*{cert-name} to find users first.
- The platform does NOT support BYO private key. Every issuance generates a fresh key pair. If you need to bring your own key, use cert-manager primitives directly (not this skill).
- For HTTPS exposure (the common case), use the
expose-service skill — it creates the right Gateway / HTTPRoute and auto-provisions the ManagedCertificate so you don't have to do both halves by hand.