Manage Google Maps API keys with the Google Cloud SDK (gcloud)

To manage cloud infrastructure I’m a huge fan of Terraform. Unfortunately I noticed that it’s not possible to use Terraform for managing API Keys for Google Maps (and other services). After some digging I found that the alpha version of the Google Cloud SDK has support for it.

Commands available in the stable gcloud release:

describe                Describe an API key's metadata.
list                    Lists API keys.

Commands available in the alpha gcloud release:

clone                   *(ALPHA)*  Create a new API key with the same
                              metadata as input key.
create                  *(ALPHA)*  Create an API key.
delete                  *(ALPHA)*  Delete an API key.
describe                *(ALPHA)*  Describe an API key's metadata.
get-key-string          *(ALPHA)*  Get key string of an API key.
list                    *(ALPHA)*  Lists API keys.
lookup                  *(ALPHA)*  Look up resource name of a key string.
undelete                *(ALPHA)*  Undelete an API key.
update                  *(ALPHA)*  Update an API key's metadata.

Aha, that’s more like it!

~

To create an API key use gcloud alpha services api-keys create. A basic API Key for uses the Map JavaScript API can be created with this command:

gcloud alpha services api-keys create \
    --display-name="My Google Maps Key" \
    --api-target=service=maps_backend \
    --allowed-referrers="https://bram.us/*,https://*.bram.us/*"

Note that this API key requires the maps-backend.googleapis.com API to be active for your GCP project:

gcloud alpha services enable maps-backend.googleapis.com

The other gcloud alpha services api-keys subcommands are pretty straightforward.

~

One thing that did require some more tweaking was the ability to extract the key string for an existing key using the Key’s Display Name. The “problem” is that get-key-string only accepts a Key Id, not a Display Name.

To work around that I nested the gcloud alpha services api-keys list call (to find the Key Id based on the Display Name) inside a gcloud alpha services api-keys get-key-string call, along with some grep and cut magic.

gcloud alpha services api-keys get-key-string \
    "$( \
        gcloud alpha services api-keys list \
        --filter DISPLAY_NAME:"My Google Maps Key" \
        | grep "projects/" \
        | cut -d ' ' -f1\
    )" \
    | cut -d ' ' -f2

(Replace My Google Maps Key with the Display Name of your key)

~

To integrate this a bit more nicely with Terraform I whipped up this little shell script:

# Extract gc-project value from Terraform environments file
TF_WORKSPACE=`terraform workspace show`
GC_PROJECT=`cat "./environments/$TF_WORKSPACE.json" | grep '"gc-project"' | cut -d '"' -f4`

# Name of the Key to create
KEY_NAME="My Google Maps Key"

# Get ID for the key.
KEY_ID=`gcloud alpha services api-keys list --filter DISPLAY_NAME:"$KEY_NAME" --project="$GC_PROJECT" | grep "projects/" | cut -d ' ' -f1`

# No Key ID Found
# ~> Key does not exist yet
# ~> Create it + Output the Key String
if [ -z "$KEY_ID" ]; then

    echo -e "\033[33m♺\033[0m Creating Key '$KEY_NAME'"

    gcloud alpha services api-keys create \
        --project="$GC_PROJECT" \
        --display-name="$KEY_NAME" \
        --api-target=service=maps_backend \
        --allowed-referrers="https://bram.us/*,https://*.bram.us/*" \
        &> /dev/null

    KEY_ID=`gcloud alpha services api-keys list --filter DISPLAY_NAME:"$KEY_NAME" --project="$GC_PROJECT" | grep "projects/" | cut -d ' ' -f1`
    KEY_STRING=`gcloud alpha services api-keys get-key-string "$KEY_ID" --project="$GC_PROJECT" | cut -d ' ' -f2`

    echo -e "\033[32m✓\033[0m Created key '$KEY_NAME'. Key String = $KEY_STRING"

# Key ID found
# ~> Output the Key String
else
    KEY_STRING=`gcloud alpha services api-keys get-key-string "$KEY_ID" --project="$GC_PROJECT" | cut -d ' ' -f2`
    echo -e "\033[32m✓\033[0m Key '$KEY_NAME' already exists. Key String = $KEY_STRING"
fi

Note that I’ve written this script to be run in conjunction with Terraform using our specific code structure. On the first few lines you can see that it extracts the value for GC_PROJECT from a JSON file that’s named after the Terraform Workspace.

Created keys won’t be stored in Terraform’s state. However, the code is written in such a way that successive runs will not create a new key nor overwrite the existing one. Note that this check to see if a key exists is only a superficial check, as it does not check the key’s settings (such as api-target) — Only the Display Name is checked.

To not have to run this script on the site, you can execute it using a local-exec

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.