5
votes

I'm trying to create a Cloud Build trigger where secret environment variables are encrypted with cloud KMS and stored as a substitution variable in Cloud Build. This way my cloud build yaml is fairly generic and the same across all environments we're deploying to.

This cloud build yaml works fine:

steps:
- name: 'ubuntu'
  entrypoint: 'bash'
  args: ['-c', 'echo "$$APP_NAME HAS A VALUE $$HELLO_WORLD"']
  env:
    - 'APP_NAME=${_APP_NAME}'
  secretEnv:
    - 'HELLO_WORLD'
secrets:
- kmsKeyName: 'projects/my-first-cicd-project/locations/europe-west1/keyRings/keyring-dev/cryptoKeys/key-backend'
  secretEnv:
    HELLO_WORLD: xxxxxxxxxxx

The build steps produce this log line:

My App Name HAS A VALUE Hello there world!

Exactly as intended.

Now for the thing that doesn't work, or at least I can't get to work. Let's say I want to make the keyring name dynamic. I'd then replace "keyring-dev" in that yaml to ${_KMS_KEYRING_NAME}. This will produce an error like:

invalid build: failed to check access to "projects/my-first-cicd-project/locations/europe-west1/keyRings/${_KMS_KEYRING_NAME}/cryptoKeys/key-backend"

If I change the base64 string in the YAML (Starting with "CiQAH...") to a substitution variable like ${_KMS_VAR_HELLO_WORLD}, I'll get this error:

failed unmarshalling build config cloudbuild.yaml: illegal base64 data at input byte 0

FYI: the value of that base64 string does not exceed the maximum amount of characters of 255 for a variable value.

So my guess is, Cloud Build does not substitute anything in the secrets section of cloudbuild.yaml. Does anyone know a solution to this?

3
Hi there. I'm able to reproduce this on my end, so I can verify that you're not alone. I'm checking with the team internally to see if this is a bug or an oversight in the documentation.sethvargo

3 Answers

4
votes

This is a known limitation of the API.

  • Substitutions applies to "string" field, although secret values are using "bytes" field. Thus, we can not apply substitution values to them.
  • Regarding Keyring names and project, changing them alters the encrypted content and the content is not substitutable.
1
votes

It is a limitation of the cloudbuild secrets api, but I've used a work-around that involves decrypting the secrets in build steps and goes as follows:

steps:
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
    - -c
    - |
      export HELLO_WORLD=$(echo -n $_ENC_HELLO_WORLD | \
        base64 -d - | \
        gcloud kms decrypt \
          --ciphertext-file - \
          --plaintext-file - \
          --project $PROJECT_ID \
          --location global \
          --keyring $_KMS_KEYRING_NAME \
          --key key-backend \
      )

      echo "$_APP_NAME has a value $$HELLO_WORLD"
0
votes

For what it's worth I've found that it appears that the auto-decrypted value seems to be implicitly injected as a bash variable.

For example, if I have the following script:

entrypoint: 'bash'
args: ['bin/hello.sh']
secretEnv:
- foo

Where hello.sh is defined as:

#!/usr/bin/env bash
echo $foo

Suppose the decrypted value is "bar" — I'm finding that by not passing in the CLI argument explicitly in args it's actually working, lol.