diff --git a/internal/cmd/config/config.go b/internal/cmd/config/config.go index 71a693c6a..85d6f6c18 100644 --- a/internal/cmd/config/config.go +++ b/internal/cmd/config/config.go @@ -22,6 +22,8 @@ import ( ) const ( + desktopCorsOrigin = "serve://boundary" + devConfig = ` disable_mlock = true @@ -327,13 +329,20 @@ func Parse(d string) (*Config, error) { } result.SharedConfig = sharedConfig - // If cors wasn't specified, enable default values for _, listener := range result.SharedConfig.Listeners { - if strutil.StrListContains(listener.Purpose, "api") { + if strutil.StrListContains(listener.Purpose, "api") && + (listener.CorsDisableDefaultAllowedOriginValues == nil || !*listener.CorsDisableDefaultAllowedOriginValues) { + // If CORS wasn't specified, enable default values if listener.CorsEnabled == nil { listener.CorsEnabled = new(bool) *listener.CorsEnabled = true - listener.CorsAllowedOrigins = []string{"serve://boundary"} + listener.CorsAllowedOrigins = []string{desktopCorsOrigin} + } + // If not the wildcard and they haven't disabled us auto-adding + // origin values, add the desktop client origin + if *listener.CorsEnabled && + !strutil.StrListContains(listener.CorsAllowedOrigins, "*") { + listener.CorsAllowedOrigins = strutil.AppendIfMissing(listener.CorsAllowedOrigins, desktopCorsOrigin) } } } diff --git a/internal/cmd/config/config_test.go b/internal/cmd/config/config_test.go index fa96d4a65..64244760e 100644 --- a/internal/cmd/config/config_test.go +++ b/internal/cmd/config/config_test.go @@ -82,6 +82,64 @@ func TestDevController(t *testing.T) { 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{desktopCorsOrigin}, 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) { diff --git a/website/content/docs/configuration/listener/tcp.mdx b/website/content/docs/configuration/listener/tcp.mdx index 7dbd131d7..804091b4a 100644 --- a/website/content/docs/configuration/listener/tcp.mdx +++ b/website/content/docs/configuration/listener/tcp.mdx @@ -61,14 +61,28 @@ allowed. `default_max_request_duration` for this listener. - `cors_enabled` `(boolean: true)` - Specifies if CORS should be enabled, which - allows Boundary to support external browser-based clients (not including - admin UI), such as Boundary Desktop. + allows Boundary to support external browser-based clients (not including admin + UI), such as Boundary Desktop. If not specified, CORS will be enabled with an + allowed origin that grants access to Boundary Desktop, unless overridden with + `cors_disable_default_allowed_origin_values`. -- `cors_allowed_origins` `(array(string): ["serve://boundary"])` - an array of +- `cors_disable_default_allowed_origin_values` `(boolean: false)` - Specifies + that Boundary should not append default allowed origin values to any specified + in `cors_allowed_origins`, such as Boundary Desktop's origin. This also + disables the behavior of enabling CORS if `cors_enabled` is not specified. + +- `cors_allowed_origins` `(array(string): ["serve://boundary"])` - An array of allowed CORS origins. Origins must include protocol, host, and port (if port - is different than the default for the specified protocol). - To allow all origins, set to `['*']`. By default, Boundary Desktop's origin - `serve://boundary` is allowed. + is different than the default for the specified protocol). To allow all + origins, set to `['*']`. By default, Boundary Desktop's origin + `serve://boundary` is appended to any values included here, unless + `cors_disable_default_allowed_origin_values` is specified. + +- `cors_allowed_headers` `(array(string): [])` – An array specifying headers + that are permitted to be on cross-origin requests. Headers set via this + parameter will be appended to the list of headers that Boundary allows by + default, such as `"Content-Type"`, `"X-Requested-With"`, and + `"Authorization"`. ### TLS diff --git a/website/content/docs/configuration/listener/unix.mdx b/website/content/docs/configuration/listener/unix.mdx index 9d8eb2741..44d1f8c49 100644 --- a/website/content/docs/configuration/listener/unix.mdx +++ b/website/content/docs/configuration/listener/unix.mdx @@ -62,14 +62,28 @@ allowed. `default_max_request_duration` for this listener. - `cors_enabled` `(boolean: true)` - Specifies if CORS should be enabled, which - allows Boundary to support external browser-based clients (not including - admin UI), such as Boundary Desktop. + allows Boundary to support external browser-based clients (not including admin + UI), such as Boundary Desktop. If not specified, CORS will be enabled with an + allowed origin that grants access to Boundary Desktop, unless overridden with + `cors_disable_default_allowed_origin_values`. -- `cors_allowed_origins` `(array(string): ["serve://boundary"])` - an array of +- `cors_disable_default_allowed_origin_values` `(boolean: false)` - Specifies + that Boundary should not append default allowed origin values to any specified + in `cors_allowed_origins`, such as Boundary Desktop's origin. This also + disables the behavior of enabling CORS if `cors_enabled` is not specified. + +- `cors_allowed_origins` `(array(string): ["serve://boundary"])` - An array of allowed CORS origins. Origins must include protocol, host, and port (if port - is different than the default for the specified protocol). - To allow all origins, set to `['*']`. By default, Boundary Desktop's origin - `serve://boundary` is allowed. + is different than the default for the specified protocol). To allow all + origins, set to `['*']`. By default, Boundary Desktop's origin + `serve://boundary` is appended to any values included here, unless + `cors_disable_default_allowed_origin_values` is specified. + +- `cors_allowed_headers` `(array(string): [])` – An array specifying headers + that are permitted to be on cross-origin requests. Headers set via this + parameter will be appended to the list of headers that Boundary allows by + default, such as `"Content-Type"`, `"X-Requested-With"`, and + `"Authorization"`. ### TLS