Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
avaly committed Dec 22, 2020
0 parents commit 51cca9c
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
steps:
- label: ":shell: Shellcheck"
plugins:
shellcheck#v1.1.2:
files: hooks/**

- label: ":sparkles:"
plugins:
plugin-linter#v2.0.0:
id: avaly/gcp-secret-manager

- label: ":docker: :hammer:"
plugins:
docker-compose#v3.7.0:
run: tests
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# GCP Secret Manager Buildkite Plugin

Use secrets from GCP Secret Manager in your environment variables.

This plugin requires a Google Cloud credentials file to be available on your Buildkite Agent machines.

Other preinstalled requirements:

- `gcloud`
- `jq`

## Example

Add the following to your `pipeline.yml`:

```yml
steps:
- command: 'echo \$SECRET_VAR'
plugins:
- avaly/gcp-secret-manager#v1.0.0:
credentials_file: /etc/gcloud-credentials.json
env:
SECRET_VAR: my-secret-name
OTHER_SECRET_VAR: my-other-secret-name
```
## Configuration
### `credentials_file` (Required, string)

The file path of a Google Cloud credentials file, which is used to access the secrets. The account of the credentials file needs to have the Secret Manager Secret Accessor role (`roles/secretmanager.secretAccessor`).

### `env` (object)

An object defining the export variables names and the secret names which will populate the values.

## Developing

To run the tests:

```shell
docker-compose run --rm shellcheck
docker-compose run --rm tests
```

## Contributing

1. Fork the repo
2. Make the changes
3. Run the tests
4. Commit and push your changes
5. Send a pull request
18 changes: 18 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '2'
services:
tests:
image: buildkite/plugin-tester
volumes:
- ".:/plugin:ro"

lint:
image: buildkite/plugin-linter
command: ['--id', 'avaly/gcp-secret-manager']
volumes:
- ".:/plugin:ro"

shellcheck:
image: koalaman/shellcheck-alpine:latest
command: ['shellcheck', '/plugin/hooks/environment']
volumes:
- ".:/plugin:ro"
88 changes: 88 additions & 0 deletions hooks/environment
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash

set -euo pipefail

echo "--- :googlecloud::key: Reading secrets from GCP Secret Manager"

initialized=""

function initialize() {
if [[ "${initialized}" -eq "1" ]]; then
return
fi

local result;
local path;

path=$(which gcloud)
result=$?
if [[ $result -ne 0 ]]; then
echo "gcloud binary is not available in \$PATH"
exit 1
fi

# shellcheck disable=SC2034
path=$(which jq)
result=$?
if [[ $result -ne 0 ]]; then
echo "jq binary is not available in \$PATH"
exit 1
fi

gcloud auth activate-service-account --key-file "${BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_CREDENTIALS_FILE}"

initialized="1"
}

function load_secret_into_env() {
local export_name="$1"
local secret_name="$2"
local secret_value

secret_value="$(get_secret_value "${secret_name}")"

echo "Exporting secret ${secret_name} from GCP Secret Manager into environment variable ${export_name}"

export "${export_name}=${secret_value}"
}

function get_secret_value() {
local secret_name="$1"
local secret_version
local secret_value

secret_version=$(gcloud secrets versions list "${secret_name}" --format=json | jq -r '.[0].name')
secret_version="${secret_version##*/}"

local result=$?
if [[ $result -ne 0 ]]; then
exit 1
fi

secret_value=$(gcloud secrets versions access "${secret_version}" \
--secret="${secret_name}" \
--format='get(payload.data)' | tr '_-' '/+' | base64 -d)

result=$?
if [[ $result -ne 0 ]]; then
exit 1
fi

echo "${secret_value}"
}

function strip_quotes() {
echo "${1}" | sed "s/^[[:blank:]]*//g;s/[[:blank:]]*$//g;s/[\"']//g"
}

# Parse env items
while IFS='=' read -r name _ ; do
if [[ $name =~ ^(BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_ENV_) ]] ; then
initialize

export_name="${name//BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_ENV_/}"
secret_name="$(strip_quotes "${!name}")"

load_secret_into_env "${export_name}" "${secret_name}"
fi
done < <(env | sort)
13 changes: 13 additions & 0 deletions plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: GCP Secret Manager
description: Read secrets from Google Cloud Secret Manager
author: https://github.com/avaly/gcp-secret-manager-buildkite-plugin
requirements:
- gcloud
- jq
configuration:
properties:
credentials_file:
type: string
env:
type: object
additionalProperties: false
30 changes: 30 additions & 0 deletions tests/environment.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bats

load "$BATS_PATH/load.bash"

environment_hook="$PWD/hooks/environment"

@test "Fetches values from GCP Secret Manager into env" {
export BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_CREDENTIALS_FILE="/tmp/credentials.json"
export BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_ENV_TARGET1="secret1"

stub which \
"gcloud : echo /test/gcloud" \
"jq : echo /test/jq"

stub gcloud \
"auth activate-service-account --key-file /tmp/credentials.json : echo OK" \
"secrets versions list secret1 --format=json : echo '[{\"name\":\"secret1/versions/10\"}]'" \
"secrets versions access 10 --secret=secret1 '--format=get(payload.data)' : echo 'dGVzdC12YWx1ZTEK'"

run "${environment_hook}"

assert_success
assert_output --partial "Exporting secret secret1 from GCP Secret Manager into environment variable TARGET1"

unstub gcloud
unstub which

unset BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_CREDENTIALS_FILE
unset BUILDKITE_PLUGIN_GCP_SECRET_MANAGER_ENV_TARGET1
}

0 comments on commit 51cca9c

Please sign in to comment.