Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable use of secrets via SecretProvider for MQTT broker credentials #197

Merged
merged 3 commits into from
Feb 3, 2021
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
3 changes: 3 additions & 0 deletions Attribution.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ https://github.com/go-mgo/mgo/blob/v2/LICENSE
gopkg.in/yaml v2 (Apache 2.0) https://github.com/go-yaml/yaml/tree/v2
https://github.com/go-yaml/yaml/blob/v2/LICENSE

gopkg.in/yaml.v3 (MIT) https://github.com/go-yaml/yaml/tree/v3
https://github.com/go-yaml/yaml/blob/v3/LICENSE

google/uuid (BSD-3) https://github.com/google/uuid
https://github.com/google/uuid/blob/master/LICENSE

Expand Down
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ RUN $MAKE

FROM alpine:3.12

# dumb-init needed for injected secure bootstrapping entrypoint script when run in secure mode.
RUN apk add --update --no-cache dumb-init

ENV APP_PORT=49982
EXPOSE $APP_PORT

Expand Down
27 changes: 23 additions & 4 deletions cmd/res/configuration.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[Writable]
LogLevel = 'INFO'
[Writable.InsecureSecrets]
[Writable.InsecureSecrets.MQTT]
path = "credentials"
[Writable.InsecureSecrets.MQTT.Secrets]
username = ""
password = ""

[Service]
BootTimeout = 30000
Expand Down Expand Up @@ -40,6 +46,19 @@ File = ''
Host = 'localhost'
Port = 48061

[SecretStore]
Host = 'localhost'
Port = 8200
Path = '/v1/secret/edgex/device-mqtt/'
Protocol = 'http'
RootCaCertPath = ''
ServerName = ''
TokenFile = '/tmp/edgex/secrets/device-mqtt/secrets-token.json'
AdditionalRetryAttempts = 10
RetryWaitPeriod = "1s"
[SecretStore.Authentication]
AuthType = 'X-Vault-Token'

[Device]
DataTransform = true
InitCmd = ''
Expand All @@ -56,20 +75,20 @@ File = ''
IncomingSchema = 'tcp'
IncomingHost = '0.0.0.0'
IncomingPort = '1883'
IncomingUser = 'admin'
IncomingPassword = 'public'
IncomingQos = '0'
IncomingKeepAlive = '3600'
IncomingClientId = 'IncomingDataSubscriber'
IncomingTopic = 'DataTopic'
IncomingCredentialsPath = 'credentials'
ResponseSchema = 'tcp'
ResponseHost = '0.0.0.0'
ResponsePort = '1883'
ResponseUser = 'admin'
ResponsePassword = 'public'
ResponseQos = '0'
ResponseKeepAlive = '3600'
ResponseClientId = 'CommandResponseSubscriber'
ResponseTopic = 'ResponseTopic'
ResponseCredentialsPath = 'credentials'
CredentialsRetryTime = '120' # Seconds
CredentialsRetryWait = '1' # Seconds
ConnEstablishingRetry = '10'
ConnRetryWaitTime = '5'
32 changes: 25 additions & 7 deletions cmd/res/example/configuration-autoevents.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[Writable]
LogLevel = 'DEBUG'
LogLevel = 'INFO'
[Writable.InsecureSecrets]
[Writable.InsecureSecrets.MQTT]
path = "credentials"
[Writable.InsecureSecrets.MQTT.Secrets]
username = ""
password = ""

[Service]
BootTimeout = 30000
Expand Down Expand Up @@ -40,6 +46,19 @@ File = ''
Host = 'localhost'
Port = 48061

[SecretStore]
Host = 'localhost'
Port = 8200
Path = '/v1/secret/edgex/device-mqtt/'
Protocol = 'http'
RootCaCertPath = ''
ServerName = ''
TokenFile = '/tmp/edgex/secrets/device-mqtt/secrets-token.json'
AdditionalRetryAttempts = 10
RetryWaitPeriod = "1s"
[SecretStore.Authentication]
AuthType = 'X-Vault-Token'

[Device]
DataTransform = true
InitCmd = ''
Expand All @@ -63,9 +82,8 @@ File = ''
Host = '0.0.0.0'
Port = '1883'
ClientId = 'CommandPublisher'
User = 'admin'
Password = 'public'
Topic = 'CommandTopic'
CredentialsPath = 'credentials'
[[DeviceList.AutoEvents]]
Frequency = '20s'
OnChange = false
Expand All @@ -76,20 +94,20 @@ File = ''
IncomingSchema = 'tcp'
IncomingHost = '0.0.0.0'
IncomingPort = '1883'
IncomingUser = 'admin'
IncomingPassword = 'public'
IncomingQos = '0'
IncomingKeepAlive = '3600'
IncomingClientId = 'IncomingDataSubscriber'
IncomingTopic = 'DataTopic'
IncomingCredentialsPath = 'credentials'
ResponseSchema = 'tcp'
ResponseHost = '0.0.0.0'
ResponsePort = '1883'
ResponseUser = 'admin'
ResponsePassword = 'public'
ResponseQos = '0'
ResponseKeepAlive = '3600'
ResponseClientId = 'CommandResponseSubscriber'
ResponseTopic = 'ResponseTopic'
ResponseCredentialsPath = 'credentials'
CredentialsRetryTime = '120' # Seconds
CredentialsRetryWait = '1' # Seconds
ConnEstablishingRetry = '10'
ConnRetryWaitTime = '5'
32 changes: 25 additions & 7 deletions cmd/res/example/configuration.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[Writable]
LogLevel = 'DEBUG'
LogLevel = 'INFO'
[Writable.InsecureSecrets]
[Writable.InsecureSecrets.MQTT]
path = "credentials"
[Writable.InsecureSecrets.MQTT.Secrets]
username = ""
password = ""

[Service]
BootTimeout = 30000
Expand Down Expand Up @@ -40,6 +46,19 @@ File = ''
Host = 'localhost'
Port = 48061

[SecretStore]
Host = 'localhost'
Port = 8200
Path = '/v1/secret/edgex/device-mqtt/'
Protocol = 'http'
RootCaCertPath = ''
ServerName = ''
TokenFile = '/tmp/edgex/secrets/device-mqtt/secrets-token.json'
AdditionalRetryAttempts = 10
RetryWaitPeriod = "1s"
[SecretStore.Authentication]
AuthType = 'X-Vault-Token'

[Device]
DataTransform = true
InitCmd = ''
Expand All @@ -63,29 +82,28 @@ File = ''
Host = '0.0.0.0'
Port = '1883'
ClientId = 'CommandPublisher'
User = 'admin'
Password = 'public'
Topic = 'CommandTopic'
CredentialsPath = 'credentials'

# Driver configs
[Driver]
IncomingSchema = 'tcp'
IncomingHost = '0.0.0.0'
IncomingPort = '1883'
IncomingUser = 'admin'
IncomingPassword = 'public'
IncomingQos = '0'
IncomingKeepAlive = '3600'
IncomingClientId = 'IncomingDataSubscriber'
IncomingTopic = 'DataTopic'
IncomingCredentialsPath = 'credentials'
ResponseSchema = 'tcp'
ResponseHost = '0.0.0.0'
ResponsePort = '1883'
ResponseUser = 'admin'
ResponsePassword = 'public'
ResponseQos = '0'
ResponseKeepAlive = '3600'
ResponseClientId = 'CommandResponseSubscriber'
ResponseTopic = 'ResponseTopic'
ResponseCredentialsPath = 'credentials'
CredentialsRetryTime = '120' # Seconds
CredentialsRetryWait = '1' # Seconds
ConnEstablishingRetry = '10'
ConnRetryWaitTime = '5'
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module github.com/edgexfoundry/device-mqtt-go

require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/edgexfoundry/device-sdk-go v1.4.0
github.com/edgexfoundry/go-mod-core-contracts v0.1.115
github.com/edgexfoundry/device-sdk-go v1.4.1-dev.6
github.com/edgexfoundry/go-mod-bootstrap v0.0.68
github.com/edgexfoundry/go-mod-core-contracts v0.1.144
github.com/kr/pretty v0.1.0 // indirect
github.com/spf13/cast v1.3.1
github.com/stretchr/testify v1.5.1
github.com/stretchr/testify v1.6.1
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
Expand Down
94 changes: 65 additions & 29 deletions internal/driver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,45 @@ import (
"reflect"
"strconv"

"github.com/edgexfoundry/device-sdk-go/pkg/service"

"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/secret"
"github.com/edgexfoundry/go-mod-bootstrap/bootstrap/startup"
"github.com/edgexfoundry/go-mod-bootstrap/config"

"github.com/edgexfoundry/go-mod-core-contracts/models"
)

type ConnectionInfo struct {
Schema string
Host string
Port string
User string
Password string
ClientId string
Topic string
Schema string
Host string
Port string
ClientId string
Topic string
CredentialsPath string
}

type configuration struct {
IncomingSchema string
IncomingHost string
IncomingPort int
IncomingUser string
IncomingPassword string
IncomingQos int
IncomingKeepAlive int
IncomingClientId string
IncomingTopic string

ResponseSchema string
ResponseHost string
ResponsePort int
ResponseUser string
ResponsePassword string
ResponseQos int
ResponseKeepAlive int
ResponseClientId string
ResponseTopic string
IncomingSchema string
IncomingHost string
IncomingPort int
IncomingQos int
IncomingKeepAlive int
IncomingClientId string
IncomingTopic string
IncomingCredentialsPath string

ResponseSchema string
ResponseHost string
ResponsePort int
ResponseQos int
ResponseKeepAlive int
ResponseClientId string
ResponseTopic string
ResponseCredentialsPath string

CredentialsRetryTime int
CredentialsRetryWait int

ConnEstablishingRetry int
ConnRetryWaitTime int
Expand Down Expand Up @@ -83,9 +89,7 @@ func load(config map[string]string, des interface{}) error {
valueField := val.Field(i)

val, ok := config[typeField.Name]
if !ok &&
typeField.Name != IncomingUser && typeField.Name != IncomingPassword &&
typeField.Name != ResponseUser && typeField.Name != ResponsePassword {
if !ok {
return fmt.Errorf(errorMessage, typeField.Name)
}

Expand All @@ -104,3 +108,35 @@ func load(config map[string]string, des interface{}) error {
}
return nil
}

func GetCredentials(secretPath string) (config.Credentials, error) {
credentials := config.Credentials{}
deviceService := service.RunningService()

timer := startup.NewTimer(driver.Config.CredentialsRetryTime, driver.Config.CredentialsRetryWait)

var secretData map[string]string
var err error
for timer.HasNotElapsed() {
secretData, err = deviceService.SecretProvider.GetSecrets(secretPath, secret.UsernameKey, secret.PasswordKey)
if err == nil {
break
}

driver.Logger.Warnf(
"Unable to retrieve MQTT credentials from SecretProvider at path '%s': %s. Retrying for %s",
secretPath,
err.Error(),
timer.RemainingAsString())
timer.SleepForInterval()
}

if err != nil {
return credentials, err
}

credentials.Username = secretData[secret.UsernameKey]
credentials.Password = secretData[secret.PasswordKey]

return credentials, nil
}
Loading