mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
logical/framework: add methods to look up secret and gen response
This commit is contained in:
@@ -106,6 +106,17 @@ func (b *Backend) Route(path string) *Path {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secret is used to look up the secret with the given type.
|
||||||
|
func (b *Backend) Secret(k string) *Secret {
|
||||||
|
for _, s := range b.Secrets {
|
||||||
|
if s.Type == k {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Backend) init() {
|
func (b *Backend) init() {
|
||||||
b.pathsRe = make([]*regexp.Regexp, len(b.Paths))
|
b.pathsRe = make([]*regexp.Regexp, len(b.Paths))
|
||||||
for i, p := range b.Paths {
|
for i, p := range b.Paths {
|
||||||
|
|||||||
@@ -319,6 +319,37 @@ func TestBackendRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBackendSecret(t *testing.T) {
|
||||||
|
cases := map[string]struct {
|
||||||
|
Secrets []*Secret
|
||||||
|
Search string
|
||||||
|
Match bool
|
||||||
|
}{
|
||||||
|
"no match": {
|
||||||
|
[]*Secret{&Secret{Type: "foo"}},
|
||||||
|
"bar",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
"match": {
|
||||||
|
[]*Secret{&Secret{Type: "foo"}},
|
||||||
|
"foo",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for n, tc := range cases {
|
||||||
|
b := &Backend{Secrets: tc.Secrets}
|
||||||
|
result := b.Secret(tc.Search)
|
||||||
|
if tc.Match != (result != nil) {
|
||||||
|
t.Fatalf("bad: %s\n\nExpected match: %v", n, tc.Match)
|
||||||
|
}
|
||||||
|
if result != nil && result.Type != tc.Search {
|
||||||
|
t.Fatalf("bad: %s\n\nExpected matching type: %#v", n, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFieldSchemaDefaultOrZero(t *testing.T) {
|
func TestFieldSchemaDefaultOrZero(t *testing.T) {
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
Schema *FieldSchema
|
Schema *FieldSchema
|
||||||
|
|||||||
@@ -7,7 +7,25 @@ import (
|
|||||||
// Request is a single request for a backend that wraps a logical.Request
|
// Request is a single request for a backend that wraps a logical.Request
|
||||||
// to provide some extra functionality.
|
// to provide some extra functionality.
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Backend *Backend
|
// Backend is the backend that generated this request.
|
||||||
Data *FieldData
|
Backend *Backend
|
||||||
|
|
||||||
|
// Data is any parameters that were passed into the request according
|
||||||
|
// to the path schema. If this request is to a secret operation
|
||||||
|
// (revoke, renew), then Data is according to the schema of the
|
||||||
|
// secret.
|
||||||
|
Data *FieldData
|
||||||
|
|
||||||
|
// The fields below are only set for secret-related requests (renew,
|
||||||
|
// revoke).
|
||||||
|
//
|
||||||
|
// SecretType is the string type of the secret.
|
||||||
|
//
|
||||||
|
// SecretId is the ID of the secret that was given when generating
|
||||||
|
// the secret, or is otherwise just the UUID that was generated.
|
||||||
|
SecretType string
|
||||||
|
SecretId string
|
||||||
|
|
||||||
|
// LogicalRequest is the raw logical.Request structure for this request.
|
||||||
LogicalRequest *logical.Request
|
LogicalRequest *logical.Request
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,62 @@
|
|||||||
package framework
|
package framework
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/logical"
|
||||||
|
)
|
||||||
|
|
||||||
// Secret is a type of secret that can be returned from a backend.
|
// Secret is a type of secret that can be returned from a backend.
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
// Type is the name of this secret type. This is used to setup the
|
// Type is the name of this secret type. This is used to setup the
|
||||||
// vault ID and to look up the proper secret structure when revocation/
|
// vault ID and to look up the proper secret structure when revocation/
|
||||||
// renewal happens. Once this is set this should not be changed.
|
// renewal happens. Once this is set this should not be changed.
|
||||||
|
//
|
||||||
|
// The format of this must match (case insensitive): ^a-Z0-9_$
|
||||||
Type string
|
Type string
|
||||||
|
|
||||||
// Fields is the mapping of data fields and schema that comprise
|
// Fields is the mapping of data fields and schema that comprise
|
||||||
// the structure of this secret.
|
// the structure of this secret.
|
||||||
Fields map[string]*FieldSchema
|
Fields map[string]*FieldSchema
|
||||||
|
|
||||||
|
// Renewable is whether or not this secret type can be renewed.
|
||||||
|
Renewable bool
|
||||||
|
|
||||||
|
// DefaultDuration and DefaultGracePeriod are the default values for
|
||||||
|
// the duration of the lease for this secret and its grace period. These
|
||||||
|
// can be manually overwritten with the result of Response().
|
||||||
|
DefaultDuration time.Duration
|
||||||
|
DefaultGracePeriod time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretType is the type of the secret with the given ID.
|
||||||
|
func SecretType(id string) string {
|
||||||
|
idx := strings.Index(id, "-")
|
||||||
|
if idx < 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return id[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Secret) Response(
|
||||||
|
data map[string]interface{}) (*logical.Response, error) {
|
||||||
|
uuid, err := logical.UUID()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := fmt.Sprintf("%s-%s", s.Type, uuid)
|
||||||
|
return &logical.Response{
|
||||||
|
IsSecret: true,
|
||||||
|
Lease: &logical.Lease{
|
||||||
|
VaultID: id,
|
||||||
|
Renewable: s.Renewable,
|
||||||
|
Duration: s.DefaultDuration,
|
||||||
|
GracePeriod: s.DefaultGracePeriod,
|
||||||
|
},
|
||||||
|
Data: data,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
19
logical/framework/secret_test.go
Normal file
19
logical/framework/secret_test.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package framework
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSecretType(t *testing.T) {
|
||||||
|
cases := [][2]string{
|
||||||
|
{"foo-bar", "foo"},
|
||||||
|
{"foo", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
actual := SecretType(tc[0])
|
||||||
|
if actual != tc[1] {
|
||||||
|
t.Fatalf("Input: %s, Output: %s, Expected: %s", tc[0], actual, tc[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user