1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Merge branch 'external-secrets:main' into main

This commit is contained in:
KianTigger 2021-07-22 13:00:59 +01:00 committed by GitHub
commit 3375969bc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 354 additions and 53 deletions

4
go.mod
View file

@ -37,8 +37,8 @@ require (
github.com/Azure/go-autorest/autorest/azure/auth v0.5.7
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/IBM/go-sdk-core/v5 v5.4.5
github.com/IBM/secrets-manager-go-sdk v0.1.21
github.com/IBM/go-sdk-core/v5 v5.5.0
github.com/IBM/secrets-manager-go-sdk v1.0.23
github.com/aws/aws-sdk-go v1.38.6
github.com/crossplane/crossplane-runtime v0.13.0
github.com/fatih/color v1.10.0 // indirect

10
go.sum
View file

@ -63,11 +63,10 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/IBM/go-sdk-core/v5 v5.4.2/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0=
github.com/IBM/go-sdk-core/v5 v5.4.5 h1:fP/SLOMxRzhHaqS+I5XN+1CWrAAWn8fdzWuZvbR5KxE=
github.com/IBM/go-sdk-core/v5 v5.4.5/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0=
github.com/IBM/secrets-manager-go-sdk v0.1.21 h1:llT2ryUHpSvNwqzNQ+8cxInIXi7WgRtgUz9ycerJKvA=
github.com/IBM/secrets-manager-go-sdk v0.1.21/go.mod h1:aw+EgLmbwxGDxlcohb/ye46O4nLeBSapAapHmWLZ2fY=
github.com/IBM/go-sdk-core/v5 v5.5.0 h1:etP4m0kzMCxjZRI4Bu6cRTfK9YDvY3xFuagXugkCyxc=
github.com/IBM/go-sdk-core/v5 v5.5.0/go.mod h1:Sn+z+qTDREQvCr+UFa22TqqfXNxx3o723y8GsfLV8e0=
github.com/IBM/secrets-manager-go-sdk v1.0.23 h1:YvRB2jmCfXVwTiTozCNVIRfl6q9Qcl2JiL4x6chOSI4=
github.com/IBM/secrets-manager-go-sdk v1.0.23/go.mod h1:ruP6eQ0/J/zHBbnMfUyWeMsTe9vgnGL4rDeLiSKhZhU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -527,7 +526,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=

View file

@ -17,6 +17,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/IBM/go-sdk-core/v5/core"
sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1"
@ -95,51 +96,197 @@ func (ibm *providerIBM) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSe
if utils.IsNil(ibm.IBMClient) {
return nil, fmt.Errorf(errUninitalizedIBMProvider)
}
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &ref.Key,
})
if err != nil {
return nil, err
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretName := ref.Key
nameSplitted := strings.Split(secretName, "/")
if len(nameSplitted) > 1 {
secretType = nameSplitted[0]
secretName = nameSplitted[1]
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
arbitrarySecretPayload := secretData["payload"].(string)
return []byte(arbitrarySecretPayload), nil
switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
arbitrarySecretPayload := secretData["payload"].(string)
return []byte(arbitrarySecretPayload), nil
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type username_password")
}
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
}
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := *secret.APIKey
return []byte(secretData), nil
case sm.CreateSecretOptionsSecretTypeImportedCertConst:
if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type imported_cert")
}
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
}
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
default:
return nil, fmt.Errorf("unknown secret type %s", secretType)
}
}
func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
if utils.IsNil(ibm.IBMClient) {
return nil, fmt.Errorf(errUninitalizedIBMProvider)
}
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &ref.Key,
})
if err != nil {
return nil, err
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretName := ref.Key
nameSplitted := strings.Split(secretName, "/")
if len(nameSplitted) > 1 {
secretType = nameSplitted[0]
secretName = nameSplitted[1]
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
arbitrarySecretPayload := secretData["payload"].(string)
switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &ref.Key,
})
if err != nil {
return nil, err
}
kv := make(map[string]string)
err = json.Unmarshal([]byte(arbitrarySecretPayload), &kv)
if err != nil {
return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
arbitrarySecretPayload := secretData["payload"].(string)
kv := make(map[string]string)
err = json.Unmarshal([]byte(arbitrarySecretPayload), &kv)
if err != nil {
return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
}
secretMap := make(map[string][]byte)
for k, v := range kv {
secretMap[k] = []byte(v)
}
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
secretMap := make(map[string][]byte)
for k, v := range secretData {
secretMap[k] = []byte(v.(string))
}
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := *secret.APIKey
secretMap := make(map[string][]byte)
secretMap["apikey"] = []byte(secretData)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeImportedCertConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
ID: &secretName,
})
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
secretMap := make(map[string][]byte)
for k, v := range secretData {
secretMap[k] = []byte(v.(string))
}
return secretMap, nil
default:
return nil, fmt.Errorf("unknown secret type %s", secretType)
}
secretMap := make(map[string][]byte)
for k, v := range kv {
secretMap[k] = []byte(v)
}
return secretMap, nil
}
func (ibm *providerIBM) Close() error {

View file

@ -78,7 +78,7 @@ func makeValidAPIOutput() *sm.GetSecret {
return &sm.GetSecret{
Resources: []sm.SecretResourceIntf{
&sm.SecretResource{
Type: utilpointer.StringPtr("testytype"),
SecretType: utilpointer.StringPtr("testytype"),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
},
@ -111,34 +111,120 @@ var setNilMockClient = func(smtc *secretManagerTestCase) {
// make sure correct values are passed and errors are handled accordingly.
func TestIBMSecretManagerGetSecret(t *testing.T) {
secretData := make(map[string]interface{})
secretValue := "changedvalue"
secretData["payload"] = secretValue
secretString := "changedvalue"
secretPassword := "P@ssw0rd"
secretAPIKey := "01234567890"
secretCertificate := "certificate_value"
secretData["payload"] = secretString
secretData["password"] = secretPassword
secretData["certificate"] = secretCertificate
// good case: default version is set
// key is passed in, output is sent back
setSecretString := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
Type: utilpointer.StringPtr("testytype"),
SecretType: utilpointer.StringPtr("testytype"),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiOutput.Resources = resources
smtc.expectedSecret = secretValue
smtc.expectedSecret = secretString
}
// good case: custom version set
setCustomKey := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
Type: utilpointer.StringPtr("testytype"),
SecretType: utilpointer.StringPtr("testytype"),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.ref.Key = "testyname"
smtc.apiInput.ID = utilpointer.StringPtr("testyname")
smtc.apiOutput.Resources = resources
smtc.expectedSecret = secretValue
smtc.expectedSecret = secretString
}
// bad case: username_password type without property
secretUserPass := "username_password/test-secret"
badSecretUserPass := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretUserPass
smtc.expectError = "remoteRef.property required for secret type username_password"
}
// good case: username_password type with property
setSecretUserPass := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretUserPass
smtc.ref.Property = "password"
smtc.expectedSecret = secretPassword
}
// good case: iam_credenatials type
setSecretIam := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
Name: utilpointer.StringPtr("testyname"),
APIKey: utilpointer.StringPtr(secretAPIKey),
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "iam_credentials/test-secret"
smtc.expectedSecret = secretAPIKey
}
// good case: imported_cert type with property
secretCert := "imported_cert/test-secret"
setSecretCert := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretCert
smtc.ref.Property = "certificate"
smtc.expectedSecret = secretCertificate
}
// bad case: imported_cert type without property
badSecretCert := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretCert
smtc.expectError = "remoteRef.property required for secret type imported_cert"
}
successCases := []*secretManagerTestCase{
@ -147,6 +233,11 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
makeValidSecretManagerTestCaseCustom(setCustomKey),
makeValidSecretManagerTestCaseCustom(setAPIErr),
makeValidSecretManagerTestCaseCustom(setNilMockClient),
makeValidSecretManagerTestCaseCustom(badSecretUserPass),
makeValidSecretManagerTestCaseCustom(setSecretUserPass),
makeValidSecretManagerTestCaseCustom(setSecretIam),
makeValidSecretManagerTestCaseCustom(setSecretCert),
makeValidSecretManagerTestCaseCustom(badSecretCert),
}
sm := providerIBM{}
@ -163,17 +254,25 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
}
func TestGetSecretMap(t *testing.T) {
secretUsername := "user1"
secretPassword := "P@ssw0rd"
secretAPIKey := "01234567890"
secretCertificate := "certificate_value"
secretPrivateKey := "private_key_value"
secretIntermediate := "intermediate_value"
// good case: default version & deserialization
setDeserialization := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{})
secretValue := `{"foo":"bar"}`
secretData["payload"] = secretValue
secretData["payload"] = `{"foo":"bar"}`
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
Type: utilpointer.StringPtr("testytype"),
SecretType: utilpointer.StringPtr("testytype"),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiOutput.Resources = resources
smtc.expectedData["foo"] = []byte("bar")
}
@ -181,26 +280,83 @@ func TestGetSecretMap(t *testing.T) {
// bad case: invalid json
setInvalidJSON := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{})
secretData["payload"] = `-----------------`
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
Type: utilpointer.StringPtr("testytype"),
SecretType: utilpointer.StringPtr("testytype"),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiOutput.Resources = resources
smtc.expectError = "unable to unmarshal secret: invalid character '-' in numeric literal"
}
// good case: username_password
setSecretUserPass := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{})
secretData["username"] = secretUsername
secretData["password"] = secretPassword
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "username_password/test-secret"
smtc.expectedData["username"] = []byte(secretUsername)
smtc.expectedData["password"] = []byte(secretPassword)
}
// good case: iam_credentials
setSecretIam := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
Name: utilpointer.StringPtr("testyname"),
APIKey: utilpointer.StringPtr(secretAPIKey),
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "iam_credentials/test-secret"
smtc.expectedData["apikey"] = []byte(secretAPIKey)
}
// good case: imported_cert
setSecretCert := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{})
secretData["certificate"] = secretCertificate
secretData["private_key"] = secretPrivateKey
secretData["intermediate"] = secretIntermediate
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "imported_cert/test-secret"
smtc.expectedData["certificate"] = []byte(secretCertificate)
smtc.expectedData["private_key"] = []byte(secretPrivateKey)
smtc.expectedData["intermediate"] = []byte(secretIntermediate)
}
successCases := []*secretManagerTestCase{
makeValidSecretManagerTestCaseCustom(setDeserialization),
makeValidSecretManagerTestCaseCustom(setInvalidJSON),
makeValidSecretManagerTestCaseCustom(setNilMockClient),
makeValidSecretManagerTestCaseCustom(setAPIErr),
makeValidSecretManagerTestCaseCustom(setSecretUserPass),
makeValidSecretManagerTestCaseCustom(setSecretIam),
makeValidSecretManagerTestCaseCustom(setSecretCert),
}
sm := providerIBM{}