# Google Cloud — load balancer with Certificate Manager

> A Cloud Run job started by Cloud Scheduler once a day updates the certificate in Certificate Manager in place, and the load balancer picks it up on its own.

URL: https://zrazu.com/en/docs/ssl-auto-gcp/

Use this for a Google Cloud external load balancer if the certificate is attached through **Certificate Manager** (a certificate map). Certificate Manager updates a certificate in place: bindings do not change. "Classic" load balancer certificates (`compute ssl-certificates`) cannot be updated in place — move the certificate to Certificate Manager.

Everything is done with commands in **Cloud Shell** (the `>_` button at the top of the Google Cloud console) — you do not need to install anything on your computer.

## What you need

- The certificate link from your account: `https://api.zrazu.com/ssl-pull/zsp_YOUR_TOKEN`.
- A private key without a password, the `key.pem` file. Upload it to Cloud Shell through the **⋮ → Upload** menu.
- The Owner or Editor role in the project.

## Step 1. The renewal script

In Cloud Shell open the editor with `nano zrazu-gcp-update.sh`, paste the text and save (Ctrl+O, Enter, Ctrl+X). If the certificate already exists in Certificate Manager under another name, change `CERT`; for a regional certificate, change `LOCATION`.

```sh file=zrazu-gcp-update.sh
#!/bin/sh
# ZRAZU: updates the certificate in Google Certificate Manager using the personal link. Runs once a day.
set -eu
PULL="https://api.zrazu.com/ssl-pull/zsp_YOUR_TOKEN"
CERT="zrazu-ssl"
LOCATION="global"
KEY=/zrazu-key/key.pem

cd /tmp
curl -fsS --retry 3 --max-time 60 -o new.pem "$PULL/fullchain.pem"
grep -q "BEGIN CERTIFICATE" new.pem || { echo "ZRAZU: not a certificate"; exit 1; }
current=$(gcloud certificate-manager certificates describe "$CERT" --location="$LOCATION" --format='value(pemCertificate)' | tr -d '\r\n ')
if [ "$current" = "$(tr -d '\r\n ' < new.pem)" ]; then echo "ZRAZU: unchanged"; exit 0; fi
gcloud certificate-manager certificates update "$CERT" --location="$LOCATION" --certificate-file=new.pem --private-key-file="$KEY" --quiet
echo "ZRAZU: updated"
```

## Step 2. The first certificate (if it is not in Certificate Manager yet)

```sh
curl -fsS -o fullchain.pem "https://api.zrazu.com/ssl-pull/zsp_YOUR_TOKEN/fullchain.pem"
gcloud certificate-manager certificates create zrazu-ssl --certificate-file=fullchain.pem --private-key-file=key.pem
```

Add it to the load balancer's certificate map (**Certificate Manager → Certificate maps**) if you have not yet.

## Step 3. The job and the schedule

Copy the whole block into Cloud Shell. You can change the job's region to the nearest one.

```sh
REGION=europe-west1
PROJECT=$(gcloud config get-value project)
SA=zrazu-ssl@$PROJECT.iam.gserviceaccount.com
gcloud services enable run.googleapis.com cloudscheduler.googleapis.com secretmanager.googleapis.com certificatemanager.googleapis.com
gcloud iam service-accounts create zrazu-ssl --display-name="ZRAZU SSL update"
gcloud secrets create zrazu-ssl-key --data-file=key.pem
gcloud secrets create zrazu-ssl-script --data-file=zrazu-gcp-update.sh
for s in zrazu-ssl-key zrazu-ssl-script; do gcloud secrets add-iam-policy-binding $s --member=serviceAccount:$SA --role=roles/secretmanager.secretAccessor; done
gcloud projects add-iam-policy-binding $PROJECT --member=serviceAccount:$SA --role=roles/certificatemanager.editor
gcloud run jobs create zrazu-ssl --region=$REGION --image=gcr.io/google.com/cloudsdktool/google-cloud-cli:stable --service-account=$SA --set-secrets=/zrazu-key/key.pem=zrazu-ssl-key:latest,/zrazu-script/update.sh=zrazu-ssl-script:latest --command=/bin/sh --args=/zrazu-script/update.sh --max-retries=1
gcloud run jobs add-iam-policy-binding zrazu-ssl --region=$REGION --member=serviceAccount:$SA --role=roles/run.invoker
gcloud scheduler jobs create http zrazu-ssl-daily --location=$REGION --schedule="17 4 * * *" --uri="https://run.googleapis.com/v2/projects/$PROJECT/locations/$REGION/jobs/zrazu-ssl:run" --http-method=POST --oauth-service-account-email=$SA
rm key.pem
```

The key is now only in Secret Manager, and it has been removed from Cloud Shell.

## Check

1. Run the job by hand: `gcloud run jobs execute zrazu-ssl --region=$REGION --wait`.
2. Log: **Cloud Run → Jobs → zrazu-ssl → Logs** — "updated" or "unchanged".
3. Site: [https://zrazu.com/tools/ssl/example.com/](https://zrazu.com/tools/ssl/example.com/). The Google load balancer may need up to a few minutes.

## If it did not work

- `PERMISSION_DENIED` — the service account was not given the role from step 3; repeat the matching line.
- An error about the key on `update` — the certificate was reissued with a new key: `gcloud secrets versions add zrazu-ssl-key --data-file=new-key.pem`.
- An error about names (SAN) — Certificate Manager updates a certificate only with the same list of domains. If the domains changed, create a new certificate and replace it in the certificate map.
- You changed the script — update the secret: `gcloud secrets versions add zrazu-ssl-script --data-file=zrazu-gcp-update.sh`.
