This page describes the steps to request a certificate using the Certificate Authority Service.
To establish trust and secure communication within your Google Distributed Cloud (GDC) air-gapped, request an ACME-enabled or disabled certificate from the Certificate Authority Service.
Before you begin
Before you can request a certificate, make sure you have the required permissions and a kubeconfig file.
Required permissions
To get the permissions you need to request a certificate, ask your Organization
IAM Admin to grant you the CA Service Certificate Requester
(certificate-authority-service-certificate-requester) role. For more
information about roles, see
Role definitions.
Get the kubeconfig file
To run commands against the Management API server, do the following:
Sign in and generate the kubeconfig file for the Management API server if you don't have one.
Use the path to the kubeconfig file of the Management API server to replace
MANAGEMENT_API_SERVER_KUBECONFIGin these instructions.
Request a certificate using CA with ACME mode enabled
If the certificate authority is hosted in ACME mode, it outputs the ACME server URL in its status after it becomes ready.
Gather the CA ACME server URL from your Distributed Cloud environment:
kubectl get certificateauthorities CA_NAME -n USER_PROJECT_NAMESPACE -ojson | jq -r '.status.acme.uri'
Replace the following:
CA_NAME: The name of the CA, which can be a root or sub CA.USER_PROJECT_NAMESPACE: The name of the namespace where the user project resides.
Request a certificate using CA with ACME mode disabled
To create a certificate request with ACME mode disabled, you must create and
apply a CertificateRequest resource to your Distributed Cloud air-gapped
instance. There are two ways to do this:
- Create a
CertificateResourceand include a CSR in the resource. - Create a
CertificateResourceusing a GDC auto-generated private key and provide the certificate configurations as custom values.
Request a certificate using a CSR
Create a
CertificateRequestresource and save it as a YAML file calledcert-request.yaml. Use your private key to create a Certificate Signing Request (CSR) and add it to your resource.Optionally, you can issue the certificate with a pre-configured set of X.509 parameters by entering the template's name into the
certificateTemplatefield.apiVersion: pki.security.gdc.goog/v1 kind: CertificateRequest metadata: name: CERT_REQ_NAME namespace: USER_PROJECT_NAMESPACE spec: certificateAuthorityRef: name: CA_NAME namespace: USER_PROJECT_NAMESPACE csr: CSR certificateTemplate: TEMPLATE_NAME signedCertificateSecret: SECRET_NAME notBefore: VALIDITY_START_TIME notAfter: VALIDITY_END_TIME subjectOverride: SUBJECT_OVERRIDEReplace the following variables:
Variable Description CERT_REQ_NAME The name of the certificate. USER_PROJECT_NAMESPACE The name of the namespace where the user project resides. CA_NAME The name of the CA, which can be a root or sub CA. CSR The Certificate Signing Request to sign using CA. SECRET_NAME The name of the Kubernetes Secret that holds the private key and signed CA certificate. Replace the following optional variables:
Variable Description TEMPLATE_NAME The name of the predefined certificate template you want to use. For a list of available templates and details concerning conflicts, see Predefined certificate templates. VALIDITY_START_TIME The time from which the certificate is considered valid. This value must be in the format YYYY-MM-DDTHH:MM:SSZ(for example,2025-10-19T21:45:30Z). If not set, the certificate is valid immediately upon issuance.VALIDITY_END_TIME The time at which the certificate expires. This value must be in the format YYYY-MM-DDTHH:MM:SSZ(for example,2026-01-17T18:25:40Z). If not set, the certificate expires 90 days after its start time.SUBJECT_OVERRIDE A custom subject to use in the issued certificate, overriding the subject information in the CSR. Provide this value as the raw, ASN.1 DER-encoded X.509 subject. Apply the custom resource to your Distributed Cloud instance:
kubectl apply -f cert-request.yaml --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIGReplace
MANAGEMENT_API_SERVER_KUBECONFIGwith the path to the kubeconfig file of the Management API server.Verify the readiness of the certificate request:
kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificaterequest.pki.security.gdc.goog/CERT_REQ_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'The output is similar to the following:
{ "lastTransitionTime": "2025-01-27T12:22:59Z", "message": "Certificate is issued", "observedGeneration": 1, "reason": "Issued", "status": "True", "type": "Ready" }Get the certificate secret name:
kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificaterequest.pki.security.gdc.goog/CERT_REQ_NAME -ojson | jq -r '.spec.signedCertificateSecret'The output shows the
SECRET_NAMEcontaining the signed certificate:test-jwk-1
Request a certificate using an auto-generated key
Create a
CertificateRequestresource and save it as a YAML file calledcert-request.yaml. Populate the chosen values for the certificate.Optionally, you can issue the certificate with a pre-configured set of X.509 parameters by entering the template's name into the
certificateTemplatefield.apiVersion: pki.security.gdc.goog/v1 kind: CertificateRequest metadata: name: CERT_REQ_NAME namespace: USER_PROJECT_NAMESPACE spec: certificateAuthorityRef: name: CA_NAME namespace: USER_PROJECT_NAMESPACE certificateConfig: subjectConfig: commonName: COMMON_NAME organization: ORGANIZATION locality: LOCALITY state: STATE country: COUNTRY dnsNames: - DNS_NAMES ipAddresses: - IP_ADDRESSES rfc822Names: - RFC822NAMES uris: - URIS certificateTemplate: TEMPLATE_NAME signedCertificateSecret: SECRET_NAME notBefore: VALIDITY_START_TIME notAfter: VALIDITY_END_TIME subjectOverride: SUBJECT_OVERRIDEReplace the following variables:
Variable Description CERT_REQ_NAME The name of the certificate. USER_PROJECT_NAMESPACE The name of the namespace where the user project resides. CA_NAME The name of the CA, which can be a root or sub CA. SECRET_NAME The name of the Kubernetes Secret that holds the private key and signed CA certificate. Replace the following optional variables. You must include at least one of the fields from the
spec.certificateConfig.subjectConfigblock of theCertificateRequestresource:Variable Description COMMON_NAME The common name of the certificate. ORGANIZATION Organization to be used on the certificate. LOCALITY The locality of the certificate. STATE State or Province to be used on the certificate. COUNTRY The country of the certificate. DNS_NAMES DNSNamesis a list ofdNSName subjectAltNamesto be set on the certificate.IP_ADDRESS A list of ipAddress subjectAltNamesto be set on the certificate.RFC822_NAMES A list of rfc822Name subjectAltNamesto be set on the certificate.URIS A list of uniformResourceIdentifier subjectAltNamesto be set on the certificate.TEMPLATE_NAME The name of the predefined certificate template you want to use. For a list of available templates and details concerning conflicts, see Predefined certificate templates. VALIDITY_START_TIME The time from which the certificate is considered valid. This value must be in the format YYYY-MM-DDTHH:MM:SSZ(for example,2025-10-19T21:45:30Z). If not set, the certificate is valid immediately upon issuance.VALIDITY_END_TIME The time at which the certificate expires. This value must be in the format YYYY-MM-DDTHH:MM:SSZ(for example,2026-01-17T18:25:40Z). If not set, the certificate expires 90 days after its start time.SUBJECT_OVERRIDE A custom subject to use in the issued certificate, overriding the subject information in the CSR. Provide this value as the raw, ASN.1 DER-encoded X.509 subject. Apply the custom resource to your Distributed Cloud instance:
kubectl apply -f cert-request.yaml --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIGVerify the readiness of the certificate request:
kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificaterequest.pki.security.gdc.goog/CERT_REQ_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'The output is similar to the following:
{ "lastTransitionTime": "2025-01-27T12:22:59Z", "message": "Certificate is issued", "observedGeneration": 1, "reason": "Issued", "status": "True", "type": "Ready" }Get the certificate secret name:
kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificaterequest.pki.security.gdc.goog/CERT_REQ_NAME -ojson | jq -r '.spec.signedCertificateSecret'The output shows the
SECRET_NAMEcontaining the signed certificate:test-jwk-1
List certificate requests
Use the certificaterequests parameter to list all CertificateRequest
resources:
kubectl --kubeconfig MANAGEMENT_API_SERVER_KUBECONFIG -n USER_PROJECT_NAMESPACE get certificaterequests
The output looks similar to the following:
NAMESPACE NAME READY AGE
foo cert-req True 30s