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 Registry & Config client access token #195

Merged
merged 1 commit into from
Mar 29, 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
19 changes: 17 additions & 2 deletions bootstrap/config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Copyright 2019 Dell Inc.
* Copyright 2020 Intel Inc.
* Copyright 2021 Intel Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"reflect"
"sync"

Expand All @@ -28,6 +29,7 @@ import (
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/flags"
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/interfaces"
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/startup"
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/token"
"github.com/edgexfoundry/go-mod-bootstrap/v2/di"

"github.com/edgexfoundry/go-mod-configuration/v2/configuration"
Expand Down Expand Up @@ -124,7 +126,18 @@ func (cp *Processor) Process(serviceKey string, configStem string, serviceConfig

switch configProviderInfo.UseProvider() {
case true:
configClient, err := cp.createProviderClient(serviceKey, configStem, configProviderInfo.ServiceConfig())
tokenFile := serviceConfig.GetBootstrap().Service.ConfigAccessTokenFile
accessToken, err := token.LoadAccessToken(tokenFile)
if err != nil {
// access token file doesn't exist means the access token is not needed.
if os.IsNotExist(err) {
lc.Warnf("Configuration Provider access token at %s doesn't exist. Skipping use of access token", tokenFile)
} else {
return fmt.Errorf("unable to load Configuration Provider client access token at %s: %s", tokenFile, err.Error())
}
}

configClient, err := cp.createProviderClient(serviceKey, configStem, accessToken, configProviderInfo.ServiceConfig())
if err != nil {
return fmt.Errorf("failed to create Configuration Provider client: %s", err.Error())
}
Expand Down Expand Up @@ -296,9 +309,11 @@ func (cp *Processor) ListenForCustomConfigChanges(
func (cp *Processor) createProviderClient(
serviceKey string,
configStem string,
accessTokenFile string,
providerConfig types.ServiceConfig) (configuration.Client, error) {

providerConfig.BasePath = configStem + serviceKey
providerConfig.AccessToken = accessTokenFile

cp.Logger.Info(fmt.Sprintf(
"Using Configuration provider (%s) from: %s with base path of %s",
Expand Down
14 changes: 14 additions & 0 deletions bootstrap/registration/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"context"
"errors"
"fmt"
"os"

"github.com/edgexfoundry/go-mod-core-contracts/v2/clients"
"github.com/edgexfoundry/go-mod-core-contracts/v2/clients/logger"
Expand All @@ -27,6 +28,7 @@ import (

"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/interfaces"
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/startup"
"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/token"
)

// createRegistryClient creates and returns a registry.Client instance.
Expand All @@ -36,10 +38,22 @@ func createRegistryClient(
lc logger.LoggingClient) (registry.Client, error) {
bootstrapConfig := serviceConfig.GetBootstrap()

tokenFile := bootstrapConfig.Registry.AccessTokenFile
accessToken, err := token.LoadAccessToken(tokenFile)
if err != nil {
// access token file doesn't exist means the access token is not needed.
if os.IsNotExist(err) {
lc.Warnf("Registry access token at %s doesn't exist. Skipping use of access token", tokenFile)
} else {
return nil, fmt.Errorf("unable to load Registry client access token at %s: %s", tokenFile, err.Error())
}
}

registryConfig := registryTypes.Config{
Host: bootstrapConfig.Registry.Host,
Port: bootstrapConfig.Registry.Port,
Type: bootstrapConfig.Registry.Type,
AccessToken: accessToken,
ServiceKey: serviceKey,
ServiceHost: bootstrapConfig.Service.Host,
ServicePort: bootstrapConfig.Service.Port,
Expand Down
37 changes: 37 additions & 0 deletions bootstrap/token/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright 2021 Intel Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*******************************************************************************/

package token

import (
"io/ioutil"
"strings"
)

// LoadAccessToken loads an access token from the specified file path. Since the
// token may not be required, an empty token is returned if the filepath is empty
// or the token file doesn't exist.
func LoadAccessToken(filepath string) (string, error) {
// access token file not specified means the access token is not needed.
if len(strings.TrimSpace(filepath)) == 0 {
return "", nil
}

token, err := ioutil.ReadFile(filepath)
if err != nil {
return "", err
}

return string(token), nil
}
56 changes: 56 additions & 0 deletions bootstrap/token/token_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright 2021 Intel Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*******************************************************************************/

package token

import (
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestLoadAccessToken(t *testing.T) {
expectedToken := "UnitTestToken"
tokenFile := "./consul-token"

err := ioutil.WriteFile(tokenFile, []byte(expectedToken), os.ModePerm)
defer func() { _ = os.Remove(tokenFile) }()
require.NoError(t, err)

tests := []struct {
name string
tokenFile string
expectedToken string
expectError bool
}{
{"token file exists", tokenFile, expectedToken, false},
{"token file doesn't exists", "./no-file", "", true},
{"token file path empty", "", "", false},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actualToken, err := LoadAccessToken(test.tokenFile)
if test.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, test.expectedToken, actualToken)
})
}
}
7 changes: 7 additions & 0 deletions config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ type ServiceInfo struct {
// Timeout specifies a timeout (in milliseconds) for
// processing REST calls from other services.
Timeout int
// ConfigAccessTokenFile is the location of the access token to use with the Configuration Provider client
ConfigAccessTokenFile string
}

// HealthCheck is a URL specifying a health check REST endpoint used by the Registry to determine if the
Expand All @@ -72,9 +74,14 @@ type ConfigProviderInfo struct {

// RegistryInfo defines the type and location (via host/port) of the desired service registry (e.g. Consul, Eureka)
type RegistryInfo struct {
// Host is the host name where the Registry client is running
Host string
// Port is the port number that the Registry client is listening
Port int
// Type is the type of Registry client to use, i.e. 'consul'
Type string
// AccessTokenFile is the location of the access token to use with the Registry client
AccessTokenFile string
}

// ClientInfo provides the host and port of another service in the eco-system.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module github.com/edgexfoundry/go-mod-bootstrap/v2

require (
github.com/BurntSushi/toml v0.3.1
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.62
github.com/edgexfoundry/go-mod-configuration/v2 v2.0.0-dev.5
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.62
github.com/edgexfoundry/go-mod-registry/v2 v2.0.0-dev.4
github.com/edgexfoundry/go-mod-secrets/v2 v2.0.0-dev.10
github.com/gorilla/mux v1.7.1
Expand Down