Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appcontext/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type Context struct {
// RetryData holds the data to be stored for later retry when the pipeline function returns an error
RetryData []byte
// SecretProvider exposes the support for getting and storing secrets
SecretProvider *security.SecretProvider
SecretProvider security.SecretProvider
}

// Complete is optional and provides a way to return the specified data.
Expand Down
13 changes: 7 additions & 6 deletions appsdk/configupdates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ import (
)

func TestWaitForConfigUpdates_InsecureSecrets(t *testing.T) {
expected := time.Now()
_ = os.Setenv(security.EnvSecretStore, "false")
defer os.Clearenv()

sdk := &AppFunctionsSDK{}
sdk.secretProvider = &security.SecretProvider{
LastUpdated: expected,
}
sdk.secretProvider = &security.SecretProviderImpl{}
sdk.secretProvider.InsecureSecretsUpdated()
expected := sdk.secretProvider.SecretsLastUpdated()

// Create all dependencies that are going to be required for this test
sdk.LoggingClient = logger.NewMockClient()
Expand Down Expand Up @@ -67,7 +68,7 @@ func TestWaitForConfigUpdates_InsecureSecrets(t *testing.T) {
// Signal update occurred and give it time to process
configUpdated <- struct{}{}
time.Sleep(1 * time.Second)
assert.Equal(t, expected, sdk.secretProvider.LastUpdated, "LastUpdated should not have changed")
assert.Equal(t, expected, sdk.secretProvider.SecretsLastUpdated(), "LastUpdated should not have changed")

// Add another new InsecureSecret entry so it is detected as changed. Must make a new map so
// it doesn't add to the old map.
Expand All @@ -83,5 +84,5 @@ func TestWaitForConfigUpdates_InsecureSecrets(t *testing.T) {
// Signal update occurred and give it time to process
configUpdated <- struct{}{}
time.Sleep(1 * time.Second)
assert.NotEqual(t, expected, sdk.secretProvider.LastUpdated, "LastUpdated should have changed")
assert.NotEqual(t, expected, sdk.secretProvider.SecretsLastUpdated(), "LastUpdated should have changed")
}
2 changes: 1 addition & 1 deletion appsdk/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ type AppFunctionsSDK struct {
registryClient registry.Client
config *common.ConfigurationStruct
storeClient interfaces.StoreClient
secretProvider *security.SecretProvider
secretProvider security.SecretProvider
storeForwardWg *sync.WaitGroup
storeForwardCancelCtx context.CancelFunc
appWg *sync.WaitGroup
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/diegoholiveira/jsonlogic v1.0.1-0.20200220175622-ab7989be08b9
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/edgexfoundry/go-mod-bootstrap v0.0.37
github.com/edgexfoundry/go-mod-core-contracts v0.1.66
github.com/edgexfoundry/go-mod-core-contracts v0.1.68
github.com/edgexfoundry/go-mod-messaging v0.1.21
github.com/edgexfoundry/go-mod-registry v0.1.21
github.com/edgexfoundry/go-mod-secrets v0.0.19
Expand Down
6 changes: 3 additions & 3 deletions internal/bootstrap/container/secretprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
)

// SecretProviderName contains the name of the security.SecretProvider implementation in the DIC.
var SecretProviderName = di.TypeInstanceToName(&security.SecretProvider{})
var SecretProviderName = di.TypeInstanceToName((*security.SecretProvider)(nil))

// SecretProviderFrom helper function queries the DIC and returns the security.SecretProvider implementation.
func SecretProviderFrom(get di.Get) *security.SecretProvider {
return get(SecretProviderName).(*security.SecretProvider)
func SecretProviderFrom(get di.Get) security.SecretProvider {
return get(SecretProviderName).(security.SecretProvider)
}
4 changes: 3 additions & 1 deletion internal/bootstrap/handlers/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ func (_ *Secrets) BootstrapHandler(
logger := bootstrapContainer.LoggingClientFrom(dic.Get)
config := container.ConfigurationFrom(dic.Get)

secretProvider := security.NewSecretProvider(logger, config)
var secretProvider security.SecretProvider

secretProvider = security.NewSecretProvider(logger, config)
ok := secretProvider.Initialize(ctx)
if !ok {
logger.Error("unable to initialize secret provider")
Expand Down
2 changes: 1 addition & 1 deletion internal/bootstrap/handlers/storeclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (_ *Database) BootstrapHandler(
// InitializeStoreClient initializes the database client for Store and Forward. This is not a receiver function so that
// it can be called directly when configuration has changed and store and forward has been enabled for the first time
func InitializeStoreClient(
secretProvider *security.SecretProvider,
secretProvider security.SecretProvider,
config *common.ConfigurationStruct,
startupTimer startup.Timer,
logger logger.LoggingClient) (interfaces.StoreClient, error) {
Expand Down
10 changes: 5 additions & 5 deletions internal/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ import (
)

const (
ConfigRegistryStem = "edgex/appservices/1.0/"
DatabaseName = "application-service"
ConfigRegistryStem = "edgex/appservices/1.0/"
DatabaseName = "application-service"
CorrelationHeaderKey = "X-Correlation-ID"

ApiTriggerRoute = clients.ApiBase + "/trigger"
ApiV2TriggerRoute = v2.ApiBase + "/trigger"
ApiSecretsRoute = clients.ApiBase + "/secrets"
ApiV2SecretsRoute = v2.ApiBase + "/secrets"
)

// SDKVersion indicates the version of the SDK - will be overwritten by build
var SDKVersion string = "0.0.0"

// ApplicationVersion indicates the version of the application itself, not the SDK - will be overwritten by build
var ApplicationVersion string = "0.0.0"

// SecretsAPIRoute api route for posting secrets
var SecretsAPIRoute = clients.ApiBase + "/secrets"
4 changes: 2 additions & 2 deletions internal/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type GolangRuntime struct {
transforms []appcontext.AppFunction
isBusyCopying sync.Mutex
storeForward storeForwardInfo
secretProvider *security.SecretProvider
secretProvider security.SecretProvider
}

type MessageError struct {
Expand Down Expand Up @@ -139,7 +139,7 @@ func (gr *GolangRuntime) ProcessMessage(edgexcontext *appcontext.Context, envelo
}

// Initialize sets the internal reference to the StoreClient for use when Store and Forward is enabled
func (gr *GolangRuntime) Initialize(storeClient interfaces.StoreClient, secretProvider *security.SecretProvider) {
func (gr *GolangRuntime) Initialize(storeClient interfaces.StoreClient, secretProvider security.SecretProvider) {
gr.storeForward.storeClient = storeClient
gr.storeForward.runtime = gr
gr.secretProvider = secretProvider
Expand Down
12 changes: 6 additions & 6 deletions internal/security/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

// GetDatabaseCredentials retrieves the login credentials for the database
// If security is disabled then we use the insecure credentials supplied by the configuration.
func (s *SecretProvider) GetDatabaseCredentials(database db.DatabaseInfo) (common.Credentials, error) {
func (s *SecretProviderImpl) GetDatabaseCredentials(database db.DatabaseInfo) (common.Credentials, error) {
var credentials map[string]string
var err error

Expand Down Expand Up @@ -63,7 +63,7 @@ func (s *SecretProvider) GetDatabaseCredentials(database db.DatabaseInfo) (commo
// path specifies the type or location of the secrets to retrieve.
// keys specifies the secrets which to retrieve. If no keys are provided then all the keys associated with the
// specified path will be returned.
func (s *SecretProvider) GetSecrets(path string, keys ...string) (map[string]string, error) {
func (s *SecretProviderImpl) GetSecrets(path string, keys ...string) (map[string]string, error) {
if !s.isSecurityEnabled() {
return s.getInsecureSecrets(path, keys...)
}
Expand All @@ -89,7 +89,7 @@ func (s *SecretProvider) GetSecrets(path string, keys ...string) (map[string]str
// path specifies the type or location of the secrets to retrieve.
// keys specifies the secrets which to retrieve. If no keys are provided then all the keys associated with the
// specified path will be returned.
func (s *SecretProvider) getInsecureSecrets(path string, keys ...string) (map[string]string, error) {
func (s *SecretProviderImpl) getInsecureSecrets(path string, keys ...string) (map[string]string, error) {
secrets := make(map[string]string)
pathExists := false
var missingKeys []string
Expand Down Expand Up @@ -130,7 +130,7 @@ func (s *SecretProvider) getInsecureSecrets(path string, keys ...string) (map[st
return secrets, nil
}

func (s *SecretProvider) getSecretsCache(path string, keys ...string) map[string]string {
func (s *SecretProviderImpl) getSecretsCache(path string, keys ...string) map[string]string {
secrets := make(map[string]string)

// Synchronize cache access
Expand Down Expand Up @@ -159,7 +159,7 @@ func (s *SecretProvider) getSecretsCache(path string, keys ...string) map[string
return nil
}

func (s *SecretProvider) updateSecretsCache(path string, secrets map[string]string) {
func (s *SecretProviderImpl) updateSecretsCache(path string, secrets map[string]string) {
// Synchronize cache access
s.cacheMuxtex.Lock()
defer s.cacheMuxtex.Unlock()
Expand All @@ -177,7 +177,7 @@ func (s *SecretProvider) updateSecretsCache(path string, secrets map[string]stri
// it sets the values requested at provided keys
// path specifies the type or location of the secrets to store
// secrets map specifies the "key": "value" pairs of secrets to store
func (s *SecretProvider) StoreSecrets(path string, secrets map[string]string) error {
func (s *SecretProviderImpl) StoreSecrets(path string, secrets map[string]string) error {
if !s.isSecurityEnabled() {
return errors.New("Storing secrets is not supported when running in insecure mode")
}
Expand Down
5 changes: 2 additions & 3 deletions internal/security/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ func getSecretsTestData() secretTestData {
}

func TestGetSecrets(t *testing.T) {

secretProvider := newMockSecretProvider(nil)

for i, test := range getSecretsTestData() {
Expand Down Expand Up @@ -189,7 +188,7 @@ func TestGetInsecureSecrets(t *testing.T) {
tearDownGetInsecureSecrets(t, origEnv)
}

func setupGetInsecureSecrets(t *testing.T) (sp *SecretProvider, origEnv string) {
func setupGetInsecureSecrets(t *testing.T) (sp *SecretProviderImpl, origEnv string) {
insecureSecrets := common.InsecureSecrets{
"no_path": common.InsecureSecretsInfo{
Path: "",
Expand Down Expand Up @@ -230,7 +229,7 @@ func tearDownGetInsecureSecrets(t *testing.T, origEnv string) {
}
}

func newMockSecretProvider(configuration *common.ConfigurationStruct) *SecretProvider {
func newMockSecretProvider(configuration *common.ConfigurationStruct) *SecretProviderImpl {
logClient := logger.NewClient("app_functions_sdk_go", false, "./test.log", "DEBUG")
mockSP := NewSecretProvider(logClient, configuration)
mockSP.SharedSecretClient = &mockSecretClient{}
Expand Down
30 changes: 22 additions & 8 deletions internal/security/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/edgexfoundry/app-functions-sdk-go/internal/security/authtokenloader"
"github.com/edgexfoundry/app-functions-sdk-go/internal/security/client"
"github.com/edgexfoundry/app-functions-sdk-go/internal/security/fileioperformer"
"github.com/edgexfoundry/app-functions-sdk-go/internal/store/db"

"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"

Expand All @@ -37,8 +38,17 @@ import (

const EnvSecretStore = "EDGEX_SECURITY_SECRET_STORE"

type SecretProvider interface {
Initialize(_ context.Context) bool
StoreSecrets(path string, secrets map[string]string) error
GetSecrets(path string, _ ...string) (map[string]string, error)
GetDatabaseCredentials(database db.DatabaseInfo) (common.Credentials, error)
InsecureSecretsUpdated()
SecretsLastUpdated() time.Time
}

// SecretProvider cache storage for the secrets
type SecretProvider struct {
type SecretProviderImpl struct {
SharedSecretClient pkg.SecretClient
ExclusiveSecretClient pkg.SecretClient
secretsCache map[string]map[string]string // secret's path, key, value
Expand All @@ -50,8 +60,8 @@ type SecretProvider struct {
}

// NewSecretProvider returns a new secret provider
func NewSecretProvider(loggingClient logger.LoggingClient, configuration *common.ConfigurationStruct) *SecretProvider {
sp := &SecretProvider{
func NewSecretProvider(loggingClient logger.LoggingClient, configuration *common.ConfigurationStruct) *SecretProviderImpl {
sp := &SecretProviderImpl{
secretsCache: make(map[string]map[string]string),
cacheMuxtex: &sync.Mutex{},
configuration: configuration,
Expand All @@ -63,7 +73,7 @@ func NewSecretProvider(loggingClient logger.LoggingClient, configuration *common
}

// Initialize creates SecretClients to be used for obtaining secrets from a secrets store manager.
func (s *SecretProvider) Initialize(ctx context.Context) bool {
func (s *SecretProviderImpl) Initialize(ctx context.Context) bool {
var err error

// initialize shared secret client if configured
Expand All @@ -83,13 +93,17 @@ func (s *SecretProvider) Initialize(ctx context.Context) bool {

// InsecureSecretsUpdated resets LastUpdate is not running in secure mode.If running in secure mode, changes to
// InsecureSecrets have no impact and are not used.
func (s *SecretProvider) InsecureSecretsUpdated() {
func (s *SecretProviderImpl) InsecureSecretsUpdated() {
if !s.isSecurityEnabled() {
s.LastUpdated = time.Now()
}
}

func (s *SecretProvider) initializeSecretClient(
func (s *SecretProviderImpl) SecretsLastUpdated() time.Time {
return s.LastUpdated
}

func (s *SecretProviderImpl) initializeSecretClient(
ctx context.Context,
secretStoreInfo bootstrapConfig.SecretStoreInfo) (pkg.SecretClient, error) {
var secretClient pkg.SecretClient
Expand Down Expand Up @@ -140,7 +154,7 @@ func (s *SecretProvider) initializeSecretClient(
// getSecretConfig creates a SecretConfig based on the SecretStoreInfo configuration properties.
// If a tokenfile is present it will override the Authentication.AuthToken value.
// the return boolean is used to indicate whether the secret store configuration is empty or not
func (s *SecretProvider) getSecretConfig(secretStoreInfo bootstrapConfig.SecretStoreInfo) (vault.SecretConfig, bool, error) {
func (s *SecretProviderImpl) getSecretConfig(secretStoreInfo bootstrapConfig.SecretStoreInfo) (vault.SecretConfig, bool, error) {
emptySecretStore := bootstrapConfig.SecretStoreInfo{}
if secretStoreInfo == emptySecretStore {
return vault.SecretConfig{}, true, nil
Expand Down Expand Up @@ -178,7 +192,7 @@ func (s *SecretProvider) getSecretConfig(secretStoreInfo bootstrapConfig.SecretS
}

// isSecurityEnabled determines if security has been enabled.
func (s *SecretProvider) isSecurityEnabled() bool {
func (s *SecretProviderImpl) isSecurityEnabled() bool {
env := os.Getenv(EnvSecretStore)
return env != "false"
}
3 changes: 2 additions & 1 deletion internal/security/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,12 @@ func TestInitializeClientFromSecretProvider(t *testing.T) {
func TestInsecureSecretsUpdated(t *testing.T) {

expected := time.Now()
target := SecretProvider{
target := SecretProviderImpl{
LastUpdated: expected,
}

os.Setenv(EnvSecretStore, "true")

target.InsecureSecretsUpdated()
assert.Equal(t, expected, target.LastUpdated, "LastUpdated should not have changed")

Expand Down
2 changes: 1 addition & 1 deletion internal/trigger/http/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (trigger *Trigger) requestHandler(writer http.ResponseWriter, r *http.Reque

logger.Debug("Request Body read", "byte count", len(data))

correlationID := r.Header.Get("X-Correlation-ID")
correlationID := r.Header.Get(internal.CorrelationHeaderKey)
edgexContext := &appcontext.Context{
CorrelationID: correlationID,
Configuration: trigger.Configuration,
Expand Down
Loading