mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-28 06:01:08 +01:00
vault: system using the framework
This commit is contained in:
parent
2d92c2ee10
commit
1be431df51
@ -24,6 +24,12 @@ type Backend struct {
|
||||
// backend is in use).
|
||||
Paths []*Path
|
||||
|
||||
// PathsRoot is the list of path patterns that denote the
|
||||
// paths above that require root-level privileges. These can't be
|
||||
// regular expressions, it is either exact match or prefix match.
|
||||
// For prefix match, append '*' as a suffix.
|
||||
PathsRoot []string
|
||||
|
||||
once sync.Once
|
||||
pathsRe []*regexp.Regexp
|
||||
}
|
||||
@ -46,12 +52,6 @@ type Path struct {
|
||||
// whereas all fields are avaiable in the Write operation.
|
||||
Fields map[string]*FieldSchema
|
||||
|
||||
// Root if not blank, denotes that this path requires root
|
||||
// privileges and the path pattern that is the root path. This can't
|
||||
// be a regular expression and must be an exact path. It may have a
|
||||
// trailing '*' to denote that it is a prefix, and not an exact match.
|
||||
Root string
|
||||
|
||||
// Callbacks are the set of callbacks that are called for a given
|
||||
// operation. If a callback for a specific operation is not present,
|
||||
// then logical.ErrUnsupportedOperation is automatically generated.
|
||||
@ -123,8 +123,7 @@ func (b *Backend) HandleRequest(req *logical.Request) (*logical.Response, error)
|
||||
|
||||
// logical.Backend impl.
|
||||
func (b *Backend) RootPaths() []string {
|
||||
// TODO
|
||||
return nil
|
||||
return b.PathsRoot
|
||||
}
|
||||
|
||||
// Route looks up the path that would be used for a given path string.
|
||||
|
||||
@ -158,7 +158,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
||||
}
|
||||
backends["generic"] = PassthroughBackendFactory
|
||||
backends["system"] = func(map[string]string) (logical.Backend, error) {
|
||||
return &SystemBackend{Core: c}, nil
|
||||
return NewSystemBackend(c), nil
|
||||
}
|
||||
|
||||
c.backends = backends
|
||||
|
||||
@ -4,8 +4,72 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
func NewSystemBackend(core *Core) logical.Backend {
|
||||
b := &SystemBackend{Core: core}
|
||||
|
||||
return &framework.Backend{
|
||||
PathsRoot: []string{
|
||||
"mount/*",
|
||||
"remount",
|
||||
},
|
||||
|
||||
Paths: []*framework.Path{
|
||||
&framework.Path{
|
||||
Pattern: "mounts",
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: b.handleMountTable,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["mounts"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["mounts"][1]),
|
||||
},
|
||||
|
||||
&framework.Path{
|
||||
Pattern: "mount/(?P<path>.+?)",
|
||||
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"path": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
|
||||
},
|
||||
|
||||
"type": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
|
||||
},
|
||||
"description": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.WriteOperation: b.handleMount,
|
||||
logical.DeleteOperation: b.handleUnmount,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["mount"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["mount"][1]),
|
||||
},
|
||||
|
||||
&framework.Path{
|
||||
Pattern: "remount",
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.WriteOperation: b.handleRemount,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["remount"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["remount"][1]),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SystemBackend implements logical.Backend and is used to interact with
|
||||
// the core of the system. This backend is hardcoded to exist at the "sys"
|
||||
// prefix. Conceptually it is similar to procfs on Linux.
|
||||
@ -13,35 +77,9 @@ type SystemBackend struct {
|
||||
Core *Core
|
||||
}
|
||||
|
||||
func (b *SystemBackend) HandleRequest(req *logical.Request) (*logical.Response, error) {
|
||||
// Switch on the path to route to the appropriate handler
|
||||
switch {
|
||||
case req.Path == "mounts":
|
||||
return b.handleMountTable(req)
|
||||
case strings.HasPrefix(req.Path, "mount/"):
|
||||
return b.handleMountOperation(req)
|
||||
case req.Path == "remount":
|
||||
return b.handleRemount(req)
|
||||
default:
|
||||
return nil, logical.ErrUnsupportedPath
|
||||
}
|
||||
}
|
||||
|
||||
func (b *SystemBackend) RootPaths() []string {
|
||||
return []string{
|
||||
"mount/*",
|
||||
"remount",
|
||||
}
|
||||
}
|
||||
|
||||
// handleMountTable handles the "mounts" endpoint to provide the mount table
|
||||
func (b *SystemBackend) handleMountTable(req *logical.Request) (*logical.Response, error) {
|
||||
switch req.Operation {
|
||||
case logical.ReadOperation:
|
||||
default:
|
||||
return nil, logical.ErrUnsupportedOperation
|
||||
}
|
||||
|
||||
func (b *SystemBackend) handleMountTable(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
b.Core.mountsLock.RLock()
|
||||
defer b.Core.mountsLock.RUnlock()
|
||||
|
||||
@ -60,35 +98,23 @@ func (b *SystemBackend) handleMountTable(req *logical.Request) (*logical.Respons
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// handleMountOperation is used to mount or unmount a path
|
||||
func (b *SystemBackend) handleMountOperation(req *logical.Request) (*logical.Response, error) {
|
||||
switch req.Operation {
|
||||
case logical.WriteOperation:
|
||||
return b.handleMount(req)
|
||||
case logical.DeleteOperation:
|
||||
return b.handleUnmount(req)
|
||||
default:
|
||||
return nil, logical.ErrUnsupportedOperation
|
||||
}
|
||||
}
|
||||
|
||||
// handleMount is used to mount a new path
|
||||
func (b *SystemBackend) handleMount(req *logical.Request) (*logical.Response, error) {
|
||||
suffix := strings.TrimPrefix(req.Path, "mount/")
|
||||
if len(suffix) == 0 {
|
||||
return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest
|
||||
}
|
||||
func (b *SystemBackend) handleMount(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
// Get all the options
|
||||
path := data.Get("path").(string)
|
||||
logicalType := data.Get("type").(string)
|
||||
description := data.Get("description").(string)
|
||||
|
||||
// Get the type and description (optionally)
|
||||
logicalType := req.GetString("type")
|
||||
if logicalType == "" {
|
||||
return logical.ErrorResponse("backend type must be specified as a string"), logical.ErrInvalidRequest
|
||||
return logical.ErrorResponse(
|
||||
"backend type must be specified as a string"),
|
||||
logical.ErrInvalidRequest
|
||||
}
|
||||
description := req.GetString("description")
|
||||
|
||||
// Create the mount entry
|
||||
me := &MountEntry{
|
||||
Path: suffix,
|
||||
Path: path,
|
||||
Type: logicalType,
|
||||
Description: description,
|
||||
}
|
||||
@ -101,7 +127,8 @@ func (b *SystemBackend) handleMount(req *logical.Request) (*logical.Response, er
|
||||
}
|
||||
|
||||
// handleUnmount is used to unmount a path
|
||||
func (b *SystemBackend) handleUnmount(req *logical.Request) (*logical.Response, error) {
|
||||
func (b *SystemBackend) handleUnmount(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
suffix := strings.TrimPrefix(req.Path, "mount/")
|
||||
if len(suffix) == 0 {
|
||||
return logical.ErrorResponse("path cannot be blank"), logical.ErrInvalidRequest
|
||||
@ -116,7 +143,8 @@ func (b *SystemBackend) handleUnmount(req *logical.Request) (*logical.Response,
|
||||
}
|
||||
|
||||
// handleRemount is used to remount a path
|
||||
func (b *SystemBackend) handleRemount(req *logical.Request) (*logical.Response, error) {
|
||||
func (b *SystemBackend) handleRemount(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
// Only accept write operations
|
||||
switch req.Operation {
|
||||
case logical.WriteOperation:
|
||||
@ -140,3 +168,46 @@ func (b *SystemBackend) handleRemount(req *logical.Request) (*logical.Response,
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// sysHelp is all the help text for the sys backend.
|
||||
var sysHelp = map[string][2]string{
|
||||
"mounts": {
|
||||
"List the currently mounted backends.",
|
||||
`
|
||||
List the currently mounted backends: the mount path, the type of the backend,
|
||||
and a user friendly description of the purpose for the mount.
|
||||
`,
|
||||
},
|
||||
|
||||
"mount": {
|
||||
`Mount a new backend at a new path.`,
|
||||
`
|
||||
Mount a backend at a new path. A backend can be mounted multiple times at
|
||||
multiple paths in order to configure multiple separately configured backends.
|
||||
Example: you might have an AWS backend for the east coast, and one for the
|
||||
west coast.
|
||||
`,
|
||||
},
|
||||
|
||||
"mount_path": {
|
||||
`The path to mount to. Example: "aws/east"`,
|
||||
"",
|
||||
},
|
||||
|
||||
"mount_type": {
|
||||
`The type of the backend. Example: "passthrough"`,
|
||||
"",
|
||||
},
|
||||
|
||||
"mount_desc": {
|
||||
`User-friendly description for this mount.`,
|
||||
"",
|
||||
},
|
||||
|
||||
"remount": {
|
||||
"Move the mount point of an already-mounted backend.",
|
||||
`
|
||||
Change the mount point of an already-mounted backend.
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@ -7,10 +7,6 @@ import (
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
func TestSystemBackend_impl(t *testing.T) {
|
||||
var _ logical.Backend = new(SystemBackend)
|
||||
}
|
||||
|
||||
func TestSystemBackend_RootPaths(t *testing.T) {
|
||||
expected := []string{
|
||||
"mount/*",
|
||||
@ -147,7 +143,7 @@ func TestSystemBackend_remount_system(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testSystemBackend(t *testing.T) *SystemBackend {
|
||||
func testSystemBackend(t *testing.T) logical.Backend {
|
||||
c, _ := TestCoreUnsealed(t)
|
||||
return &SystemBackend{Core: c}
|
||||
return NewSystemBackend(c)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user