Skip to content

Commit

Permalink
feat: SecretProvider for storing/retrieving secrets
Browse files Browse the repository at this point in the history
Add the ability to create SecretProvider and properly initilize it when in secure mode,
Use of SecretProvied will be added in future PRs.

close #653

Signed-off-by: lenny <[email protected]>
  • Loading branch information
lenny committed Dec 30, 2020
1 parent 42e5a1e commit 50a8ddc
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 45 deletions.
24 changes: 24 additions & 0 deletions example/cmd/device-simple/res/configuration.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
[Writable]
LogLevel = 'INFO'
# Example InsecureSecrets configuration that simulates SecretStore for when EDGEX_SECURITY_SECRET_STORE=false
[Writable.InsecureSecrets]
[Writable.InsecureSecrets.Sample]
path = "sample"
[Writable.InsecureSecrets.Sample.Secrets]
username = ""
password = ""

[Service]
BootTimeout = 30000
Expand Down Expand Up @@ -30,6 +37,23 @@ Type = 'consul'
Host = 'localhost'
Port = 48081

# Example SecretStore configuration.
# Only used when EDGEX_SECURITY_SECRET_STORE=true
# Must also add `ADD_SECRETSTORE_TOKENS: "device-simple"` to vault-worker environment so it generates
# the token and secret store in vault for 'device-simple'
[SecretStore]
Host = 'localhost'
Port = 8200
Path = '/v1/secret/edgex/device-simple/'
Protocol = 'http'
RootCaCertPath = ''
ServerName = ''
TokenFile = '/tmp/edgex/secrets/device-simple/secrets-token.json'
AdditionalRetryAttempts = 10
RetryWaitPeriod = "1s"
[SecretStore.Authentication]
AuthType = 'X-Vault-Token'

[Device]
DataTransform = true
InitCmd = ''
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module github.com/edgexfoundry/device-sdk-go
require (
bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690
github.com/OneOfOne/xxhash v1.2.8
github.com/edgexfoundry/go-mod-bootstrap v0.0.60
github.com/edgexfoundry/go-mod-core-contracts v0.1.115
github.com/edgexfoundry/go-mod-registry v0.1.26
github.com/edgexfoundry/go-mod-bootstrap v0.0.65
github.com/edgexfoundry/go-mod-core-contracts v0.1.135
github.com/edgexfoundry/go-mod-registry v0.1.27
github.com/fxamacker/cbor/v2 v2.2.0
github.com/google/uuid v1.1.2
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.5.1
github.com/stretchr/testify v1.6.1
gopkg.in/yaml.v2 v2.4.0
)

Expand Down
14 changes: 11 additions & 3 deletions internal/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type ConfigurationStruct struct {
DeviceList []DeviceConfig `consul:"-"`
// Driver is a string map contains customized configuration for the protocol driver implemented based on Device SDK
Driver map[string]string
// SecretStore contain information for connecting to the secure SecretStore (Vault) to retrieve or store secrets
SecretStore bootstrapConfig.SecretStoreInfo
}

// UpdateFromRaw converts configuration received from the registry to a service-specific configuration struct which is
Expand Down Expand Up @@ -64,9 +66,10 @@ func (c *ConfigurationStruct) UpdateWritableFromRaw(rawWritable interface{}) boo
// into an bootstrapConfig.BootstrapConfiguration struct contained within ConfigurationStruct).
func (c *ConfigurationStruct) GetBootstrap() bootstrapConfig.BootstrapConfiguration {
return bootstrapConfig.BootstrapConfiguration{
Clients: c.Clients,
Service: c.Service.GetBootstrapServiceInfo(),
Registry: c.Registry,
Clients: c.Clients,
Service: c.Service.GetBootstrapServiceInfo(),
Registry: c.Registry,
SecretStore: c.SecretStore,
}
}

Expand All @@ -79,3 +82,8 @@ func (c *ConfigurationStruct) GetLogLevel() string {
func (c *ConfigurationStruct) GetRegistryInfo() bootstrapConfig.RegistryInfo {
return c.Registry
}

// GetInsecureSecrets returns the service's InsecureSecrets.
func (c *ConfigurationStruct) GetInsecureSecrets() bootstrapConfig.InsecureSecrets {
return c.Writable.InsecureSecrets
}
9 changes: 5 additions & 4 deletions internal/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
// WritableInfo is a struct which contains configuration settings that can be changed in the Registry .
type WritableInfo struct {
// Level is the logging level of writing log message
LogLevel string
LogLevel string
InsecureSecrets bootstrapConfig.InsecureSecrets
}

// ServiceInfo is a struct which contains service related configuration
Expand Down Expand Up @@ -57,7 +58,7 @@ type ServiceInfo struct {
// DeviceInfo is a struct which contains device specific configuration settings.
type DeviceInfo struct {
// DataTransform specifies whether or not the DS perform transformations
// specified by valuedescriptor on a actuation or query command.
// specified by value descriptor on a actuation or query command.
DataTransform bool
// InitCmd specifies a device resource command which is automatically
// generated whenever a new device is added to the DS.
Expand All @@ -68,15 +69,15 @@ type DeviceInfo struct {
// can be sent to a Driver in a single command.
MaxCmdOps int
// MaxCmdValueLen is the maximum string length of a command parameter or
// result (including the valuedescriptor name) that can be returned
// result (including the value descriptor name) that can be returned
// by a Driver.
MaxCmdValueLen int
// InitCmd specifies a device resource command which is automatically
// generated whenever a new device is removed from the DS.
RemoveCmd string
// RemoveCmdArgs specify arguments to be used when building the RemoveCmd.
RemoveCmdArgs string
// ProfilesDir specifies a directory which contains deviceprofile
// ProfilesDir specifies a directory which contains device profile
// files which should be imported on startup.
ProfilesDir string
// UpdateLastConnected specifies whether to update device's LastConnected
Expand Down
55 changes: 27 additions & 28 deletions internal/v2/application/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import (
"github.com/edgexfoundry/device-sdk-go/internal/container"
"github.com/edgexfoundry/device-sdk-go/internal/transformer"
dsModels "github.com/edgexfoundry/device-sdk-go/pkg/models"

bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/bootstrap/container"
"github.com/edgexfoundry/go-mod-bootstrap/di"
"github.com/edgexfoundry/go-mod-core-contracts/clients/coredata"
"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
edgexErr "github.com/edgexfoundry/go-mod-core-contracts/errors"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
v2 "github.com/edgexfoundry/go-mod-core-contracts/v2"
"github.com/edgexfoundry/go-mod-core-contracts/v2/dtos"
)

Expand Down Expand Up @@ -491,28 +493,28 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)

origin := time.Now().UnixNano()
switch strings.ToLower(dr.Properties.Value.Type) {
case strings.ToLower(dtos.ValueTypeString):
case strings.ToLower(v2.ValueTypeString):
result = dsModels.NewStringValue(dr.Name, origin, v)
case strings.ToLower(dtos.ValueTypeBool):
case strings.ToLower(v2.ValueTypeBool):
value, err := strconv.ParseBool(v)
if err != nil {
return result, err
}
result, err = dsModels.NewBoolValue(dr.Name, origin, value)
case strings.ToLower(dtos.ValueTypeBoolArray):
case strings.ToLower(v2.ValueTypeBoolArray):
var arr []bool
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewBoolArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeUint8):
case strings.ToLower(v2.ValueTypeUint8):
n, err := strconv.ParseUint(v, 10, 8)
if err != nil {
return result, err
}
result, err = dsModels.NewUint8Value(dr.Name, origin, uint8(n))
case strings.ToLower(dtos.ValueTypeUint8Array):
case strings.ToLower(v2.ValueTypeUint8Array):
var arr []uint8
strArr := strings.Split(strings.Trim(v, "[]"), ",")
for _, u := range strArr {
Expand All @@ -523,13 +525,13 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
arr = append(arr, uint8(n))
}
result, err = dsModels.NewUint8ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeUint16):
case strings.ToLower(v2.ValueTypeUint16):
n, err := strconv.ParseUint(v, 10, 16)
if err != nil {
return result, err
}
result, err = dsModels.NewUint16Value(dr.Name, origin, uint16(n))
case strings.ToLower(dtos.ValueTypeUint16Array):
case strings.ToLower(v2.ValueTypeUint16Array):
var arr []uint16
strArr := strings.Split(strings.Trim(v, "[]"), ",")
for _, u := range strArr {
Expand All @@ -540,13 +542,13 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
arr = append(arr, uint16(n))
}
result, err = dsModels.NewUint16ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeUint32):
case strings.ToLower(v2.ValueTypeUint32):
n, err := strconv.ParseUint(v, 10, 32)
if err != nil {
return result, err
}
result, err = dsModels.NewUint32Value(dr.Name, origin, uint32(n))
case strings.ToLower(dtos.ValueTypeUint32Array):
case strings.ToLower(v2.ValueTypeUint32Array):
var arr []uint32
strArr := strings.Split(strings.Trim(v, "[]"), ",")
for _, u := range strArr {
Expand All @@ -557,13 +559,13 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
arr = append(arr, uint32(n))
}
result, err = dsModels.NewUint32ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeUint64):
case strings.ToLower(v2.ValueTypeUint64):
n, err := strconv.ParseUint(v, 10, 64)
if err != nil {
return result, err
}
result, err = dsModels.NewUint64Value(dr.Name, origin, n)
case strings.ToLower(dtos.ValueTypeUint64Array):
case strings.ToLower(v2.ValueTypeUint64Array):
var arr []uint64
strArr := strings.Split(strings.Trim(v, "[]"), ",")
for _, u := range strArr {
Expand All @@ -574,59 +576,59 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
arr = append(arr, n)
}
result, err = dsModels.NewUint64ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeInt8):
case strings.ToLower(v2.ValueTypeInt8):
n, err := strconv.ParseInt(v, 10, 8)
if err != nil {
return result, err
}
result, err = dsModels.NewInt8Value(dr.Name, origin, int8(n))
case strings.ToLower(dtos.ValueTypeInt8Array):
case strings.ToLower(v2.ValueTypeInt8Array):
var arr []int8
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewInt8ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeInt16):
case strings.ToLower(v2.ValueTypeInt16):
n, err := strconv.ParseInt(v, 10, 16)
if err != nil {
return result, err
}
result, err = dsModels.NewInt16Value(dr.Name, origin, int16(n))
case strings.ToLower(dtos.ValueTypeInt16Array):
case strings.ToLower(v2.ValueTypeInt16Array):
var arr []int16
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewInt16ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeInt32):
case strings.ToLower(v2.ValueTypeInt32):
n, err := strconv.ParseInt(v, 10, 32)
if err != nil {
return result, err
}
result, err = dsModels.NewInt32Value(dr.Name, origin, int32(n))
case strings.ToLower(dtos.ValueTypeInt32Array):
case strings.ToLower(v2.ValueTypeInt32Array):
var arr []int32
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewInt32ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeInt64):
case strings.ToLower(v2.ValueTypeInt64):
n, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return result, err
}
result, err = dsModels.NewInt64Value(dr.Name, origin, n)
case strings.ToLower(dtos.ValueTypeInt64Array):
case strings.ToLower(v2.ValueTypeInt64Array):
var arr []int64
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewInt64ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeFloat32):
case strings.ToLower(v2.ValueTypeFloat32):
n, e := strconv.ParseFloat(v, 32)
if e == nil {
result, err = dsModels.NewFloat32Value(dr.Name, origin, float32(n))
Expand All @@ -651,14 +653,14 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
result, err = dsModels.NewFloat32Value(dr.Name, origin, val)
}
}
case strings.ToLower(dtos.ValueTypeFloat32Array):
case strings.ToLower(v2.ValueTypeFloat32Array):
var arr []float32
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
return result, err
}
result, err = dsModels.NewFloat32ArrayValue(dr.Name, origin, arr)
case strings.ToLower(dtos.ValueTypeFloat64):
case strings.ToLower(v2.ValueTypeFloat64):
var val float64
val, err = strconv.ParseFloat(v, 64)
if err == nil {
Expand All @@ -682,7 +684,7 @@ func createCommandValueFromDeviceResource(dr *contract.DeviceResource, v string)
result, err = dsModels.NewFloat64Value(dr.Name, origin, val)
}
}
case strings.ToLower(dtos.ValueTypeFloat64Array):
case strings.ToLower(v2.ValueTypeFloat64Array):
var arr []float64
err = json.Unmarshal([]byte(v), &arr)
if err != nil {
Expand Down Expand Up @@ -717,13 +719,10 @@ func commandValueToReading(cv *dsModels.CommandValue, deviceName string, mediaTy
encoding = dsModels.DefaultFloatEncoding
}

reading := &dtos.BaseReading{Name: cv.DeviceResourceName, DeviceName: deviceName, ValueType: cv.ValueTypeToString()}
reading := &dtos.BaseReading{ResourceName: cv.DeviceResourceName, DeviceName: deviceName, ValueType: cv.ValueTypeToString()}
if cv.Type == dsModels.Binary {
reading.BinaryValue = cv.BinValue
reading.MediaType = mediaType
} else if cv.Type == dsModels.Float32 || cv.Type == dsModels.Float64 {
reading.Value = cv.ValueToString(encoding)
reading.FloatEncoding = encoding
} else {
reading.Value = cv.ValueToString(encoding)
}
Expand All @@ -745,7 +744,7 @@ func SendEvent(event *dtos.Event, correlationID string, lc logger.LoggingClient,
//ctx = context.WithValue(ctx, clients.ContentType, clients.ContentTypeJSON)
//responseBody, err := ec.Add(ctx, event)
//if err != nil {
// lc.Error("SendEvent: failed to push event to coredata", "device", event.DeviceName, "response", responseBody, "error", err)
// lc.Error("SendEvent: failed to push event to core data", "device", event.DeviceName, "response", responseBody, "error", err)
//} else {
// lc.Info("SendEvent: pushed event to core data", clients.ContentType, clients.FromContext(ctx, clients.ContentType), clients.CorrelationHeader, id)
//}
Expand Down
14 changes: 8 additions & 6 deletions pkg/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ import (
"github.com/edgexfoundry/device-sdk-go/internal/clients"
"github.com/edgexfoundry/device-sdk-go/internal/common"
"github.com/edgexfoundry/device-sdk-go/internal/container"

"github.com/edgexfoundry/go-mod-bootstrap/bootstrap"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/flags"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/handlers/httpserver"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/handlers/message"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/handlers"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/interfaces"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/startup"
"github.com/edgexfoundry/go-mod-bootstrap/di"

"github.com/gorilla/mux"
)

var instanceName string

func Main(serviceName string, serviceVersion string, proto interface{}, ctx context.Context, cancel context.CancelFunc, router *mux.Router, readyStream chan<- bool) {
func Main(serviceName string, serviceVersion string, proto interface{}, ctx context.Context, cancel context.CancelFunc, router *mux.Router, _ chan<- bool) {
startupTimer := startup.NewStartUpTimer(serviceName)

additionalUsage :=
Expand All @@ -47,7 +48,7 @@ func Main(serviceName string, serviceVersion string, proto interface{}, ctx cont
},
})

httpServer := httpserver.NewBootstrap(router, true)
httpServer := handlers.NewHttpServer(router, true)

bootstrap.Run(
ctx,
Expand All @@ -59,17 +60,18 @@ func Main(serviceName string, serviceVersion string, proto interface{}, ctx cont
startupTimer,
dic,
[]interfaces.BootstrapHandler{
handlers.SecureProviderBootstrapHandler,
httpServer.BootstrapHandler,
clients.NewClients().BootstrapHandler,
NewBootstrap(router).BootstrapHandler,
autodiscovery.BootstrapHandler,
message.NewBootstrap(serviceName, serviceVersion).BootstrapHandler,
handlers.NewStartMessage(serviceName, serviceVersion).BootstrapHandler,
})

ds.Stop(false)
}

func setServiceName(name string, profile string) string {
func setServiceName(name string, _ string) string {
envValue := os.Getenv(common.EnvInstanceName)
if len(envValue) > 0 {
instanceName = envValue
Expand Down
Loading

0 comments on commit 50a8ddc

Please sign in to comment.