Skip to content

Commit

Permalink
Fix so that link API values are used over env vars
Browse files Browse the repository at this point in the history
When a link is created via the API, those values should take precedence over
the values set by environment variables. This change loads all the env vars
initially as part of the config builder rather than on demand.
  • Loading branch information
mkam committed Feb 7, 2024
1 parent 45d6454 commit d0ad88a
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 10 deletions.
66 changes: 57 additions & 9 deletions agent/config/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package config

import (
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
Expand Down Expand Up @@ -2580,11 +2581,37 @@ func validateAutoConfigAuthorizer(rt RuntimeConfig) error {
}

func (b *builder) cloudConfigVal(v Config) hcpconfig.CloudConfig {
// Load the same environment variables expected by hcp-sdk-go
envHostname, ok := os.LookupEnv("HCP_API_ADDRESS")
if !ok {
if legacyEnvHostname, ok := os.LookupEnv("HCP_API_HOST"); ok {
// Remove only https scheme prefixes from the deprecated environment
// variable for specifying the API host. Mirrors the same behavior as
// hcp-sdk-go.
if strings.HasPrefix(strings.ToLower(legacyEnvHostname), "https://") {
legacyEnvHostname = legacyEnvHostname[8:]
}
envHostname = legacyEnvHostname
}
}

var envTLSConfig *tls.Config
if os.Getenv("HCP_AUTH_TLS") == "insecure" ||
os.Getenv("HCP_SCADA_TLS") == "insecure" ||
os.Getenv("HCP_API_TLS") == "insecure" {
envTLSConfig = &tls.Config{InsecureSkipVerify: true}
}

val := hcpconfig.CloudConfig{
ResourceID: os.Getenv("HCP_RESOURCE_ID"),
ClientID: os.Getenv("HCP_CLIENT_ID"),
ClientSecret: os.Getenv("HCP_CLIENT_SECRET"),
AuthURL: os.Getenv("HCP_AUTH_URL"),
Hostname: envHostname,
ScadaAddress: os.Getenv("HCP_SCADA_ADDRESS"),
TLSConfig: envTLSConfig,
}

// Node id might get overridden in setup.go:142
nodeID := stringVal(v.NodeID)
val.NodeID = types.NodeID(nodeID)
Expand All @@ -2594,20 +2621,41 @@ func (b *builder) cloudConfigVal(v Config) hcpconfig.CloudConfig {
return val
}

val.AuthURL = stringVal(v.Cloud.AuthURL)
val.Hostname = stringVal(v.Cloud.Hostname)
val.ScadaAddress = stringVal(v.Cloud.ScadaAddress)
// Load configuration file variables for anything not set by environment variables
if val.AuthURL == "" {
if authURL := stringVal(v.Cloud.AuthURL); authURL != "" {
val.AuthURL = authURL
}
}

if resourceID := stringVal(v.Cloud.ResourceID); resourceID != "" {
val.ResourceID = resourceID
if val.Hostname == "" {
if hostname := stringVal(v.Cloud.Hostname); hostname != "" {
val.Hostname = hostname
}
}

if clientID := stringVal(v.Cloud.ClientID); clientID != "" {
val.ClientID = clientID
if val.ScadaAddress == "" {
if scadaAddress := stringVal(v.Cloud.ScadaAddress); scadaAddress != "" {
val.ScadaAddress = scadaAddress
}
}

if val.ResourceID == "" {
if resourceID := stringVal(v.Cloud.ResourceID); resourceID != "" {
val.ResourceID = resourceID
}
}

if clientSecret := stringVal(v.Cloud.ClientSecret); clientSecret != "" {
val.ClientSecret = clientSecret
if val.ClientID == "" {
if clientID := stringVal(v.Cloud.ClientID); clientID != "" {
val.ClientID = clientID
}
}

if val.ClientSecret == "" {
if clientSecret := stringVal(v.Cloud.ClientSecret); clientSecret != "" {
val.ClientSecret = clientSecret
}
}

return val
Expand Down
106 changes: 106 additions & 0 deletions agent/config/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

hcpconfig "github.com/hashicorp/consul/agent/hcp/config"
"github.com/hashicorp/consul/types"
)

Expand Down Expand Up @@ -707,3 +708,108 @@ func TestBuilder_WarnCloudConfigWithResourceApis(t *testing.T) {
}
}
}

func TestBuilder_CloudConfigWithEnvironmentVars(t *testing.T) {
tests := map[string]struct {
hcl string
env map[string]string
expected hcpconfig.CloudConfig
}{
"ConfigurationOnly": {
hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id"
client_secret = "config-client-secret" auth_url = "auth.config.com"
hostname = "api.config.com" scada_address = "scada.config.com"}`,
expected: hcpconfig.CloudConfig{
ResourceID: "config-resource-id",
ClientID: "config-client-id",
ClientSecret: "config-client-secret",
AuthURL: "auth.config.com",
Hostname: "api.config.com",
ScadaAddress: "scada.config.com",
},
},
"EnvVarsOnly": {
env: map[string]string{
"HCP_RESOURCE_ID": "env-resource-id",
"HCP_CLIENT_ID": "env-client-id",
"HCP_CLIENT_SECRET": "env-client-secret",
"HCP_AUTH_URL": "auth.env.com",
"HCP_API_ADDRESS": "api.env.com",
"HCP_SCADA_ADDRESS": "scada.env.com",
},
expected: hcpconfig.CloudConfig{
ResourceID: "env-resource-id",
ClientID: "env-client-id",
ClientSecret: "env-client-secret",
AuthURL: "auth.env.com",
Hostname: "api.env.com",
ScadaAddress: "scada.env.com",
},
},
"EnvVarsOverrideConfig": {
hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id"
client_secret = "config-client-secret" auth_url = "auth.config.com"
hostname = "api.config.com" scada_address = "scada.config.com"}`,
env: map[string]string{
"HCP_RESOURCE_ID": "env-resource-id",
"HCP_CLIENT_ID": "env-client-id",
"HCP_CLIENT_SECRET": "env-client-secret",
"HCP_AUTH_URL": "auth.env.com",
"HCP_API_ADDRESS": "api.env.com",
"HCP_SCADA_ADDRESS": "scada.env.com",
},
expected: hcpconfig.CloudConfig{
ResourceID: "env-resource-id",
ClientID: "env-client-id",
ClientSecret: "env-client-secret",
AuthURL: "auth.env.com",
Hostname: "api.env.com",
ScadaAddress: "scada.env.com",
},
},
"Combination": {
hcl: `cloud{ resource_id = "config-resource-id" client_id = "config-client-id"
client_secret = "config-client-secret"}`,
env: map[string]string{
"HCP_AUTH_URL": "auth.env.com",
"HCP_API_ADDRESS": "api.env.com",
"HCP_SCADA_ADDRESS": "scada.env.com",
},
expected: hcpconfig.CloudConfig{
ResourceID: "config-resource-id",
ClientID: "config-client-id",
ClientSecret: "config-client-secret",
AuthURL: "auth.env.com",
Hostname: "api.env.com",
ScadaAddress: "scada.env.com",
},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
for k, v := range tc.env {
t.Setenv(k, v)
}
devMode := true
builderOpts := LoadOpts{
DevMode: &devMode,
Overrides: []Source{
FileSource{
Name: "overrides",
Format: "hcl",
Data: tc.hcl,
},
},
}
loaded, err := Load(builderOpts)
require.NoError(t, err)

nodeName, err := os.Hostname()
require.NoError(t, err)
tc.expected.NodeName = nodeName

actual := loaded.RuntimeConfig.Cloud
require.Equal(t, tc.expected, actual)
})
}
}
10 changes: 9 additions & 1 deletion agent/hcp/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ func (c *CloudConfig) Resource() (resource.Resource, error) {
return resource.FromString(c.ResourceID)
}

// HCPConfig returns a configuration to use with the HCP SDK. It assumes that the environment
// variables for the HCP configuration have already been loaded and set in the CloudConfig.
func (c *CloudConfig) HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfig, error) {
// Prevent attempting to login via a browser
opts = append(opts, hcpcfg.WithoutBrowserLogin())

// Load from environment variables first to support any configurations that can only be
// set via environment variables and not the CloudConfig.
opts = append(opts, hcpcfg.FromEnv())

if c.TLSConfig == nil {
c.TLSConfig = &tls.Config{}
}
Expand All @@ -62,7 +71,6 @@ func (c *CloudConfig) HCPConfig(opts ...hcpcfg.HCPConfigOption) (hcpcfg.HCPConfi
if c.ScadaAddress != "" {
opts = append(opts, hcpcfg.WithSCADA(c.ScadaAddress, c.TLSConfig))
}
opts = append(opts, hcpcfg.FromEnv(), hcpcfg.WithoutBrowserLogin())
return hcpcfg.NewHCPConfig(opts...)
}

Expand Down

0 comments on commit d0ad88a

Please sign in to comment.