http: help

This commit is contained in:
Mitchell Hashimoto
2015-04-02 22:21:33 -07:00
parent 4dc1d6351f
commit ce9ed56be6
5 changed files with 106 additions and 1 deletions

View File

@@ -56,6 +56,17 @@ that can be enabled (see
Authentication is done with the login endpoint. The login endpoint Authentication is done with the login endpoint. The login endpoint
returns an access token that is set as the `token` cookie. returns an access token that is set as the `token` cookie.
## Help
To retrieve the help for any API within Vault, including mounted
backends, credential providers, etc. then append `?help=1` to any
URL. If you have valid permission to access the path, then the help text
will be returned with the following structure:
{
"help": "help text"
}
## Error Response ## Error Response
A common JSON structure is always returned to return errors: A common JSON structure is always returned to return errors:

6
api/help.go Normal file
View File

@@ -0,0 +1,6 @@
package api
// Help reads the help information for the given path.
func (c *Client) Help(path string) (string, error) {
return "", nil
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strings"
"github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault"
@@ -15,6 +16,7 @@ const AuthCookieName = "token"
// Handler returns an http.Handler for the API. This can be used on // Handler returns an http.Handler for the API. This can be used on
// its own to mount the Vault API within another web server. // its own to mount the Vault API within another web server.
func Handler(core *vault.Core) http.Handler { func Handler(core *vault.Core) http.Handler {
// Create the muxer to handle the actual endpoints
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle("/v1/sys/init", handleSysInit(core)) mux.Handle("/v1/sys/init", handleSysInit(core))
mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core)) mux.Handle("/v1/sys/seal-status", handleSysSealStatus(core))
@@ -29,7 +31,26 @@ func Handler(core *vault.Core) http.Handler {
mux.Handle("/v1/sys/audit", handleSysListAudit(core)) mux.Handle("/v1/sys/audit", handleSysListAudit(core))
mux.Handle("/v1/sys/audit/", handleSysAudit(core)) mux.Handle("/v1/sys/audit/", handleSysAudit(core))
mux.Handle("/v1/", handleLogical(core)) mux.Handle("/v1/", handleLogical(core))
return mux
// Wrap the handler in another handler to trigger all help paths.
handler := handleHelpHandler(mux, core)
return handler
}
// stripPrefix is a helper to strip a prefix from the path. It will
// return false from the second return value if it the prefix doesn't exist.
func stripPrefix(prefix, path string) (string, bool) {
if !strings.HasPrefix(path, prefix) {
return "", false
}
path = path[len(prefix):]
if path == "" {
return "", false
}
return path, true
} }
func parseRequest(r *http.Request, out interface{}) error { func parseRequest(r *http.Request, out interface{}) error {

40
http/help.go Normal file
View File

@@ -0,0 +1,40 @@
package http
import (
"net/http"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/vault"
)
func handleHelpHandler(h http.Handler, core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// If the help parameter is not blank, then show the help
if v := req.URL.Query().Get("help"); v != "" {
handleHelp(core, w, req)
return
}
h.ServeHTTP(w, req)
return
})
}
func handleHelp(core *vault.Core, w http.ResponseWriter, req *http.Request) {
path, ok := stripPrefix("/v1/", req.URL.Path)
if !ok {
respondError(w, http.StatusNotFound, nil)
return
}
resp, err := core.HandleRequest(requestAuth(req, &logical.Request{
Operation: logical.HelpOperation,
Path: path,
}))
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
respondOk(w, resp.Data)
}

27
http/help_test.go Normal file
View File

@@ -0,0 +1,27 @@
package http
import (
"net/http"
"testing"
"github.com/hashicorp/vault/vault"
)
func TestHelp(t *testing.T) {
core, _, token := vault.TestCoreUnsealed(t)
ln, addr := TestServer(t, core)
defer ln.Close()
TestServerAuth(t, addr, token)
resp, err := http.Get(addr + "/v1/sys/mounts?help=1")
if err != nil {
t.Fatalf("err: %s", err)
}
var actual map[string]interface{}
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)
if _, ok := actual["help"]; !ok {
t.Fatalf("bad: %#v", actual)
}
}