Skip to content

Commit

Permalink
improved a series of features
Browse files Browse the repository at this point in the history
  • Loading branch information
Mads Schou-Andreasen committed Mar 4, 2021
1 parent a36aac0 commit 7a27e46
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FALLBACK_IDENTIFIER=VALUE
BOTH_IDENTIFIER=ENV
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
test:
go test -race ./...

test.cover:
go test -race -coverprofile=coverage.out ./...
#go tool cover -func=coverage.out
go tool cover -html=coverage.out
67 changes: 56 additions & 11 deletions fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package gcpsecretfetch

import (
"fmt"
"github.com/joho/godotenv"
"github.com/panjf2000/ants/v2"
"github.com/pkg/errors"
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
"log"
"os"
"reflect"
"sync"
)
Expand Down Expand Up @@ -34,15 +37,17 @@ type params struct {
// then dispatching calls to get the secret payloads from GCP for the corresponding secrets.
// The function must be passed a pointer to an arbitrary config struct, and
// the config struct must only have string fields.
func InitializeConfig(cfg interface{}, project string) error {
func InitializeConfig(cfg interface{}, project string, envFileAction EnvFileAction) error {

grabber, err := newClient(project)
defer grabber.client.Close()

if err != nil {
return err
}

t := reflect.TypeOf(cfg)
if t.Kind() == reflect.Struct {

if t.Kind() != reflect.Ptr {
return errors.New("cfg argument must be a pointer to a struct")
}

Expand All @@ -53,16 +58,44 @@ func InitializeConfig(cfg interface{}, project string) error {

var wg sync.WaitGroup

c := make(chan error, s.NumField())
type errorStruct struct {
err error
name string
}

if envFileAction != DISABLE {
err := godotenv.Load()
if err != nil {
//return errors.New("Error loading .env file. If you dont want to use .env files, then specify `DISABLE` as envFileAction.")
log.Print("Error loading .env file. If you dont want to use .env files, then specify `DISABLE` as envFileAction.")
}
}

c := make(chan errorStruct, s.NumField())

p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
defer wg.Done()
p := i.(params)
err := grabber.setValue(p)

if err != nil {
c <- err
secret := os.Getenv(p.name)

if envFileAction == PRIORITIZE && secret != "" {
grabber.setValueLiteral(p, secret)
return
}

err := grabber.setValueFromGcp(p)
if err == nil {
return
}
wg.Done()

if envFileAction == FALLBACK && secret != "" {
grabber.setValueLiteral(p, secret)
return
}

c <- errorStruct{err, p.name}

})
defer ants.Release()

Expand Down Expand Up @@ -91,15 +124,15 @@ func InitializeConfig(cfg interface{}, project string) error {
close(c)

for err := range c {
if err != nil {
return err
if err.err != nil {
return err.err
}
}

return nil
}

func (svc *secretClient) setValue(p params) error {
func (svc *secretClient) setValueFromGcp(p params) error {
secretString, err := svc.accessSecretVersion(p.name)
if err != nil {
return err
Expand All @@ -108,3 +141,15 @@ func (svc *secretClient) setValue(p params) error {
p.v.SetString(secretString)
return nil
}

func (svc *secretClient) setValueLiteral(p params, secretString string) {
p.v.SetString(secretString)
}

type EnvFileAction string

const (
PRIORITIZE EnvFileAction = "prioritize"
DISABLE EnvFileAction = "disable"
FALLBACK EnvFileAction = "fallback"
)
127 changes: 127 additions & 0 deletions fetch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package gcpsecretfetch

import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)

const GCP_PROJECT = "ob-playground"

func TestInitializeConfig(t *testing.T) {

type config struct {
SECRET_IDENTIFIER string
FALLBACK_IDENTIFIER string
}

var cfg config

err := InitializeConfig(&cfg, GCP_PROJECT, PRIORITIZE)
assert.NoError(t, err)
assert.Equal(t, cfg.FALLBACK_IDENTIFIER, "VALUE")
assert.Equal(t, cfg.SECRET_IDENTIFIER, "SECRET_VALUE")

}

func TestMissingSecret(t *testing.T) {

type config struct {
MISSING_SECRET string
}

var cfg config

err := InitializeConfig(&cfg, GCP_PROJECT, PRIORITIZE)
assert.Error(t, err)

}

func TestInitializeConfigMissing(t *testing.T) {

type config struct {
SECRET_IDENTIFIER string
FALLBACK_IDENTIFIER string
}

var cfg config

err := InitializeConfig(&cfg, GCP_PROJECT, DISABLE)
assert.Error(t, err)

}

func TestInitializeConfigEnvPrioritize(t *testing.T) {

type config struct {
BOTH_IDENTIFIER string
}

var cfg config

err := InitializeConfig(&cfg, GCP_PROJECT, PRIORITIZE)
assert.NoError(t, err)
assert.Equal(t, cfg.BOTH_IDENTIFIER, "ENV")

err = InitializeConfig(&cfg, GCP_PROJECT, FALLBACK)
assert.NoError(t, err)
assert.Equal(t, cfg.BOTH_IDENTIFIER, "GCP")

}

func TestSetSecrets(t *testing.T) {

err := UpdateSecrets(GCP_PROJECT, map[string]string{"SECRET_IDENTIFIER": "SECRET_VALUE", "BOTH_IDENTIFIER": "GCP"}, true)
assert.NoError(t, err)

}

func TestBadProjectUpdate(t *testing.T) {

err := UpdateSecrets("bad-project-name-alkdjwopiunhauwihd", map[string]string{"SECRET_IDENTIFIER": "SECRET_VALUE", "BOTH_IDENTIFIER": "GCP"}, true)
assert.Error(t, err)

}

func TestBadProjectInitialize(t *testing.T) {

type config struct {
BOTH_IDENTIFIER string
}

var cfg config

err := InitializeConfig(&cfg, "aawdwadawdawdwaawdawdawdawd", DISABLE)
assert.Error(t, err)
fmt.Println(cfg)
}

func TestNotAPointer(t *testing.T) {

type config struct {
BOTH_IDENTIFIER string
}
var cfg config
err := InitializeConfig(cfg, "bad-project-name-alkdjwopiunhauwihd", FALLBACK)
assert.Error(t, err)

}

func TestNotAStruct(t *testing.T) {

err := InitializeConfig("cfg", "bad-project-name-alkdjwopiunhauwihd", FALLBACK)
assert.Error(t, err)

}

func TestStructWithNonStringField(t *testing.T) {

type config struct {
BOTH_IDENTIFIER string
INTFIELD int
}
var cfg config
err := InitializeConfig(cfg, "bad-project-name-alkdjwopiunhauwihd", FALLBACK)
assert.Error(t, err)

}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ go 1.15

require (
cloud.google.com/go v0.70.0
github.com/davecgh/go-spew v1.1.1
github.com/joho/godotenv v1.3.0
github.com/panjf2000/ants/v2 v2.4.3
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20201026091529-146b70c837a4 // indirect
google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
Expand Down
3 changes: 3 additions & 0 deletions set_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ func (svc *secretClient) listVersions(name string) ([]*secretmanagerpb.SecretVer

func (svc *secretClient) deletePrior(versions []*secretmanagerpb.SecretVersion) error {
for _, v := range versions {
if v.State == secretmanagerpb.SecretVersion_DESTROYED {
continue
}
req := &secretmanagerpb.DestroySecretVersionRequest{Name: v.Name}
_, err := svc.client.DestroySecretVersion(svc.ctx, req)
if err != nil {
Expand Down

0 comments on commit 7a27e46

Please sign in to comment.