Stay organized with collections
Save and categorize content based on your preferences.
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
To get the permissions you need to request a certificate, ask your
Organization IAM Admin to grant you the Certificate Authority Service Admin
(certificate-authority-service-admin) role.
Get the kubeconfig file
To run commands against the Management API server, ensure you have the following
resources:
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_KUBECONFIG in 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:
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 CertificateResource and include a CSR in the resource.
Create a CertificateResource using a GDC
auto-generated private key and provide the certificate configurations as
custom values.
Request a certificate using a CSR
Create a CertificateRequest resource and save it as a YAML file called
cert-request.yaml. Use your private key to create a Certificate Signing
Request (CSR) and add it to your resource:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-25 UTC."],[[["\u003cp\u003eThis guide provides instructions on how to request a certificate from the Certificate Authority Service within a Google Distributed Cloud (GDC) air-gapped environment, which can be either ACME-enabled or disabled.\u003c/p\u003e\n"],["\u003cp\u003eBefore requesting a certificate, you must have the \u003ccode\u003eCertificate Authority Service Admin\u003c/code\u003e role and obtain the kubeconfig file for the Management API server.\u003c/p\u003e\n"],["\u003cp\u003eWhen requesting a certificate with ACME mode enabled, you'll need to retrieve the CA's ACME server URL using \u003ccode\u003ekubectl\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eWith ACME mode disabled, you can request a certificate by either creating a \u003ccode\u003eCertificateRequest\u003c/code\u003e resource with a provided Certificate Signing Request (CSR) or by utilizing a GDC auto-generated private key.\u003c/p\u003e\n"],["\u003cp\u003eTo verify a certificate request, run the specified kubectl command to ensure the status is "True" and the type is "Ready", and to see the list of certificate request run the \u003ccode\u003ekubectl get certificaterequests\u003c/code\u003e command.\u003c/p\u003e\n"]]],[],null,["# Request a certificate\n\nThis page describes the steps to request a certificate using the Certificate Authority\nService.\n\nTo establish trust and secure communication within your\nGoogle Distributed Cloud (GDC) air-gapped, request an ACME-enabled or disabled certificate\nfrom the Certificate Authority Service.\n\nBefore you begin\n----------------\n\nTo get the permissions you need to request a certificate, ask your\nOrganization IAM Admin to grant you the Certificate Authority Service Admin\n(`certificate-authority-service-admin`) role.\n\n### Get the kubeconfig file\n\nTo run commands against the Management API server, ensure you have the following\nresources:\n\n[Sign in and generate](/distributed-cloud/hosted/docs/latest/gdch/application/ao-user/iam/sign-in#cli) the\nkubeconfig file for the Management API server if you don't have one.\n\nUse the path to the kubeconfig file of the Management API server to replace\n\u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e in these instructions.\n\nRequest a certificate using CA with ACME mode enabled\n-----------------------------------------------------\n\nIf the certificate authority is hosted in ACME mode, it outputs the ACME server\nURL in its status after it becomes ready.\n\nGather the CA ACME server URL from your Distributed Cloud environment: \n\n kubectl get certificateauthorities \u003cvar translate=\"no\"\u003eCA_NAME\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e -ojson | jq -r '.status.acme.uri'\n\nReplace the following:\n\n- \u003cvar translate=\"no\"\u003eCA_NAME\u003c/var\u003e: The name of the CA, which can be a root or sub CA.\n- \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e: The name of the namespace where the user project resides.\n\nRequest a certificate using CA with ACME mode disabled\n------------------------------------------------------\n\nTo create a certificate request with ACME mode disabled, you must create and\napply a `CertificateRequest` resource to your Distributed Cloud air-gapped\ninstance. There are two ways to do this:\n\n- Create a `CertificateResource` and include a CSR in the resource.\n- Create a `CertificateResource` using a GDC auto-generated private key and provide the certificate configurations as custom values.\n\n### Request a certificate using a CSR\n\n1. Create a `CertificateRequest` resource and save it as a YAML file called\n `cert-request.yaml`. Use your private key to create a Certificate Signing\n Request (CSR) and add it to your resource:\n\n apiVersion: pki.security.gdc.goog/v1\n kind: CertificateRequest\n metadata:\n name: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCERT_REQ_NAME\u003c/span\u003e\u003c/var\u003e\n namespace: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eUSER_PROJECT_NAMESPACE\u003c/span\u003e\u003c/var\u003e\n spec:\n certificateAuthorityRef:\n name: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCA_NAME\u003c/span\u003e\u003c/var\u003e\n namespace: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eUSER_PROJECT_NAMESPACE\u003c/span\u003e\u003c/var\u003e\n csr: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCSR\u003c/span\u003e\u003c/var\u003e\n signedCertificateSecret: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eSECRET_NAME\u003c/span\u003e\u003c/var\u003e\n\n Replace the following variables:\n\n2. Apply the custom resource to your Distributed Cloud instance:\n\n kubectl apply -f cert-request.yaml --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e\n\n Replace \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e with the\n path to the kubeconfig file of the Management API server.\n3. Verify the readiness of the certificate request:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e get certificaterequest.pki.security.gdc.goog/\u003cvar translate=\"no\"\u003eCERT_REQ_NAME\u003c/var\u003e -ojson | jq -r ' .status.conditions[] | select( .type as $id | \"Ready\" | index($id))'\n\n The output is similar to the following: \n\n {\n \"lastTransitionTime\": \"2025-01-27T12:22:59Z\",\n \"message\": \"Certificate is issued\",\n \"observedGeneration\": 1,\n \"reason\": \"Issued\",\n \"status\": \"True\",\n \"type\": \"Ready\"\n }\n\n4. Get the certificate secret name:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e get certificaterequest.pki.security.gdc.goog/\u003cvar translate=\"no\"\u003eCERT_REQ_NAME\u003c/var\u003e -ojson | jq -r '.spec.signedCertificateSecret'\n\n The output shows the \u003cvar translate=\"no\"\u003eSECRET_NAME\u003c/var\u003e containing the\n signed certificate: \n\n test-jwk-1\n\n### Request a certificate using an auto-generated key\n\n1. Create a `CertificateRequest` resource and save it as a YAML file called\n `cert-request.yaml`. Populate the chosen values for the certificate:\n\n apiVersion: pki.security.gdc.goog/v1\n kind: CertificateRequest\n metadata:\n name: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCERT_REQ_NAME\u003c/span\u003e\u003c/var\u003e\n namespace: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eUSER_PROJECT_NAMESPACE\u003c/span\u003e\u003c/var\u003e\n spec:\n certificateAuthorityRef:\n name: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCA_NAME\u003c/span\u003e\u003c/var\u003e\n namespace: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eUSER_PROJECT_NAMESPACE\u003c/span\u003e\u003c/var\u003e\n certificateConfig:\n subjectConfig:\n commonName: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCOMMON_NAME\u003c/span\u003e\u003c/var\u003e\n organization: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eORGANIZATION\u003c/span\u003e\u003c/var\u003e\n locality: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eLOCALITY\u003c/span\u003e\u003c/var\u003e\n state: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eSTATE\u003c/span\u003e\u003c/var\u003e\n country: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eCOUNTRY\u003c/span\u003e\u003c/var\u003e\n dnsNames: \n - \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eDNS_NAMES\u003c/span\u003e\u003c/var\u003e\n ipAddresses:\n - \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eIP_ADDRESSES\u003c/span\u003e\u003c/var\u003e\n rfc822Names:\n - \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eRFC822NAMES\u003c/span\u003e\u003c/var\u003e\n uris:\n - \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eURIS\u003c/span\u003e\u003c/var\u003e\n signedCertificateSecret: \u003cvar translate=\"no\"\u003e\u003cspan class=\"devsite-syntax-l devsite-syntax-l-Scalar devsite-syntax-l-Scalar-Plain\"\u003eSECRET_NAME\u003c/span\u003e\u003c/var\u003e\n\n Replace \u003cvar translate=\"no\"\u003eCOMMON_NAME\u003c/var\u003e with the common name of the\n certificate.\n\n Replace the following optional variables. You must include at least one of\n these values in the `CertificateRequest` resource:\n\n2. Apply the custom resource to your Distributed Cloud instance:\n\n kubectl apply -f cert-request.yaml --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e\n\n3. Verify the readiness of the certificate request:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e get certificaterequest.pki.security.gdc.goog/\u003cvar translate=\"no\"\u003eCERT_REQ_NAME\u003c/var\u003e -ojson | jq -r ' .status.conditions[] | select( .type as $id | \"Ready\" | index($id))'\n\n The output is similar to the following: \n\n {\n \"lastTransitionTime\": \"2025-01-27T12:22:59Z\",\n \"message\": \"Certificate is issued\",\n \"observedGeneration\": 1,\n \"reason\": \"Issued\",\n \"status\": \"True\",\n \"type\": \"Ready\"\n }\n\n4. Get the certificate secret name:\n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e get certificaterequest.pki.security.gdc.goog/\u003cvar translate=\"no\"\u003eCERT_REQ_NAME\u003c/var\u003e -ojson | jq -r '.spec.signedCertificateSecret'\n\n The output shows the \u003cvar translate=\"no\"\u003eSECRET_NAME\u003c/var\u003e containing the\n signed certificate: \n\n test-jwk-1\n\nList certificate requests\n-------------------------\n\nUse the `certificaterequests` parameter to list all `CertificateRequest`\nresources: \n\n kubectl --kubeconfig \u003cvar translate=\"no\"\u003eMANAGEMENT_API_SERVER_KUBECONFIG\u003c/var\u003e -n \u003cvar translate=\"no\"\u003eUSER_PROJECT_NAMESPACE\u003c/var\u003e get certificaterequests\n\nThe output looks similar to the following: \n\n NAMESPACE NAME READY AGE\n foo cert-req True 30s"]]