From 728ba8511ed0bc212119d6477c0d3e25834825ed Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sat, 15 Jul 2017 14:35:14 -0400 Subject: [PATCH 01/27] This comment didn't make a lot of sense. --- vault/core.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vault/core.go b/vault/core.go index 725f7f775eab..ffeab2891988 100644 --- a/vault/core.go +++ b/vault/core.go @@ -454,8 +454,8 @@ func NewCore(conf *CoreConfig) (*Core, error) { enableMlock: !conf.DisableMlock, } - // Load CORS config and provide core c.corsConfig = &CORSConfig{core: c} + // Load CORS config and provide a value for the core field. // Wrap the physical backend in a cache layer if enabled and not already wrapped if _, isCache := conf.Physical.(*physical.Cache); !conf.DisableCache && !isCache { From 6c44bcb2028ab17d48b10f5a2849e16731aced68 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sat, 15 Jul 2017 16:17:06 -0400 Subject: [PATCH 02/27] Added new field AllowedHeaders. Enable func now accepts a slice of headers. --- vault/cors.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/vault/cors.go b/vault/cors.go index c1fd961284c2..e74b9f131879 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -21,6 +21,7 @@ type CORSConfig struct { core *Core Enabled uint32 `json:"enabled"` AllowedOrigins []string `json:"allowed_origins,omitempty"` + AllowedHeaders []string `json:"allowed_headers,omitempty"` } func (c *Core) saveCORSConfig() error { @@ -72,7 +73,7 @@ func (c *Core) loadCORSConfig() error { // Enable takes either a '*' or a comma-seprated list of URLs that can make // cross-origin requests to Vault. -func (c *CORSConfig) Enable(urls []string) error { +func (c *CORSConfig) Enable(urls []string, headers []string) error { if len(urls) == 0 { return errors.New("the list of allowed origins cannot be empty") } @@ -85,6 +86,14 @@ func (c *CORSConfig) Enable(urls []string) error { c.AllowedOrigins = urls c.Unlock() + // Allow the user to add additional headers to the list of + // headers allowed on cross-origin requests. + if len(headers) > 0 { + c.Lock() + c.AllowedHeaders = append(c.AllowedHeaders, headers...) + c.Unlock() + } + atomic.StoreUint32(&c.Enabled, CORSEnabled) return c.core.saveCORSConfig() From bd4d0066a509cfa63cb87533e94b04f796d37644 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:37:55 -0400 Subject: [PATCH 03/27] Cleaned up comment. --- http/cors.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/http/cors.go b/http/cors.go index 2a25a377fc67..769148f5acae 100644 --- a/http/cors.go +++ b/http/cors.go @@ -38,8 +38,7 @@ func wrapCORSHandler(h http.Handler, core *vault.Core) http.Handler { return } - // Return a 403 if the origin is not - // allowed to make cross-origin requests. + // Return a 403 if the origin is not allowed to make cross-origin requests. if !corsConf.IsValidOrigin(origin) { respondError(w, http.StatusForbidden, fmt.Errorf("origin not allowed")) return From 1ee92b3a4f2a7c354b06e077174c024a67ec4903 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:39:02 -0400 Subject: [PATCH 04/27] No need to have the preflight headers as a package global. --- http/cors.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/http/cors.go b/http/cors.go index 769148f5acae..a01228be2da6 100644 --- a/http/cors.go +++ b/http/cors.go @@ -9,11 +9,6 @@ import ( "github.com/hashicorp/vault/vault" ) -var preflightHeaders = map[string]string{ - "Access-Control-Allow-Headers": "*", - "Access-Control-Max-Age": "300", -} - var allowedMethods = []string{ http.MethodDelete, http.MethodGet, @@ -55,10 +50,9 @@ func wrapCORSHandler(h http.Handler, core *vault.Core) http.Handler { // apply headers for preflight requests if req.Method == http.MethodOptions { w.Header().Set("Access-Control-Allow-Methods", strings.Join(allowedMethods, ",")) + w.Header().Set("Access-Control-Allow-Headers", strings.Join(corsConf.AllowedHeaders, ",")) + w.Header().Set("Access-Control-Max-Age", "300") - for k, v := range preflightHeaders { - w.Header().Set(k, v) - } return } From c4ca1e68136fb2ee6bc7d9a1fe8c1c43e45178e4 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:39:38 -0400 Subject: [PATCH 05/27] Added the headers param. --- http/handler_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/handler_test.go b/http/handler_test.go index 41a7a69c7ad4..45b96f12b295 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -21,7 +21,7 @@ func TestHandler_cors(t *testing.T) { // Enable CORS and allow from any origin for testing. corsConfig := core.CORSConfig() - err := corsConfig.Enable([]string{addr}) + err := corsConfig.Enable([]string{addr}, []string{}) if err != nil { t.Fatalf("Error enabling CORS: %s", err) } From 31770b65bc6b1979afb88fdc96165f37e2c90344 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:40:39 -0400 Subject: [PATCH 06/27] Specifying the actual headers instead of using the wildcard. --- http/handler_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/handler_test.go b/http/handler_test.go index 45b96f12b295..d99fa4be31c5 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -78,7 +78,7 @@ func TestHandler_cors(t *testing.T) { // expHeaders := map[string]string{ "Access-Control-Allow-Origin": addr, - "Access-Control-Allow-Headers": "*", + "Access-Control-Allow-Headers": "Content-Type,X-Requested-With,X-Vault-AWS-IAM-Server-ID,X-Vault-No-Request-Forwarding,X-Vault-Token,X-Vault-Wrap-Format,X-Vault-Wrap-TTL", "Access-Control-Max-Age": "300", "Vary": "Origin", } From 8aad9e3d0094e90d1f870bbdc91d14c1bd5a54bc Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:41:53 -0400 Subject: [PATCH 07/27] Added list of standard headers that are allowed on CORS requests. --- vault/cors.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vault/cors.go b/vault/cors.go index e74b9f131879..0e2108d7483a 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -15,6 +15,16 @@ const ( CORSEnabled ) +var stdAllowedHeaders = []string{ + "Content-Type", + "X-Requested-With", + "X-Vault-AWS-IAM-Server-ID", + "X-Vault-No-Request-Forwarding", + "X-Vault-Token", + "X-Vault-Wrap-Format", + "X-Vault-Wrap-TTL", +} + // CORSConfig stores the state of the CORS configuration. type CORSConfig struct { sync.RWMutex `json:"-"` From aeae18831180cf8631ba186195c5ded90de9bef1 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:43:27 -0400 Subject: [PATCH 08/27] Made origin param no longer required to enable CORS. Defaults to wildcard. --- vault/cors.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vault/cors.go b/vault/cors.go index 0e2108d7483a..e54ae62031c9 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -85,10 +85,8 @@ func (c *Core) loadCORSConfig() error { // cross-origin requests to Vault. func (c *CORSConfig) Enable(urls []string, headers []string) error { if len(urls) == 0 { - return errors.New("the list of allowed origins cannot be empty") - } - - if strutil.StrListContains(urls, "*") && len(urls) > 1 { + urls = append(urls, "*") + } else if strutil.StrListContains(urls, "*") { return errors.New("to allow all origins the '*' must be the only value for allowed_origins") } From 89ef2679bab314953f8a9853a8cd144c1349c4e8 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:44:18 -0400 Subject: [PATCH 09/27] Allowed headers defaults to stdAllowedHeaders. --- vault/cors.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vault/cors.go b/vault/cors.go index e54ae62031c9..a29699a96410 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -94,6 +94,10 @@ func (c *CORSConfig) Enable(urls []string, headers []string) error { c.AllowedOrigins = urls c.Unlock() + c.Lock() + c.AllowedHeaders = stdAllowedHeaders + c.Unlock() + // Allow the user to add additional headers to the list of // headers allowed on cross-origin requests. if len(headers) > 0 { From ce6d754430c26dbf4654ca751309624583502e49 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:44:43 -0400 Subject: [PATCH 10/27] Clearing AllowedHeaders when CORS is disabled. --- vault/cors.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vault/cors.go b/vault/cors.go index a29699a96410..e9efd2e4b9ed 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -116,12 +116,17 @@ func (c *CORSConfig) IsEnabled() bool { return atomic.LoadUint32(&c.Enabled) == CORSEnabled } -// Disable sets CORS to disabled and clears the allowed origins +// Disable sets CORS to disabled and clears the allowed origins & headers. func (c *CORSConfig) Disable() error { atomic.StoreUint32(&c.Enabled, CORSDisabled) c.Lock() c.AllowedOrigins = []string(nil) c.Unlock() + + c.Lock() + c.AllowedHeaders = []string(nil) + c.Unlock() + return c.core.saveCORSConfig() } From c1d629bb0fc475e45b499cd05423b4a22e5ded2b Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:47:25 -0400 Subject: [PATCH 11/27] Added headers to call to Enable. --- vault/logical_system.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vault/logical_system.go b/vault/logical_system.go index 583859d05a49..0ae93bd1c12e 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -859,8 +859,9 @@ func (b *SystemBackend) handleCORSRead(req *logical.Request, d *framework.FieldD // cross-origin requests and sets the CORS enabled flag to true func (b *SystemBackend) handleCORSUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { origins := d.Get("allowed_origins").([]string) + headers := d.Get("allowed_headers").([]string) - return nil, b.Core.corsConfig.Enable(origins) + return nil, b.Core.corsConfig.Enable(origins, headers) } // handleCORSDelete clears the allowed origins and sets the CORS enabled flag From 558e95563c56c167aa2c7e4eda730d3c9a307c8d Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:47:44 -0400 Subject: [PATCH 12/27] Updated comment. --- vault/logical_system.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vault/logical_system.go b/vault/logical_system.go index 0ae93bd1c12e..cfbde6dac97b 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -864,8 +864,8 @@ func (b *SystemBackend) handleCORSUpdate(req *logical.Request, d *framework.Fiel return nil, b.Core.corsConfig.Enable(origins, headers) } -// handleCORSDelete clears the allowed origins and sets the CORS enabled flag -// to false +// handleCORSDelete sets the CORS enabled flag to false and clears the list of +// allowed origins & headers. func (b *SystemBackend) handleCORSDelete(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { return nil, b.Core.corsConfig.Disable() } From ea6debafb1980cb7d3c41c404a50fa6443149e27 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:48:11 -0400 Subject: [PATCH 13/27] Added list of allowed headers to response. --- vault/logical_system.go | 1 + 1 file changed, 1 insertion(+) diff --git a/vault/logical_system.go b/vault/logical_system.go index cfbde6dac97b..8586b3a49a11 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -849,6 +849,7 @@ func (b *SystemBackend) handleCORSRead(req *logical.Request, d *framework.FieldD if enabled { corsConf.RLock() resp.Data["allowed_origins"] = corsConf.AllowedOrigins + resp.Data["allowed_headers"] = corsConf.AllowedHeaders corsConf.RUnlock() } From 5d289ede87b650a4466e64881e4c645908465ff9 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:48:29 -0400 Subject: [PATCH 14/27] Added allowed_headers field. --- vault/logical_system.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vault/logical_system.go b/vault/logical_system.go index 8586b3a49a11..b622c0d76703 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -112,6 +112,10 @@ func NewSystemBackend(core *Core) *SystemBackend { Type: framework.TypeCommaStringSlice, Description: "A comma-separated string or array of strings indicating origins that may make cross-origin requests.", }, + "allowed_headers": &framework.FieldSchema{ + Type: framework.TypeCommaStringSlice, + Description: "A comma-separated string or array of strings indicating headers that are allowed on cross-origin requests.", + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ From e8a68e8019dfa0ec1e582194f12290a70657e6cb Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 11:48:55 -0400 Subject: [PATCH 15/27] Initial commit of test. --- http/sys_config_cors_test.go | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 http/sys_config_cors_test.go diff --git a/http/sys_config_cors_test.go b/http/sys_config_cors_test.go new file mode 100644 index 000000000000..19517f7c4c82 --- /dev/null +++ b/http/sys_config_cors_test.go @@ -0,0 +1,68 @@ +package http + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/hashicorp/vault/vault" +) + +func TestSysConfigCors(t *testing.T) { + core, _, token := vault.TestCoreUnsealed(t) + ln, addr := TestServer(t, core) + defer ln.Close() + TestServerAuth(t, addr, token) + + corsConf := core.CORSConfig() + + // Enable CORS + resp := testHttpPut(t, token, addr+"/v1/sys/config/cors", map[string]interface{}{ + "allowed_origins": addr, + "allowed_headers": "X-Custom-Header", + }) + + testResponseStatus(t, resp, 204) + + // Read the CORS configuration + resp = testHttpGet(t, token, addr+"/v1/sys/config/cors") + testResponseStatus(t, resp, 200) + + var actual map[string]interface{} + var expected map[string]interface{} + + lenStdHeaders := len(corsConf.AllowedHeaders) + + expectedHeaders := make([]interface{}, lenStdHeaders) + + for i := range corsConf.AllowedHeaders { + expectedHeaders[i] = corsConf.AllowedHeaders[i] + } + + expected = map[string]interface{}{ + "lease_id": "", + "renewable": false, + "lease_duration": json.Number("0"), + "wrap_info": nil, + "warnings": nil, + "auth": nil, + "data": map[string]interface{}{ + "enabled": true, + "allowed_origins": []interface{}{addr}, + "allowed_headers": expectedHeaders, + }, + "enabled": true, + "allowed_origins": []interface{}{addr}, + "allowed_headers": expectedHeaders, + } + + testResponseStatus(t, resp, 200) + + testResponseBody(t, resp, &actual) + expected["request_id"] = actual["request_id"] + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad: expected: %#v\nactual: %#v", expected, actual) + } + +} From 704e7a3162cce1786d834939abc1561883c0cf79 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 13:48:23 -0400 Subject: [PATCH 16/27] Persisting the allowed headers. --- vault/cors.go | 1 + 1 file changed, 1 insertion(+) diff --git a/vault/cors.go b/vault/cors.go index e9efd2e4b9ed..7271ee0d04c0 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -42,6 +42,7 @@ func (c *Core) saveCORSConfig() error { } c.corsConfig.RLock() localConfig.AllowedOrigins = c.corsConfig.AllowedOrigins + localConfig.AllowedHeaders = c.corsConfig.AllowedHeaders c.corsConfig.RUnlock() entry, err := logical.StorageEntryJSON("cors", localConfig) From 158f690e59242ee13fa61c45285f1f66e2630a54 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 13:48:55 -0400 Subject: [PATCH 17/27] Set default allowed headers if they have not been set yet. --- vault/cors.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vault/cors.go b/vault/cors.go index 7271ee0d04c0..d323c760c684 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -96,16 +96,16 @@ func (c *CORSConfig) Enable(urls []string, headers []string) error { c.Unlock() c.Lock() - c.AllowedHeaders = stdAllowedHeaders - c.Unlock() + if len(c.AllowedHeaders) == 0 { + c.AllowedHeaders = append(c.AllowedHeaders, stdAllowedHeaders...) + } // Allow the user to add additional headers to the list of // headers allowed on cross-origin requests. if len(headers) > 0 { - c.Lock() c.AllowedHeaders = append(c.AllowedHeaders, headers...) - c.Unlock() } + c.Unlock() atomic.StoreUint32(&c.Enabled, CORSEnabled) From 5cd956d92321f70a51001c56b5608351302d8264 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 13:49:46 -0400 Subject: [PATCH 18/27] allowed_origins is returned as an array. --- website/source/api/system/config-cors.html.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/api/system/config-cors.html.md b/website/source/api/system/config-cors.html.md index 659a74a38cb4..c65604033acf 100644 --- a/website/source/api/system/config-cors.html.md +++ b/website/source/api/system/config-cors.html.md @@ -34,7 +34,7 @@ $ curl \ ```json { "enabled": true, - "allowed_origins": "http://www.example.com" + "allowed_origins": ["http://www.example.com"], } ``` From dafb1f828bc9286badf0f2d2dbb2ea0a9a3875fa Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 13:50:00 -0400 Subject: [PATCH 19/27] Added docs for allowed_headers. --- website/source/api/system/config-cors.html.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/website/source/api/system/config-cors.html.md b/website/source/api/system/config-cors.html.md index c65604033acf..307f94003b52 100644 --- a/website/source/api/system/config-cors.html.md +++ b/website/source/api/system/config-cors.html.md @@ -35,13 +35,22 @@ $ curl \ { "enabled": true, "allowed_origins": ["http://www.example.com"], + "allowed_headers": [ + "Content-Type", + "X-Requested-With", + "X-Vault-AWS-IAM-Server-ID", + "X-Vault-No-Request-Forwarding", + "X-Vault-Token", + "X-Vault-Wrap-Format", + "X-Vault-Wrap-TTL", + ] } ``` ## Configure CORS Settings This endpoint allows configuring the origins that are permitted to make -cross-origin requests. +cross-origin requests, as well as headers that are allowed on cross-origin requests. | Method | Path | Produces | | :------- | :--------------------------- | :--------------------- | @@ -51,11 +60,14 @@ cross-origin requests. - `allowed_origins` `(string or string array: "" or [])` – A wildcard (`*`), comma-delimited string, or array of strings specifying the origins that are permitted to make cross-origin requests. +- `allowed_headers` `(string or string array: "" or [])` – A comma-delimited string or array of strings 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 Vault allows by default. + ### Sample Payload ```json { - "allowed_origins": "*" + "allowed_origins": "*", + "allowed_headers": "X-Custom-Header" } ``` From e29e68a40bf097701244fa147e9ce34c2cac5ad4 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 16 Jul 2017 14:30:55 -0400 Subject: [PATCH 20/27] Added allowed_headers to request and expected result. --- vault/logical_system_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 12b7c5de3f75..a40bab2225b9 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -55,6 +55,7 @@ func TestSystemConfigCORS(t *testing.T) { req := logical.TestRequest(t, logical.UpdateOperation, "config/cors") req.Data["allowed_origins"] = "http://www.example.com" + req.Data["allowed_headers"] = "X-Custom-Header" _, err := b.HandleRequest(req) if err != nil { t.Fatal(err) @@ -64,6 +65,7 @@ func TestSystemConfigCORS(t *testing.T) { Data: map[string]interface{}{ "enabled": true, "allowed_origins": []string{"http://www.example.com"}, + "allowed_headers": append(stdAllowedHeaders, "X-Custom-Header"), }, } From 0f54b4da4d421a36654e4ae4cb5e848625913ed3 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 12:27:15 -0400 Subject: [PATCH 21/27] Removing unnecessary locking/unlocking. --- vault/cors.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vault/cors.go b/vault/cors.go index d323c760c684..f27d30daa4e7 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -93,9 +93,7 @@ func (c *CORSConfig) Enable(urls []string, headers []string) error { c.Lock() c.AllowedOrigins = urls - c.Unlock() - c.Lock() if len(c.AllowedHeaders) == 0 { c.AllowedHeaders = append(c.AllowedHeaders, stdAllowedHeaders...) } @@ -121,11 +119,10 @@ func (c *CORSConfig) IsEnabled() bool { func (c *CORSConfig) Disable() error { atomic.StoreUint32(&c.Enabled, CORSDisabled) c.Lock() - c.AllowedOrigins = []string(nil) - c.Unlock() - c.Lock() + c.AllowedOrigins = []string(nil) c.AllowedHeaders = []string(nil) + c.Unlock() return c.core.saveCORSConfig() From 0a051546e38051a4da3dea275f3fb5983e7b7de7 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 12:32:19 -0400 Subject: [PATCH 22/27] Fixing logic error. --- vault/cors.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vault/cors.go b/vault/cors.go index f27d30daa4e7..4ab5d7d6b479 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -85,9 +85,7 @@ func (c *Core) loadCORSConfig() error { // Enable takes either a '*' or a comma-seprated list of URLs that can make // cross-origin requests to Vault. func (c *CORSConfig) Enable(urls []string, headers []string) error { - if len(urls) == 0 { - urls = append(urls, "*") - } else if strutil.StrListContains(urls, "*") { + if strutil.StrListContains(urls, "*") && len(urls) > 1 { return errors.New("to allow all origins the '*' must be the only value for allowed_origins") } From 88c20e1bdb7df07e76751166870aa4615a69c106 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 12:39:36 -0400 Subject: [PATCH 23/27] Each call to Enable should replace AllowedHeaders, not append to the existing value. --- vault/cors.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vault/cors.go b/vault/cors.go index 4ab5d7d6b479..beb5717cd8a1 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -92,9 +92,8 @@ func (c *CORSConfig) Enable(urls []string, headers []string) error { c.Lock() c.AllowedOrigins = urls - if len(c.AllowedHeaders) == 0 { - c.AllowedHeaders = append(c.AllowedHeaders, stdAllowedHeaders...) - } + // Start with the standard headers to Vault accepts. + c.AllowedHeaders = append(c.AllowedHeaders, stdAllowedHeaders...) // Allow the user to add additional headers to the list of // headers allowed on cross-origin requests. From 094e2a87a5cc208e2a91c2e24b0389067637bf67 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 13:58:56 -0400 Subject: [PATCH 24/27] An origin to allow must be required when calling Enable. --- vault/cors.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vault/cors.go b/vault/cors.go index beb5717cd8a1..ea46aa086a2f 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -85,6 +85,10 @@ func (c *Core) loadCORSConfig() error { // Enable takes either a '*' or a comma-seprated list of URLs that can make // cross-origin requests to Vault. func (c *CORSConfig) Enable(urls []string, headers []string) error { + if len(urls) == 0 { + return errors.New("at least one origin or the wildcard must be provided.") + } + if strutil.StrListContains(urls, "*") && len(urls) > 1 { return errors.New("to allow all origins the '*' must be the only value for allowed_origins") } From 5abce39a62cd88ef6c8f45ec5e26031588a54cd6 Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 14:32:22 -0400 Subject: [PATCH 25/27] Update test to check that allowed_origins is required. --- http/sys_config_cors_test.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/http/sys_config_cors_test.go b/http/sys_config_cors_test.go index 19517f7c4c82..bd6c7aeae83d 100644 --- a/http/sys_config_cors_test.go +++ b/http/sys_config_cors_test.go @@ -2,6 +2,7 @@ package http import ( "encoding/json" + "net/http" "reflect" "testing" @@ -9,6 +10,8 @@ import ( ) func TestSysConfigCors(t *testing.T) { + var resp *http.Response + core, _, token := vault.TestCoreUnsealed(t) ln, addr := TestServer(t, core) defer ln.Close() @@ -16,8 +19,15 @@ func TestSysConfigCors(t *testing.T) { corsConf := core.CORSConfig() - // Enable CORS - resp := testHttpPut(t, token, addr+"/v1/sys/config/cors", map[string]interface{}{ + // Try to enable CORS without providing a value for allowed_origins + resp = testHttpPut(t, token, addr+"/v1/sys/config/cors", map[string]interface{}{ + "allowed_headers": "X-Custom-Header", + }) + + testResponseStatus(t, resp, 500) + + // Enable CORS, but provide an origin this time. + resp = testHttpPut(t, token, addr+"/v1/sys/config/cors", map[string]interface{}{ "allowed_origins": addr, "allowed_headers": "X-Custom-Header", }) From 6aa45919a52b72c67aa5626304b2525ed7e4da0e Mon Sep 17 00:00:00 2001 From: Aaron Salvo Date: Sun, 6 Aug 2017 14:35:22 -0400 Subject: [PATCH 26/27] Indicating that allowed_origins is required. --- website/source/api/system/config-cors.html.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/api/system/config-cors.html.md b/website/source/api/system/config-cors.html.md index 307f94003b52..26c5b42a3295 100644 --- a/website/source/api/system/config-cors.html.md +++ b/website/source/api/system/config-cors.html.md @@ -58,7 +58,7 @@ cross-origin requests, as well as headers that are allowed on cross-origin reque ### Parameters -- `allowed_origins` `(string or string array: "" or [])` – A wildcard (`*`), comma-delimited string, or array of strings specifying the origins that are permitted to make cross-origin requests. +- `allowed_origins` `(string or string array: )` – A wildcard (`*`), comma-delimited string, or array of strings specifying the origins that are permitted to make cross-origin requests. - `allowed_headers` `(string or string array: "" or [])` – A comma-delimited string or array of strings 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 Vault allows by default. From a0b2fe56ba99dfc163f5407a2589651e34ca7a62 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 7 Aug 2017 10:03:00 -0400 Subject: [PATCH 27/27] Minor adjustments --- http/handler_test.go | 5 +++-- vault/cors.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/http/handler_test.go b/http/handler_test.go index 810320b2bda7..0c9e08eda40c 100644 --- a/http/handler_test.go +++ b/http/handler_test.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httptest" "reflect" + "strings" "testing" "github.com/hashicorp/go-cleanhttp" @@ -21,7 +22,7 @@ func TestHandler_cors(t *testing.T) { // Enable CORS and allow from any origin for testing. corsConfig := core.CORSConfig() - err := corsConfig.Enable([]string{addr}, []string{}) + err := corsConfig.Enable([]string{addr}, nil) if err != nil { t.Fatalf("Error enabling CORS: %s", err) } @@ -78,7 +79,7 @@ func TestHandler_cors(t *testing.T) { // expHeaders := map[string]string{ "Access-Control-Allow-Origin": addr, - "Access-Control-Allow-Headers": "Content-Type,X-Requested-With,X-Vault-AWS-IAM-Server-ID,X-Vault-No-Request-Forwarding,X-Vault-Token,X-Vault-Wrap-Format,X-Vault-Wrap-TTL", + "Access-Control-Allow-Headers": strings.Join(stdAllowedHeaders, ","), "Access-Control-Max-Age": "300", "Vary": "Origin", } diff --git a/vault/cors.go b/vault/cors.go index ea46aa086a2f..de201200bf43 100644 --- a/vault/cors.go +++ b/vault/cors.go @@ -19,6 +19,7 @@ var stdAllowedHeaders = []string{ "Content-Type", "X-Requested-With", "X-Vault-AWS-IAM-Server-ID", + "X-Vault-MFA", "X-Vault-No-Request-Forwarding", "X-Vault-Token", "X-Vault-Wrap-Format", @@ -121,8 +122,8 @@ func (c *CORSConfig) Disable() error { atomic.StoreUint32(&c.Enabled, CORSDisabled) c.Lock() - c.AllowedOrigins = []string(nil) - c.AllowedHeaders = []string(nil) + c.AllowedOrigins = nil + c.AllowedHeaders = nil c.Unlock()