Sectigo GCP Certificate Management solution

Overview

The Sectigo GCP Certificate Management tool (SectigoGCPCM) is a serverless solution created as a Google Cloud function to provide a secure automation layer for managing Sectigo issued SSL/TLS certificates on Google Cloud Platform (GCP). In Google Cloud terms, this is called "self-managed SSL certificates".

Self-managed SSL certificates are certificates that you obtain, provision, and renew either manually or through automation from your own Certificate Authority (CA) or a third party CA. SectigoGCPCM is an automation tool that facilitates the automatic certificate management of certificates issued by a Sectigo private or public CA. The SectigoGCPCM can obtain the following types of SSL/TLS certificates:

  • Domain Validation (DV)

  • Organization Validation (OV)

  • Extended Validation (EV) certificates

The SectigoGCPCM acts as a Registration Authority (RA) that verifies and authenticates the Google Cloud Function which connects to the Sectigo CA backend to create a self-managed SSL certificate resource.

Once the Sectigo certificates are available on the Load balancing  Advanced menu  Certificates tab of the Google Cloud Console, they can be used to enable HTTPS communication on GCP load balancers for secure endpoints connection. This tool also supports automatic certificate renewal before the certificate expiry or upon revocation.

Scope

This guide covers instructions on connecting to the Sectigo ACME servers and uploading certificates to the Certificate tab of the Google Cloud Console. Configuring the certificates on load balancers for SSL/TLS enablement is outside the scope of this guide.

Assumptions

It is assumed that customers will use their own script(s) to associate an SSL/TLS certificate with a target load balancer. Example scripts for Terraform and Ansible are provided for customer reference.

Audience

This guide is intended for IT administrators and system administrators who have knowledge of IT Security, Cloud Security, Google Cloud Platform, and are also familiar with Sectigo Certificate Manager (SCM).

Architecture

Sectigo GCPCM architecture

The SectigoGCPCM tool execution is controlled using the GCP resource policies. Only the specified principals (typically IAM user or role) can invoke it.

Users of this tool are responsible for configuring the SectigoGCPCM, with information about each ACME account that will be used. Each account is identified by an alias. Some configuration information, such as external account binding (EAB) parameters, can be collected from SCM. The configuration parameters will be explained in detail. When enrolling certificates using SectigoGCPCM, users control which ACME account settings to use for enrollment, by passing the ACME account alias as a parameter.

Since SectigoGCPCM uses Certbot as the ACME client, the current iteration of the product only allows EAB information corresponding to one ACME account to be used for each ACME endpoint. You can define multiple aliases for the same ACME account, to control other parameters, such as the key size.

SectigoGCPCM is installed in a specific region, but provisioned certificates have a global scope.

SectigoGCPCM supports only the pre-validated domains in Sectigo Certificate Manager (SCM). The domains for which certificates are requested should go through Domain Control Validation (DCV) in SCM as per the instructions provided in Section 6.4.2 How To Validate Domains of the SCM Administrator Guide. For more information on DCV methods, see Domain Control Validation Methods in Sectigo’s Knowledge Base.

Deploying SectigoGCPCM

Deploy the Cloud Function to GCP with Terraform CLI

The following diagram illustrates the steps to deploy the SectigoGCPCM Cloud Function to GCP with Terraform CLI (the terraform command line tool).

Deploying the SectigoGCPCM Cloud Function
Nested module structure is preferred, one module per resource.

Module list

  • cloud_storage: A Cloud Storage bucket that securely stores the acme-account.yaml file and the SectigoGCPCM source code files

  • cloud_function: A Cloud Function that provides core enroll/renew actions via Python code

  • cloud_scheduler: A cronjob scheduler to force renew certificates after the specified time interval

GCP resources used by SectigoGCPCM

Resource Name Description

google_storage_bucket

A Cloud Storage bucket for storing the acme-accounts.yaml file

google_storage_bucket_object

A zip archive that contains the Python code

google_cloudfunctions_function

A Cloud Function for running the code

google_cloudfunctions_function_iam_member

The IAM member that has the permission to invoke the function.

google_service_account

A service account for invoking the function

google_project_iam_member

The proper role for the service account

google_cloud_scheduler_job

A Cloud Scheduler cronjob for invoking the function

Installing SectigoGCPCM

Installation script

Installation is provided as a bash(sh) script. The script supports multi-region installation of SectigoGCPCM. The number of regions is not limited. The script also creates the backend configuration.

The installation script does the following during execution:

  • Checks the GCP credentials (for Terraform), GCP project, and GOOGLE_APPLICATION_CREDENTIALS environment variable (for the Google Cloud CLI)

  • Configures a Cloud Storage bucket for the Terraform backend configuration and for the acme_accounts.yaml file and the SectigoGCPCM source code files

  • Configures the workspace

  • Executes Terraform commands

The script will create the following items on GCP for the certificate management to work seamlessly:

  • Install configuration file(s) and source code files in the Cloud Storage bucket

  • Install the Cloud Function module

  • Install the Cloud Scheduler module for logging and auto-renewal

  • Enable the IAM SA for accessing the Cloud Function trigger

A Cloud Storage bucket will be created for the backend configuration of Terraform. When you run terraform init for the first time, Terraform will create the first state file in the bucket. For every subsequent action (apply, change, destroy), these state files will be updated. Terraform needs access to that bucket for proper operation. If the .terraform.lock.hcl file is removed accidentally, run terraform init again.

Prerequisites

The following requirements must be met before running the script:

  • GCP account: An active GCP account

  • Client machine: A client machine to install the Terraform script and Google Cloud CLI. Both Windows and Linux are supported.

  • ACME account: An ACME account from SCM (the ACME URL and EAB values)

  • Terraform script: If you encounter any problems during the script installation, please contact Sectigo Support or the Onboarding Team.

  • Terraform CLI: The SectigoGCPCM solution is deployed using the Terraform CLI commands. For Terraform installation instructions, see Install Terraform.

    • Terraform: v1.1.4+

    • Google provider: v4.7.0

  • Google Cloud CLI: Google Cloud CLI (the gcloud command) is used to invoke the Cloud Function. It is also used in the install.sh and destroy.sh scripts.

    The acme-account.yaml file is uploaded to a bucket in Cloud Storage—​this file contains EAB information for the ACME accounts, which is sensitive data and must be protected. Use the gcloud command to edit or redeploy the file. You can also work with the file using the Google Cloud Console.

    For the Google Cloud CLI installation instructions, see Recommended installation.

  • Authentication with GCP: After installing Google Cloud CLI and before executing the script, you must Authenticate with your GCP account using a valid service account key file.

  • GCP project ID: If you have multiple projects in your GCP account, specify the ID of the project where SectigoGCPCM will be deployed.

    gcloud projects list                     # retrieves a list of your projects
    gcloud config set project <project_id>   # sets the `project` property in the core section

Authenticate with your GCP account

  1. Create a service account:

    1. Go to the Create service account page in the Cloud Console.

    2. Select your project.

    3. In the Service account name field, enter a name. The Cloud Console generates a Service account ID based on this name. Edit the ID if necessary. You cannot change the ID later.

    4. (Optional) In the Service account description field, enter a description.

    5. Click Create and continue to proceed to the next step and set access controls.

  2. Grant IAM roles to your service account in Project  Owner:

    1. In the Select a role list, select the basic Owner role or click Add another role and add these roles:

      • roles/cloudfunctions.admin: Cloud Functions Admin

      • roles/storage.admin: Storage Admin

      • roles/compute.loadBalancerAdmin: Compute Load Balancer Admin

      • roles/cloudscheduler.admin: Cloud Scheduler Admin

      • roles/iam.serviceAccountCreator: Create Service Accounts

    2. Click Continue.

    3. Click Done to finish creating the service account.

  3. Create and download a service account key file:

    1. In the Cloud Console, click the email address for your service account.

    2. Click Keys.

    3. Click Add key, then click Create new key.

    4. Click Create. A JSON key file will be downloaded to your computer.

    5. Click Close.

  4. Authorize access to Google Cloud with the service account.

    gcloud auth activate-service-account \
    --key-file=<full_path_to_the_service_account_key_file>
  5. Set the environment variable to provide authentication credentials for Terraform.

    export GOOGLE_APPLICATION_CREDENTIALS=<full_path_to_the_service_account_key_file>

Pre-installation

The following steps must be performed before running the script:

  1. Extract the contents of the SectigoGCPCM.zip archive to the current path.

  2. Navigate to the ./sectigo_gcpcm_iac directory.

  3. Give the execute permission to the install.sh file using the chmod +x install.sh command.

A bucket for the Terraform backend configuration will be created in Cloud Storage via install.sh in the default region. You can run gcloud config get-value functions/region to find out the default region. The backend bucket will not be changed (created) again for the same region.

Installation

Execute the install.sh file in your shell to run the installation script. You can install the script for a default or specific region, including multiple regions.

  • Default region

  • Specific region

Run ./install.sh (if you have not provided the execute permission to the script, run bash install.sh). The script will install SectigoGCPCM to your default GCP region. The script does the following:

  • Creates a backend Cloud Storage bucket in the default region and initializes state files in this bucket.

  • Creates a Cloud Storage bucket for the acme_accounts.yaml file and SectigoGCPCM source code files in the default region.

  • Creates the Terraform workspace with the same name as the GPCP region.

  • Executes terraform plan && terraform apply.

Run ./install.sh <region-name>. For example, to install SectigoGCPCM to the us-east1 region, you would run ./install.sh us-east1. For multiple regions installation, repeat this step for each region. The script does the following:

  • Creates a backend Cloud Storage bucket in a specific region and initializes state files in this bucket.

  • Creates a Cloud Storage bucket for the acme_accounts.yaml file and SectigoGCPCM source code files in a specific region.

  • Creates the Terraform workspace with the same name as the GCP region.

  • Executes terraform plan && terraform apply.

Post-installation

After the script has executed, GCP resources will be created with a specific naming convention to allow for multi-region installation. The script appends the region-name to all resource names. For example, if you install SectigoGCPCM in the us-central1 region, then the GCP resources will be given the following names:

  • Cloud Function: SectigoGCPCM-us-central1

  • Cloud Storage bucket: sectigo-gcp-cm-us-central1-$date (the bucket’s name must be unique, therefore a timestamp is appended)

  • HTTP trigger: us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1

GCP resources names

After installing SectigoGCPCM, the names of all important resources will be printed out to your console (the Cloud Function name, the URL of the Cloud Storage bucket, the trigger URL for an HTTP function, and more). Make sure to write the Cloud Function name correctly when you invoke the function for your region.

gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "enroll, " "domains": "<your_domain>", "account": "<account_name>"}' \
--format=json

The logs will be stored in the install-<region>.log (created by SectigoGCPCM) and terraform-install.txt (created by Terraform) files. The <region> part of the log filename indicates the region where the resources were installed.

Uninstallation

To uninstall SectigoGCPCM, you can either run terraform destroy manually or have the resources destroyed automatically by our destroy.sh script. We recommend using the script, which automatically deletes all GCP components that are used for SectigoGCPCM.

The script also supports destroying resources in a specific region (other than the default one) or multiple regions. For example, if you have two separate instances of SectigoGCPCM in different GCP regions and you want to uninstall only one, run the script with the region name as an argument.

Make sure to give execute permission to the destroy.sh file using the chmod +x destroy.sh command.

./destroy.sh                   # destroy with the default region
./destroy.sh <region name>     # destroy with a specific region

The logs will be stored in the terraform-destroy.txt file. The install-<region>.log file will be removed after destroying resources.

Using SectigoGCPCM

Locating the ACME account information and EAB keys

After creating an ACME account in SCM, you can register an ACME agent of your choice with the Sectigo ACME server. You will need the External Account binding (EAB) information--Key ID and HMAC Key, for agent configuration.

To obtain these values:

  1. Log in to SCM at https://cert-manager.com/customer/<customer_uri> with your credentials.

  2. Expand the left pane and navigate to Enrollment > ACME.

  3. On the ACME page, select your ACME URL, and click Accounts.

  4. Select your account and click Details.

EAB details

Configuring the acme_accounts.yaml file

Make sure to validate your YAML file using a YAML validator—​for example, Code Beautify. If you are getting a 200 status code response, but the tool is not performing the requested operation, it is likely that there’s a YAML syntax error in your file.

The acme_accounts.yaml file contains the following fields.

Field Description

<account_name>

An alias for your ACME account. This value will identify the ACME account when invoking SectigoGCPCM.

acme-endpoint

The ACME URL

eab-hmac-key

The HMAC key

eab-key

The key ID

email

Your email address, which will be used when enrolling certificates via ACME

RenewBeforeDays

If certificateExpirationDate-RenewBeforeDays >= currentDate, then the certificate will be renewed during the script execution with the renewal action

KeyType

The key type which will be used for certificate enrollment. Can be RSA or ECDSA.

KeySize

The key size which will be used for certificate enrollment. Google Cloud supports only 2048 (RSA-2048) and P-256 (ECDSA P-256) for SSL/TLS certificates for load balancers.

Using SectigoGCPCM with the Google Cloud CLI

The following are example commands for enrolling and renewing certificates using the Google Cloud CLI.

By default, GCP allows enrolling or renewing of up to 10 certificates in a single call. If you need more than 10 certificates, please contact GCP support. If an attempt is made to enroll a certificate for a domain that already has a certificate, the name of the existing certificate will be returned.

Enroll a certificate for a domain

  • Default region

  • Specific region

gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "enroll", "domains": "ccmqa.com", "account": "demo2"}' \
--format=json
gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "enroll", "domains": "ccmqa.com", "account": "demo2"}' \
--format=json \
--region=us-central1

Enroll multi-domain (SAN) and wildcard certificates

  • Default region

  • Specific region

gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "enroll", "domains": "*.ccmqa.com,d2.ccmqa.com,d3.ccmqa.com", \
"account": "demo2"}' \
--format=json
gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "enroll", "domains": "*.ccmqa.com,d2.ccmqa.com,d3.ccmqa.com", \
"account": "demo2"}' \
--format=json \
--region=us-central1

The following image shows a list of provisioned certificates on the Certificate tab of the Google Cloud Console.

Issued certificates in GCP

Renew revoked certificates for a specific alias

  • Default region

  • Specific region

gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "renew", "account": "d365_tuesday"}' \
--format=json
gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "renew", "account": "d365_tuesday"}' \
--format=json \
--region=us-central1

Renew all revoked certificates (for all aliases)

  • Default region

  • Specific region

gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "renew"}' \
--format=json
gcloud functions call SectigoGCPCM-us-central1 \
--data '{"action": "renew"}' \
--format=json \
--region=us-central1

Using SectigoGCPSCM with an HTTPS endpoint

The following are example commands for enrolling and renewing certificates using an HTTPS request.

By default, GCP allows enrolling or renewing of up to 10 certificates in a single call. If you need more than 10 certificates, please contact GCP support. If an attempt is made to enroll a certificate for a domain that already has a certificate, the name of the existing certificate will be returned.

Enroll a certificate for a domain

  • Default region

  • Specific region

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"enroll","account":"demo2","domains":"ccmqa.com"}'
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"enroll","account":"demo2","domains":"ccmqa.com"}' \
--region=us-central1

Enroll multi-domain (SAN) and wildcard certificates

  • Default region

  • Specific region

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"enroll","account":"demo2","domains":"d1.ccmqa.com,d2.ccmqa.com"}'
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"enroll","account":"demo2","domains":"d1.ccmqa.com,d2.ccmqa.com"}' \
--region=us-central1

The following image shows a list of provisioned certificates on the Certificate tab of the Google Cloud Console.

Issued certificates in GCP

Renew revoked certificates for a specific alias

  • Default region

  • Specific region

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"renew","account":"demo2"}'
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"renew","account":"demo2"}' \
--region=us-central1

Renew all revoked certificates (for all aliases)

  • Default region

  • Specific region

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"renew"}'
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
'https://us-central1-local-project-340815.cloudfunctions.net/SectigoGCP-us-central1' \
-H "Content-Type:application/json" \
--data '{"action":"renew"}' \
--region=us-central1

Notes

  • Duplicate certificates for a specific domain are not allowed for a specific ACME account alias.

  • Multiple aliases can be defined for the same ACME account.

  • If you need different key sizes, you can create two aliases with the needed key sizes.

  • Make sure the signature algorithm of the server certificate matches the CA certificate. For example, the RSA server certificate should have the RSA CA chain, and the ECDSA server certificate should have the ECDSA CA chain. Please contact Sectigo support for more details.

Enabling auto-renewal and logging using Cloud Scheduler

The Cloud Scheduler service allows you to create a cronjob that will invoke a Cloud Function on a schedule. You can integrate Cloud Scheduler with SectigoGCPCM to trigger the Cloud Function that will check the certificate expiry status on a schedule. There are three ways to enable auto-renewal and logging:

  • set up a cronjob in Cloud Scheduler automatically using Terraform

  • set up a cronjob in Cloud Scheduler manually in the web interface

  • set up a cronjob on your Linux machine

Creating a cronjob with Terraform

You can set up a cronjob in Cloud Scheduler automatically using Terraform. For this, specify your own values for the google_cloud_schedulerjob resource block in the Terraform file and deploy it with the terraform init command.

resource "google_cloud_scheduler_job" "cloud_function_cronjob" {
    name         = var.scheduler_name
    description  = "CronJob for renew certificates"
    schedule     = "0 0 1 * *"
    http_target {
        http_method = "POST"
        uri = var.http_trigger
        body = base64encode("{\"action\":\"forcerenew\",\"account\":\"rsa_2048\"}")
        oidc_token {
            service_account_email = "${google_service_account.scheduler_sa.email}"
        }
        headers = {
            Content-Type = "application/json"
        }
    }
}

The following is a breakdown of this resource block:

  • name: The name of the Cloud Scheduler job

  • schedule: The interval at which certificates will be renewed (the value in the sample file means the Cloud Function will be triggered on the first day of every month at 12:00 AM)

  • uri: The trigger URL for invoking the Cloud Function with an HTTP request

  • body: The data that will be sent in the body of an HTTP request to trigger the Cloud Function

  • service_account_email: The service account that provides permission for Cloud Scheduler to invoke the Cloud Function.

Creating a cronjob in in the web interface

You can set up a cronjob manually in the Cloud Scheduler web interface:

  1. Log in to the Cloud Scheduler console.

  2. Click Create a job.

  3. Give a name to the job and select the Region.

  4. Define the schedule for the job in Frequency. For example, the string 0 0 1 * * will trigger the Cloud Function on the first day of every month at 12:00 AM.

  5. Select the timezone to be used for the job schedule.

    Define the schedule in Cloud Scheduler
  6. Click Continue.

  7. Select HTTP in the Target type.

  8. Specify the HTTP trigger URL.

  9. Select POST as the HTTP method.

  10. Specify Body for an HTTP request.

  11. Select Add OIDC token in Auth header.

  12. Select the Service account that has permission to invoke the Function.

  13. Other tabs are optional and you may skip them.

  14. Click Create to confirm the settings and create the job.

    Configure the execution in Cloud Scheduler

Creating a cronjob on your Linux machine

You can set up a cronjob on your Linux machine which will call the Cloud Function on a schedule, using the gcloud command:

  1. Run crontab -e on the terminal.

  2. Add a cronjob that will trigger the Cloud Function.

    0 0 1 * * gcloud functions call SectigoGCPCM-us-central1 \
    --data '{"action":"forcerenew","account":"rsa_2048"}'
  3. Save the changes and exit.

Provisioning certificates for load balancers

The SectigoGCPCM_https_lb_example and SectigoGCPCM_ssl_lb_example archives contain Terraform sample configuration for provisioning and attaching certificates to external HTTP(S) load balancers and SSL proxy load balancers.

Add the external data source configuration to your main Terraform module. The data source will trigger the enroll.sh script that calls the Cloud Function to enroll a certificate and attach it to the target proxy for the load balancer. The README.md file in the archive provides instructions on using the external data source.

The following is a sample data source configuration.

// Data source for enrolling a certificate
data "external" "example" {
  program = ["/bin/bash","./enroll.sh","sectigohttpslb.ccmqa.com"]
}

output cert_name {
  value = "${data.external.example.result.result}"
}

// Target HTTPS proxy for the load balancer
resource "google_compute_target_https_proxy" "default" {
  depends_on = [
    data.external.example
  ]
  name             = "example-target-proxy"
  url_map          = google_compute_url_map.default.id
  ssl_certificates = ["${data.external.example.result.result}"]
}