diff --git a/vault/logical_system.go b/vault/logical_system.go index 43af47423..5cbfccc00 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -23,6 +23,7 @@ func NewSystemBackend(core *Core) logical.Backend { "audit", "audit/*", "seal", // Must be set for Core.Seal() logic + "raw/*", }, }, @@ -260,6 +261,25 @@ func NewSystemBackend(core *Core) logical.Backend { HelpSynopsis: strings.TrimSpace(sysHelp["audit"][0]), HelpDescription: strings.TrimSpace(sysHelp["audit"][1]), }, + + &framework.Path{ + Pattern: "raw/(?P.+)", + + Fields: map[string]*framework.FieldSchema{ + "path": &framework.FieldSchema{ + Type: framework.TypeString, + }, + "value": &framework.FieldSchema{ + Type: framework.TypeString, + }, + }, + + Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.ReadOperation: b.handleRawRead, + logical.WriteOperation: b.handleRawWrite, + logical.DeleteOperation: b.handleRawDelete, + }, + }, }, } } @@ -597,6 +617,50 @@ func (b *SystemBackend) handleDisableAudit( return nil, nil } +// handleRawRead is used to read directly from the barrier +func (b *SystemBackend) handleRawRead( + req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + path := data.Get("path").(string) + entry, err := b.Core.barrier.Get(path) + if err != nil { + return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest + } + if entry == nil { + return nil, nil + } + resp := &logical.Response{ + Data: map[string]interface{}{ + "value": string(entry.Value), + }, + } + return resp, nil +} + +// handleRawWrite is used to write directly to the barrier +func (b *SystemBackend) handleRawWrite( + req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + path := data.Get("path").(string) + value := data.Get("value").(string) + entry := &Entry{ + Key: path, + Value: []byte(value), + } + if err := b.Core.barrier.Put(entry); err != nil { + return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest + } + return nil, nil +} + +// handleRawDelete is used to delete directly from the barrier +func (b *SystemBackend) handleRawDelete( + req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + path := data.Get("path").(string) + if err := b.Core.barrier.Delete(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": { diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index c0de5b167..9ee4b2c56 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -19,6 +19,7 @@ func TestSystemBackend_RootPaths(t *testing.T) { "audit", "audit/*", "seal", + "raw/*", } b := testSystemBackend(t) @@ -601,6 +602,75 @@ func TestSystemBackend_disableAudit_invalid(t *testing.T) { } } +func TestSystemBackend_rawRead(t *testing.T) { + b := testSystemBackend(t) + + req := logical.TestRequest(t, logical.ReadOperation, "raw/"+coreMountConfigPath) + resp, err := b.HandleRequest(req) + if err != nil { + t.Fatalf("err: %v", err) + } + if resp.Data["value"].(string)[0] != '{' { + t.Fatalf("bad: %v", resp) + } +} + +func TestSystemBackend_rawWrite(t *testing.T) { + c, b, _ := testCoreSystemBackend(t) + + req := logical.TestRequest(t, logical.WriteOperation, "raw/sys/policy/test") + req.Data["value"] = `path "secret/" { policy = "read" }` + resp, err := b.HandleRequest(req) + if err != nil { + t.Fatalf("err: %v", err) + } + if resp != nil { + t.Fatalf("bad: %v", resp) + } + + // Read the policy! + p, err := c.policy.GetPolicy("test") + if err != nil { + t.Fatalf("err: %v", err) + } + if p == nil || len(p.Paths) == 0 { + t.Fatalf("missing policy %#v", p) + } + if p.Paths[0].Prefix != "secret/" || p.Paths[0].Policy != PathPolicyRead { + t.Fatalf("Bad: %#v", p) + } +} + +func TestSystemBackend_rawDelete(t *testing.T) { + c, b, _ := testCoreSystemBackend(t) + + // set the policy! + p := &Policy{Name: "test"} + err := c.policy.SetPolicy(p) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Delete the policy + req := logical.TestRequest(t, logical.DeleteOperation, "raw/sys/policy/test") + resp, err := b.HandleRequest(req) + if err != nil { + t.Fatalf("err: %v", err) + } + if resp != nil { + t.Fatalf("bad: %v", resp) + } + + // Policy should be gone + out, err := c.policy.GetPolicy("test") + if err != nil { + t.Fatalf("err: %v", err) + } + if out != nil { + t.Fatalf("policy should be gone") + } +} + func testSystemBackend(t *testing.T) logical.Backend { c, _, _ := TestCoreUnsealed(t) return NewSystemBackend(c)