Merge pull request #631 from hashicorp/remove-generic-leases
Don't use leases on the generic backend
This commit is contained in:
commit
8f7e56b81d
|
@ -45,12 +45,16 @@ func outputFormatTable(ui cli.Ui, s *api.Secret, whitespace bool) int {
|
|||
input := make([]string, 0, 5)
|
||||
input = append(input, fmt.Sprintf("Key %s Value", config.Delim))
|
||||
|
||||
if s.LeaseID != "" && s.LeaseDuration > 0 {
|
||||
input = append(input, fmt.Sprintf("lease_id %s %s", config.Delim, s.LeaseID))
|
||||
if s.LeaseDuration > 0 {
|
||||
if s.LeaseID != "" {
|
||||
input = append(input, fmt.Sprintf("lease_id %s %s", config.Delim, s.LeaseID))
|
||||
}
|
||||
input = append(input, fmt.Sprintf(
|
||||
"lease_duration %s %d", config.Delim, s.LeaseDuration))
|
||||
input = append(input, fmt.Sprintf(
|
||||
"lease_renewable %s %s", config.Delim, strconv.FormatBool(s.Renewable)))
|
||||
if s.LeaseID != "" {
|
||||
input = append(input, fmt.Sprintf(
|
||||
"lease_renewable %s %s", config.Delim, strconv.FormatBool(s.Renewable)))
|
||||
}
|
||||
}
|
||||
|
||||
if s.Auth != nil {
|
||||
|
|
|
@ -350,7 +350,10 @@ func NewCore(conf *CoreConfig) (*Core, error) {
|
|||
for k, f := range conf.LogicalBackends {
|
||||
logicalBackends[k] = f
|
||||
}
|
||||
logicalBackends["generic"] = PassthroughBackendFactory
|
||||
_, ok := logicalBackends["generic"]
|
||||
if !ok {
|
||||
logicalBackends["generic"] = PassthroughBackendFactory
|
||||
}
|
||||
logicalBackends["cubbyhole"] = CubbyholeBackendFactory
|
||||
logicalBackends["system"] = func(config *logical.BackendConfig) (logical.Backend, error) {
|
||||
return NewSystemBackend(c, config), nil
|
||||
|
@ -503,15 +506,31 @@ func (c *Core) handleRequest(req *logical.Request) (retResp *logical.Response, r
|
|||
resp.Secret.TTL = maxTTL
|
||||
}
|
||||
|
||||
// Register the lease
|
||||
leaseID, err := c.expiration.Register(req, resp)
|
||||
if err != nil {
|
||||
c.logger.Printf(
|
||||
"[ERR] core: failed to register lease "+
|
||||
"(request: %#v, response: %#v): %v", req, resp, err)
|
||||
// Generic mounts should return the TTL but not register
|
||||
// for a lease as this provides a massive slowdown
|
||||
registerLease := true
|
||||
matchingBackend := c.router.MatchingBackend(req.Path)
|
||||
if matchingBackend == nil {
|
||||
c.logger.Println("[ERR] core: unable to retrieve generic backend from router")
|
||||
return nil, auth, ErrInternalError
|
||||
}
|
||||
resp.Secret.LeaseID = leaseID
|
||||
if ptbe, ok := matchingBackend.(*PassthroughBackend); ok {
|
||||
if !ptbe.GeneratesLeases() {
|
||||
registerLease = false
|
||||
resp.Secret.Renewable = false
|
||||
}
|
||||
}
|
||||
|
||||
if registerLease {
|
||||
leaseID, err := c.expiration.Register(req, resp)
|
||||
if err != nil {
|
||||
c.logger.Printf(
|
||||
"[ERR] core: failed to register lease "+
|
||||
"(request: %#v, response: %#v): %v", req, resp, err)
|
||||
return nil, auth, ErrInternalError
|
||||
}
|
||||
resp.Secret.LeaseID = leaseID
|
||||
}
|
||||
}
|
||||
|
||||
// Only the token store is allowed to return an auth block, for any
|
||||
|
|
|
@ -43,6 +43,9 @@ func TestCore_Init(t *testing.T) {
|
|||
conf := &CoreConfig{
|
||||
Physical: inm,
|
||||
DisableMlock: true,
|
||||
LogicalBackends: map[string]logical.Factory{
|
||||
"generic": LeasedPassthroughBackendFactory,
|
||||
},
|
||||
}
|
||||
c, err := NewCore(conf)
|
||||
if err != nil {
|
||||
|
|
|
@ -10,9 +10,23 @@ import (
|
|||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
// logical.Factory
|
||||
// PassthroughBackendFactory returns a PassthroughBackend
|
||||
// with leases switched off
|
||||
func PassthroughBackendFactory(conf *logical.BackendConfig) (logical.Backend, error) {
|
||||
return LeaseSwitchedPassthroughBackend(conf, false)
|
||||
}
|
||||
|
||||
// PassthroughBackendWithLeasesFactory returns a PassthroughBackend
|
||||
// with leases switched on
|
||||
func LeasedPassthroughBackendFactory(conf *logical.BackendConfig) (logical.Backend, error) {
|
||||
return LeaseSwitchedPassthroughBackend(conf, true)
|
||||
}
|
||||
|
||||
// LeaseSwitchedPassthroughBackendFactory returns a PassthroughBackend
|
||||
// with leases switched on or off
|
||||
func LeaseSwitchedPassthroughBackend(conf *logical.BackendConfig, leases bool) (logical.Backend, error) {
|
||||
var b PassthroughBackend
|
||||
b.generateLeases = leases
|
||||
b.Backend = &framework.Backend{
|
||||
Help: strings.TrimSpace(passthroughHelp),
|
||||
|
||||
|
@ -42,15 +56,17 @@ func PassthroughBackendFactory(conf *logical.BackendConfig) (logical.Backend, er
|
|||
HelpDescription: strings.TrimSpace(passthroughHelpDescription),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Secrets: []*framework.Secret{
|
||||
if b.generateLeases {
|
||||
b.Backend.Secrets = []*framework.Secret{
|
||||
&framework.Secret{
|
||||
Type: "generic",
|
||||
|
||||
Renew: b.handleRead,
|
||||
Revoke: b.handleRevoke,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if conf == nil {
|
||||
|
@ -58,7 +74,7 @@ func PassthroughBackendFactory(conf *logical.BackendConfig) (logical.Backend, er
|
|||
}
|
||||
b.Backend.Setup(conf)
|
||||
|
||||
return b, nil
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
// PassthroughBackend is used storing secrets directly into the physical
|
||||
|
@ -67,6 +83,7 @@ func PassthroughBackendFactory(conf *logical.BackendConfig) (logical.Backend, er
|
|||
// fancy.
|
||||
type PassthroughBackend struct {
|
||||
*framework.Backend
|
||||
generateLeases bool
|
||||
}
|
||||
|
||||
func (b *PassthroughBackend) handleRevoke(
|
||||
|
@ -94,9 +111,17 @@ func (b *PassthroughBackend) handleRead(
|
|||
return nil, fmt.Errorf("json decoding failed: %v", err)
|
||||
}
|
||||
|
||||
// Generate the response
|
||||
resp := b.Secret("generic").Response(rawData, nil)
|
||||
resp.Secret.Renewable = false
|
||||
var resp *logical.Response
|
||||
if b.generateLeases {
|
||||
// Generate the response
|
||||
resp = b.Secret("generic").Response(rawData, nil)
|
||||
resp.Secret.Renewable = false
|
||||
} else {
|
||||
resp = &logical.Response{
|
||||
Secret: &logical.Secret{},
|
||||
Data: rawData,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is a ttl key
|
||||
var ttl string
|
||||
|
@ -105,14 +130,19 @@ func (b *PassthroughBackend) handleRead(
|
|||
ttl, _ = rawData["ttl"].(string)
|
||||
}
|
||||
|
||||
ttlDuration := b.System().DefaultLeaseTTL()
|
||||
if len(ttl) != 0 {
|
||||
ttlDuration, err := time.ParseDuration(ttl)
|
||||
if err == nil {
|
||||
ttlDuration, err = time.ParseDuration(ttl)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to parse ttl for entry"), nil
|
||||
}
|
||||
if b.generateLeases {
|
||||
resp.Secret.Renewable = true
|
||||
resp.Secret.TTL = ttlDuration
|
||||
}
|
||||
}
|
||||
|
||||
resp.Secret.TTL = ttlDuration
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
|
@ -163,6 +193,10 @@ func (b *PassthroughBackend) handleList(
|
|||
return logical.ListResponse(keys), nil
|
||||
}
|
||||
|
||||
func (b *PassthroughBackend) GeneratesLeases() bool {
|
||||
return b.generateLeases
|
||||
}
|
||||
|
||||
const passthroughHelp = `
|
||||
The generic backend reads and writes arbitrary secrets to the backend.
|
||||
The secrets are encrypted/decrypted by Vault: they are never stored
|
||||
|
|
|
@ -10,169 +10,160 @@ import (
|
|||
|
||||
func TestPassthroughBackend_RootPaths(t *testing.T) {
|
||||
b := testPassthroughBackend()
|
||||
root := b.SpecialPaths()
|
||||
if root != nil {
|
||||
t.Fatalf("unexpected: %v", root)
|
||||
test := func(b logical.Backend) {
|
||||
root := b.SpecialPaths()
|
||||
if root != nil {
|
||||
t.Fatalf("unexpected: %v", root)
|
||||
}
|
||||
}
|
||||
test(b)
|
||||
b = testPassthroughLeasedBackend()
|
||||
test(b)
|
||||
}
|
||||
|
||||
func TestPassthroughBackend_Write(t *testing.T) {
|
||||
test := func(b logical.Backend) {
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
|
||||
out, err := req.Storage.Get("foo")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if out == nil {
|
||||
t.Fatalf("failed to write to view")
|
||||
}
|
||||
}
|
||||
b := testPassthroughBackend()
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
|
||||
out, err := req.Storage.Get("foo")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if out == nil {
|
||||
t.Fatalf("failed to write to view")
|
||||
}
|
||||
test(b)
|
||||
b = testPassthroughLeasedBackend()
|
||||
test(b)
|
||||
}
|
||||
|
||||
func TestPassthroughBackend_Read_Lease(t *testing.T) {
|
||||
b := testPassthroughBackend()
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
req.Data["lease"] = "1h"
|
||||
storage := req.Storage
|
||||
func TestPassthroughBackend_Read(t *testing.T) {
|
||||
test := func(b logical.Backend, ttlType string, leased bool) {
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
req.Data[ttlType] = "1h"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "foo")
|
||||
req.Storage = storage
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "foo")
|
||||
req.Storage = storage
|
||||
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := &logical.Response{
|
||||
Secret: &logical.Secret{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
TTL: time.Hour,
|
||||
expected := &logical.Response{
|
||||
Secret: &logical.Secret{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
TTL: time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: map[string]interface{}{
|
||||
"raw": "test",
|
||||
"lease": "1h",
|
||||
},
|
||||
}
|
||||
|
||||
resp.Secret.InternalData = nil
|
||||
resp.Secret.LeaseID = ""
|
||||
if !reflect.DeepEqual(resp, expected) {
|
||||
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPassthroughBackend_Read_TTL(t *testing.T) {
|
||||
b := testPassthroughBackend()
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
req.Data["ttl"] = "1h"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "foo")
|
||||
req.Storage = storage
|
||||
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := &logical.Response{
|
||||
Secret: &logical.Secret{
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
TTL: time.Hour,
|
||||
Data: map[string]interface{}{
|
||||
"raw": "test",
|
||||
ttlType: "1h",
|
||||
},
|
||||
},
|
||||
Data: map[string]interface{}{
|
||||
"raw": "test",
|
||||
"ttl": "1h",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
resp.Secret.InternalData = nil
|
||||
resp.Secret.LeaseID = ""
|
||||
if !reflect.DeepEqual(resp, expected) {
|
||||
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
|
||||
if !leased {
|
||||
expected.Secret.Renewable = false
|
||||
}
|
||||
resp.Secret.InternalData = nil
|
||||
resp.Secret.LeaseID = ""
|
||||
if !reflect.DeepEqual(resp, expected) {
|
||||
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
|
||||
}
|
||||
}
|
||||
b := testPassthroughLeasedBackend()
|
||||
test(b, "lease", true)
|
||||
test(b, "ttl", true)
|
||||
b = testPassthroughBackend()
|
||||
test(b, "lease", false)
|
||||
test(b, "ttl", false)
|
||||
}
|
||||
|
||||
func TestPassthroughBackend_Delete(t *testing.T) {
|
||||
test := func(b logical.Backend) {
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.DeleteOperation, "foo")
|
||||
req.Storage = storage
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "foo")
|
||||
req.Storage = storage
|
||||
resp, err = b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
b := testPassthroughBackend()
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.DeleteOperation, "foo")
|
||||
req.Storage = storage
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "foo")
|
||||
req.Storage = storage
|
||||
resp, err = b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
test(b)
|
||||
b = testPassthroughLeasedBackend()
|
||||
test(b)
|
||||
}
|
||||
|
||||
func TestPassthroughBackend_List(t *testing.T) {
|
||||
test := func(b logical.Backend) {
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ListOperation, "")
|
||||
req.Storage = storage
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"keys": []string{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(resp, expected) {
|
||||
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
|
||||
}
|
||||
}
|
||||
b := testPassthroughBackend()
|
||||
req := logical.TestRequest(t, logical.WriteOperation, "foo")
|
||||
req.Data["raw"] = "test"
|
||||
storage := req.Storage
|
||||
|
||||
if _, err := b.HandleRequest(req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ListOperation, "")
|
||||
req.Storage = storage
|
||||
resp, err := b.HandleRequest(req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"keys": []string{"foo"},
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(resp, expected) {
|
||||
t.Fatalf("bad response.\n\nexpected: %#v\n\nGot: %#v", expected, resp)
|
||||
}
|
||||
test(b)
|
||||
b = testPassthroughLeasedBackend()
|
||||
test(b)
|
||||
}
|
||||
|
||||
func testPassthroughBackend() logical.Backend {
|
||||
|
@ -185,3 +176,14 @@ func testPassthroughBackend() logical.Backend {
|
|||
})
|
||||
return b
|
||||
}
|
||||
|
||||
func testPassthroughLeasedBackend() logical.Backend {
|
||||
b, _ := LeasedPassthroughBackendFactory(&logical.BackendConfig{
|
||||
Logger: nil,
|
||||
System: logical.StaticSystemView{
|
||||
DefaultLeaseTTLVal: time.Hour * 24,
|
||||
MaxLeaseTTLVal: time.Hour * 24 * 30,
|
||||
},
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ func TestCore(t *testing.T) *Core {
|
|||
for backendName, backendFactory := range noopBackends {
|
||||
logicalBackends[backendName] = backendFactory
|
||||
}
|
||||
logicalBackends["generic"] = LeasedPassthroughBackendFactory
|
||||
for backendName, backendFactory := range testLogicalBackends {
|
||||
logicalBackends[backendName] = backendFactory
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue