mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	http: help
This commit is contained in:
		
							
								
								
									
										11
									
								
								api/SPEC.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								api/SPEC.md
									
									
									
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										6
									
								
								api/help.go
									
									
									
									
									
										Normal 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 | ||||||
|  | } | ||||||
| @@ -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
									
								
							
							
						
						
									
										40
									
								
								http/help.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										27
									
								
								http/help_test.go
									
									
									
									
									
										Normal 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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Mitchell Hashimoto
					Mitchell Hashimoto