vault: Adding sys/ paths to enable/disable audit backends
This commit is contained in:
parent
0943c2bf45
commit
dda8dec5bf
|
@ -20,6 +20,8 @@ func NewSystemBackend(core *Core) logical.Backend {
|
|||
"revoke-prefix/*",
|
||||
"policy",
|
||||
"policy/*",
|
||||
"audit",
|
||||
"audit/*",
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -215,6 +217,48 @@ func NewSystemBackend(core *Core) logical.Backend {
|
|||
HelpSynopsis: strings.TrimSpace(sysHelp["policy"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["policy"][1]),
|
||||
},
|
||||
|
||||
&framework.Path{
|
||||
Pattern: "audit$",
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: b.handleAuditTable,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["audit-table"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["audit-table"][1]),
|
||||
},
|
||||
|
||||
&framework.Path{
|
||||
Pattern: "audit/(?P<path>.+)",
|
||||
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"path": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["audit_path"][0]),
|
||||
},
|
||||
"type": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["audit_type"][0]),
|
||||
},
|
||||
"description": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["audit_desc"][0]),
|
||||
},
|
||||
"options": &framework.FieldSchema{
|
||||
Type: framework.TypeMap,
|
||||
Description: strings.TrimSpace(sysHelp["audit_opts"][0]),
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.WriteOperation: b.handleEnableAudit,
|
||||
logical.DeleteOperation: b.handleDisableAudit,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["audit"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["audit"][1]),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +419,6 @@ func (b *SystemBackend) handleAuthTable(
|
|||
}
|
||||
resp.Data[entry.Path] = info
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
@ -487,6 +530,72 @@ func (b *SystemBackend) handlePolicyDelete(
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// handleAuditTable handles the "audit" endpoint to provide the audit table
|
||||
func (b *SystemBackend) handleAuditTable(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
b.Core.audit.Lock()
|
||||
defer b.Core.audit.Unlock()
|
||||
|
||||
resp := &logical.Response{
|
||||
Data: make(map[string]interface{}),
|
||||
}
|
||||
for _, entry := range b.Core.audit.Entries {
|
||||
info := map[string]interface{}{
|
||||
"type": entry.Type,
|
||||
"description": entry.Description,
|
||||
"options": entry.Options,
|
||||
}
|
||||
resp.Data[entry.Path] = info
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// handleEnableAudit is used to enable a new audit backend
|
||||
func (b *SystemBackend) handleEnableAudit(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
// Get all the options
|
||||
path := data.Get("path").(string)
|
||||
backendType := data.Get("type").(string)
|
||||
description := data.Get("description").(string)
|
||||
options := data.Get("options").(map[string]interface{})
|
||||
|
||||
optionMap := make(map[string]string)
|
||||
for k, v := range options {
|
||||
vStr, ok := v.(string)
|
||||
if !ok {
|
||||
return logical.ErrorResponse("options must be string valued"),
|
||||
logical.ErrInvalidRequest
|
||||
}
|
||||
optionMap[k] = vStr
|
||||
}
|
||||
|
||||
// Create the mount entry
|
||||
me := &MountEntry{
|
||||
Path: path,
|
||||
Type: backendType,
|
||||
Description: description,
|
||||
Options: optionMap,
|
||||
}
|
||||
|
||||
// Attempt enabling
|
||||
if err := b.Core.enableAudit(me); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// handleDisableAudit is used to disable an audit backend
|
||||
func (b *SystemBackend) handleDisableAudit(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
path := data.Get("path").(string)
|
||||
|
||||
// Attempt disable
|
||||
if err := b.Core.disableAudit(path); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// sysHelp is all the help text for the sys backend.
|
||||
var sysHelp = map[string][2]string{
|
||||
"mounts": {
|
||||
|
@ -643,4 +752,39 @@ or delete a policy.
|
|||
`The rules of the policy. Either given in HCL or JSON format.`,
|
||||
"",
|
||||
},
|
||||
|
||||
"audit-table": {
|
||||
"List the currently enabled audit backends.",
|
||||
`
|
||||
List the currently enabled audit backends: the name, the type of the backend,
|
||||
a user friendly description of the audit backend, and it's configuration options.
|
||||
`,
|
||||
},
|
||||
|
||||
"audit_path": {
|
||||
`The name of the backend. Cannot be delimited. Example: "mysql"`,
|
||||
"",
|
||||
},
|
||||
|
||||
"audit_type": {
|
||||
`The type of the backend. Example: "mysql"`,
|
||||
"",
|
||||
},
|
||||
|
||||
"audit_desc": {
|
||||
`User-friendly description for this audit backend.`,
|
||||
"",
|
||||
},
|
||||
|
||||
"audit_opts": {
|
||||
`Configuration options for the audit backend.`,
|
||||
"",
|
||||
},
|
||||
|
||||
"audit": {
|
||||
`Enable or disable audit backends.`,
|
||||
`
|
||||
Enable a new audit backend or disable an existing backend.
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/audit"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
|
@ -15,6 +16,8 @@ func TestSystemBackend_RootPaths(t *testing.T) {
|
|||
"revoke-prefix/*",
|
||||
"policy",
|
||||
"policy/*",
|
||||
"audit",
|
||||
"audit/*",
|
||||
}
|
||||
|
||||
b := testSystemBackend(t)
|
||||
|
@ -494,6 +497,109 @@ func TestSystemBackend_policyCRUD(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_enableAudit(t *testing.T) {
|
||||
c, b, _ := testCoreSystemBackend(t)
|
||||
c.auditBackends["noop"] = func(map[string]string) (audit.Backend, error) {
|
||||
return &NoopAudit{}, nil
|
||||
}
|
||||
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "audit/foo")
|
||||
req.Data["type"] = "noop"
|
||||
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_enableAudit_invalid(t *testing.T) {
|
||||
b := testSystemBackend(t)
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "audit/foo")
|
||||
req.Data["type"] = "nope"
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != logical.ErrInvalidRequest {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp.Data["error"] != "unknown backend type: nope" {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_auditTable(t *testing.T) {
|
||||
c, b, _ := testCoreSystemBackend(t)
|
||||
c.auditBackends["noop"] = func(map[string]string) (audit.Backend, error) {
|
||||
return &NoopAudit{}, nil
|
||||
}
|
||||
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "audit/foo")
|
||||
req.Data["type"] = "noop"
|
||||
req.Data["description"] = "testing"
|
||||
req.Data["options"] = map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}
|
||||
b.HandleRequest(req)
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "audit")
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
exp := map[string]interface{}{
|
||||
"foo": map[string]interface{}{
|
||||
"type": "noop",
|
||||
"description": "testing",
|
||||
"options": map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(resp.Data, exp) {
|
||||
t.Fatalf("got: %#v expect: %#v", resp.Data, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_disableAudit(t *testing.T) {
|
||||
c, b, _ := testCoreSystemBackend(t)
|
||||
c.auditBackends["noop"] = func(map[string]string) (audit.Backend, error) {
|
||||
return &NoopAudit{}, nil
|
||||
}
|
||||
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "audit/foo")
|
||||
req.Data["type"] = "noop"
|
||||
req.Data["description"] = "testing"
|
||||
req.Data["options"] = map[string]interface{}{
|
||||
"foo": "bar",
|
||||
}
|
||||
b.HandleRequest(req)
|
||||
|
||||
// Deregister it
|
||||
req = logical.TestRequest(t, logical.DeleteOperation, "audit/foo")
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_disableAudit_invalid(t *testing.T) {
|
||||
b := testSystemBackend(t)
|
||||
|
||||
req := logical.TestRequest(t, logical.DeleteOperation, "audit/foo")
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != logical.ErrInvalidRequest {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp.Data["error"] != "no matching backend" {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func testSystemBackend(t *testing.T) logical.Backend {
|
||||
c, _, _ := TestCoreUnsealed(t)
|
||||
return NewSystemBackend(c)
|
||||
|
|
Loading…
Reference in New Issue