diff --git a/example/cmd/device-simple/res/configuration.toml b/example/cmd/device-simple/res/configuration.toml index 2092c37e..8542f7ab 100644 --- a/example/cmd/device-simple/res/configuration.toml +++ b/example/cmd/device-simple/res/configuration.toml @@ -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 @@ -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 = '' diff --git a/go.mod b/go.mod index 0e013721..e981ff0f 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/internal/common/config.go b/internal/common/config.go index d6ca5afe..d164b5bf 100644 --- a/internal/common/config.go +++ b/internal/common/config.go @@ -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 @@ -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, } } @@ -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 +} diff --git a/internal/common/types.go b/internal/common/types.go index bdafbe8c..92926724 100644 --- a/internal/common/types.go +++ b/internal/common/types.go @@ -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 @@ -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. @@ -68,7 +69,7 @@ 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 @@ -76,7 +77,7 @@ type DeviceInfo struct { 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 diff --git a/internal/v2/application/command.go b/internal/v2/application/command.go index c0530e41..7e80500c 100644 --- a/internal/v2/application/command.go +++ b/internal/v2/application/command.go @@ -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" ) @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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)) @@ -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 { @@ -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 { @@ -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) } @@ -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) //} diff --git a/pkg/service/main.go b/pkg/service/main.go index 2f04b168..a07d3fac 100644 --- a/pkg/service/main.go +++ b/pkg/service/main.go @@ -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 := @@ -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, @@ -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 diff --git a/pkg/service/service.go b/pkg/service/service.go index a0205752..10136018 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -18,6 +18,8 @@ import ( "os" "time" + "github.com/edgexfoundry/go-mod-bootstrap/bootstrap/interfaces" + "github.com/edgexfoundry/device-sdk-go/internal/autoevent" "github.com/edgexfoundry/device-sdk-go/internal/clients" "github.com/edgexfoundry/device-sdk-go/internal/common" @@ -47,6 +49,7 @@ type DeviceService struct { ServiceName string LoggingClient logger.LoggingClient RegistryClient registry.Client + SecretProvider interfaces.SecretProvider edgexClients clients.EdgeXClients controller *controller.RestController config *common.ConfigurationStruct @@ -90,6 +93,7 @@ func (s *DeviceService) Initialize(serviceName, serviceVersion string, proto int func (s *DeviceService) UpdateFromContainer(r *mux.Router, dic *di.Container) { s.LoggingClient = bootstrapContainer.LoggingClientFrom(dic.Get) s.RegistryClient = bootstrapContainer.RegistryFrom(dic.Get) + s.SecretProvider = bootstrapContainer.SecretProviderFrom(dic.Get) s.edgexClients.GeneralClient = container.GeneralClientFrom(dic.Get) s.edgexClients.DeviceClient = container.MetadataDeviceClientFrom(dic.Get) s.edgexClients.DeviceServiceClient = container.MetadataDeviceServiceClientFrom(dic.Get)