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

Add attached file support to all onepassword secrets (#3901)

* Add attached file support to all onepassword secrets

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

* Small clean up

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

* Fix PR comments

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

* Fix sonarcloud issues

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

* Fix PR comments

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

* Fix PR comments

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>

---------

Signed-off-by: Thibault Cohen <47721+titilambert@users.noreply.github.com>
Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
This commit is contained in:
Thibault Cohen 2024-09-20 13:17:09 -04:00 committed by GitHub
parent 3c2246b6f1
commit f4fc3b3a0d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 156 additions and 24 deletions

View file

@ -20,6 +20,7 @@ import (
"fmt"
"net/url"
"sort"
"strings"
"time"
"github.com/1Password/connect-sdk-go/connect"
@ -63,6 +64,9 @@ const (
errExpectedOneFieldMsgF = "%w: '%s' in '%s', got %d"
documentCategory = "DOCUMENT"
fieldPrefix = "field"
filePrefix = "file"
prefixSplitter = "/"
)
// Custom Errors //.
@ -329,6 +333,22 @@ func (provider *ProviderOnePassword) PushSecret(ctx context.Context, secret *cor
return nil
}
// Clean property string by removing property prefix if needed.
func getObjType(documentType onepassword.ItemCategory, property string) (string, string) {
if strings.HasPrefix(property, fieldPrefix+prefixSplitter) {
return fieldPrefix, property[6:]
}
if strings.HasPrefix(property, filePrefix+prefixSplitter) {
return filePrefix, property[5:]
}
if documentType == documentCategory {
return filePrefix, property
}
return fieldPrefix, property
}
// GetSecret returns a single secret from the provider.
func (provider *ProviderOnePassword) GetSecret(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
if ref.Version != "" {
@ -340,14 +360,11 @@ func (provider *ProviderOnePassword) GetSecret(_ context.Context, ref esv1beta1.
return nil, err
}
// handle files
if item.Category == documentCategory {
// default to the first file when ref.Property is empty
return provider.getFile(item, ref.Property)
propertyType, property := getObjType(item.Category, ref.Property)
if propertyType == filePrefix {
return provider.getFile(item, property)
}
// handle fields
return provider.getField(item, ref.Property)
return provider.getField(item, property)
}
// Validate checks if the client is configured correctly
@ -374,13 +391,11 @@ func (provider *ProviderOnePassword) GetSecretMap(_ context.Context, ref esv1bet
return nil, err
}
// handle files
if item.Category == documentCategory {
return provider.getFiles(item, ref.Property)
propertyType, property := getObjType(item.Category, ref.Property)
if propertyType == filePrefix {
return provider.getFiles(item, property)
}
// handle fields
return provider.getFields(item, ref.Property)
return provider.getFields(item, property)
}
// GetAllSecrets syncs multiple 1Password Items into a single Kubernetes Secret, for dataFrom.find.
@ -568,13 +583,9 @@ func (provider *ProviderOnePassword) getAllForVault(vaultID string, ref esv1beta
}
// handle files
if item.Category == documentCategory {
err = provider.getAllFiles(item, ref, secretData)
if err != nil {
return err
}
continue
err = provider.getAllFiles(item, ref, secretData)
if err != nil {
return err
}
// handle fields

View file

@ -685,11 +685,26 @@ func TestGetSecret(t *testing.T) {
vaults: map[string]int{myVault: 1},
client: fake.NewMockClient().
AddPredictableVault(myVault).
AddPredictableItemWithField(myVault, myItem, key1, value1).
AppendItem(myVaultID, onepassword.Item{
ID: myItemID,
Title: myItem,
Vault: onepassword.ItemVault{ID: myVaultID},
Files: []*onepassword.File{
{
ID: myFilePNGID,
Name: myFilePNG,
},
},
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: password,
Value: value2,
}),
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: key1,
Value: value1,
}).
SetFileContents(myFilePNG, []byte(myContents)),
},
checks: []check{
{
@ -701,6 +716,15 @@ func TestGetSecret(t *testing.T) {
expectedValue: value1,
expectedErr: nil,
},
{
checkNote: key1 + " with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: fieldPrefix + prefixSplitter + key1,
},
expectedValue: value1,
expectedErr: nil,
},
{
checkNote: "'password' (defaulted property)",
ref: esv1beta1.ExternalSecretDataRemoteRef{
@ -718,6 +742,15 @@ func TestGetSecret(t *testing.T) {
},
expectedErr: errors.New(errVersionNotImplemented),
},
{
checkNote: "file named my-file.png with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: filePrefix + prefixSplitter + myFilePNG,
},
expectedValue: myContents,
expectedErr: nil,
},
},
},
{
@ -738,9 +771,22 @@ func TestGetSecret(t *testing.T) {
},
},
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: key1,
Value: value2,
}).
SetFileContents(myFilePNG, []byte(myContents)),
},
checks: []check{
{
checkNote: "field named password",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: fieldPrefix + prefixSplitter + key1,
},
expectedValue: value2,
expectedErr: nil,
},
{
checkNote: "file named my-file.png",
ref: esv1beta1.ExternalSecretDataRemoteRef{
@ -750,6 +796,15 @@ func TestGetSecret(t *testing.T) {
expectedValue: myContents,
expectedErr: nil,
},
{
checkNote: "file named my-file.png with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: filePrefix + prefixSplitter + myFilePNG,
},
expectedValue: myContents,
expectedErr: nil,
},
{
checkNote: "empty ref.Property",
ref: esv1beta1.ExternalSecretDataRemoteRef{
@ -766,8 +821,17 @@ func TestGetSecret(t *testing.T) {
},
expectedErr: fmt.Errorf(errDocumentNotFound, errors.New("'my-item', 'you-cant-find-me.png'")),
},
{
checkNote: "file non existent with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: "file/you-cant-find-me.png",
},
expectedErr: fmt.Errorf(errDocumentNotFound, errors.New("'my-item', 'you-cant-find-me.png'")),
},
},
},
{
setupNote: "one vault, one item, two fields w/ same Label",
provider: &ProviderOnePassword{
@ -845,11 +909,31 @@ func TestGetSecretMap(t *testing.T) {
vaults: map[string]int{myVault: 1},
client: fake.NewMockClient().
AddPredictableVault(myVault).
AddPredictableItemWithField(myVault, myItem, key1, value1).
AppendItem(myVaultID, onepassword.Item{
ID: myItemID,
Title: myItem,
Vault: onepassword.ItemVault{ID: myVaultID},
Files: []*onepassword.File{
{
ID: myFilePNGID,
Name: myFilePNG,
},
{
ID: myFile2ID,
Name: myFile2PNG,
},
},
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: key1,
Value: value1,
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: password,
Value: value2,
}),
}).
SetFileContents(myFilePNG, []byte(myContents)).
SetFileContents(myFile2PNG, []byte(myContents2)),
},
checks: []check{
{
@ -883,6 +967,17 @@ func TestGetSecretMap(t *testing.T) {
},
expectedErr: errors.New(errVersionNotImplemented),
},
{
checkNote: "limit by Property with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: filePrefix + prefixSplitter + myFilePNG,
},
expectedMap: map[string][]byte{
myFilePNG: []byte(myContents),
},
expectedErr: nil,
},
},
},
{
@ -907,6 +1002,10 @@ func TestGetSecretMap(t *testing.T) {
},
},
}).
AppendItemField(myVaultID, myItemID, onepassword.ItemField{
Label: key1,
Value: value2,
}).
SetFileContents(myFilePNG, []byte(myContents)).
SetFileContents(myFile2PNG, []byte(myContents2)),
},
@ -933,6 +1032,28 @@ func TestGetSecretMap(t *testing.T) {
},
expectedErr: nil,
},
{
checkNote: "limit by Property with prefix",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: filePrefix + prefixSplitter + myFilePNG,
},
expectedMap: map[string][]byte{
myFilePNG: []byte(myContents),
},
expectedErr: nil,
},
{
checkNote: "get field limit by Property",
ref: esv1beta1.ExternalSecretDataRemoteRef{
Key: myItem,
Property: fieldPrefix + prefixSplitter + key1,
},
expectedMap: map[string][]byte{
key1: []byte(value2),
},
expectedErr: nil,
},
},
},
{