diff --git a/command/agent/http.go b/command/agent/http.go index 22f1c118eb..02c20b3a43 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -463,13 +463,18 @@ func (s *HTTPServer) parseDC(req *http.Request, dc *string) { } } -// parseToken is used to parse the ?token query param +// parseToken is used to parse the ?token query param or the X-Consul-Token header func (s *HTTPServer) parseToken(req *http.Request, token *string) { if other := req.URL.Query().Get("token"); other != "" { *token = other return } + if other := req.Header.Get("X-Consul-Token"); other != "" { + *token = other + return + } + // Set the AtlasACLToken if SCADA if s.addr == scadaHTTPAddr && s.agent.config.AtlasACLToken != "" { *token = s.agent.config.AtlasACLToken diff --git a/command/agent/http_test.go b/command/agent/http_test.go index 9869b258dd..1f13f3a4bb 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -472,6 +472,22 @@ func TestACLResolution(t *testing.T) { t.Fatalf("err: %v", err) } + // Request with header token only + reqHeaderToken, err := http.NewRequest("GET", + "/v1/catalog/nodes", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + reqHeaderToken.Header.Add("X-Consul-Token", "bar") + + // Request with header and querystring tokens + reqBothTokens, err := http.NewRequest("GET", + "/v1/catalog/nodes?token=baz", nil) + if err != nil { + t.Fatalf("err: %v", err) + } + reqBothTokens.Header.Add("X-Consul-Token", "zap") + httpTest(t, func(srv *HTTPServer) { // Check when no token is set srv.agent.config.ACLToken = "" @@ -513,6 +529,18 @@ func TestACLResolution(t *testing.T) { if token != "foo" { t.Fatalf("bad: %s", token) } + + // Header token has precedence over agent token + srv.parseToken(reqHeaderToken, &token) + if token != "bar" { + t.Fatalf("bad: %s", token) + } + + // Querystring token has precendence over header and agent tokens + srv.parseToken(reqBothTokens, &token) + if token != "baz" { + t.Fatalf("bad: %s", token) + } }) } diff --git a/website/source/docs/agent/http.html.markdown b/website/source/docs/agent/http.html.markdown index 9e1ae0b9be..d3fa365a2e 100644 --- a/website/source/docs/agent/http.html.markdown +++ b/website/source/docs/agent/http.html.markdown @@ -91,5 +91,6 @@ on the query string, formatted JSON will be returned. Several endpoints in Consul use or require ACL tokens to operate. An agent can be configured to use a default token in requests using the `acl_token` configuration option. However, the token can also be specified per-request -by using the `token` query parameter. This will take precedent over the -default token. +by using the `X-Consul-Token` request header or the `token` querystring +parameter. The request header takes precedence over the default token, and +the querystring parameter takes precedence over everything.