From ec4fcd39eb084e5f78b1cb7ff68c133fb7dda899 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 11 May 2015 10:56:41 -0700 Subject: [PATCH] http: allow header for auth token [GH-124] --- CHANGELOG.md | 3 +- http/handler.go | 8 +++++ http/handler_test.go | 45 ++++++++++++++++++++++++++ website/source/docs/http/index.html.md | 5 +-- 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 http/handler_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index cb55e0b4cd..2c7f1e684f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ FEATURES: * **New physical backend: `zookeeper`**: store physical data in Zookeeper. HA not supported yet. - * ** New credential backend: `ldap`**: authenticate using LDAP credentials. + * **New credential backend: `ldap`**: authenticate using LDAP credentials. IMPROVEMENTS: @@ -13,6 +13,7 @@ IMPROVEMENTS: * command/*: `VAULT_TOKEN` overrides local stored auth [GH-162] * command/server: environment variables are copy-pastable * credential/app-id: hash of app and user ID are in metadata [GH-176] + * http: HTTP API accepts `X-Vault-Token` as auth header [GH-124] * logical/*: Generate help output even if no synopsis specified BUG FIXES: diff --git a/http/handler.go b/http/handler.go index b6ae82e989..1363400869 100644 --- a/http/handler.go +++ b/http/handler.go @@ -14,6 +14,9 @@ import ( // AuthCookieName is the name of the cookie containing the token. const AuthCookieName = "token" +// AuthHeaderName is the name of the header containing the token. +const AuthHeaderName = "X-Vault-Token" + // Handler returns an http.Handler for the API. This can be used on // its own to mount the Vault API within another web server. func Handler(core *vault.Core) http.Handler { @@ -135,6 +138,11 @@ func requestAuth(r *http.Request, req *logical.Request) *logical.Request { req.ClientToken = cookie.Value } + // Attach the header value if we have it + if v := r.Header.Get(AuthHeaderName); v != "" { + req.ClientToken = v + } + return req } diff --git a/http/handler_test.go b/http/handler_test.go new file mode 100644 index 0000000000..a0a5b28d1f --- /dev/null +++ b/http/handler_test.go @@ -0,0 +1,45 @@ +package http + +import ( + "net/http" + "reflect" + "testing" + + "github.com/hashicorp/vault/vault" +) + +// We use this test to verify header auth +func TestSysMounts_headerAuth(t *testing.T) { + core, _, token := vault.TestCoreUnsealed(t) + ln, addr := TestServer(t, core) + defer ln.Close() + + req, err := http.NewRequest("GET", addr+"/v1/sys/mounts", nil) + if err != nil { + t.Fatalf("err: %s", err) + } + req.Header.Set(AuthHeaderName, token) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + t.Fatalf("err: %s", err) + } + + var actual map[string]interface{} + expected := map[string]interface{}{ + "secret/": map[string]interface{}{ + "description": "generic secret storage", + "type": "generic", + }, + "sys/": map[string]interface{}{ + "description": "system endpoints used for control, policy and debugging", + "type": "system", + }, + } + testResponseStatus(t, resp, 200) + testResponseBody(t, resp, &actual) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad: %#v", actual) + } +} diff --git a/website/source/docs/http/index.html.md b/website/source/docs/http/index.html.md index ae0ef140ba..6ac68e85ec 100644 --- a/website/source/docs/http/index.html.md +++ b/website/source/docs/http/index.html.md @@ -35,7 +35,8 @@ depending on user settings. Once the Vault is unsealed, every other operation requires a _client token_. A user may have a client token explicitly. -The client token must be sent as the `token` cookie. +The client token must be sent as the `token` cookie or the +`X-Vault-Token` HTTP header. Otherwise, a client token can be retrieved via [authentication backends](#). @@ -46,7 +47,7 @@ and are used for authentication itself. These endpoints are specific to each authentication backend. Login endpoints for authentication backends that generate an identity -will be sent down with a `Set-Cookie` header. If you are using a +will be sent down with a `Set-Cookie` header as well as via JSON. If you have a well-behaved HTTP client, then authentication information will automatically be saved and sent to the Vault API.