http: help

This commit is contained in:
Mitchell Hashimoto 2015-04-02 22:21:33 -07:00
parent eec6c27fae
commit 020af2fac2
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
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
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"
"fmt"
"net/http"
"strings"
"github.com/hashicorp/vault/logical"
"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
// its own to mount the Vault API within another web server.
func Handler(core *vault.Core) http.Handler {
// Create the muxer to handle the actual endpoints
mux := http.NewServeMux()
mux.Handle("/v1/sys/init", handleSysInit(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/", handleSysAudit(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 {

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)
}
}