diff --git a/README.md b/README.md index 609f2b387..c21fe3476 100644 --- a/README.md +++ b/README.md @@ -577,9 +577,12 @@ The special `vault://` URL scheme can be used to retrieve data from [Hashicorp Vault](https://vaultproject.io). To use this, you must put the Vault server's URL in the `$VAULT_ADDR` environment variable. -Currently, the [`app-id`](https://www.vaultproject.io/docs/auth/app-id.html) -auth backend is supported, as well as Vault tokens obtained through external -means. +This table describes the currently-supported authentication mechanisms and how to use them, in order of precedence: + +| auth backend | configuration | +| ---: |--| +| [`app-id`](https://www.vaultproject.io/docs/auth/app-id.html) | Environment variables `$VAULT_APP_ID` and `$VAULT_USER_ID` must be set to the appropriate values.
If the backend is mounted to a different location, set `$VAULT_AUTH_APP_ID_MOUNT`. | +| [`token`](https://www.vaultproject.io/docs/auth/token.html) | Determined from either the `$VAULT_TOKEN` environment variable, or read from the file `~/.vault-token` | To use a Vault datasource with a single secret, just use a URL of `vault:///secret/mysecret`. Note the 3 `/`s - the host portion of the URL is left diff --git a/vault/app-id_strategy.go b/vault/app-id_strategy.go index 06603f0b7..39d11e385 100644 --- a/vault/app-id_strategy.go +++ b/vault/app-id_strategy.go @@ -14,6 +14,7 @@ import ( type AppIDAuthStrategy struct { AppID string `json:"app_id"` UserID string `json:"user_id"` + Mount string `json:"-"` hc *http.Client } @@ -22,8 +23,12 @@ type AppIDAuthStrategy struct { func NewAppIDAuthStrategy() *AppIDAuthStrategy { appID := os.Getenv("VAULT_APP_ID") userID := os.Getenv("VAULT_USER_ID") + mount := os.Getenv("VAULT_AUTH_APP_ID_MOUNT") + if mount == "" { + mount = "app-id" + } if appID != "" && userID != "" { - return &AppIDAuthStrategy{appID, userID, nil} + return &AppIDAuthStrategy{appID, userID, mount, nil} } return nil } @@ -54,12 +59,12 @@ func (a *AppIDAuthStrategy) GetToken(addr *url.URL) (string, error) { u := &url.URL{} *u = *addr - u.Path = "/v1/auth/app-id/login" + u.Path = "/v1/auth/" + a.Mount + "/login" res, err := requestAndFollow(a, "POST", u, buf.Bytes()) if err != nil { return "", err } - response := &AuthResponse{} + response := &AppIDAuthResponse{} err = json.NewDecoder(res.Body).Decode(response) res.Body.Close() if err != nil { @@ -78,11 +83,11 @@ func (a *AppIDAuthStrategy) Revokable() bool { } func (a *AppIDAuthStrategy) String() string { - return fmt.Sprintf("app-id: %s, user-id: %s", a.AppID, a.UserID) + return fmt.Sprintf("app-id: %s, user-id: %s, mount: %s", a.AppID, a.UserID, a.Mount) } -// AuthResponse - the Auth response from /v1/auth/app-id/login -type AuthResponse struct { +// AppIDAuthResponse - the Auth response from /v1/auth/app-id/login +type AppIDAuthResponse struct { Auth struct { ClientToken string `json:"client_token"` LeaseDuration int64 `json:"lease_duration"` @@ -95,7 +100,7 @@ type AuthResponse struct { } `json:"auth"` } -func (a *AuthResponse) String() string { +func (a *AppIDAuthResponse) String() string { buf := new(bytes.Buffer) json.NewEncoder(buf).Encode(&a) return string(buf.Bytes()) diff --git a/vault/app-id_strategy_test.go b/vault/app-id_strategy_test.go index 81824549b..a5e9effc0 100644 --- a/vault/app-id_strategy_test.go +++ b/vault/app-id_strategy_test.go @@ -1,9 +1,6 @@ package vault import ( - "fmt" - "net/http" - "net/http/httptest" "net/url" "os" "testing" @@ -36,7 +33,7 @@ func TestGetToken_AppIDErrorsGivenNetworkError(t *testing.T) { vaultURL, _ := url.Parse("http://vault:8200") - auth := &AppIDAuthStrategy{"foo", "bar", client} + auth := &AppIDAuthStrategy{"foo", "bar", "app-id", client} _, err := auth.GetToken(vaultURL) assert.Error(t, err) } @@ -47,7 +44,7 @@ func TestGetToken_AppIDErrorsGivenHTTPErrorStatus(t *testing.T) { vaultURL, _ := url.Parse("http://vault:8200") - auth := &AppIDAuthStrategy{"foo", "bar", client} + auth := &AppIDAuthStrategy{"foo", "bar", "app-id", client} _, err := auth.GetToken(vaultURL) assert.Error(t, err) } @@ -58,7 +55,7 @@ func TestGetToken_AppIDErrorsGivenBadJSON(t *testing.T) { vaultURL, _ := url.Parse("http://vault:8200") - auth := &AppIDAuthStrategy{"foo", "bar", client} + auth := &AppIDAuthStrategy{"foo", "bar", "app-id", client} _, err := auth.GetToken(vaultURL) assert.Error(t, err) } @@ -69,43 +66,9 @@ func TestGetToken_AppID(t *testing.T) { vaultURL, _ := url.Parse("http://vault:8200") - auth := &AppIDAuthStrategy{"foo", "bar", client} + auth := &AppIDAuthStrategy{"foo", "bar", "app-id", client} token, err := auth.GetToken(vaultURL) assert.NoError(t, err) assert.Equal(t, "baz", token) } - -func setupHTTP(code int, mimetype string, body string) (*httptest.Server, *http.Client) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", mimetype) - w.WriteHeader(code) - fmt.Fprintln(w, body) - })) - - client := &http.Client{ - Transport: &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL) - }, - }, - } - - return server, client -} - -func setupErrorHTTP() (*httptest.Server, *http.Client) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - panic("boo") - })) - - client := &http.Client{ - Transport: &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL) - }, - }, - } - - return server, client -} diff --git a/vault/testutils.go b/vault/testutils.go new file mode 100644 index 000000000..d7e38190b --- /dev/null +++ b/vault/testutils.go @@ -0,0 +1,42 @@ +package vault + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" +) + +func setupHTTP(code int, mimetype string, body string) (*httptest.Server, *http.Client) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", mimetype) + w.WriteHeader(code) + fmt.Fprintln(w, body) + })) + + client := &http.Client{ + Transport: &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse(server.URL) + }, + }, + } + + return server, client +} + +func setupErrorHTTP() (*httptest.Server, *http.Client) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + panic("boo") + })) + + client := &http.Client{ + Transport: &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse(server.URL) + }, + }, + } + + return server, client +}