Requesting certificates

This topic describes how you can request a certificate from Certificate Authority Service, as well as how you can view issued certificates.

Overview

There are two ways to request a certificate from Certificate Authority Service:

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

Using a CSR

You would first need to generate a CSR. Once you have done that, continue with the procedure mentioned below.

Console

  1. In the Google Cloud Console, go to the Certificate Authority Service page.

    Go to Certificate Authority Service

  2. Find your CA under the CA Manager tab.

  3. Click the name of the CA you want to issue from.

  4. On the bottom of the CA details page, click Request a certificate.

  5. If you want to use a certificate template, select a template from the dropdown. For more information see Certificate templates.

  6. Click Provide CSR.

  7. Optionally, you can overwrite the automatically generated Certificate name.

  8. Optionally, you can configure validity period for certificate.

  9. Copy and paste your CSR to the Certificate CSR box or upload your CSR using the Browse button.

  10. Click Upload CSR.

  11. Click Next.

  12. Click Download Certificate or copy the certificate chain using the copy icon.

  13. Click Done.

gcloud

gcloud privateca certificates create CERT_ID \
     --issuer-pool POOL_ID \
     --csr CSR_FILENAME \
     --cert-output-file CERT_FILENAME \
     --validity "P30D"

Replace the following:

  • CERT_ID is the unique identifier of the certificate.
  • POOL_ID is the unique identifier of the CA pool that issues the certificate.
  • CSR_FILENAME is the file the stores the PEM-encoded CSR.

The --validity flag defines the duration the certificate is valid. It is an optional flag whose default value is 30 days.

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

Using an auto-generated key

Console

You can use Google Cloud Console to generate client or server TLS certificates.

  1. In the Google Cloud Console, go to the Certificate Authority Service page.

    Go to Certificate Authority Service

  2. Find your CA under the CA Manager tab.

  3. Click the name of the CA you want to issue from.

  4. On the bottom of the CA details page, click Request a certificate.

  5. If you want to use a certificate template, select a template from the dropdown. For more information, see Certificate templates.

  6. Navigate to Request Certificate tab.

  7. Click Enter details.

  8. Under Enter details:

    1. Keep the auto-generated Certificate name, or choose a different unique name.
    2. Under Add domain name, click Add Item.
    3. Enter a domain-name into the FQDN field.
    4. Check Server TLS and/or Client TLS depending on your use-case.
    5. Click Next.
  9. Under Configure key size and algorithm:

    1. Keep the default algorithm, or choose a different one from the drop-down. A new asymmetric key-pair is generated using the selected algorithm. For more information on which key algorithm to use, see Key Sizes and Algorithms.
    2. Click Continue.
  10. Under Download signed certificate:

    1. Select Download Certificate Chain to download the PEM-encoded certificate chain.
    2. Select Download Private Key to download the associated PEM-encoded private key.
    3. Click Done.

gcloud

To use the auto-generated key functionality, you need to install the Python Cryptographic Authority (PyCA) library. For instructions about installing the Pyca cryptography library, see Including the Pyca cryptography library.

To create a certificate, use the following gcloud command:

gcloud privateca certificates create \
  --issuer-pool POOL_ID \
  --generate-key \
  --key-output-file KEY_FILENAME \
  --cert-output-file CERT_FILENAME \
  --dns-san "DNS_NAME" \
  --use-preset-profile "leaf-server-tls"

Replace the following:

  • POOL_ID is the unique identifier of the CA pool.

The gcloud command mentions the following flags:

  • --generate-key flag generates a new RSA-2048 private key on your machine.
  • --key-output-file flag specifies the path where the generated private key file is written (in PEM format).
  • --cert-output-file flag specifies the path where the resulting PEM-encoded certificate chain file is written (ordered from end-entity to root).
  • --dns-san flag specifies one or more comma-separated DNS SANs.
  • --use-preset-profile flag specifies the certificate profile. For more information about certificate profiles, see Certificate profiles.

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

Code samples

Java


import com.google.api.core.ApiFuture;
import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.Certificate;
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.CreateCertificateRequest;
import com.google.cloud.security.privateca.v1.KeyUsage;
import com.google.cloud.security.privateca.v1.KeyUsage.ExtendedKeyUsageOptions;
import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions;
import com.google.cloud.security.privateca.v1.PublicKey;
import com.google.cloud.security.privateca.v1.PublicKey.KeyFormat;
import com.google.cloud.security.privateca.v1.Subject;
import com.google.cloud.security.privateca.v1.SubjectAltNames;
import com.google.cloud.security.privateca.v1.X509Parameters;
import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions;
import com.google.protobuf.ByteString;
import com.google.protobuf.Duration;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

public class CreateCertificate {

  public static void main(String[] args)
      throws InterruptedException, ExecutionException, IOException {
    // TODO(developer): Replace these variables before running the sample.

    // publicKeyBytes: Public key used in signing the certificates.
    // location: For a list of locations, see:
    // https://cloud.google.com/certificate-authority-service/docs/locations
    // pool_Id: Set a unique id for the CA pool.
    // certificateAuthorityName: The name of the certificate authority which issues the certificate.
    // certificateName: Set a unique name for the certificate.
    String project = "your-project-id";
    ByteString publicKeyBytes = ByteString.copyFrom(new byte[] {});
    String location = "ca-location";
    String pool_Id = "ca-pool_Id";
    String certificateAuthorityName = "certificate-authority-name";
    String certificateName = "certificate-name";

    createCertificate(
        project, location, pool_Id, certificateAuthorityName, certificateName, publicKeyBytes);
  }

  // Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
  // The public key used to sign the certificate can be generated using any crypto
  // library/framework.
  public static void createCertificate(
      String project,
      String location,
      String pool_Id,
      String certificateAuthorityName,
      String certificateName,
      ByteString publicKeyBytes)
      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()) {

      // commonName: Enter a title for your certificate.
      // orgName: Provide the name of your company.
      // domainName: List the fully qualified domain name.
      // certificateLifetime: The validity of the certificate in seconds.
      String commonName = "common-name";
      String orgName = "org-name";
      String domainName = "dns.your-domain.com";
      long certificateLifetime = 1000L;

      // Set the Public Key and its format.
      PublicKey publicKey =
          PublicKey.newBuilder().setKey(publicKeyBytes).setFormat(KeyFormat.PEM).build();

      SubjectConfig subjectConfig =
          SubjectConfig.newBuilder()
              // Set the common name and org name.
              .setSubject(
                  Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build())
              // Set the fully qualified domain name.
              .setSubjectAltName(SubjectAltNames.newBuilder().addDnsNames(domainName).build())
              .build();

      // Set the X.509 fields required for the certificate.
      X509Parameters x509Parameters =
          X509Parameters.newBuilder()
              .setKeyUsage(
                  KeyUsage.newBuilder()
                      .setBaseKeyUsage(
                          KeyUsageOptions.newBuilder()
                              .setDigitalSignature(true)
                              .setKeyEncipherment(true)
                              .setCertSign(true)
                              .build())
                      .setExtendedKeyUsage(
                          ExtendedKeyUsageOptions.newBuilder().setServerAuth(true).build())
                      .build())
              .setCaOptions(CaOptions.newBuilder().setIsCa(true).buildPartial())
              .build();

      // Create certificate.
      Certificate certificate =
          Certificate.newBuilder()
              .setConfig(
                  CertificateConfig.newBuilder()
                      .setPublicKey(publicKey)
                      .setSubjectConfig(subjectConfig)
                      .setX509Config(x509Parameters)
                      .build())
              .setLifetime(Duration.newBuilder().setSeconds(certificateLifetime).build())
              .build();

      // Create the Certificate Request.
      CreateCertificateRequest certificateRequest =
          CreateCertificateRequest.newBuilder()
              .setParent(CaPoolName.of(project, location, pool_Id).toString())
              .setCertificateId(certificateName)
              .setCertificate(certificate)
              .setIssuingCertificateAuthorityId(certificateAuthorityName)
              .build();

      // Get the Certificate response.
      ApiFuture<Certificate> future =
          certificateAuthorityServiceClient
              .createCertificateCallable()
              .futureCall(certificateRequest);

      Certificate response = future.get();
      // Get the PEM encoded, signed X.509 certificate.
      System.out.println(response.getPemCertificate());
      // To verify the obtained certificate, use this intermediate chain list.
      System.out.println(response.getPemCertificateChainList());
    }
  }
}

Python

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


def create_certificate(
    project_id: str,
    location: str,
    ca_pool_name: str,
    ca_name: str,
    certificate_name: str,
    common_name: str,
    domain_name: str,
    certificate_lifetime: int,
    public_key_bytes: bytes,
) -> None:
    """
    Create a Certificate which is issued by the Certificate Authority present in the CA Pool.
    The key used to sign the certificate is created by the Cloud KMS.

    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 a unique name for the CA pool.
        ca_name: the name of the certificate authority which issues the certificate.
        certificate_name: set a unique name for the certificate.
        common_name: a title for your certificate.
        domain_name: fully qualified domain name for your certificate.
        certificate_lifetime: the validity of the certificate in seconds.
        public_key_bytes: public key used in signing the certificates.
    """

    caServiceClient = privateca_v1.CertificateAuthorityServiceClient()

    # The public key used to sign the certificate can be generated using any crypto library/framework.
    # Also you can use Cloud KMS to retrieve an already created public key.
    # For more info, see: https://cloud.google.com/kms/docs/retrieve-public-key.

    # Set the Public Key and its format.
    public_key = privateca_v1.PublicKey(
        key=public_key_bytes,
        format_=privateca_v1.PublicKey.KeyFormat.PEM,
    )

    subject_config = privateca_v1.CertificateConfig.SubjectConfig(
        subject=privateca_v1.Subject(common_name=common_name),
        subject_alt_name=privateca_v1.SubjectAltNames(dns_names=[domain_name]),
    )

    # Set the X.509 fields required for the certificate.
    x509_parameters = privateca_v1.X509Parameters(
        key_usage=privateca_v1.KeyUsage(
            base_key_usage=privateca_v1.KeyUsage.KeyUsageOptions(
                digital_signature=True,
                key_encipherment=True,
            ),
            extended_key_usage=privateca_v1.KeyUsage.ExtendedKeyUsageOptions(
                server_auth=True,
                client_auth=True,
            ),
        ),
    )

    # Create certificate.
    certificate = privateca_v1.Certificate(
        config=privateca_v1.CertificateConfig(
            public_key=public_key,
            subject_config=subject_config,
            x509_config=x509_parameters,
        ),
        lifetime=duration_pb2.Duration(seconds=certificate_lifetime),
    )

    # Create the Certificate Request.
    request = privateca_v1.CreateCertificateRequest(
        parent=caServiceClient.ca_pool_path(project_id, location, ca_pool_name),
        certificate_id=certificate_name,
        certificate=certificate,
        issuing_certificate_authority_id=ca_name,
    )
    result = caServiceClient.create_certificate(request=request)

    print("Certificate creation result:", result)

Performing common operations with certificates

This section describes how you can perform certain common operations with certificates.

Issue a certificate from a specific CA in a CA pool

gcloud

To target a specific CA in the CA pool for certificate issuance, add the --ca flag with the CA_ID of the CA that must issue the certificate.

gcloud privateca certificates create \
  --issuer-pool POOL_ID \
  --ca CA_ID \
  --generate-key \
  --key-output-file KEY_FILENAME \
  --cert-output-file CERT_FILENAME \
  --dns-san "DNS_NAME" \
  --use-preset-profile "leaf-server-tls"

Console

The Google Cloud Console only supports certificate issuance from a particular CA. Use the instructions in the Use an auto-generated Key section or the Use a CSR section to choose the CA that must issue the certificate.

View issued certificates

Console

  1. In the Google Cloud Console, go to the Certificate Authority Service page.

    Go to Certificate Authority Service

  2. Pick your target CA under the CA Manager tab.

  3. Click the CA name

  4. On the bottom of the CA details page, click the View Issued Certificates button to see the list of issued certificates. A custom view with the specified CA and CA pool IDs is displayed.

gcloud

To list all certificates issued by a particular CA in a CA pool, use the following gcloud command:

gcloud privateca certificates list --issuer-pool ISSUER_POOL --ca CA_NAME

For more information about the gcloud privateca certificates list command, see gcloud privateca certificates list.

To list all certificates across all CAs in a given location, use the following gcloud command:

gcloud privateca certificates list --location LOCATION

Code samples

Java


import com.google.cloud.security.privateca.v1.CaPoolName;
import com.google.cloud.security.privateca.v1.Certificate;
import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient;
import java.io.IOException;

public class ListCertificates {

  public static void main(String[] args) throws 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: Id of the CA pool which contains the certificates to be listed.
    String project = "your-project-id";
    String location = "ca-location";
    String pool_Id = "ca-pool-id";
    listCertificates(project, location, pool_Id);
  }

  // List Certificates present in the given CA pool.
  public static void listCertificates(String project, String location, String pool_Id)
      throws 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()) {

      CaPoolName caPool =
          CaPoolName.newBuilder()
              .setProject(project)
              .setLocation(location)
              .setCaPool(pool_Id)
              .build();

      // Retrieve and print the certificate names.
      System.out.println("Available certificates: ");
      for (Certificate certificate :
          certificateAuthorityServiceClient.listCertificates(caPool).iterateAll()) {
        System.out.println(certificate.getName());
      }
    }
  }
}

Python


import google.cloud.security.privateca_v1 as privateca_v1


def list_certificates(
    project_id: str,
    location: str,
    ca_pool_name: str,
) -> None:
    """
    List Certificates present in the given CA 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: name of the CA pool which contains the certificates to be listed.
    """

    caServiceClient = privateca_v1.CertificateAuthorityServiceClient()

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

    # Retrieve and print the certificate names.
    print(f"Available certificates in CA pool {ca_pool_name}:")
    for certificate in caServiceClient.list_certificates(parent=ca_pool_path):
        print(certificate.name)

View details for a single certificate

Console

  1. In the Google Cloud Console, go to the Certificate Authority Service page.

    Go to Certificate Authority Service

  2. Pick your target CA under the CA Manager tab.

  3. Click the CA name.

  4. On the bottom of the CA details page, click View issued certificates to see the list of issued certificates. A custom view with the specified CA and Pool IDs is displayed.

  5. Pick a specific certificate and select the ellipse icon.

  6. Click Download Certificate.

gcloud

To show the full description of a certificate, use the following gcloud command:

gcloud privateca certificates describe CERT_NAME \
    --issuer-pool POOL_ID

For more information about the gcloud privateca certificates describe command, see gcloud privateca certificates describe.

To export the PEM-encoded X.509 certificate chain and to a file, use the following gcloud command:

gcloud privateca certificates export CERT_NAME \
    --issuer-pool POOL_ID \
    --include-chain \
    --output-file certificate-file

For more information about the gcloud privateca certificates export command, see gcloud privateca certificates export.

Reference

Proof-of-possession for certificates

Proof-of-possession of the private key ensures that the requester of a certificate holds the private key for that certificate. CA Service checks proof-of-possession only if the requester provides a PKCS #10 CSR according to RFC 2986. Proof-of-possession for other forms of certificate requests, such as requests by CertificateConfig is not enforced.

It is the responsibility of client applications that accept certificates to validate whether the certificate holder possesses the private key of that certificate. Enforcing proof-of-possession checks during certificate issuance is a form of defense-in-depth to protect again misbehaving clients. The existence of such clients, regardless of whether proof-of-possession is checked by the CA, could constitute a security vulnerability.

What's next