Skip to content

Commit

Permalink
Feat/conjur (#195)
Browse files Browse the repository at this point in the history
* feat: add conjur provider

Signed-off-by: Antoine Miquel <[email protected]>
Signed-off-by: antoinemiquel <[email protected]>
  • Loading branch information
antoinemiquel authored Jan 21, 2024
1 parent 9548bcc commit b752901
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 0 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ It supports various backends including:
- CredHub(Coming soon)
- Pulumi State
- Kubernetes
- Conjur

- Use `vals eval -f refs.yaml` to replace all the `ref`s in the file to actual values and secrets.
- Use `vals exec -f env.yaml -- <COMMAND>` to populate envvars and execute the command.
Expand Down Expand Up @@ -220,6 +221,7 @@ Please see the [relevant unit test cases](https://github.com/helmfile/vals/blob/
- [Doppler](#doppler)
- [Pulumi State](#pulumi-state)
- [Kubernetes](#kubernetes)
- [Conjur](#conjur)

Please see [pkg/providers](https://github.com/helmfile/vals/tree/master/pkg/providers) for the implementations of all the providers. The package names corresponds to the URI schemes.

Expand Down Expand Up @@ -748,6 +750,23 @@ Examples:
> NOTE: This provider only supports kind "Secret" or "ConfigMap" in apiVersion "v1" at this time.
### Conjur
This provider retrieves the value of secrets stored in [Conjur](https://www.conjur.org/).
It's based on the https://github.com/cyberark/conjur-api-go lib.
The following env vars have to be configured:
- `CONJUR_APPLIANCE_URL`
- `CONJUR_ACCOUNT`
- `CONJUR_AUTHN_LOGIN`
- `CONJUR_AUTHN_API_KEY`
- `ref+conjur://PATH/TO/VARIABLE[?address=CONJUR_APPLIANCE_URL&account=CONJUR_ACCOUNT&login=CONJUR_AUTHN_LOGIN&apikey=CONJUR_AUTHN_API_KEY]/CONJUR_SECRET_ID`
Example:
- `ref+conjur://branch/variable_name`
## Advanced Usages
### Discriminating config and secrets
Expand Down
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go-v2 v1.21.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 // indirect
Expand All @@ -70,10 +71,13 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 // indirect
github.com/aws/smithy-go v1.14.2 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cyberark/conjur-api-go v0.11.1 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
Expand All @@ -84,6 +88,7 @@ require (
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.1.0 // indirect
Expand Down Expand Up @@ -143,6 +148,7 @@ require (
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/urfave/cli v1.22.14 // indirect
github.com/zalando/go-keyring v0.2.3-0.20230503081219-17db2e5354bd // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
Expand Down
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/a8m/envsubst v1.3.0 h1:GmXKmVssap0YtlU3E230W98RWtWCyIZzjtf1apWWyAg=
github.com/a8m/envsubst v1.3.0/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
Expand Down Expand Up @@ -119,6 +121,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 h1:CQBFElb0LS8RojMJlxRSo/HXipvT
github.com/aws/aws-sdk-go-v2/service/sts v1.21.5/go.mod h1:VC7JDqsqiwXukYEDjoHh9U0fOJtNWh04FPQz4ct4GGU=
github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ=
github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
Expand All @@ -140,6 +144,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyberark/conjur-api-go v0.11.1 h1:vjaMkw0geJsA+ikMM6UDLg4VLFQWKo/B0i9IWlOQ1f0=
github.com/cyberark/conjur-api-go v0.11.1/go.mod h1:n1p46Hj9l8wkZjM17cVYdfcatyPboWyioLGlC0QszCs=
github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -185,6 +193,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
Expand Down Expand Up @@ -417,6 +427,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zalando/go-keyring v0.2.3-0.20230503081219-17db2e5354bd h1:D+eeEnOlWcMXbwZ5X3oy68nHafBtGcj1jMKFHtVdybY=
github.com/zalando/go-keyring v0.2.3-0.20230503081219-17db2e5354bd/go.mod h1:sI3evg9Wvpw3+n4SqplGSJUMwtDeROfD4nsFz4z9PG0=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
Expand Down Expand Up @@ -483,6 +495,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
91 changes: 91 additions & 0 deletions pkg/providers/conjur/conjur.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package conjur

import (
"fmt"
"os"

"github.com/cyberark/conjur-api-go/conjurapi"
"github.com/cyberark/conjur-api-go/conjurapi/authn"

"github.com/helmfile/vals/pkg/api"
"github.com/helmfile/vals/pkg/log"
)

type provider struct {
client *conjurapi.Client
log *log.Logger

Address string
Account string
Login string
Apikey string
}

func New(l *log.Logger, cfg api.StaticConfig) *provider {
p := &provider{
log: l,
}
p.Address = cfg.String("address")
if p.Address == "" {
p.Address = os.Getenv("CONJUR_APPLIANCE_URL")
}
p.Account = cfg.String("account")
if p.Account == "" {
p.Account = os.Getenv("CONJUR_ACCOUNT")
}
p.Login = cfg.String("login")
if p.Login == "" {
p.Login = os.Getenv("CONJUR_AUTHN_LOGIN")
}
p.Apikey = cfg.String("apikey")
if p.Apikey == "" {
p.Apikey = os.Getenv("CONJUR_AUTHN_API_KEY")
}

return p
}

func (p *provider) GetString(varId string) (string, error) {
cli, err := p.ensureClient()
if err != nil {
return "", fmt.Errorf("cannot create Conjur Client: %v", err)
}

secretValue, err := cli.RetrieveSecret(varId)
if err != nil {
return "", fmt.Errorf("no variable found for path %q", varId)
}

return string(secretValue), nil
}

func (p *provider) GetStringMap(path string) (map[string]interface{}, error) {
return nil, fmt.Errorf("this provider does not support values from URI fragments")
}

func (p *provider) ensureClient() (*conjurapi.Client, error) {
if p.client == nil {
config, err := conjurapi.LoadConfig()
if err != nil {
p.log.Debugf("conjur: cannot get conjur config")
return nil, err
}

config.ApplianceURL = p.Address
config.Account = p.Account

cli, err := conjurapi.NewClientFromKey(config,
authn.LoginPair{
Login: p.Login,
APIKey: p.Apikey,
},
)
if err != nil {
p.log.Debugf("conjur: connection failed")
return nil, err
}

p.client = cli
}
return p.client, nil
}
134 changes: 134 additions & 0 deletions pkg/providers/conjur/conjur_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package conjur

import (
"testing"

"github.com/cyberark/conjur-api-go/conjurapi"
"github.com/stretchr/testify/assert"

"github.com/helmfile/vals/pkg/config"
"github.com/helmfile/vals/pkg/log"
)

func Test_New(t *testing.T) {
testsConfig := []struct {
name string
options map[string]interface{}
envVars map[string]string
want *provider
}{
{
name: "onlyConf",
options: map[string]interface{}{
"address": "http://127.0.0.1",
"account": "myAccount",
"login": "user",
"apikey": "pass",
},
envVars: map[string]string{},
want: &provider{
log: log.New(log.Config{}),
Address: "http://127.0.0.1",
Account: "myAccount",
Login: "user",
Apikey: "pass",
},
},
{
name: "onlyEnvVars",
options: map[string]interface{}{},
envVars: map[string]string{
"CONJUR_APPLIANCE_URL": "http://127.0.0.1",
"CONJUR_ACCOUNT": "myAccount",
"CONJUR_AUTHN_LOGIN": "user",
"CONJUR_AUTHN_API_KEY": "pass",
},
want: &provider{
log: log.New(log.Config{}),
Address: "http://127.0.0.1",
Account: "myAccount",
Login: "user",
Apikey: "pass",
},
},
{
name: "mixConfigAndEnvVars",
options: map[string]interface{}{
"address": "http://127.0.0.1",
"account": "myAccount",
"login": "user",
"apikey": "pass",
},
envVars: map[string]string{
"CONJUR_APPLIANCE_URL": "http://192.168.0.10",
"CONJUR_ACCOUNT": "myAccount2",
"CONJUR_AUTHN_LOGIN": "user2",
"CONJUR_AUTHN_API_KEY": "pass2",
},
want: &provider{
log: log.New(log.Config{}),
Address: "http://127.0.0.1",
Account: "myAccount",
Login: "user",
Apikey: "pass",
},
},
}

for _, tt := range testsConfig {
t.Run(tt.name, func(t *testing.T) {
conf := config.Map(tt.options)
logger := log.New(log.Config{})

for k, v := range tt.envVars {
t.Setenv(k, v)
}

p := New(logger, conf)

assert.EqualValues(t, tt.want, p)

// cleanup envVars
for k := range tt.envVars {
t.Setenv(k, "")
}
})
}
}

func Test_GetStringMap(t *testing.T) {
options := map[string]interface{}{
"address": "http://127.0.0.1",
"account": "myAccount",
"login": "user",
"apikey": "pass",
}
conf := config.Map(options)
logger := log.New(log.Config{})

p := New(logger, conf)

mapRes, err := p.GetStringMap("somePath")

assert.Empty(t, mapRes)
assert.Error(t, err)
}

func Test_ensureClient(t *testing.T) {
options := map[string]interface{}{
"address": "http://127.0.0.1",
"account": "myAccount",
"login": "user",
"apikey": "pass",
}
conf := config.Map(options)
logger := log.New(log.Config{})

p := New(logger, conf)
p.client = &conjurapi.Client{}

cli, err := p.ensureClient()

assert.Equal(t, p.client, cli)
assert.NoError(t, err)
}
3 changes: 3 additions & 0 deletions pkg/stringprovider/stringprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/helmfile/vals/pkg/providers/awskms"
"github.com/helmfile/vals/pkg/providers/awssecrets"
"github.com/helmfile/vals/pkg/providers/azurekeyvault"
"github.com/helmfile/vals/pkg/providers/conjur"
"github.com/helmfile/vals/pkg/providers/doppler"
"github.com/helmfile/vals/pkg/providers/gcpsecrets"
"github.com/helmfile/vals/pkg/providers/gcs"
Expand Down Expand Up @@ -67,6 +68,8 @@ func New(l *log.Logger, provider api.StaticConfig) (api.LazyLoadedStringProvider
return gkms.New(l, provider), nil
case "k8s":
return k8s.New(l, provider)
case "conjur":
return conjur.New(l, provider), nil
}

return nil, fmt.Errorf("failed initializing string provider from config: %v", provider)
Expand Down
Loading

0 comments on commit b752901

Please sign in to comment.