mirror of https://github.com/hashicorp/boundary
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
9.4 KiB
414 lines
9.4 KiB
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/boundary/internal/errors"
|
|
"github.com/hashicorp/boundary/internal/observability/event"
|
|
"github.com/hashicorp/go-secure-stdlib/configutil"
|
|
"github.com/hashicorp/go-secure-stdlib/listenerutil"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDevController(t *testing.T) {
|
|
actual, err := DevController()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
truePointer := new(bool)
|
|
*truePointer = true
|
|
exp := &Config{
|
|
Eventing: event.DefaultEventerConfig(),
|
|
SharedConfig: &configutil.SharedConfig{
|
|
DisableMlock: true,
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"api"},
|
|
TLSDisable: true,
|
|
CorsEnabled: truePointer,
|
|
CorsAllowedOrigins: []string{"*"},
|
|
},
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"cluster"},
|
|
},
|
|
},
|
|
Seals: []*configutil.KMS{
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"root"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_root",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"worker-auth"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_worker-auth",
|
|
},
|
|
},
|
|
{
|
|
Type: "aead",
|
|
Purpose: []string{"recovery"},
|
|
Config: map[string]string{
|
|
"aead_type": "aes-gcm",
|
|
"key_id": "global_recovery",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Controller: &Controller{
|
|
Name: "dev-controller",
|
|
Description: "A default controller created in dev mode",
|
|
},
|
|
DevController: true,
|
|
}
|
|
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Listeners[1].RawConfig = actual.Listeners[1].RawConfig
|
|
exp.Seals[0].Config["key"] = actual.Seals[0].Config["key"]
|
|
exp.Seals[1].Config["key"] = actual.Seals[1].Config["key"]
|
|
exp.Seals[2].Config["key"] = actual.Seals[2].Config["key"]
|
|
exp.DevControllerKey = actual.Seals[0].Config["key"]
|
|
exp.DevWorkerAuthKey = actual.Seals[1].Config["key"]
|
|
exp.DevRecoveryKey = actual.Seals[2].Config["key"]
|
|
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Do some CORS-specific testing
|
|
{
|
|
// CORS disabled
|
|
conf := `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_enabled = false
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 := actual.Listeners[0]
|
|
assert.False(t, *l0.CorsEnabled)
|
|
assert.Empty(t, l0.CorsAllowedHeaders)
|
|
|
|
// Enabled with a wildcard
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_enabled = true
|
|
cors_allowed_origins = ["*"]
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.True(t, *l0.CorsEnabled)
|
|
assert.Equal(t, []string{"*"}, l0.CorsAllowedOrigins)
|
|
assert.Nil(t, l0.CorsDisableDefaultAllowedOriginValues)
|
|
|
|
// Disabled, default behavior
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.True(t, *l0.CorsEnabled)
|
|
assert.Equal(t, []string{"*"}, l0.CorsAllowedOrigins)
|
|
assert.Nil(t, l0.CorsDisableDefaultAllowedOriginValues)
|
|
|
|
// Disabled, default behavior
|
|
conf = `
|
|
listener "tcp" {
|
|
purpose = "api"
|
|
cors_disable_default_allowed_origin_values = true
|
|
}
|
|
`
|
|
actual, err = Parse(conf)
|
|
assert.NoError(t, err)
|
|
l0 = actual.Listeners[0]
|
|
assert.Nil(t, l0.CorsEnabled)
|
|
assert.Empty(t, l0.CorsAllowedOrigins)
|
|
assert.True(t, *l0.CorsDisableDefaultAllowedOriginValues)
|
|
}
|
|
}
|
|
|
|
func TestDevWorker(t *testing.T) {
|
|
actual, err := DevWorker()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
exp := &Config{
|
|
Eventing: event.DefaultEventerConfig(),
|
|
SharedConfig: &configutil.SharedConfig{
|
|
DisableMlock: true,
|
|
Listeners: []*listenerutil.ListenerConfig{
|
|
{
|
|
Type: "tcp",
|
|
Purpose: []string{"proxy"},
|
|
},
|
|
},
|
|
},
|
|
Worker: &Worker{
|
|
Name: "dev-worker",
|
|
Description: "A default worker created in dev mode",
|
|
Controllers: []string{"127.0.0.1"},
|
|
Tags: map[string][]string{
|
|
"type": {"dev", "local"},
|
|
},
|
|
},
|
|
}
|
|
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Redo it with key=value syntax for tags
|
|
devWorkerKeyValueConfig := `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-worker"
|
|
description = "A default worker created in dev mode"
|
|
controllers = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
actual, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.NoError(t, err)
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
assert.Equal(t, exp, actual)
|
|
|
|
// Handle when there is a singular value not indicated as a slice
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-worker"
|
|
description = "A default worker created in dev mode"
|
|
controllers = ["127.0.0.1"]
|
|
tags {
|
|
type = "local"
|
|
}
|
|
}
|
|
`
|
|
|
|
actual, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.NoError(t, err)
|
|
exp.Listeners[0].RawConfig = actual.Listeners[0].RawConfig
|
|
exp.Worker.TagsRaw = actual.Worker.TagsRaw
|
|
prevTags := exp.Worker.Tags
|
|
exp.Worker.Tags = map[string][]string{"type": {"local"}}
|
|
assert.Equal(t, exp, actual)
|
|
exp.Worker.Tags = prevTags
|
|
|
|
// Redo it with non-lower-cased keys
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-worker"
|
|
description = "A default worker created in dev mode"
|
|
controllers = ["127.0.0.1"]
|
|
tags = ["tyPe=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
|
|
// Redo it with non-lower-cased values
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-worker"
|
|
description = "A default worker created in dev mode"
|
|
controllers = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=loCal"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
|
|
// Redo with non-printable characters to validate the strutil function
|
|
devWorkerKeyValueConfig = `
|
|
listener "tcp" {
|
|
purpose = "proxy"
|
|
}
|
|
|
|
worker {
|
|
name = "dev-work\u0000er"
|
|
description = "A default worker created in dev mode"
|
|
controllers = ["127.0.0.1"]
|
|
tags = ["type=dev", "type=local"]
|
|
}
|
|
`
|
|
|
|
_, err = Parse(devConfig + devWorkerKeyValueConfig)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestParsingName(t *testing.T) {
|
|
t.Parallel()
|
|
config := `
|
|
controller {
|
|
name = "%s"
|
|
}
|
|
worker {
|
|
name = "%s"
|
|
}
|
|
`
|
|
controllerEnv := "FOOENV"
|
|
workerEnv := "BARENV"
|
|
cases := []struct {
|
|
name string
|
|
templateController string
|
|
templateWorker string
|
|
envController string
|
|
envWorker string
|
|
expectedController string
|
|
expectedWorker string
|
|
}{
|
|
{
|
|
name: "no env",
|
|
templateController: "foobar",
|
|
templateWorker: "barfoo",
|
|
expectedController: "foobar",
|
|
expectedWorker: "barfoo",
|
|
},
|
|
{
|
|
name: "env",
|
|
templateController: fmt.Sprintf("env://%s", controllerEnv),
|
|
templateWorker: fmt.Sprintf("env://%s", workerEnv),
|
|
envController: "foobar2",
|
|
envWorker: "barfoo2",
|
|
expectedController: "foobar2",
|
|
expectedWorker: "barfoo2",
|
|
},
|
|
}
|
|
for _, tt := range cases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.envController != "" {
|
|
os.Setenv(controllerEnv, tt.envController)
|
|
}
|
|
if tt.envWorker != "" {
|
|
os.Setenv(workerEnv, tt.envWorker)
|
|
}
|
|
out, err := Parse(fmt.Sprintf(config, tt.templateController, tt.templateWorker))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expectedController, out.Controller.Name)
|
|
assert.Equal(t, tt.expectedWorker, out.Worker.Name)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_EventingConfig(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
config string
|
|
wantEventerConfig *event.EventerConfig
|
|
wantErrMatch *errors.Template
|
|
}{
|
|
{
|
|
name: "default",
|
|
wantEventerConfig: event.DefaultEventerConfig(),
|
|
},
|
|
{
|
|
name: "audit-enabled",
|
|
config: `
|
|
events {
|
|
audit_enabled = true
|
|
}
|
|
`,
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: true,
|
|
ObservationsEnabled: false,
|
|
Sinks: []event.SinkConfig{
|
|
event.DefaultSink(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "observations-enabled",
|
|
config: `
|
|
events {
|
|
observations_enabled = true
|
|
}
|
|
`,
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: false,
|
|
ObservationsEnabled: true,
|
|
Sinks: []event.SinkConfig{
|
|
event.DefaultSink(),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "sinks-configured",
|
|
config: `
|
|
events {
|
|
audit_enabled = false
|
|
observations_enabled = true
|
|
sinks = [
|
|
{
|
|
name = "configured-sink"
|
|
file_name = "file-name"
|
|
event_types = [ "audit", "observation" ]
|
|
}
|
|
]
|
|
}
|
|
`,
|
|
wantEventerConfig: &event.EventerConfig{
|
|
AuditEnabled: false,
|
|
ObservationsEnabled: true,
|
|
Sinks: []event.SinkConfig{
|
|
{
|
|
Name: "configured-sink",
|
|
FileName: "file-name",
|
|
EventTypes: []event.Type{"audit", "observation"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
assert, require := assert.New(t), require.New(t)
|
|
c, err := Parse(tt.config)
|
|
if tt.wantErrMatch != nil {
|
|
require.NoError(err)
|
|
assert.Empty(c)
|
|
assert.Truef(errors.Match(tt.wantErrMatch, err), "want %q and got %q", tt.wantErrMatch.Code, err.Error())
|
|
return
|
|
}
|
|
require.NoError(err)
|
|
assert.NotEmpty(c)
|
|
assert.Equal(tt.wantEventerConfig, c.Eventing)
|
|
})
|
|
}
|
|
}
|