feat(credential): add credential type to credential library on create
This change adds a credential type attribute to credential library and allows it to be set when creating a credential library. Specifying the type of credential returned from a library allows for new features and additional error checking to be added over time. A User Password credential type and an Unspecified credential type are included with the expectation that additional credential types will be added in the future. This change also adds the credential type attribute to existing credential libraries and sets it to Unspecified. Known Limitations: - Credential type is only supported on the repository create method. Support for the other CRUD methods will be added in the future.
This commit is contained in:
1 parent
f4b9b83caf
commit
c317901db4
26 files changed
+1033
-107
No files matched your search
@@ -18,11 +18,23 @@ type Store interface {
|
||||
GetScopeId() string
|
||||
}
|
||||
|
||||
// Type is the type of credential provided by a library.
|
||||
type Type string
|
||||
|
||||
// Credential type values.
|
||||
const (
|
||||
UnspecifiedType Type = "unspecified"
|
||||
UserPasswordType Type = "user_password"
|
||||
)
|
||||
|
||||
// A Library is a resource that provides credentials that are of the same
|
||||
// type and access level from a single store.
|
||||
type Library interface {
|
||||
boundary.Resource
|
||||
GetStoreId() string
|
||||
|
||||
// TODO(mgaffney) 10/2021: Add method for returning the credential type
|
||||
// of the library
|
||||
}
|
||||
|
||||
// Purpose is the purpose of the credential.
|
||||
|
||||
@@ -92,6 +92,10 @@ type Library struct {
|
||||
// The store_id of the owning store and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
StoreId string `protobuf:"bytes,2,opt,name=store_id,json=storeId,proto3" json:"store_id,omitempty" gorm:"not_null"`
|
||||
// credential_type is optional. If set, it indicates the type of
|
||||
// credential the library returns.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
CredentialType string `protobuf:"bytes,3,opt,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *Library) Reset() {
|
||||
@@ -140,6 +144,13 @@ func (x *Library) GetStoreId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Library) GetCredentialType() string {
|
||||
if x != nil {
|
||||
return x.CredentialType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Credential struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -320,27 +331,29 @@ var file_controller_storage_credential_store_v1_credential_proto_rawDesc = []byt
|
||||
0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x49, 0x64, 0x22, 0x41, 0x0a, 0x07, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x0a,
|
||||
0x49, 0x64, 0x22, 0x6a, 0x0a, 0x07, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x0a,
|
||||
0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x49, 0x64, 0x22, 0x29, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64,
|
||||
0x6f, 0x72, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
|
||||
0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x29,
|
||||
0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x22, 0x40, 0x0a, 0x06, 0x53, 0x74, 0x61,
|
||||
0x74, 0x69, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64,
|
||||
0x22, 0x40, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75,
|
||||
0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x49, 0x64, 0x22, 0x45, 0x0a, 0x07, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x12, 0x1b, 0x0a,
|
||||
0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69,
|
||||
0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x49, 0x64, 0x22, 0x45, 0x0a, 0x07, 0x44,
|
||||
0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69,
|
||||
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
|
||||
0x49, 0x64, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/store"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
@@ -21,17 +24,20 @@ const (
|
||||
type CredentialLibrary struct {
|
||||
*store.CredentialLibrary
|
||||
tableName string `gorm:"-"`
|
||||
|
||||
MappingOverride MappingOverride `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewCredentialLibrary creates a new in memory CredentialLibrary
|
||||
// for a Vault backend at vaultPath assigned to storeId.
|
||||
// Name, description, method, and request body are the only valid options.
|
||||
// All other options are ignored.
|
||||
// Name, description, method, request body, credential type, and mapping
|
||||
// override are the only valid options. All other options are ignored.
|
||||
func NewCredentialLibrary(storeId string, vaultPath string, opt ...Option) (*CredentialLibrary, error) {
|
||||
const op = "vault.NewCredentialLibrary"
|
||||
opts := getOpts(opt...)
|
||||
|
||||
l := &CredentialLibrary{
|
||||
MappingOverride: opts.withMappingOverride,
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: storeId,
|
||||
Name: opts.withName,
|
||||
@@ -39,12 +45,21 @@ func NewCredentialLibrary(storeId string, vaultPath string, opt ...Option) (*Cre
|
||||
VaultPath: vaultPath,
|
||||
HttpRequestBody: opts.withRequestBody,
|
||||
HttpMethod: string(opts.withMethod),
|
||||
CredentialType: string(opts.withCredentialType),
|
||||
},
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *CredentialLibrary) validate(ctx context.Context, caller errors.Op) error {
|
||||
switch {
|
||||
case !validMappingOverride(l.MappingOverride, l.CredentialType()):
|
||||
return errors.New(ctx, errors.VaultInvalidMappingOverride, caller, "invalid credential type for mapping override")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func allocCredentialLibrary() *CredentialLibrary {
|
||||
return &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{},
|
||||
@@ -52,12 +67,25 @@ func allocCredentialLibrary() *CredentialLibrary {
|
||||
}
|
||||
|
||||
func (l *CredentialLibrary) clone() *CredentialLibrary {
|
||||
var m MappingOverride
|
||||
if l.MappingOverride != nil {
|
||||
m = l.MappingOverride.clone()
|
||||
}
|
||||
|
||||
cp := proto.Clone(l.CredentialLibrary)
|
||||
return &CredentialLibrary{
|
||||
MappingOverride: m,
|
||||
CredentialLibrary: cp.(*store.CredentialLibrary),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CredentialLibrary) setId(i string) {
|
||||
l.PublicId = i
|
||||
if l.MappingOverride != nil {
|
||||
l.MappingOverride.setLibraryId(i)
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (l *CredentialLibrary) TableName() string {
|
||||
if l.tableName != "" {
|
||||
@@ -83,4 +111,14 @@ func (l *CredentialLibrary) oplog(op oplog.OpType) oplog.Metadata {
|
||||
return metadata
|
||||
}
|
||||
|
||||
// CredentialType returns the type of credential the library retrieves.
|
||||
func (l *CredentialLibrary) CredentialType() credential.Type {
|
||||
switch ct := l.GetCredentialType(); ct {
|
||||
case "":
|
||||
return credential.UnspecifiedType
|
||||
default:
|
||||
return credential.Type(ct)
|
||||
}
|
||||
}
|
||||
|
||||
var _ credential.Library = (*CredentialLibrary)(nil)
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
@@ -37,7 +38,6 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
name string
|
||||
args args
|
||||
want *CredentialLibrary
|
||||
wantErr bool
|
||||
wantCreateErr bool
|
||||
}{
|
||||
{
|
||||
@@ -190,6 +190,42 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
},
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "minimum-actually-valid",
|
||||
args: args{
|
||||
storeId: cs.PublicId,
|
||||
vaultPath: "vault/path",
|
||||
opts: []Option{
|
||||
WithMethod(MethodGet),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.PublicId,
|
||||
VaultPath: "vault/path",
|
||||
HttpMethod: string(MethodGet),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "credential-type",
|
||||
args: args{
|
||||
storeId: cs.PublicId,
|
||||
vaultPath: "vault/path",
|
||||
opts: []Option{
|
||||
WithMethod(MethodGet),
|
||||
WithCredentialType(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.PublicId,
|
||||
VaultPath: "vault/path",
|
||||
HttpMethod: string(MethodGet),
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -198,17 +234,21 @@ func TestCredentialLibrary_New(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
ctx := context.Background()
|
||||
got, err := NewCredentialLibrary(tt.args.storeId, tt.args.vaultPath, tt.args.opts...)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
require.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
switch ct := tt.want.GetCredentialType(); ct {
|
||||
case string(credential.UserPasswordType):
|
||||
assert.Equal(credential.UserPasswordType, got.CredentialType())
|
||||
case string(credential.UnspecifiedType), "":
|
||||
assert.Equal(credential.UnspecifiedType, got.CredentialType())
|
||||
default:
|
||||
assert.Failf("Unknown credential type", "%s", ct)
|
||||
}
|
||||
|
||||
id, err := newCredentialLibraryId()
|
||||
assert.NoError(err)
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/store"
|
||||
"github.com/hashicorp/boundary/internal/db/sanitize"
|
||||
"github.com/hashicorp/boundary/internal/db/sentinel"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// validMappingOverride reports whether the given mapping override is valid
|
||||
// for the given credential type.
|
||||
func validMappingOverride(m MappingOverride, ct credential.Type) bool {
|
||||
switch m.(type) {
|
||||
case nil:
|
||||
return true // it is always valid to not specify a mapping override
|
||||
case *UserPasswordOverride:
|
||||
return ct == credential.UserPasswordType
|
||||
default:
|
||||
return false // an unknown mapping override type is never valid
|
||||
}
|
||||
}
|
||||
|
||||
// A MappingOverride is an interface holding one of the mapping override
|
||||
// types: UserPasswordOverride.
|
||||
type MappingOverride interface {
|
||||
clone() MappingOverride
|
||||
setLibraryId(i string)
|
||||
|
||||
// sanitize replaces all sentinel values in the MappingOverride with
|
||||
// zero values. It is called before a MappingOverride is returned from
|
||||
// the domain layer when the MappingOverride has been loaded from the
|
||||
// database.
|
||||
sanitize()
|
||||
}
|
||||
|
||||
// A UserPasswordOverride contains optional values for overriding the
|
||||
// default mappings used to map a Vault secret to a UserPassword credential
|
||||
// type for the credential library that owns it.
|
||||
type UserPasswordOverride struct {
|
||||
*store.UserPasswordOverride
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
var _ MappingOverride = (*UserPasswordOverride)(nil)
|
||||
|
||||
// NewUserPasswordOverride creates a new in memory UserPasswordOverride.
|
||||
// WithOverrideUsernameAttribute and WithOverridePasswordAttribute are the
|
||||
// only valid options. All other options are ignored.
|
||||
func NewUserPasswordOverride(opt ...Option) *UserPasswordOverride {
|
||||
opts := getOpts(opt...)
|
||||
o := &UserPasswordOverride{
|
||||
UserPasswordOverride: &store.UserPasswordOverride{
|
||||
UsernameAttribute: sanitize.String(opts.withOverrideUsernameAttribute),
|
||||
PasswordAttribute: sanitize.String(opts.withOverridePasswordAttribute),
|
||||
},
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func allocUserPasswordOverride() *UserPasswordOverride {
|
||||
return &UserPasswordOverride{
|
||||
UserPasswordOverride: &store.UserPasswordOverride{},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *UserPasswordOverride) clone() MappingOverride {
|
||||
cp := proto.Clone(o.UserPasswordOverride)
|
||||
return &UserPasswordOverride{
|
||||
UserPasswordOverride: cp.(*store.UserPasswordOverride),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *UserPasswordOverride) setLibraryId(i string) {
|
||||
o.LibraryId = i
|
||||
}
|
||||
|
||||
func (o *UserPasswordOverride) sanitize() {
|
||||
if sentinel.Is(o.UsernameAttribute) {
|
||||
o.UsernameAttribute = ""
|
||||
}
|
||||
if sentinel.Is(o.PasswordAttribute) {
|
||||
o.PasswordAttribute = ""
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (o *UserPasswordOverride) TableName() string {
|
||||
if o.tableName != "" {
|
||||
return o.tableName
|
||||
}
|
||||
return "credential_vault_library_user_password_mapping_override"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (o *UserPasswordOverride) SetTableName(n string) {
|
||||
o.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type unknownMapper int
|
||||
|
||||
func (u unknownMapper) clone() MappingOverride { return u }
|
||||
func (u unknownMapper) setLibraryId(_ string) {}
|
||||
func (u unknownMapper) sanitize() {}
|
||||
|
||||
var _ MappingOverride = unknownMapper(0)
|
||||
|
||||
func TestValidMappingOverrides(t *testing.T) {
|
||||
tests := []struct {
|
||||
m MappingOverride
|
||||
ct credential.Type
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
m: nil,
|
||||
ct: "invalid",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: nil,
|
||||
ct: credential.UnspecifiedType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: nil,
|
||||
ct: credential.UserPasswordType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: unknownMapper(1),
|
||||
ct: credential.UnspecifiedType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: unknownMapper(1),
|
||||
ct: credential.UserPasswordType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: allocUserPasswordOverride(),
|
||||
ct: credential.UnspecifiedType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: allocUserPasswordOverride(),
|
||||
ct: credential.UserPasswordType,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(fmt.Sprintf("%T-%s", tt.m, tt.ct), func(t *testing.T) {
|
||||
got := validMappingOverride(tt.m, tt.ct)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package vault
|
||||
|
||||
import "github.com/hashicorp/boundary/internal/credential"
|
||||
|
||||
// getOpts - iterate the inbound Options and return a struct
|
||||
func getOpts(opt ...Option) options {
|
||||
opts := getDefaultOptions()
|
||||
@@ -14,16 +16,21 @@ type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withName string
|
||||
withDescription string
|
||||
withLimit int
|
||||
withCACert []byte
|
||||
withNamespace string
|
||||
withTlsServerName string
|
||||
withTlsSkipVerify bool
|
||||
withClientCert *ClientCertificate
|
||||
withMethod Method
|
||||
withRequestBody []byte
|
||||
withName string
|
||||
withDescription string
|
||||
withLimit int
|
||||
withCACert []byte
|
||||
withNamespace string
|
||||
withTlsServerName string
|
||||
withTlsSkipVerify bool
|
||||
withClientCert *ClientCertificate
|
||||
withMethod Method
|
||||
withRequestBody []byte
|
||||
withCredentialType credential.Type
|
||||
|
||||
withOverrideUsernameAttribute string
|
||||
withOverridePasswordAttribute string
|
||||
withMappingOverride MappingOverride
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
@@ -109,3 +116,35 @@ func WithRequestBody(b []byte) Option {
|
||||
o.withRequestBody = b
|
||||
}
|
||||
}
|
||||
|
||||
// WithCredentialType provides an optional credential type to associate
|
||||
// with a credential library.
|
||||
func WithCredentialType(t credential.Type) Option {
|
||||
return func(o *options) {
|
||||
o.withCredentialType = t
|
||||
}
|
||||
}
|
||||
|
||||
// WithOverrideUsernameAttribute provides the name of an attribute in the
|
||||
// Data field of a Vault api.Secret that maps to a username value.
|
||||
func WithOverrideUsernameAttribute(s string) Option {
|
||||
return func(o *options) {
|
||||
o.withOverrideUsernameAttribute = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithOverridePasswordAttribute provides the name of an attribute in the
|
||||
// Data field of a Vault api.Secret that maps to a password value.
|
||||
func WithOverridePasswordAttribute(s string) Option {
|
||||
return func(o *options) {
|
||||
o.withOverridePasswordAttribute = s
|
||||
}
|
||||
}
|
||||
|
||||
// WithMappingOverride provides an optional mapping override to use for
|
||||
// mapping the Data fields of a Vault api.Secret to a credential.
|
||||
func WithMappingOverride(m MappingOverride) Option {
|
||||
return func(o *options) {
|
||||
o.withMappingOverride = m
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package vault
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -83,4 +84,28 @@ func Test_GetOpts(t *testing.T) {
|
||||
testOpts.withRequestBody = []byte("body")
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithCredentialType", func(t *testing.T) {
|
||||
opts := getOpts(WithCredentialType(credential.UserPasswordType))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withCredentialType = credential.UserPasswordType
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithOverrideUsernameAttribute", func(t *testing.T) {
|
||||
opts := getOpts(WithOverrideUsernameAttribute("test"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withOverrideUsernameAttribute = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithOverridePasswordAttribute", func(t *testing.T) {
|
||||
opts := getOpts(WithOverridePasswordAttribute("test"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withOverridePasswordAttribute = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithMappingOverride", func(t *testing.T) {
|
||||
opts := getOpts(WithMappingOverride(unknownMapper(1)))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withMappingOverride = unknownMapper(1)
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -48,11 +48,15 @@ func (r *Repository) CreateCredentialLibrary(ctx context.Context, scopeId string
|
||||
l.HttpMethod = string(MethodGet)
|
||||
}
|
||||
|
||||
if err := l.validate(ctx, op); err != nil {
|
||||
return nil, err // intentionally not wrapped.
|
||||
}
|
||||
|
||||
id, err := newCredentialLibraryId()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
l.PublicId = id
|
||||
l.setId(id)
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
@@ -62,11 +66,34 @@ func (r *Repository) CreateCredentialLibrary(ctx context.Context, scopeId string
|
||||
var newCredentialLibrary *CredentialLibrary
|
||||
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
newCredentialLibrary = l.clone()
|
||||
err := w.Create(ctx, newCredentialLibrary, db.WithOplog(oplogWrapper, l.oplog(oplog.OpType_OP_TYPE_CREATE)))
|
||||
var msgs []*oplog.Message
|
||||
ticket, err := w.GetTicket(l)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket"))
|
||||
}
|
||||
|
||||
// insert credential library
|
||||
newCredentialLibrary = l.clone()
|
||||
var lOplogMsg oplog.Message
|
||||
if err := w.Create(ctx, newCredentialLibrary, db.NewOplogMsg(&lOplogMsg)); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
msgs = append(msgs, &lOplogMsg)
|
||||
|
||||
// insert mapper override (if exists)
|
||||
if l.MappingOverride != nil {
|
||||
var msg oplog.Message
|
||||
if err := w.Create(ctx, newCredentialLibrary.MappingOverride, db.NewOplogMsg(&msg)); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
newCredentialLibrary.MappingOverride.sanitize()
|
||||
msgs = append(msgs, &msg)
|
||||
}
|
||||
|
||||
metadata := l.oplog(oplog.OpType_OP_TYPE_CREATE)
|
||||
if err := w.WriteOplogEntryWith(ctx, oplogWrapper, ticket, metadata, msgs); err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog"))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/store"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbassert "github.com/hashicorp/boundary/internal/db/assert"
|
||||
@@ -166,6 +167,71 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-user-password-credential-type",
|
||||
in: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unknown-mapping-override-type",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: unknownMapper(1),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "invalid-mapping-override-type",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewUserPasswordOverride(WithOverrideUsernameAttribute("test")),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "valid-user-password-credential-type-with-override",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewUserPasswordOverride(WithOverrideUsernameAttribute("test")),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
MappingOverride: NewUserPasswordOverride(WithOverrideUsernameAttribute("test")),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(credential.UserPasswordType),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -191,8 +257,28 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
assert.NotSame(tt.in, got)
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
assert.Equal(tt.want.CredentialType(), got.CredentialType())
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.GetPublicId(), db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
|
||||
if tt.in.MappingOverride != nil {
|
||||
require.NotNil(got.MappingOverride)
|
||||
assert.IsType(tt.want.MappingOverride, got.MappingOverride)
|
||||
switch w := tt.want.MappingOverride.(type) {
|
||||
case *UserPasswordOverride:
|
||||
g, ok := got.MappingOverride.(*UserPasswordOverride)
|
||||
require.True(ok)
|
||||
assert.Equal(w.UsernameAttribute, g.UsernameAttribute)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
default:
|
||||
assert.Fail("Unknown mapping override")
|
||||
}
|
||||
|
||||
// verify it was persisted in the database
|
||||
override := allocUserPasswordOverride()
|
||||
assert.NoError(rw.LookupWhere(ctx, &override, "library_id = ?", got.GetPublicId()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -502,6 +502,10 @@ type CredentialLibrary struct {
|
||||
// Can only be set if http_method is POST.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
HttpRequestBody []byte `protobuf:"bytes,10,opt,name=http_request_body,json=httpRequestBody,proto3" json:"http_request_body,omitempty" gorm:"default:null"`
|
||||
// credential_type is optional. If set, it indicates the type of
|
||||
// credential the library returns.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
CredentialType string `protobuf:"bytes,11,opt,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *CredentialLibrary) Reset() {
|
||||
@@ -606,6 +610,13 @@ func (x *CredentialLibrary) GetHttpRequestBody() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CredentialLibrary) GetCredentialType() string {
|
||||
if x != nil {
|
||||
return x.CredentialType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Credential struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -776,6 +787,87 @@ func (x *Credential) GetStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type UserPasswordOverride struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// library_id of the owning vault credential library.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
LibraryId string `protobuf:"bytes,1,opt,name=library_id,json=libraryId,proto3" json:"library_id,omitempty" gorm:"primary_key"`
|
||||
// username_attribute is the name of the attribute in the Data field of a
|
||||
// Vault api.Secret that maps to a username.
|
||||
// If set, it overrides any default attribute names the system uses to
|
||||
// find a username attribute.
|
||||
//
|
||||
// See https://github.com/hashicorp/vault/blob/5e505ec039177e8212cbbab74ccb644c46e62e63/api/secret.go#L25
|
||||
//
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
UsernameAttribute string `protobuf:"bytes,2,opt,name=username_attribute,json=usernameAttribute,proto3" json:"username_attribute,omitempty" gorm:"default:null"`
|
||||
// password_attribute is the name of the attribute in the Data field of a
|
||||
// Vault api.Secret that maps to a password.
|
||||
// If set, it overrides any default attribute names the system uses to
|
||||
// find a password attribute.
|
||||
//
|
||||
// See https://github.com/hashicorp/vault/blob/5e505ec039177e8212cbbab74ccb644c46e62e63/api/secret.go#L25
|
||||
//
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
PasswordAttribute string `protobuf:"bytes,3,opt,name=password_attribute,json=passwordAttribute,proto3" json:"password_attribute,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *UserPasswordOverride) Reset() {
|
||||
*x = UserPasswordOverride{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UserPasswordOverride) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UserPasswordOverride) ProtoMessage() {}
|
||||
|
||||
func (x *UserPasswordOverride) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UserPasswordOverride.ProtoReflect.Descriptor instead.
|
||||
func (*UserPasswordOverride) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *UserPasswordOverride) GetLibraryId() string {
|
||||
if x != nil {
|
||||
return x.LibraryId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserPasswordOverride) GetUsernameAttribute() string {
|
||||
if x != nil {
|
||||
return x.UsernameAttribute
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserPasswordOverride) GetPasswordAttribute() string {
|
||||
if x != nil {
|
||||
return x.PasswordAttribute
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_controller_storage_credential_vault_store_v1_vault_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = []byte{
|
||||
@@ -897,7 +989,7 @@ var file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = []by
|
||||
0x18, 0x82, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x48, 0x6d, 0x61, 0x63, 0x12, 0x15, 0x0a, 0x06, 0x6b,
|
||||
0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79,
|
||||
0x49, 0x64, 0x22, 0xd4, 0x04, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||
0x49, 0x64, 0x22, 0xfd, 0x04, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||
0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f,
|
||||
@@ -934,48 +1026,60 @@ var file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = []by
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x61, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x52, 0x0f, 0x68, 0x74, 0x74, 0x70, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc3, 0x04, 0x0a, 0x0a, 0x43, 0x72,
|
||||
0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c,
|
||||
0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62,
|
||||
0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61,
|
||||
0x72, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x68, 0x6d, 0x61,
|
||||
0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x6d,
|
||||
0x61, 0x63, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x56, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f,
|
||||
0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f,
|
||||
0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
0x53, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x65,
|
||||
0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
||||
0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42,
|
||||
0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61,
|
||||
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79,
|
||||
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x61, 0x6c, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65,
|
||||
0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65,
|
||||
0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79,
|
||||
0x70, 0x65, 0x22, 0xc3, 0x04, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61,
|
||||
0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x12, 0x4b, 0x0a, 0x0b, 0x63,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
|
||||
0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64,
|
||||
0x12, 0x56, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c,
|
||||
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
|
||||
0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x6e,
|
||||
0x65, 0x77, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65,
|
||||
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a,
|
||||
0x0c, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0b, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x14, 0x55, 0x73, 0x65,
|
||||
0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64,
|
||||
0x12, 0x2d, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12,
|
||||
0x2d, 0x0a, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x42, 0x45,
|
||||
0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -990,29 +1094,30 @@ func file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP()
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_goTypes = []interface{}{
|
||||
(*CredentialStore)(nil), // 0: controller.storage.credential.vault.store.v1.CredentialStore
|
||||
(*Token)(nil), // 1: controller.storage.credential.vault.store.v1.Token
|
||||
(*ClientCertificate)(nil), // 2: controller.storage.credential.vault.store.v1.ClientCertificate
|
||||
(*CredentialLibrary)(nil), // 3: controller.storage.credential.vault.store.v1.CredentialLibrary
|
||||
(*Credential)(nil), // 4: controller.storage.credential.vault.store.v1.Credential
|
||||
(*timestamp.Timestamp)(nil), // 5: controller.storage.timestamp.v1.Timestamp
|
||||
(*CredentialStore)(nil), // 0: controller.storage.credential.vault.store.v1.CredentialStore
|
||||
(*Token)(nil), // 1: controller.storage.credential.vault.store.v1.Token
|
||||
(*ClientCertificate)(nil), // 2: controller.storage.credential.vault.store.v1.ClientCertificate
|
||||
(*CredentialLibrary)(nil), // 3: controller.storage.credential.vault.store.v1.CredentialLibrary
|
||||
(*Credential)(nil), // 4: controller.storage.credential.vault.store.v1.Credential
|
||||
(*UserPasswordOverride)(nil), // 5: controller.storage.credential.vault.store.v1.UserPasswordOverride
|
||||
(*timestamp.Timestamp)(nil), // 6: controller.storage.timestamp.v1.Timestamp
|
||||
}
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_depIdxs = []int32{
|
||||
5, // 0: controller.storage.credential.vault.store.v1.CredentialStore.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 1: controller.storage.credential.vault.store.v1.CredentialStore.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 2: controller.storage.credential.vault.store.v1.CredentialStore.delete_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 3: controller.storage.credential.vault.store.v1.Token.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 4: controller.storage.credential.vault.store.v1.Token.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 5: controller.storage.credential.vault.store.v1.Token.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 6: controller.storage.credential.vault.store.v1.Token.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 7: controller.storage.credential.vault.store.v1.CredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 8: controller.storage.credential.vault.store.v1.CredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 9: controller.storage.credential.vault.store.v1.Credential.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 10: controller.storage.credential.vault.store.v1.Credential.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 11: controller.storage.credential.vault.store.v1.Credential.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 12: controller.storage.credential.vault.store.v1.Credential.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 0: controller.storage.credential.vault.store.v1.CredentialStore.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 1: controller.storage.credential.vault.store.v1.CredentialStore.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 2: controller.storage.credential.vault.store.v1.CredentialStore.delete_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 3: controller.storage.credential.vault.store.v1.Token.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 4: controller.storage.credential.vault.store.v1.Token.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 5: controller.storage.credential.vault.store.v1.Token.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 6: controller.storage.credential.vault.store.v1.Token.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 7: controller.storage.credential.vault.store.v1.CredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 8: controller.storage.credential.vault.store.v1.CredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 9: controller.storage.credential.vault.store.v1.Credential.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 10: controller.storage.credential.vault.store.v1.Credential.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 11: controller.storage.credential.vault.store.v1.Credential.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
6, // 12: controller.storage.credential.vault.store.v1.Credential.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
13, // [13:13] is the sub-list for method output_type
|
||||
13, // [13:13] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
@@ -1086,6 +1191,18 @@ func file_controller_storage_credential_vault_store_v1_vault_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UserPasswordOverride); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@@ -1093,7 +1210,7 @@ func file_controller_storage_credential_vault_store_v1_vault_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 5,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
begin;
|
||||
|
||||
create function wt_to_sentinel(string text)
|
||||
returns text
|
||||
as $$
|
||||
select concat(
|
||||
u&'\fffe',
|
||||
trim(trailing u&'\ffff' from trim(leading u&'\fffe ' from string)),
|
||||
u&'\ffff'
|
||||
);
|
||||
$$ language sql
|
||||
immutable
|
||||
returns null on null input;
|
||||
comment on function wt_to_sentinel is
|
||||
'wt_to_sentinel takes a string and returns it as a wt_sentinel';
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,77 @@
|
||||
begin;
|
||||
|
||||
create table credential_type_enm (
|
||||
name text primary key
|
||||
constraint only_predefined_credential_types_allowed
|
||||
check (
|
||||
name in (
|
||||
'unspecified',
|
||||
'user_password'
|
||||
)
|
||||
)
|
||||
);
|
||||
comment on table credential_type_enm is
|
||||
'credential_type_enm is an enumeration table for the types of credentials a credential library can provide.';
|
||||
|
||||
insert into credential_type_enm (name)
|
||||
values
|
||||
('unspecified'),
|
||||
('user_password');
|
||||
|
||||
-- Add a credential_type column to the base credential_library table and the
|
||||
-- credential_vault_library subtype table.
|
||||
|
||||
alter table credential_library
|
||||
add column credential_type text not null default 'unspecified'
|
||||
constraint credential_type_enm_fkey
|
||||
references credential_type_enm (name)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
add constraint credential_library_store_id_public_id_credential_type_uq
|
||||
unique(store_id, public_id, credential_type)
|
||||
;
|
||||
|
||||
alter table credential_vault_library
|
||||
add column credential_type text not null default 'unspecified'
|
||||
constraint credential_type_enm_fkey
|
||||
references credential_type_enm (name)
|
||||
on delete restrict
|
||||
on update cascade,
|
||||
drop constraint credential_library_fkey,
|
||||
add constraint credential_library_fkey
|
||||
foreign key (store_id, public_id, credential_type)
|
||||
references credential_library (store_id, public_id, credential_type)
|
||||
on delete cascade
|
||||
on update cascade
|
||||
;
|
||||
|
||||
-- This drops a constraint that is no longer needed.
|
||||
-- It could not be dropped until after the credential_library_fkey constraint was
|
||||
-- dropped and then recreated.
|
||||
alter table credential_library
|
||||
drop constraint credential_library_store_id_public_id_uq
|
||||
;
|
||||
|
||||
-- Drop and recreate the insert trigger function for credential_library subtypes.
|
||||
|
||||
drop trigger insert_credential_library_subtype on credential_vault_library;
|
||||
drop function insert_credential_library_subtype();
|
||||
|
||||
-- insert_credential_library_subtype() is a before insert trigger
|
||||
-- function for subtypes of credential_library
|
||||
create function insert_credential_library_subtype()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
insert into credential_library
|
||||
(public_id, store_id, credential_type)
|
||||
values
|
||||
(new.public_id, new.store_id, new.credential_type);
|
||||
return new;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
create trigger insert_credential_library_subtype before insert on credential_vault_library
|
||||
for each row execute procedure insert_credential_library_subtype();
|
||||
|
||||
commit;
|
||||
@@ -0,0 +1,40 @@
|
||||
begin;
|
||||
|
||||
create table credential_vault_library_mapping_override (
|
||||
library_id wt_public_id primary key
|
||||
constraint credential_vault_library_fkey
|
||||
references credential_vault_library (public_id)
|
||||
on delete cascade
|
||||
on update cascade
|
||||
);
|
||||
comment on table credential_vault_library_mapping_override is
|
||||
'credential_vault_library_mapping_override is a base table for the vault library mapping override type. '
|
||||
'Each row is owned by a single vault library and maps 1-to-1 to a row in one of the vault library mapping override subtype tables.';
|
||||
|
||||
-- insert_credential_vault_library_mapping_override_subtype() is a before insert trigger
|
||||
-- function for subtypes of credential_vault_library_mapping_override
|
||||
create function insert_credential_vault_library_mapping_override_subtype()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
insert into credential_vault_library_mapping_override
|
||||
(library_id)
|
||||
values
|
||||
(new.library_id);
|
||||
return new;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
-- delete_credential_vault_library_mapping_override_subtype() is an after delete trigger
|
||||
-- function for subtypes of credential_vault_library_mapping_override
|
||||
create function delete_credential_vault_library_mapping_override_subtype()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
delete from credential_vault_library_mapping_override
|
||||
where library_id = old.library_id;
|
||||
return null; -- result is ignored since this is an after trigger
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
commit;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
begin;
|
||||
|
||||
create table credential_vault_library_user_password_mapping_override (
|
||||
library_id wt_public_id primary key
|
||||
constraint credential_vault_library_fkey
|
||||
references credential_vault_library (public_id)
|
||||
on delete cascade
|
||||
on update cascade
|
||||
constraint credential_vault_library_mapping_override_fkey
|
||||
references credential_vault_library_mapping_override (library_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
username_attribute wt_sentinel
|
||||
default wt_to_sentinel('no override')
|
||||
not null,
|
||||
password_attribute wt_sentinel
|
||||
default wt_to_sentinel('no override')
|
||||
not null
|
||||
);
|
||||
comment on table credential_vault_library_user_password_mapping_override is
|
||||
'credential_vault_library_user_password_mapping_override is a table '
|
||||
'where each row represents a mapping that overrides the default mapping '
|
||||
'from a generic vault secret to a user password credential type '
|
||||
'for a vault credential library.';
|
||||
|
||||
create trigger insert_credential_vault_library_mapping_override_subtype before insert on credential_vault_library_user_password_mapping_override
|
||||
for each row execute procedure insert_credential_vault_library_mapping_override_subtype();
|
||||
|
||||
create trigger delete_credential_vault_library_mapping_override_subtype after delete on credential_vault_library_user_password_mapping_override
|
||||
for each row execute procedure delete_credential_vault_library_mapping_override_subtype();
|
||||
|
||||
commit;
|
||||
@@ -18,7 +18,9 @@ endif
|
||||
PROVE_OPTS ?=
|
||||
|
||||
TESTS ?= tests/setup/*.sql \
|
||||
tests/wh/*/*.sql
|
||||
tests/wh/*/*.sql \
|
||||
tests/sentinel/*.sql \
|
||||
tests/credential/*/*.sql
|
||||
|
||||
POSTGRES_DOCKER_IMAGE_BASE ?= postgres
|
||||
|
||||
|
||||
@@ -314,11 +314,35 @@ begin;
|
||||
('p____bwidget', 'vs_______wvs', 'widget vault store', 'None', 'https://vault.widget', 'default');
|
||||
|
||||
insert into credential_vault_library
|
||||
(store_id, public_id, name, description, vault_path, http_method)
|
||||
(store_id, public_id, name, description, vault_path, http_method, credential_type)
|
||||
values
|
||||
('vs_______wvs', 'vl______wvl1', 'widget vault library', 'None', '/secrets', 'GET'),
|
||||
('vs_______wvs', 'vl______wvl2', 'widget vault ssh', 'None', '/secrets/ssh/admin', 'GET'),
|
||||
('vs_______wvs', 'vl______wvl3', 'widget vault kv', 'None', '/secrets/kv', 'GET');
|
||||
('vs_______wvs', 'vl______wvl1', 'widget vault library', 'None', '/secrets', 'GET', 'unspecified'),
|
||||
('vs_______wvs', 'vl______wvl2', 'widget vault ssh', 'None', '/secrets/ssh/admin', 'GET', 'unspecified'),
|
||||
('vs_______wvs', 'vl______wvl3', 'widget vault kv one', 'None', '/secrets/kv/one', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl4', 'widget vault kv two', 'None', '/secrets/kv/two', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl5', 'widget vault kv three', 'None', '/secrets/kv/three', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl6', 'widget vault kv four', 'None', '/secrets/kv/four', 'GET', 'user_password'),
|
||||
('vs_______wvs', 'vl______wvl7', 'widget vault kv five', 'None', '/secrets/kv/five', 'GET', 'user_password');
|
||||
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id)
|
||||
values
|
||||
('vl______wvl4');
|
||||
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id, username_attribute)
|
||||
values
|
||||
('vl______wvl5', 'my_username');
|
||||
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id, password_attribute)
|
||||
values
|
||||
('vl______wvl6', 'my_password');
|
||||
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id, username_attribute, password_attribute)
|
||||
values
|
||||
('vl______wvl7', 'my_username', 'my_password');
|
||||
|
||||
insert into target_credential_library
|
||||
(target_id, credential_library_id, credential_purpose)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
-- credential_vault_library tests:
|
||||
-- the following triggers
|
||||
-- insert_credential_library_subtype
|
||||
-- delete_credential_library_subtype
|
||||
|
||||
begin;
|
||||
select plan(10);
|
||||
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'credentials');
|
||||
|
||||
-- validate the setup data
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl______wvl1' and credential_type = 'unspecified';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl______wvl1' and credential_type = 'unspecified';
|
||||
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl______wvl3' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl______wvl3' and credential_type = 'user_password';
|
||||
|
||||
-- validate the insert triggers
|
||||
prepare insert_vault_library as
|
||||
insert into credential_vault_library
|
||||
(store_id, public_id, vault_path, http_method, credential_type)
|
||||
values
|
||||
('vs_______wvs', 'vl_______tt1', '/secrets/kv', 'GET', 'user_password');
|
||||
select lives_ok('insert_vault_library');
|
||||
|
||||
select is(count(*), 1::bigint) from credential_vault_library where public_id = 'vl_______tt1' and credential_type = 'user_password';
|
||||
select is(count(*), 1::bigint) from credential_library where public_id = 'vl_______tt1' and credential_type = 'user_password';
|
||||
|
||||
-- validate the delete triggers
|
||||
prepare delete_vault_library as
|
||||
delete
|
||||
from credential_vault_library
|
||||
where public_id = 'vl_______tt1';
|
||||
select lives_ok('delete_vault_library');
|
||||
|
||||
select is(count(*), 0::bigint) from credential_vault_library where public_id = 'vl_______tt1';
|
||||
select is(count(*), 0::bigint) from credential_library where public_id = 'vl_______tt1';
|
||||
|
||||
select * from finish();
|
||||
rollback;
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
-- credential_vault_library_user_password_mapping_override tests:
|
||||
-- the following triggers
|
||||
-- insert_credential_vault_library_mapping_override_subtype
|
||||
-- delete_credential_vault_library_mapping_override_subtype
|
||||
|
||||
begin;
|
||||
select plan(10);
|
||||
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'credentials');
|
||||
|
||||
-- validate the setup data
|
||||
select is(count(*), 4::bigint)
|
||||
from credential_vault_library_user_password_mapping_override
|
||||
where library_id in ('vl______wvl4', 'vl______wvl5', 'vl______wvl6', 'vl______wvl7');
|
||||
|
||||
select is(count(*), 4::bigint)
|
||||
from credential_vault_library_mapping_override
|
||||
where library_id in ('vl______wvl4', 'vl______wvl5', 'vl______wvl6', 'vl______wvl7');
|
||||
|
||||
-- validate the insert triggers
|
||||
select is(count(*), 0::bigint) from credential_vault_library_user_password_mapping_override where library_id = 'vl______wvl3';
|
||||
select is(count(*), 0::bigint) from credential_vault_library_mapping_override where library_id = 'vl______wvl3';
|
||||
|
||||
prepare insert_credential_vault_library_user_password_mapping_override as
|
||||
insert into credential_vault_library_user_password_mapping_override
|
||||
(library_id, username_attribute, password_attribute)
|
||||
values
|
||||
('vl______wvl3', 'my_username', 'my_password');
|
||||
select lives_ok('insert_credential_vault_library_user_password_mapping_override');
|
||||
|
||||
select is(count(*), 1::bigint) from credential_vault_library_user_password_mapping_override where library_id = 'vl______wvl3';
|
||||
select is(count(*), 1::bigint) from credential_vault_library_mapping_override where library_id = 'vl______wvl3';
|
||||
|
||||
-- validate the delete triggers
|
||||
prepare delete_credential_vault_library_user_password_mapping_override as
|
||||
delete
|
||||
from credential_vault_library_user_password_mapping_override
|
||||
where library_id = 'vl______wvl3';
|
||||
select lives_ok('delete_credential_vault_library_user_password_mapping_override');
|
||||
|
||||
select is(count(*), 0::bigint) from credential_vault_library_user_password_mapping_override where library_id = 'vl______wvl3';
|
||||
select is(count(*), 0::bigint) from credential_vault_library_mapping_override where library_id = 'vl______wvl3';
|
||||
|
||||
select * from finish();
|
||||
rollback;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- is_sentinel tests:
|
||||
-- wt_is_sentinel function
|
||||
|
||||
begin;
|
||||
select plan(10);
|
||||
|
||||
select has_domain('wt_sentinel');
|
||||
select has_function('wt_is_sentinel', array['text']);
|
||||
|
||||
select ok(wt_is_sentinel(u&'\fffe' || 'default' || u&'\ffff'), 'basic sentinel');
|
||||
select ok(wt_is_sentinel(u&'\fffe' || u&'\ffff'), '0 length sentinel');
|
||||
select ok(wt_is_sentinel(u&'\fffe' || ' ' || u&'\ffff'), 'empty sentinel');
|
||||
|
||||
select ok(not wt_is_sentinel('default'), 'a word is not a sentinel');
|
||||
select ok(not wt_is_sentinel(''), '0 length string is not a sentinel');
|
||||
select ok(not wt_is_sentinel(' '), 'empty string is not a sentinel');
|
||||
select ok(not wt_is_sentinel(u&'\fffe' || 'default'), 'missing suffix of ffff is not a sentinel');
|
||||
select ok(not wt_is_sentinel('default' || u&'\ffff'), 'missing prefix of fffe is not a sentinel');
|
||||
|
||||
select * from finish();
|
||||
rollback;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- to_sentinel tests:
|
||||
-- wt_to_sentinel function
|
||||
|
||||
begin;
|
||||
select plan(10);
|
||||
|
||||
select has_domain('wt_sentinel');
|
||||
select has_function('wt_to_sentinel', array['text']);
|
||||
|
||||
select is(wt_to_sentinel('default'), u&'\fffe' || 'default' || u&'\ffff', 'create basic sentinel');
|
||||
select is(wt_to_sentinel(u&'\fffe' || 'default' || u&'\ffff'), u&'\fffe' || 'default' || u&'\ffff', 'no changes to existing sentinel');
|
||||
select is(wt_to_sentinel(''), u&'\fffe' || u&'\ffff', '0 length sentinel');
|
||||
select is(wt_to_sentinel(' '), u&'\fffe' || u&'\ffff', 'empty string becomes 0 length sentinel');
|
||||
select is(wt_to_sentinel(u&'\fffe' || u&'\ffff'), u&'\fffe' || u&'\ffff', '0 length sentinel to 0 length sentinel');
|
||||
select is(wt_to_sentinel(u&'\fffe'), u&'\fffe' || u&'\ffff', 'prefix to 0 length sentinel');
|
||||
select is(wt_to_sentinel(u&'\ffff'), u&'\fffe' || u&'\ffff', 'suffix to 0 length sentinel');
|
||||
|
||||
select is(wt_to_sentinel(NULL), NULL, 'null to null');
|
||||
|
||||
select * from finish();
|
||||
rollback;
|
||||
@@ -108,6 +108,7 @@ const (
|
||||
VaultTokenMissingCapabilities Code = 3013 // VaultTokenMissingCapabilities represents an error for a Vault token that is missing capabilities
|
||||
VaultCredentialRequest Code = 3014 // VaultCredentialRequest represents an error returned from Vault when retrieving a credential
|
||||
VaultEmptySecret Code = 3015 // VaultEmptySecret represents a empty secret was returned from Vault without error
|
||||
VaultInvalidMappingOverride Code = 3016 // VaultInvalidMappingOverride represents an error returned when a credential mapping is unknown or does not match a credential type
|
||||
|
||||
// OIDC authentication provided errors
|
||||
OidcProviderCallbackError Code = 4000 // OidcProviderCallbackError represents an error that is passed by the OIDC provider to the callback endpoint
|
||||
|
||||
@@ -287,6 +287,11 @@ func TestCode_Both_String_Info(t *testing.T) {
|
||||
c: VaultEmptySecret,
|
||||
want: VaultEmptySecret,
|
||||
},
|
||||
{
|
||||
name: "VaultInvalidMappingOverride",
|
||||
c: VaultInvalidMappingOverride,
|
||||
want: VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "OidcProviderCallbackError",
|
||||
c: OidcProviderCallbackError,
|
||||
|
||||
@@ -232,6 +232,10 @@ var errorCodeInfo = map[Code]Info{
|
||||
Message: "vault secret is empty",
|
||||
Kind: Integrity,
|
||||
},
|
||||
VaultInvalidMappingOverride: {
|
||||
Message: "invalid credential mapping override",
|
||||
Kind: Parameter,
|
||||
},
|
||||
OidcProviderCallbackError: {
|
||||
Message: "oidc provider callback error",
|
||||
Kind: External,
|
||||
|
||||
@@ -22,6 +22,11 @@ message Library {
|
||||
// The store_id of the owning store and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string store_id = 2;
|
||||
|
||||
// credential_type is optional. If set, it indicates the type of
|
||||
// credential the library returns.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string credential_type = 3;
|
||||
}
|
||||
|
||||
message Credential {
|
||||
|
||||
@@ -205,6 +205,11 @@ message CredentialLibrary {
|
||||
// Can only be set if http_method is POST.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
bytes http_request_body = 10 [(custom_options.v1.mask_mapping) = {this:"HttpRequestBody" that: "attributes.http_request_body"}];
|
||||
|
||||
// credential_type is optional. If set, it indicates the type of
|
||||
// credential the library returns.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string credential_type = 11;
|
||||
}
|
||||
|
||||
message Credential {
|
||||
@@ -267,3 +272,29 @@ message Credential {
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string status = 12;
|
||||
}
|
||||
|
||||
message UserPasswordOverride {
|
||||
// library_id of the owning vault credential library.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string library_id = 1;
|
||||
|
||||
// username_attribute is the name of the attribute in the Data field of a
|
||||
// Vault api.Secret that maps to a username.
|
||||
// If set, it overrides any default attribute names the system uses to
|
||||
// find a username attribute.
|
||||
//
|
||||
// See https://github.com/hashicorp/vault/blob/5e505ec039177e8212cbbab74ccb644c46e62e63/api/secret.go#L25
|
||||
//
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string username_attribute = 2;
|
||||
|
||||
// password_attribute is the name of the attribute in the Data field of a
|
||||
// Vault api.Secret that maps to a password.
|
||||
// If set, it overrides any default attribute names the system uses to
|
||||
// find a password attribute.
|
||||
//
|
||||
// See https://github.com/hashicorp/vault/blob/5e505ec039177e8212cbbab74ccb644c46e62e63/api/secret.go#L25
|
||||
//
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string password_attribute = 3;
|
||||
}
|
||||
Reference in new issue
Block a user