Creating certificate authorities

This topic describes how to create certificate authorities (CAs) in a CA pool.

Before you begin

  • Make sure you have the CA Service Operation Manager (roles/privateca.caManager) or the CA Service Admin (roles/privateca.admin) IAM role. For information about granting an IAM to a principal, see Grant a single role.

  • Create a CA pool by following the instructions in Creating CA pools.

Deciding the CA's settings

You cannot change some CA settings after creating the CA. Some of these settings are specific to Certificate Authority Service, while other settings are inherently immutable to CAs, because they appear in the CA's own certificate. For example, the CA type (root or subordinate) is a permanent setting.

For more information, see Permanent CA settings.

Creating a root CA

A root CA has a self-signed certificate that you must distribute to the trust stores of your clients. The root CA's certificate is at the top of the certificate chain. No other CA can revoke the CA certificate. The CRL of the root CA applies only to the other certificates the root CA issued, but not to itself.

Console

To create a root CA, do the following.

  1. Go to the Certificate Authority Service page in the Google Cloud console.

    Go to Certificate Authority Service

  2. Click the CA manager tab.

  3. Click Create CA.

Select CA type

To configure the permanent settings of the CA, such as tier, location, lifetime, and the operational state at creation, do the following:

  1. Select Root CA.
  2. In the Valid for field, enter the duration for which you want the certificates issued by the CA certificate to be valid.
  3. Optional: Choose a tier for the CA. For more information, see Workload-optimized tiers.
  4. Click Region and in the list, select the location where you want to create the CA. We recommend creating the CA geographically near your application's clients. For more information, see Choosing the best location.
  5. Optional: Select the operational state of the CA to be created in.

    Choose the operation state of the CA to be created in.

  6. Optional: Click Certificate profile. In the list, select the certificate profile that matches the type of certificates you want the CA to issue.

  7. Click Next.

Configure CA subject name
  1. In the Organization (O) field, enter the name of your company.
  2. Optional: In the Organization unit (OU) field, enter the company subdivision or business unit.
  3. Optional: In the Country name field, enter a two letter country code.
  4. Optional: In the State or province name field, enter the name of your state.
  5. Optional: In the Locality name field, enter the name of your city.
  6. In the CA common name (CN) field, enter the CA name.
  7. In the Pool ID field, enter the CA pool name. You cannot change the CA pool after creating the CA.
  8. Click Next.
Configure CA key size and algorithm
  1. Choose the key algorithm that best meets your needs. For information about deciding the suitable key algorithm, see Choosing a key algorithm.
  2. Click Next.
Configure CA artifacts

The following steps are optional. If you skip these steps, the default settings apply.

  1. Choose whether you want to use a Google-managed or a self-managed Cloud Storage bucket.
  2. If you don't select a self-managed Cloud Storage bucket, CA Service creates a Google-managed bucket in the same location as the CA.

  3. Choose whether you want to disable the publication of certificate revocation lists (CRLs) and CA certificates to the Cloud Storage bucket.
  4. The publication of CRL and CA certificate on a Cloud Storage bucket is enabled by default. To disable these settings, click the toggles.

  5. Click Next.
Add labels

The following steps are optional.

If you want to add labels to the CA, do the following:

  1. Click Add item.
  2. In the Key 1 field, enter the label key.
  3. In the Value 1 field, enter the label value.
  4. If you want to add another label, click Add item. Then, add the label key and value as mentioned in steps 2 and 3.
  5. Click Next.
Review the settings

Carefully review all the settings, then click Create to create the CA.

gcloud

  1. To create a CA pool, run the following command:

    gcloud privateca pools create POOL_ID
    

    Replace POOL_ID with the name of the CA pool.

    For more information, see Creating a CA pool.

    For more information about this gcloud command, see gcloud privateca pools create.

  2. Create a new root CA in the CA pool you created.

    gcloud privateca roots create ROOT_CA_ID --pool=POOL_ID \
      --key-algorithm=KEY_ALGORITHM \
      --subject="CN=my-ca, O=Test LLC"
    

    Replace the following:

    • ROOT_CA_ID: The name of the CA.
    • POOL_ID: The name of the CA pool.
    • KEY_ALGORITHM: The algorithm to use for creating a Cloud KMS key. This flag is optional. If you don't include this flag, the key algorithm defaults to rsa-pkcs1-4096-sha256. For more information, see --key-algorithm flag.

    By default, the CA is created in the STAGED state. To enable a CA by default, include the --auto-enable flag.

    If you want to use a customer-managed Cloud Storage bucket for publishing CA certificates and CRLs, add --bucket bucket-name to the command. Replace bucket-name with the name of the Cloud Storage bucket.

    To see the exhaustive list of settings, run the following command:

    gcloud privateca roots create --help
    

REST API

  1. Create a root CA.

    HTTP method and URL:

    POST https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/caPools/POOL_ID/certificateAuthorities?certificate_authority_id=ROOT_CA_ID

    Request JSON body:

    {
    "type": "SELF_SIGNED",
    "lifetime": {
     "seconds": 315576000,
     "nanos": 0
    },
    "config": {
     "subject_config": {
       "subject": {
         "organization": "ORGANIZATION_NAME",
         "common_name": "COMMON_NAME"
       }
     },
     "x509_config":{
       "ca_options":{
         "is_ca":true
       },
       "key_usage":{
         "base_key_usage":{
           "cert_sign":true,
           "crl_sign":true
         }
       }
     }
    },
    "key_spec":{
     "algorithm":"RSA_PKCS1_4096_SHA256"
    }
    }
    

    To send your request, expand one of these options:

    You should receive a JSON response similar to the following:

    {
     "name": "projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID",
     "metadata": {...},
     "done": false
    }
    

  2. Poll the operation until it has completed.

    HTTP method and URL:

    GET https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID

    To send your request, expand one of these options:

    You should receive a JSON response similar to the following:

    {
     "name": "projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID",
     "metadata": {...},
     "done": true,
     "response": {
       "@type": "type.googleapis.com/google.cloud.security.privateca.v1.CertificateAuthority",
       "name": "...",
     }
    }
    

Code samples

Java


import com.google.api.core.ApiFuture;
import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.CertificateAuthority;
import com.google.cloud.security.privateca.v1.CertificateAuthority.KeyVersionSpec;
import com.google.cloud.security.privateca.v1.CertificateAuthority.SignHashAlgorithm;
import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient;
import com.google.cloud.security.privateca.v1.CertificateConfig;
import com.google.cloud.security.privateca.v1.CertificateConfig.SubjectConfig;
import com.google.cloud.security.privateca.v1.CreateCertificateAuthorityRequest;
import com.google.cloud.security.privateca.v1.KeyUsage;
import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions;
import com.google.cloud.security.privateca.v1.Subject;
import com.google.cloud.security.privateca.v1.X509Parameters;
import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions;
import com.google.longrunning.Operation;
import com.google.protobuf.Duration;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

public class CreateCertificateAuthority {

  public static void main(String[] args)
      throws InterruptedException, ExecutionException, IOException {
    // TODO(developer): Replace these variables before running the sample.
    // location: For a list of locations, see:
    // https://cloud.google.com/certificate-authority-service/docs/locations
    // pool_Id: Set it to the CA Pool under which the CA should be created.
    // certificateAuthorityName: Unique name for the CA.
    String project = "your-project-id";
    String location = "ca-location";
    String pool_Id = "ca-pool-id";
    String certificateAuthorityName = "certificate-authority-name";
    createCertificateAuthority(project, location, pool_Id, certificateAuthorityName);
  }

  // Create Certificate Authority which is the root CA in the given CA Pool.
  public static void createCertificateAuthority(
      String project, String location, String pool_Id, String certificateAuthorityName)
      throws InterruptedException, ExecutionException, IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `certificateAuthorityServiceClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (CertificateAuthorityServiceClient certificateAuthorityServiceClient =
        CertificateAuthorityServiceClient.create()) {

      String commonName = "common-name";
      String orgName = "org-name";
      int caDuration = 100000; // Validity of this CA in seconds.

      // Set the type of Algorithm.
      KeyVersionSpec keyVersionSpec =
          KeyVersionSpec.newBuilder().setAlgorithm(SignHashAlgorithm.RSA_PKCS1_4096_SHA256).build();

      // Set CA subject config.
      SubjectConfig subjectConfig =
          SubjectConfig.newBuilder()
              .setSubject(
                  Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build())
              .build();

      //  Set the key usage options for X.509 fields.
      X509Parameters x509Parameters =
          X509Parameters.newBuilder()
              .setKeyUsage(
                  KeyUsage.newBuilder()
                      .setBaseKeyUsage(
                          KeyUsageOptions.newBuilder().setCrlSign(true).setCertSign(true).build())
                      .build())
              .setCaOptions(CaOptions.newBuilder().setIsCa(true).build())
              .build();

      // Set certificate authority settings.
      CertificateAuthority certificateAuthority =
          CertificateAuthority.newBuilder()
              // CertificateAuthority.Type.SELF_SIGNED denotes that this CA is a root CA.
              .setType(CertificateAuthority.Type.SELF_SIGNED)
              .setKeySpec(keyVersionSpec)
              .setConfig(
                  CertificateConfig.newBuilder()
                      .setSubjectConfig(subjectConfig)
                      .setX509Config(x509Parameters)
                      .build())
              // Set the CA validity duration.
              .setLifetime(Duration.newBuilder().setSeconds(caDuration).build())
              .build();

      // Create the CertificateAuthorityRequest.
      CreateCertificateAuthorityRequest certificateAuthorityRequest =
          CreateCertificateAuthorityRequest.newBuilder()
              .setParent(CaPoolName.of(project, location, pool_Id).toString())
              .setCertificateAuthorityId(certificateAuthorityName)
              .setCertificateAuthority(certificateAuthority)
              .build();

      // Create Certificate Authority.
      ApiFuture<Operation> futureCall =
          certificateAuthorityServiceClient
              .createCertificateAuthorityCallable()
              .futureCall(certificateAuthorityRequest);
      Operation response = futureCall.get();

      if (response.hasError()) {
        System.out.println("Error while creating CA !" + response.getError());
        return;
      }

      System.out.println(
          "Certificate Authority created successfully : " + certificateAuthorityName);
    }
  }
}

Python

import google.cloud.security.privateca_v1 as privateca_v1
from google.protobuf import duration_pb2


def create_certificate_authority(
    project_id: str,
    location: str,
    ca_pool_name: str,
    ca_name: str,
    common_name: str,
    organization: str,
    ca_duration: int,
) -> None:
    """
    Create Certificate Authority which is the root CA in the given CA Pool. This CA will be
    responsible for signing certificates within this pool.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        location: location you want to use. For a list of locations, see: https://cloud.google.com/certificate-authority-service/docs/locations.
        ca_pool_name: set it to the CA Pool under which the CA should be created.
        ca_name: unique name for the CA.
        common_name: a title for your certificate authority.
        organization: the name of your company for your certificate authority.
        ca_duration: the validity of the certificate authority in seconds.
    """

    caServiceClient = privateca_v1.CertificateAuthorityServiceClient()

    # Set the types of Algorithm used to create a cloud KMS key.
    key_version_spec = privateca_v1.CertificateAuthority.KeyVersionSpec(
        algorithm=privateca_v1.CertificateAuthority.SignHashAlgorithm.RSA_PKCS1_4096_SHA256
    )

    # Set CA subject config.
    subject_config = privateca_v1.CertificateConfig.SubjectConfig(
        subject=privateca_v1.Subject(common_name=common_name, organization=organization)
    )

    # Set the key usage options for X.509 fields.
    x509_parameters = privateca_v1.X509Parameters(
        key_usage=privateca_v1.KeyUsage(
            base_key_usage=privateca_v1.KeyUsage.KeyUsageOptions(
                crl_sign=True,
                cert_sign=True,
            )
        ),
        ca_options=privateca_v1.X509Parameters.CaOptions(
            is_ca=True,
        ),
    )

    # Set certificate authority settings.
    certificate_authority = privateca_v1.CertificateAuthority(
        # CertificateAuthority.Type.SELF_SIGNED denotes that this CA is a root CA.
        type_=privateca_v1.CertificateAuthority.Type.SELF_SIGNED,
        key_spec=key_version_spec,
        config=privateca_v1.CertificateConfig(
            subject_config=subject_config,
            x509_config=x509_parameters,
        ),
        lifetime=duration_pb2.Duration(seconds=ca_duration),
    )

    ca_pool_path = caServiceClient.ca_pool_path(project_id, location, ca_pool_name)

    # Create the CertificateAuthorityRequest.
    request = privateca_v1.CreateCertificateAuthorityRequest(
        parent=ca_pool_path,
        certificate_authority_id=ca_name,
        certificate_authority=certificate_authority,
    )

    operation = caServiceClient.create_certificate_authority(request=request)
    result = operation.result()

    print("Operation result:", result)

Terraform

To create a root CA using a Google-managed key, use the following sample configuration:

resource "google_privateca_certificate_authority" "default" {
  // This example assumes this pool already exists.
  // Pools cannot be deleted in normal test circumstances, so we depend on static pools
  pool = "ca-pool"
  certificate_authority_id = "my-certificate-authority"
  location = "us-central1"
  deletion_protection = "true"
  config {
    subject_config {
      subject {
        organization = "HashiCorp"
        common_name = "my-certificate-authority"
      }
      subject_alt_name {
        dns_names = ["hashicorp.com"]
      }
    }
    x509_config {
      ca_options {
        is_ca = true
        max_issuer_path_length = 10
      }
      key_usage {
        base_key_usage {
          digital_signature = true
          content_commitment = true
          key_encipherment = false
          data_encipherment = true
          key_agreement = true
          cert_sign = true
          crl_sign = true
          decipher_only = true
        }
        extended_key_usage {
          server_auth = true
          client_auth = false
          email_protection = true
          code_signing = true
          time_stamping = true
        }
      }
    }
  }
  lifetime = "86400s"
  key_spec {
    algorithm = "RSA_PKCS1_4096_SHA256"
  }
}

To create a root CA using a self-managed key, use the following sample configuration:

resource "google_project_service_identity" "privateca_sa" {
  service = "privateca.googleapis.com"
}

resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_signerverifier" {
  crypto_key_id = "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key"
  role          = "roles/cloudkms.signerVerifier"

  members = [
    "serviceAccount:${google_project_service_identity.privateca_sa.email}",
  ]
}

resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_viewer" {
  crypto_key_id = "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key"
  role          = "roles/viewer"
  members = [
    "serviceAccount:${google_project_service_identity.privateca_sa.email}",
  ]
}

resource "google_privateca_certificate_authority" "default" {
  // This example assumes this pool already exists.
  // Pools cannot be deleted in normal test circumstances, so we depend on static pools
  pool = "ca-pool"
  certificate_authority_id = "my-certificate-authority"
  location = "us-central1"
  deletion_protection = "true"
  key_spec {
    cloud_kms_key_version = "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key/cryptoKeyVersions/1"
  }

  config  {
    subject_config  {
      subject {
        organization = "Example, Org."
        common_name  = "Example Authority"
      }
    }
    x509_config {
      ca_options {
        # is_ca *MUST* be true for certificate authorities
        is_ca = true
        max_issuer_path_length = 10
      }
      key_usage {
        base_key_usage {
          # cert_sign and crl_sign *MUST* be true for certificate authorities
          cert_sign = true
          crl_sign = true
        }
        extended_key_usage {
          server_auth = false
        }
      }
    }
  }

  depends_on = [
    google_kms_crypto_key_iam_binding.privateca_sa_keyuser_signerverifier,
    google_kms_crypto_key_iam_binding.privateca_sa_keyuser_viewer,
  ]
}

After you have verified that the CA works as expected, you can enable it to start issuing load-balanced certificates for the CA pool. For more information, see Enabling a CA.

Testing a CA

To verify that a CA is able to issue certificates, request a certificate from the associated CA pool and explicitly mention the name of the CA you want to test using the --ca flag.

You can use the following methods to request a certificate from a CA pool:

  1. Have CA Service create a private or public key for you.
  2. Generate your own private or public key and submit a Certificate Signing Request (CSR).

It is easier to use an auto-generated private key or public key to request a certificate from a CA in a CA pool. This section provides information on testing a CA using that method.

To use an auto-generated private key or public key to request a certificate from a CA in a CA pool, run the following gcloud command:

gcloud privateca certificates create \
  --issuer-pool=POOL_ID \
  --ca=ROOT_CA_ID \
  --generate-key \
  --key-output-file=KEY_FILENAME \
  --cert-output-file=CERT_FILENAME \
  --dns-san=DNS_NAME

Replace the following:

  • POOL_ID: The name of the CA pool.
  • ROOT_CA_ID: The unique identifier of the CA that you want to test.
  • KEY_FILENAME: The file where the generated key is written in PEM format.
  • CERT_FILENAME: The file where the resulting PEM-encoded certificate chain file is written. The order of the certificate chain is from leaf to root.
  • DNS_NAME: One or more comma-separated DNS Subject Alternative Names (SANs).

    The --generate-key flag generates a new RSA-2048 private key on your machine.

To use a Certificate Signing Request (CSR) to request a certificate from a CA in a CA pool, or for more information about requesting certificates, see Requesting certificates.

Enabling a root CA

gcloud

To enable a root CA, run the following gcloud command:

gcloud privateca roots enable ROOT_CA_ID --pool=POOL_ID

Replace the following:

  • ROOT_CA_ID: The name of the CA.
  • POOL_ID: The name of the CA pool.

REST API

  1. Enable the CA to issue certificates from the CA pool.

    HTTP method and URL:

    POST https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/caPools/POOL_ID/certificateAuthorities/ROOT_CA_ID:enable

    To send your request, expand one of these options:

    You should receive a JSON response similar to the following:

    {
     "name": "projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID",
     "metadata": {...},
     "done": false
    }
    

  2. Poll the operation until it has completed.

    HTTP method and URL:

    GET https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID

    To send your request, expand one of these options:

    You should receive a JSON response similar to the following:

    {
     "name": "projects/PROJECT_ID/locations/LOCATION/operations/operation-UUID",
     "metadata": {...},
     "done": true,
     "response": {
       "@type": "type.googleapis.com/google.cloud.security.privateca.v1.CertificateAuthority",
       "name": "...",
     }
    }
    

Creating a subordinate CA

Subordinate CAs are easier to revoke and rotate than root CAs. If you have multiple certificate issuance scenarios, you can create a subordinate CA for each of those scenarios. Adding multiple subordinate CAs in a CA pool helps you achieve better load-balancing of certificate requests and a higher total effective QPS.

To create a subordinate CA, do the following:

Console

  1. Go to the Certificate Authority Service page in the Google Cloud console.

    Go to Certificate Authority Service

  2. Click CA manager.

  3. Click Create CA.

    Create a CA using the Cloud console.

Select CA type

  1. Click Subordinate CA.
  2. Click Root CA is in Google Cloud.
  3. In the Valid for field, enter the duration for which you want the CA certificate to be valid.
  4. Optional: Choose the tier for the CA. The default tier is Enterprise. For more information, see Workload-optimized tiers.
  5. Click Region to select a location for the CA. For more information, see Locations.
  6. Optional: Under Initialized state, select the state the CA must be in at creation.
  7. Optional: Under Set up an issuance scenario, click Certificate profile and select the certificate profile that best suits your requirements from the list. For more information, see Certificate profiles.
  8. Click Next.
Configure CA subject name
  1. In the Organization (O) field, enter the name of your company.
  2. Optional: In the Organization unit (OU) field, enter the company subdivision or business unit.
  3. Optional: In the Country name field, enter a two letter country code.
  4. Optional: In the State or province name field, enter the name of your state.
  5. Optional: In the Locality name field, enter the name of your city.
  6. In the CA common name (CN) field, enter the CA name.
  7. In the Pool ID field, enter the CA pool name. You cannot change the CA pool after creating the CA.
  8. Click Next.
Configure CA key size and algorithm
  1. Choose the key algorithm that best meets your needs. For information about deciding the suitable key algorithm, see Choosing a key algorithm.
  2. Click Next.
Configure CA artifacts

The following steps are optional. If you skip these steps, the default settings apply.

  1. Choose whether you want to use a Google-managed or a self-managed Cloud Storage bucket.
  2. If you don't select a self-managed Cloud Storage bucket, CA Service creates a Google-managed bucket in the same location as the CA.

  3. Choose whether you want to disable the publication of certificate revocation lists (CRLs) and CA certificates to the Cloud Storage bucket.
  4. The publication of CRL and CA certificate on a Cloud Storage bucket is enabled by default. To disable these settings, click the toggles.

  5. Click Next.
Add labels

The following steps are optional.

If you want to add labels to the CA, do the following:

  1. Click Add item.
  2. In the Key 1 field, enter the label key.
  3. In the Value 1 field, enter the label value.
  4. If you want to add another label, click Add item. Then, add the label key and value as mentioned in steps 2 and 3.
  5. Click Next.
Review the settings

Carefully review all the settings, then click Create to create the CA.

gcloud

  1. Create a CA pool for the subordinate CA:

    gcloud privateca pools create SUBORDINATE_POOL_ID
    

    Replace SUBORDINATE_POOL_ID with the name of the CA pool.

    For more information about creating CA pools, see Creating a CA pool.

    For more information about the gcloud privateca pools create command, see gcloud privateca pools create.

  2. Create a subordinate CA in the created CA pool.

    gcloud privateca subordinates create SUBORDINATE_CA_ID \
      --pool=SUBORDINATE_POOL_ID \
      --issuer-pool=POOL_ID \
      --key-algorithm="ec-p256-sha256" \
      --subject="CN=Example Server TLS CA, O=Example LLC"
    

    The following statement is returned when the subordinate CA is created.

    Created Certificate Authority [projects/my-project-pki/locations/us-west1/caPools/SUBORDINATE_POOL_ID/certificateAuthorities/SUBORDINATE_CA_ID].
    

    To see an exhaustive list of settings, run the following gcloud command:

    gcloud privateca subordinates create --help
    

    The command returns examples to create a subordinate CA whose issuer is either located on CA Service or located elsewhere.

Terraform

resource "google_privateca_certificate_authority" "root-ca" {
  pool = "ca-pool"
  certificate_authority_id = "my-certificate-authority-root"
  location = "us-central1"
  deletion_protection = false
  ignore_active_certificates_on_deletion = true
  config {
    subject_config {
      subject {
        organization = "HashiCorp"
        common_name = "my-certificate-authority"
      }
      subject_alt_name {
        dns_names = ["hashicorp.com"]
      }
    }
    x509_config {
      ca_options {
        # is_ca *MUST* be true for certificate authorities
        is_ca = true
      }
      key_usage {
        base_key_usage {
          # cert_sign and crl_sign *MUST* be true for certificate authorities
          cert_sign = true
          crl_sign = true
        }
        extended_key_usage {
          server_auth = false
        }
      }
    }
  }
  key_spec {
    algorithm = "RSA_PKCS1_4096_SHA256"
  }
}

resource "google_privateca_certificate_authority" "default" {
  // This example assumes this pool already exists.
  // Pools cannot be deleted in normal test circumstances, so we depend on static pools
  pool = "ca-pool"
  certificate_authority_id = "my-certificate-authority-sub"
  location = "us-central1"
  deletion_protection = "true"
  subordinate_config {
    certificate_authority = google_privateca_certificate_authority.root-ca.name
  }
  config {
    subject_config {
      subject {
        organization = "HashiCorp"
        common_name = "my-subordinate-authority"
      }
      subject_alt_name {
        dns_names = ["hashicorp.com"]
      }
    }
    x509_config {
      ca_options {
        is_ca = true
        # Force the sub CA to only issue leaf certs
        max_issuer_path_length = 0
      }
      key_usage {
        base_key_usage {
          digital_signature = true
          content_commitment = true
          key_encipherment = false
          data_encipherment = true
          key_agreement = true
          cert_sign = true
          crl_sign = true
          decipher_only = true
        }
        extended_key_usage {
          server_auth = true
          client_auth = false
          email_protection = true
          code_signing = true
          time_stamping = true
        }
      }
    }
  }
  lifetime = "86400s"
  key_spec {
    algorithm = "RSA_PKCS1_4096_SHA256"
  }
  type = "SUBORDINATE"
}

Creating a subordinate CA from an external CA

Creating a subordinate CA from an external CA is a three-step process. The first step is to create a CSR for this CA and download the CSR. Once you have the CSR, it needs to be signed by your external CA (specific instructions depend on your setup). Finally, you can use either the gcloud CLI command-line tool or the Google Cloud console to upload the signed PEM certificate chain. For more details, see the following example.

Step 1: Create a CSR

Console

  1. Visit the Security > Certificate Authority Service menu in Google Cloud console.

    Go to Certificate Authority Service

  2. Click the CA manager tab.

  3. Click Create CA.

Select CA type:

  1. Click Subordinate CA.
  2. In the Valid for field, enter the duration for which you want the certificates issued by the CA certificate to be valid.
  3. Click Root CA is external.
  4. Pick one of the available options for the CA Tier. For more information, see Workload-optimized tiers.
  5. Under Regionalization, select a CA location from the list.
  6. Click Next.
Configure CA subject name
  1. In the Organization (O) field, enter the name of your company.
  2. Optional: In the Organization unit (OU) field, enter the company subdivision or business unit.
  3. Optional: In the Country name field, enter a two letter country code.
  4. Optional: In the State or province name field, enter the name of your state.
  5. Optional: In the Locality name field, enter the name of your city.
  6. In the CA common name (CN) field, enter the CA name.
  7. In the Pool ID field, enter the CA pool name. You cannot change the CA pool after creating the CA.
  8. Click Next.
Configure CA key size and algorithm
  1. Choose the key algorithm that best meets your needs. For information about deciding the suitable key algorithm, see Choosing a key algorithm.
  2. Click Next.
Configure CA artifacts

The following steps are optional. If you skip these steps, the default settings apply.

  1. Choose whether you want to use a Google-managed or a self-managed Cloud Storage bucket.
  2. If you don't select a self-managed Cloud Storage bucket, CA Service creates a Google-managed bucket in the same location as the CA.

  3. Choose whether you want to disable the publication of certificate revocation lists (CRLs) and CA certificates to the Cloud Storage bucket.
  4. The publication of CRL and CA certificate on a Cloud Storage bucket is enabled by default. To disable these settings, click the toggles.

  5. Click Next.
Add labels

The following steps are optional.

If you want to add labels to the CA, do the following:

  1. Click Add item.
  2. In the Key 1 field, enter the label key.
  3. In the Value 1 field, enter the label value.
  4. If you want to add another label, click Add item. Then, add the label key and value as mentioned in steps 2 and 3.
  5. Click Next.
Review the settings

Carefully review all the settings, then click Create to create the CA.

Download the CSR

  1. On the Certificate authority page, select the CA you want to activate.
  2. Click Activate.
  3. In the dialog that opens, click Download CSR.

    Download the CSR of the CA.

gcloud

  1. To create a CA pool for the subordinate CA, run the following command. For more information, see Creating a CA pool.

    gcloud privateca pools create SUBORDINATE_POOL_ID
    

    Replace SUBORDINATE_POOL_ID with the name of the CA pool.

  2. To create a subordinate CA in the created CA pool, run the following gcloud command. The gcloud command also creates a CSR and saves it to FILE_NAME file.

    gcloud privateca subordinates create SUBORDINATE_CA_ID \
      --pool=SUBORDINATE_POOL_ID \
      --create-csr --csr-output-file=FILE_NAME \
      --key-algorithm="ec-p256-sha256" \
      --subject="CN=Example Server TLS CA, O=Example LLC"
    

    Replace the following:

    • SUBORDINATE_CA_ID: The unique identifier of the subordinate CA.
    • SUBORDINATE_POOL_ID: The name of the CA pool.
    • FILE_NAME: The name of the file where the PEM-encoded CSR is written.

    --key-algorithm flag takes the cryptographic algorithm that you want to use for creating a managed Cloud HSM key for the CA.

    --subject flag takes the X.501 name of the certificate subject.

    For more information about the gcloud privateca subordinates create command, see gcloud privateca subordinates create.

The following statement is returned when the CSR is created:

Created Certificate Authority [projects/my-project-pki/locations/us-west1/caPools/SUBORDINATE_POOL_ID/certificateAuthorities/SUBORDINATE_CA_ID] and saved CSR to FILE_NAME.

To see the exhaustive list of available settings, run the following command:

gcloud privateca subordinates create --help

If you lose the CSR, you can download it again using the following command:

gcloud privateca subordinates get-csr SUBORDINATE_CA_ID \
  --pool=SUBORDINATE_POOL_ID

Step 2: Sign the CSR

Pass the generated CSR file from step 1 to the member of your organization responsible for certificate issuance, and request that they sign it. The specific steps depend on your organization's setup.

You can experiment with a simple root CA using the following openssl commands:

Shell

Configure settings for the new root CA.

cat > root.conf <<- EOM
[ req ]
distinguished_name = req_distinguished_name
x509_extensions    = v3_ca
prompt             = no
[ req_distinguished_name ]
commonName = Sample Root
[ v3_ca ]
subjectKeyIdentifier=hash
basicConstraints=critical, CA:true
EOM

Create the new root CA.

openssl req -x509 -new -nodes -config root.conf -keyout rootCA.key \
  -days 3000 -out rootCA.crt -batch

Configure the extensions that must be added to the new subordinate CA certificate.

cat > extensions.conf <<- EOM
basicConstraints=critical,CA:TRUE,pathlen:0
keyUsage=critical,keyCertSign,cRLSign
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
EOM

Sign the subordinate CA's CSR with this root.

openssl x509 -req -in FILE_NAME -CA rootCA.crt -CAkey rootCA.key \
  -CAcreateserial -out subordinate.crt -days 1095 -sha256 -extfile extensions.conf

Concatenate the entire certificate chain into a single file.

cat subordinate.crt > chain.crt
cat rootCA.crt >> chain.crt

Step 3: Upload the signed certificate

To activate a subordinate CA using a signed certificate, do the following:

Console

  1. Go to the Certificate Authority Service page in the Google Cloud console.

    Go to Certificate Authority Service

  2. Click the CA manager tab.

  3. Under Certificate authorities, choose the CA you created in Step 1: Create CSR.

  4. Click Activate.

  5. In the dialog that opens, click Download CSR to download the PEM-encoded CSR file that the issuing CA can sign.

  6. Click Next.

  7. In the Upload Certificate Chain field, click Browse.

  8. Upload the signed certificate file with .crt extension.

  9. Click Activate.

gcloud

gcloud privateca subordinates activate SUBORDINATE_CA_ID \
  --pool=SUBORDINATE_POOL_ID \
  --pem-chain ./chain.crt

Replace the following:

  • SUBORDINATE_CA_ID: the unique identifier of the subordinate CA that you want to activate.
  • SUBORDINATE_POOL_ID: the name of the CA pool that contains the subordinate CA.

The --pem-chain flag is required. This flag takes the file containing the list of PEM-encoded certificates. The list of certificates starts with the current CA certificate and ends with the root CA certificate.

For more information about the gcloud privateca subordinates activate command, see gcloud privateca subordinates activate.

The following statement is returned when the signed certificate is uploaded:

Activated certificate authority [SUBORDINATE_CA_ID].

Enabling a subordinate CA

To enable a subordinate CA, do the following:

Console

  1. Go to the Certificate Authority Service page in the Google Cloud console.

    Go to Certificate Authority Service

  2. Click the CA manager tab.

  3. Under Certificate authorities, select the CA you want to activate.

  4. Click Activate.

  5. In the dialog that opens, click Download CSR to download the PEM-encoded CSR file that the issuing CA can sign.

  6. Click Next.

  7. In the Upload Certificate Chain field, click Browse.

  8. Upload the signed certificate file with .crt extension.

  9. Click Activate.

gcloud

To enable a newly created CA, run the following command:

gcloud privateca subordinates enable SUBORDINATE_CA_ID --pool=SUBORDINATE_POOL_ID

Replace the following:

  • SUBORDINATE_CA_ID: the unique identifier of the subordinate CA.
  • SUBORDINATE_POOL_ID: the name of the CA pool that contains the subordinate CA.

For more information about the gcloud privateca subordinates enable command, see gcloud privateca subordinates enable.

Cloning certificate authorities

To clone an existing CA to renew that CA, or to create a new CA with the same configuration, run the following command:

gcloud privateca roots create NEW_CA_ID --pool=POOL_ID \
  --from-ca=EXISTING_CA_ID \
  --key-algorithm "ec-p384-sha384"

Replace the following:

  • NEW_CA_ID: The unique identifier of the new CA.
  • POOL_ID: The name of the CA pool in which you want to create the new CA.

The --from-ca flag is supported for root and subordinate CA creation. The existing CA must be in the same CA pool as the new CA.

The --key-algorithm flag copies all CA configuration from the existing CA (except for the Cloud KMS key version and Cloud Storage bucket). However, you can still override any of the configuration values in the new CA by explicitly providing the appropriate flag. For example, you can still specify `--subject SUBJECT to use a new subject.

If you omit the --key-algorithm flag, the algorithm defaults to: - rsa-pkcs1-4096-sha256 for root CAs. - rsa-pkcs1-2048-sha256 for subordinate CAs.

For more information about this gcloud command, see gcloud privateca roots create.

What's next