Skip to content

Commit

Permalink
Support secrets (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
abstrctn authored Sep 10, 2021
1 parent 6ac8785 commit a43280f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 31 deletions.
35 changes: 7 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,13 @@ steps:
environment:
VAR_1: "var01"
ANOTHER_ENV_VAR: "env_var_value"
secrets: # set environment variables or file path contents to a Secret Manager secret value
MY_SECRET: "my-secret:latest"
/mount/path: "mounted-secret:latest"
env_secret_api_key:
from_secret: api_key_prod
```

For usage in drone v0.8:
```
kind: pipeline
name: default
steps:
- name: deploy-using-new-drone-plugin-version
image: oliver006/drone-cloud-run:latest
pull: always
# plugin settings are top-level
action: deploy
service: my-api-service
deployment_image: org-name/my-api-service-image
memory: 512Mi
region: us-central1
allow_unauthenticated: true
svc_account: [email protected]
addl_flags:
clear-cloudsql-instances: ''
secrets:
- source: google_credentials
target: token
- source: api_key_prod
target: env_secret_api_key
```

### Updating traffic

You can optionally use the `update-traffic` action to change which revisions
Expand Down Expand Up @@ -115,4 +90,8 @@ in the [documentation](https://cloud.google.com/sdk/gcloud/reference/run/deploy)
the prefix `--` (eg. `--set-config-maps` becomes `set-config-maps`). If the flag doesn't
require any arguments, use `''` as the value.

## Drone version compatibility

Versions `0.3.0` and below of this plugin support `.drone.yml` syntax for either Drone v0.8 or Drone v1.0 and above.

Beginning with the `1.0.0` release, Drone v0.8 is no longer supported. This is due to naming conflicts in the config between configuring [Secret Manager secrets](https://cloud.google.com/run/docs/configuring/secrets) and [Drone Secrets](https://0-8-0.docs.drone.io/manage-secrets/).
23 changes: 21 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Config struct {
Memory string
Timeout string
Environment map[string]string
Secrets map[string]string
EnvSecrets []string

AdditionalFlags map[string]string
Expand Down Expand Up @@ -92,6 +93,12 @@ func parseConfig() (*Config, error) {
log.Printf("os.Getenv(PLUGIN_ENVIRONMENT): %s", envStr)
}

secretsStr := os.Getenv("PLUGIN_SECRETS")
if err := json.Unmarshal([]byte(secretsStr), &cfg.Secrets); err != nil && secretsStr != "" {
log.Printf("json.Unmarshal() err: %s", err)
log.Printf("os.Getenv(PLUGIN_SECRETS): %s", secretsStr)
}

addlFlagsStr := os.Getenv("PLUGIN_ADDL_FLAGS")
if err := json.Unmarshal([]byte(addlFlagsStr), &cfg.AdditionalFlags); err != nil && addlFlagsStr != "" {
log.Printf("json.Unmarshal() err: %s", err)
Expand Down Expand Up @@ -160,6 +167,9 @@ func CreateExecutionPlan(cfg *Config) ([]string, error) {
args = append(args, cfg.ServiceName)
args = append(args, "--image", cfg.ImageName)

// we're using ":||:" as the separator for args, let's hope no one puts that in an env or secret variable value
sep := ":||:"

if cfg.SvcAccount != "" {
args = append(args, "--service-account", cfg.SvcAccount)
}
Expand All @@ -171,13 +181,22 @@ func CreateExecutionPlan(cfg *Config) ([]string, error) {
e = append(e, fmt.Sprintf(`%s=%s`, k, v))
}

// we're using ":||:" as the separator for the args, let's hope no one puts that in an env variable value
sep := ":||:"
envStr := strings.Join(e, sep)
envStr = "^" + sep + "^" + envStr
args = append(args, "--set-env-vars", envStr)
}

if len(cfg.Secrets) > 0 {
e := make([]string, 0)
for k, v := range cfg.Secrets {
e = append(e, fmt.Sprintf(`%s=%s`, k, v))
}

secretsStr := strings.Join(e, sep)
secretsStr = "^" + sep + "^" + secretsStr
args = append(args, "--set-secrets", secretsStr)
}

// If --quiet and none selected, GCP defaults to --no-allow-unauthenticated
if cfg.AllowUnauthenticated {
args = append(args, "--allow-unauthenticated")
Expand Down
30 changes: 29 additions & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func TestParseAndRunConfig(t *testing.T) {
cfgExpectedProjectId string
cfgExpectedEnvSecrets []string
cfgExpectedEnvKeys []string
cfgExpectedSecrets map[string]string
planExpectedOk bool
planExpectedFlags []string
}{
Expand All @@ -105,7 +106,7 @@ func TestParseAndRunConfig(t *testing.T) {
},
{
cfgExpectedOk: true,
env: map[string]string{"PLUGIN_ACTION": "deploy", "PLUGIN_TOKEN": validGCPKey, "PLUGIN_ENVIRONMENT": `{"var_1":"var01","version":"d0c13cb8646875cf94387f0d3de4e92b85eee3b0"}`, "PLUGIN_SERVICE": "my-service", "PLUGIN_IMAGE": "my-image"},
env: map[string]string{"PLUGIN_ACTION": "deploy", "PLUGIN_TOKEN": validGCPKey, "PLUGIN_ENVIRONMENT": `{"VAR_1":"var01","VERSION":"d0c13cb8646875cf94387f0d3de4e92b85eee3b0"}`, "PLUGIN_SERVICE": "my-service", "PLUGIN_IMAGE": "my-image"},
cfgExpectedProjectId: "my-project-id",
cfgExpectedEnvKeys: []string{"VAR_1=var01", "VERSION=d0c13cb8646875cf94387f0d3de4e92b85eee3b0"},
planExpectedOk: true,
Expand All @@ -119,6 +120,25 @@ func TestParseAndRunConfig(t *testing.T) {
planExpectedOk: true,
},

// Test exposing secret as environment variable
{
cfgExpectedOk: true,
env: map[string]string{"PLUGIN_ACTION": "deploy", "PLUGIN_TOKEN": validGCPKey, "PLUGIN_SECRETS": `{"var_1":"secretname:latest"}`, "PLUGIN_SERVICE": "my-service", "PLUGIN_IMAGE": "my-image"},
cfgExpectedProjectId: "my-project-id",
cfgExpectedSecrets: map[string]string{"var_1": "secretname:latest"},
planExpectedFlags: []string{"--set-secrets", "^:||:^var_1=secretname:latest"},
planExpectedOk: true,
},
// Test exposing secret as file
{
cfgExpectedOk: true,
env: map[string]string{"PLUGIN_ACTION": "deploy", "PLUGIN_TOKEN": validGCPKey, "PLUGIN_SECRETS": `{"/mnt/path":"secretname:1"}`, "PLUGIN_SERVICE": "my-service", "PLUGIN_IMAGE": "my-image"},
cfgExpectedProjectId: "my-project-id",
cfgExpectedSecrets: map[string]string{"/mnt/path": "secretname:1"},
planExpectedFlags: []string{"--set-secrets", "^:||:^/mnt/path=secretname:1"},
planExpectedOk: true,
},

// test all the options to see if a proper execution plan is being created
{
cfgExpectedOk: true,
Expand Down Expand Up @@ -352,6 +372,14 @@ func TestParseAndRunConfig(t *testing.T) {
}
}

// for _, e := range tst.cfgExpectedSecrets {
for k, v := range tst.cfgExpectedSecrets {
found := v == cfg.Secrets[k]
if !found {
t.Errorf("missing secret: %s=%s, got: %#v", k, v, cfg.Secrets)
}
}

if !tst.cfgExpectedOk {
return
}
Expand Down

0 comments on commit a43280f

Please sign in to comment.