Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wardviaene committed Apr 25, 2020
0 parents commit 62fe721
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/gcloud-load-secrets-*
/gcloud-load-secrets
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
BINARY = gcloud-load-secrets
GOARCH = amd64

all: build-linux build-darwin

build-linux:
CGO_ENABLED=0 GOOS=linux GOARCH=${GOARCH} go build -a -installsuffix cgo ${LDFLAGS} -o ${BINARY}-linux-${GOARCH} cmd/${BINARY}/main.go

build-darwin:
CGO_ENABLED=0 GOOS=darwin GOARCH=${GOARCH} go build -a -installsuffix cgo ${LDFLAGS} -o ${BINARY}-darwin-${GOARCH} cmd/${BINARY}/main.go

clean:
rm -f ${BINARY}-linux-${GOARCH}

9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Google Cloud load secrets
Execute binary with secrets loaded as environment variables

## Usage
Run bash command and inject environment variables that start with "myapp"
```
export GOOGLE_APPLICATION_CREDENTIALS=credentials.json
./gcloud-load-secrets-darwin-amd64 -prefix myapp -cmd '/bin/bash -c ls -ahl' -debug true
```
68 changes: 68 additions & 0 deletions cmd/gcloud-load-secrets/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"flag"
"fmt"
"log"
"os"
"strings"
"syscall"

gcloudSecrets "github.com/in4it/gcloud-load-secrets/pkg/gcloud/secrets"
)

func main() {

var (
secretsPrefix string
cmd string
debug bool
)
flag.StringVar(&secretsPrefix, "prefix", "", "prefix to use when retrieving secrets")
flag.StringVar(&cmd, "cmd", "", "execute command")
flag.BoolVar(&debug, "debug", false, "enable debug output")

flag.Parse()

if cmd == "" {
fmt.Printf("missing required -cmd argument/flag\n")
os.Exit(2)
}

readSecrets, err := gcloudSecrets.NewReadSecrets()

if err != nil {
panic(err)
}

secrets, err := readSecrets.ListSecrets(secretsPrefix)
if err != nil {
panic(err)
}
secretsWithVersion, err := readSecrets.GetSecretsValue(secrets)
if err != nil {
panic(err)
}
if debug {
for _, v := range secretsWithVersion {
fmt.Printf("[debug] secrets: %s %s\n", v.Name, v.Payload)
}
}
execCommand(cmd, readSecrets.GetKV(secrets))
}

func execCommand(input string, secrets []string) {
var (
args []string
env []string
command string
)
args = strings.Split(input, " ")
command = args[0]
env = append(os.Environ(), secrets...)

err := syscall.Exec(command, args, env)
if err != nil {
log.Println(err)
}
}
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/in4it/gcloud-load-secrets

go 1.14

require (
cloud.google.com/go v0.54.0
github.com/golang/mock v1.4.2
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
google.golang.org/api v0.20.0
google.golang.org/genproto v0.0.0-20200305110556-506484158171
)
269 changes: 269 additions & 0 deletions go.sum

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions pkg/gcloud/secrets/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package secrets

import (
"context"
"fmt"
"strings"

secretmanager "cloud.google.com/go/secretmanager/apiv1"
"golang.org/x/oauth2/google"
"google.golang.org/api/iterator"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
)

type Secret struct {
Name string
ID string
Version string
Payload string
}

type ReadSecrets struct {
Client *secretmanager.Client
ProjectID string
}

func NewReadSecrets() (*ReadSecrets, error) {
ctx := context.Background()
c, err := secretmanager.NewClient(ctx)
if err != nil {
return nil, err
}
credentials, err := google.FindDefaultCredentials(ctx)
if err != nil {
panic(err)
}
return &ReadSecrets{
Client: c,
ProjectID: credentials.ProjectID,
}, nil
}

func (r *ReadSecrets) ListSecrets(secretsPrefix string) ([]Secret, error) {
ctx := context.Background()

req := &secretmanagerpb.ListSecretsRequest{
Parent: fmt.Sprintf("projects/%s", r.ProjectID),
}
it := r.Client.ListSecrets(ctx, req)
secrets := []Secret{}
for {
resp, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return secrets, err
}
secretElements := strings.Split(resp.Name, "/")
if len(secretElements) < 4 {
return secrets, fmt.Errorf("secret name in unexpected format: %s", resp.Name)
}
secretName := strings.Join(secretElements[3:], "/")
if strings.HasPrefix(secretName, secretsPrefix) {
secrets = append(secrets, Secret{ID: resp.Name, Name: secretName})
}
}
return secrets, nil
}

func (r *ReadSecrets) GetSecretsValue(secrets []Secret) ([]Secret, error) {
ctx := context.Background()

for k, secret := range secrets {
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: fmt.Sprintf("%s/versions/latest", secret.ID),
}
resp, err := r.Client.AccessSecretVersion(ctx, req)
if err != nil {
return secrets, err
}
secrets[k].Payload = string(resp.Payload.Data)
}
return secrets, nil
}

func (r *ReadSecrets) GetKV(secrets []Secret) []string {
ret := []string{}
for _, secret := range secrets {
ret = append(ret, fmt.Sprintf("%s=%s", secret.Name, secret.Payload))
}
return ret
}

0 comments on commit 62fe721

Please sign in to comment.