mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 19:47:54 +00:00
logical/framework: support root help
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
@@ -14,6 +15,8 @@ func Factory(map[string]string) (logical.Backend, error) {
|
||||
func Backend() *framework.Backend {
|
||||
var b backend
|
||||
b.Backend = &framework.Backend{
|
||||
Help: strings.TrimSpace(backendHelp),
|
||||
|
||||
PathsSpecial: &logical.Paths{
|
||||
Root: []string{
|
||||
"root",
|
||||
@@ -41,3 +44,9 @@ func Backend() *framework.Backend {
|
||||
type backend struct {
|
||||
*framework.Backend
|
||||
}
|
||||
|
||||
const backendHelp = `
|
||||
The AWS backend dynamically generates AWS access keys for a set of
|
||||
IAM policies. The AWS access keys have a configurable lease set and
|
||||
are automatically revoked at the end of the lease.
|
||||
`
|
||||
|
||||
@@ -16,6 +16,11 @@ import (
|
||||
//
|
||||
// This is recommended over implementing logical.Backend directly.
|
||||
type Backend struct {
|
||||
// Help is the help text that is shown when a help request is made
|
||||
// on the root of this resource. The root help is special since we
|
||||
// show all the paths that can be requested.
|
||||
Help string
|
||||
|
||||
// Paths are the various routes that the backend responds to.
|
||||
// This cannot be modified after construction (i.e. dynamically changing
|
||||
// paths, including adding or removing, is not allowed once the
|
||||
@@ -54,6 +59,8 @@ type RollbackFunc func(*logical.Request, string, interface{}) error
|
||||
|
||||
// logical.Backend impl.
|
||||
func (b *Backend) HandleRequest(req *logical.Request) (*logical.Response, error) {
|
||||
b.once.Do(b.init)
|
||||
|
||||
// Check for special cased global operations. These don't route
|
||||
// to a specific Path.
|
||||
switch req.Operation {
|
||||
@@ -65,6 +72,11 @@ func (b *Backend) HandleRequest(req *logical.Request) (*logical.Response, error)
|
||||
return b.handleRollback(req)
|
||||
}
|
||||
|
||||
// If the path is empty and it is a help operation, handle that.
|
||||
if req.Path == "" && req.Operation == logical.HelpOperation {
|
||||
return b.handleRootHelp()
|
||||
}
|
||||
|
||||
// Find the matching route
|
||||
path, captures := b.route(req.Path)
|
||||
if path == nil {
|
||||
@@ -171,6 +183,23 @@ func (b *Backend) route(path string) (*Path, map[string]string) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *Backend) handleRootHelp() (*logical.Response, error) {
|
||||
paths := make([]string, 0, len(b.Paths))
|
||||
for _, p := range b.pathsRe {
|
||||
paths = append(paths, p.String())
|
||||
}
|
||||
|
||||
help, err := executeTemplate(rootHelpTemplate, &rootHelpTemplateData{
|
||||
Help: b.Help,
|
||||
Paths: paths,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return logical.HelpResponse(help, nil), nil
|
||||
}
|
||||
|
||||
func (b *Backend) handleRevokeRenew(
|
||||
req *logical.Request) (*logical.Response, error) {
|
||||
if req.Secret == nil {
|
||||
@@ -295,3 +324,24 @@ func (t FieldType) Zero() interface{} {
|
||||
panic("unknown type: " + t.String())
|
||||
}
|
||||
}
|
||||
|
||||
type rootHelpTemplateData struct {
|
||||
Help string
|
||||
Paths []string
|
||||
}
|
||||
|
||||
const rootHelpTemplate = `
|
||||
## DESCRIPTION
|
||||
|
||||
{{.Help}}
|
||||
|
||||
## PATHS
|
||||
|
||||
The following paths are supported by this backend. To view help for
|
||||
any of the paths below, use the help command with any route matching
|
||||
the path pattern.
|
||||
|
||||
{{range .Paths}} {{.}}
|
||||
{{end}}
|
||||
|
||||
`
|
||||
|
||||
@@ -137,6 +137,23 @@ func TestBackendHandleRequest_help(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendHandleRequest_helpRoot(t *testing.T) {
|
||||
b := &Backend{
|
||||
Help: "42",
|
||||
}
|
||||
|
||||
resp, err := b.HandleRequest(&logical.Request{
|
||||
Operation: logical.HelpOperation,
|
||||
Path: "",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if resp.Data["help"] == nil {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendHandleRequest_renew(t *testing.T) {
|
||||
var called uint32
|
||||
callback := func(*logical.Request, *FieldData) (*logical.Response, error) {
|
||||
|
||||
24
logical/framework/template.go
Normal file
24
logical/framework/template.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package framework
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func executeTemplate(tpl string, data interface{}) (string, error) {
|
||||
// Parse the help template
|
||||
t, err := template.New("root").Parse(tpl)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing template: %s", err)
|
||||
}
|
||||
|
||||
// Execute the template and store the output
|
||||
var buf bytes.Buffer
|
||||
if err := t.Execute(&buf, data); err != nil {
|
||||
return "", fmt.Errorf("error executing template: %s", err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(buf.String()), nil
|
||||
}
|
||||
Reference in New Issue
Block a user