Skip to content

Commit

Permalink
feat: add secret store provider registry impl
Browse files Browse the repository at this point in the history
  • Loading branch information
adohe committed Nov 22, 2023
1 parent 2c7781c commit 9bbc3b2
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
File renamed without changes.
71 changes: 71 additions & 0 deletions pkg/secrets/providers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package secrets

import (
"encoding/json"
"fmt"
"sync"

"golang.org/x/exp/maps"

"kusionstack.io/kusion/pkg/apis/secrets"
"kusionstack.io/kusion/pkg/log"
)

type Providers struct {
lock sync.RWMutex
registry map[string]SecretStoreProvider
}

func NewProviders() *Providers {
return &Providers{}
}

// Register registers a provider with associated spec. This
// is expected to happen during app startup.
func (ps *Providers) Register(sp SecretStoreProvider, spec *secrets.ProviderSpec) {
providerName, err := getProviderName(spec)
if err != nil {
panic(fmt.Sprintf("provider registery failed to parse spec: %s", err.Error()))
}

ps.lock.Lock()
defer ps.lock.Unlock()
if ps.registry != nil {
_, found := ps.registry[providerName]
if found {
log.Warnf("Provider %s was registered twice", providerName)
}
} else {
ps.registry = map[string]SecretStoreProvider{}
}

log.Infof("Registered secret store provider %s", providerName)
ps.registry[providerName] = sp
}

// GetProviderByName returns registered provider by name.
func (ps *Providers) GetProviderByName(providerName string) (SecretStoreProvider, bool) {
ps.lock.RLock()
defer ps.lock.RUnlock()
provider, found := ps.registry[providerName]
return provider, found
}

func getProviderName(spec *secrets.ProviderSpec) (string, error) {
specBytes, err := json.Marshal(spec)
if err != nil || specBytes == nil {
return "", fmt.Errorf("failed to marshal secret store provider spec: %w", err)
}

specMap := make(map[string]interface{})
err = json.Unmarshal(specBytes, &specMap)
if err != nil {
return "", fmt.Errorf("failed to unmarshal secret store provider spec: %w", err)
}

if len(specMap) != 1 {
return "", fmt.Errorf("secret stores must only have exactly one provider specified, found %d", len(specMap))
}

return maps.Keys(specMap)[0], nil
}
74 changes: 74 additions & 0 deletions pkg/secrets/providers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package secrets

import (
"context"
"testing"

"github.com/stretchr/testify/assert"

"kusionstack.io/kusion/pkg/apis/secrets"
)

// FakeSecretStore is the fake implementation of SecretStore.
type FakeSecretStore struct{}

// Fake implementation of SecretStore.GetSecret.
func (fss *FakeSecretStore) GetSecret(_ context.Context, _ string) ([]byte, error) {
return []byte("NOOP"), nil
}

// FakeSecretStoreProvider is the fake implementation of SecretStoreProvider.
type FakeSecretStoreProvider struct{}

// Fake implementation of SecretStoreProvider.Type.
func (fsp *FakeSecretStoreProvider) Type() string {
return "fake"
}

// Fake implementation of SecretStoreProvider.NewSecretStore.
func (fsp *FakeSecretStoreProvider) NewSecretStore(_ *secrets.SecretStoreSpec) (SecretStore, error) {
return &FakeSecretStore{}, nil
}

func TestRegister(t *testing.T) {
testcases := []struct {
name string
providerName string
shouldPanic bool
expExists bool
spec *secrets.ProviderSpec
}{
{
name: "should panic when given an invalid provider spec",
shouldPanic: true,
spec: &secrets.ProviderSpec{},
},
{
name: "should register a valid provider",
providerName: "aws",
shouldPanic: false,
expExists: true,
spec: &secrets.ProviderSpec{
AWS: &secrets.AWSProvider{},
},
},
}

providers := NewProviders()
fsp := &FakeSecretStoreProvider{}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
if tc.shouldPanic {
defer func() {
if r := recover(); r == nil {
t.Errorf("Register should panic")
}
}()
}

providers.Register(fsp, tc.spec)
_, ok := providers.GetProviderByName(tc.providerName)
assert.Equal(t, tc.expExists, ok, "provider should be registered")
})
}
}

0 comments on commit 9bbc3b2

Please sign in to comment.