vault: Support sys/revoke-prefix/
This commit is contained in:
parent
f08659aaaa
commit
a24192b728
|
@ -15,6 +15,7 @@ func NewSystemBackend(core *Core) logical.Backend {
|
|||
PathsRoot: []string{
|
||||
"mounts/*",
|
||||
"remount",
|
||||
"revoke-prefix/*",
|
||||
},
|
||||
|
||||
Paths: []*framework.Path{
|
||||
|
@ -107,6 +108,24 @@ func NewSystemBackend(core *Core) logical.Backend {
|
|||
HelpSynopsis: strings.TrimSpace(sysHelp["revoke"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["revoke"][1]),
|
||||
},
|
||||
|
||||
&framework.Path{
|
||||
Pattern: "revoke-prefix/(?P<prefix>.+)",
|
||||
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"prefix": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: strings.TrimSpace(sysHelp["revoke-prefix-path"][0]),
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.WriteOperation: b.handleRevokePrefix,
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(sysHelp["revoke-prefix"][0]),
|
||||
HelpDescription: strings.TrimSpace(sysHelp["revoke-prefix"][1]),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -241,6 +260,19 @@ func (b *SystemBackend) handleRevoke(
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// handleRevokePrefix is used to revoke a prefix with many VaultIDs
|
||||
func (b *SystemBackend) handleRevokePrefix(
|
||||
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
// Get all the options
|
||||
prefix := data.Get("prefix").(string)
|
||||
|
||||
// Invoke the expiration manager directly
|
||||
if err := b.Core.expiration.RevokePrefix(prefix); 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": {
|
||||
|
@ -312,4 +344,21 @@ you may want to force an immediate revocation. This endpoint can be
|
|||
used to revoke the secret with the given Vault ID.
|
||||
`,
|
||||
},
|
||||
|
||||
"revoke-prefix": {
|
||||
"Revoke all secrets generated in a given prefix",
|
||||
`
|
||||
Revokes all the secrets generated under a given mount prefix. As
|
||||
an example, "prod/aws/" might be the AWS logical backend, and due to
|
||||
a change in the "ops" policy, we may want to invalidate all the secrets
|
||||
generated. We can do a revoke prefix at "prod/aws/ops" to revoke all
|
||||
the ops secrets. This does a prefix match on the Vault IDs and revokes
|
||||
all matching leases.
|
||||
`,
|
||||
},
|
||||
|
||||
"revoke-prefix-path": {
|
||||
`The path to revoke keys under. Example: "prod/aws/ops"`,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ func TestSystemBackend_RootPaths(t *testing.T) {
|
|||
expected := []string{
|
||||
"mounts/*",
|
||||
"remount",
|
||||
"revoke-prefix/*",
|
||||
}
|
||||
|
||||
b := testSystemBackend(t)
|
||||
|
@ -223,7 +224,7 @@ func TestSystemBackend_revoke(t *testing.T) {
|
|||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
// Attempt renew
|
||||
// Attempt revoke
|
||||
req2 := logical.TestRequest(t, logical.WriteOperation, "revoke/"+resp.Lease.VaultID)
|
||||
resp2, err := b.HandleRequest(req2)
|
||||
if err != nil {
|
||||
|
@ -232,6 +233,16 @@ func TestSystemBackend_revoke(t *testing.T) {
|
|||
if resp2 != nil {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
// Attempt renew
|
||||
req3 := logical.TestRequest(t, logical.WriteOperation, "renew/"+resp.Lease.VaultID)
|
||||
resp3, err := b.HandleRequest(req3)
|
||||
if err != logical.ErrInvalidRequest {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp3.Data["error"] != "lease not found" {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_revoke_invalidID(t *testing.T) {
|
||||
|
@ -248,6 +259,52 @@ func TestSystemBackend_revoke_invalidID(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSystemBackend_revokePrefix(t *testing.T) {
|
||||
core, b := testCoreSystemBackend(t)
|
||||
|
||||
// Create a key with a lease
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "secret/foo")
|
||||
req.Data["foo"] = "bar"
|
||||
req.Data["lease"] = "1h"
|
||||
resp, err := core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
// Read a key with a VaultID
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "secret/foo")
|
||||
resp, err = core.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp == nil || resp.Lease == nil || resp.Lease.VaultID == "" {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
// Attempt revoke
|
||||
req2 := logical.TestRequest(t, logical.WriteOperation, "revoke-prefix/secret/")
|
||||
resp2, err := b.HandleRequest(req2)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v %#v", err, resp2)
|
||||
}
|
||||
if resp2 != nil {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
|
||||
// Attempt renew
|
||||
req3 := logical.TestRequest(t, logical.WriteOperation, "renew/"+resp.Lease.VaultID)
|
||||
resp3, err := b.HandleRequest(req3)
|
||||
if err != logical.ErrInvalidRequest {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp3.Data["error"] != "lease not found" {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func testSystemBackend(t *testing.T) logical.Backend {
|
||||
c, _ := TestCoreUnsealed(t)
|
||||
return NewSystemBackend(c)
|
||||
|
|
Loading…
Reference in New Issue