feat(credential/vault): Implement repository for vault password credential (#6140)
This commit is contained in:
1 parent
3ab1019bc2
commit
4a8009fec4
13 files changed
+990
-30
No files matched your search
@@ -11,6 +11,7 @@ const (
|
||||
UnspecifiedCredentialType CredentialType = "unspecified"
|
||||
UsernamePasswordCredentialType CredentialType = "username_password"
|
||||
UsernamePasswordDomainCredentialType CredentialType = "username_password_domain"
|
||||
PasswordCredentialType CredentialType = "password"
|
||||
SshPrivateKeyCredentialType CredentialType = "ssh_private_key"
|
||||
SshCertificateCredentialType CredentialType = "ssh_certificate"
|
||||
JsonCredentialType CredentialType = "json"
|
||||
|
||||
@@ -143,6 +143,13 @@ type UsernamePasswordDomain interface {
|
||||
Domain() string
|
||||
}
|
||||
|
||||
// PasswordCredential is a credential containing a username and a password.
|
||||
// Does not follow naming convention to avoid conflict with existing Password type.
|
||||
type PasswordCredential interface {
|
||||
Credential
|
||||
Password() Password
|
||||
}
|
||||
|
||||
// SshPrivateKey is a credential containing a username an SSH private key and
|
||||
// an optional private key passphrase.
|
||||
type SshPrivateKey interface {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
// Package password provides access to the password
|
||||
// stored in a Vault secret.
|
||||
package password
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package password
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/pointerstructure"
|
||||
)
|
||||
|
||||
type (
|
||||
data map[string]any
|
||||
|
||||
// extractFunc attempts to extract the password
|
||||
// from sd using the provided attribute names, using a known
|
||||
// Vault data response format.
|
||||
extractFunc func(sd data, passwordAttr string) string
|
||||
)
|
||||
|
||||
// Extract attempts to extract the values of the password
|
||||
// stored within the provided data using the given attribute names.
|
||||
//
|
||||
// Extract does not return partial results, i.e. if one of the attributes
|
||||
// were extracted but not the other ("") will be returned.
|
||||
func Extract(d data, passwordAttr string) string {
|
||||
for _, f := range []extractFunc{
|
||||
defaultExtract,
|
||||
kv2Extract,
|
||||
} {
|
||||
password := f(d, passwordAttr)
|
||||
if password != "" {
|
||||
// got valid password from secret
|
||||
return password
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// defaultExtract looks for the passwordAttr in the data map
|
||||
func defaultExtract(sd data, passwordAttr string) (password string) {
|
||||
if sd == nil {
|
||||
// nothing to do return early
|
||||
return ""
|
||||
}
|
||||
|
||||
var p any
|
||||
switch {
|
||||
case strings.HasPrefix(passwordAttr, "/"):
|
||||
var err error
|
||||
p, err = pointerstructure.Get(sd, passwordAttr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
default:
|
||||
p = sd[passwordAttr]
|
||||
}
|
||||
|
||||
if p, ok := p.(string); ok {
|
||||
password = p
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
// kv2Extract looks for the the passwordAttr in the embedded
|
||||
// 'data' field within the data map.
|
||||
//
|
||||
// Additionally it validates the data is in the expected KV-v2 format:
|
||||
//
|
||||
// {
|
||||
// "data": {},
|
||||
// "metadata: {}
|
||||
// }
|
||||
//
|
||||
// If the format does not match, it returns (""). See:
|
||||
// https://www.vaultproject.io/api/secret/kv/kv-v2#sample-response-1
|
||||
func kv2Extract(sd data, passwordAttr string) (password string) {
|
||||
if sd == nil {
|
||||
// nothing to do return early
|
||||
return ""
|
||||
}
|
||||
|
||||
var data, metadata map[string]any
|
||||
for k, v := range sd {
|
||||
switch k {
|
||||
case "data":
|
||||
var ok bool
|
||||
if data, ok = v.(map[string]any); !ok {
|
||||
// data field should be of type map[string]interface{} in KV-v2
|
||||
return ""
|
||||
}
|
||||
case "metadata":
|
||||
var ok bool
|
||||
if metadata, ok = v.(map[string]any); !ok {
|
||||
// metadata field should be of type map[string]interface{} in KV-v2
|
||||
return ""
|
||||
}
|
||||
default:
|
||||
// secretData contains a non valid KV-v2 top level field
|
||||
return ""
|
||||
}
|
||||
}
|
||||
if data == nil || metadata == nil {
|
||||
// missing required KV-v2 field
|
||||
return ""
|
||||
}
|
||||
|
||||
if p, ok := data[passwordAttr]; ok {
|
||||
if p, ok := p.(string); ok {
|
||||
password = p
|
||||
}
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package password
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBaseToPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type args struct {
|
||||
s data
|
||||
pAttr string
|
||||
}
|
||||
type pass struct {
|
||||
pass string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
given args
|
||||
want pass
|
||||
}{
|
||||
{
|
||||
name: "nil-input",
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "no-input",
|
||||
given: args{},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "no-secret",
|
||||
given: args{
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "no-match-password-secret",
|
||||
given: args{
|
||||
s: data{
|
||||
"password-wrong": "pass",
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "valid-default",
|
||||
given: args{
|
||||
s: data{
|
||||
"password": "pass",
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: "pass"},
|
||||
},
|
||||
{
|
||||
name: "no-match-password-secret-kv2",
|
||||
given: args{
|
||||
s: data{
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password-wrong": "pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "valid-kv2",
|
||||
given: args{
|
||||
s: data{
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: "pass"},
|
||||
},
|
||||
{
|
||||
name: "no-metadata-kv2",
|
||||
given: args{
|
||||
s: data{
|
||||
"data": map[string]any{
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "invalid-metadata-kv2",
|
||||
given: args{
|
||||
s: data{
|
||||
"metadata": "string",
|
||||
"data": map[string]any{
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "invalid-field-kv2",
|
||||
given: args{
|
||||
s: data{
|
||||
"invalid": map[string]any{},
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: ""},
|
||||
},
|
||||
{
|
||||
name: "valid-order-default-first",
|
||||
given: args{
|
||||
s: data{
|
||||
"password": "default-pass",
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "kv2-pass",
|
||||
},
|
||||
},
|
||||
pAttr: "password",
|
||||
},
|
||||
want: pass{pass: "default-pass"},
|
||||
},
|
||||
{
|
||||
name: "json-pointer-password",
|
||||
given: args{
|
||||
s: data{
|
||||
"testing": map[string]any{
|
||||
"my-password": "secret",
|
||||
},
|
||||
},
|
||||
pAttr: "/testing/my-password",
|
||||
},
|
||||
want: pass{pass: "secret"},
|
||||
},
|
||||
{
|
||||
name: "deep-json-pointer",
|
||||
given: args{
|
||||
s: data{
|
||||
"first-path": map[string]any{
|
||||
"deeper-path": map[string]any{
|
||||
"my-password": "deeper-secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
pAttr: "/first-path/deeper-path/my-password",
|
||||
},
|
||||
want: pass{pass: "deeper-secret"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
pass := Extract(tt.given.s, tt.given.pAttr)
|
||||
assert.Equal(tt.want.pass, pass)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ func validMappingOverride(m MappingOverride, ct globals.CredentialType) bool {
|
||||
return ct == globals.UsernamePasswordCredentialType
|
||||
case *UsernamePasswordDomainOverride:
|
||||
return ct == globals.UsernamePasswordDomainCredentialType
|
||||
case *PasswordOverride:
|
||||
return ct == globals.PasswordCredentialType
|
||||
case *SshPrivateKeyOverride:
|
||||
return ct == globals.SshPrivateKeyCredentialType
|
||||
default:
|
||||
@@ -171,6 +173,65 @@ func (o *UsernamePasswordDomainOverride) SetTableName(n string) {
|
||||
o.tableName = n
|
||||
}
|
||||
|
||||
// A PasswordOverride contains optional values for overriding the
|
||||
// default mappings used to map a Vault secret to a Password credential
|
||||
// type for the credential library that owns it.
|
||||
type PasswordOverride struct {
|
||||
*store.PasswordOverride
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
var _ MappingOverride = (*PasswordOverride)(nil)
|
||||
|
||||
// NewPasswordOverride creates a new in memory PasswordOverride.
|
||||
// WithOverrideAttribute and WithOverridePasswordAttribute are the
|
||||
// only valid options. All other options are ignored.
|
||||
func NewPasswordOverride(opt ...Option) *PasswordOverride {
|
||||
opts := getOpts(opt...)
|
||||
o := &PasswordOverride{
|
||||
PasswordOverride: &store.PasswordOverride{
|
||||
PasswordAttribute: sanitize.String(opts.withOverridePasswordAttribute),
|
||||
},
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func allocPasswordOverride() *PasswordOverride {
|
||||
return &PasswordOverride{
|
||||
PasswordOverride: &store.PasswordOverride{},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PasswordOverride) clone() MappingOverride {
|
||||
cp := proto.Clone(o.PasswordOverride)
|
||||
return &PasswordOverride{
|
||||
PasswordOverride: cp.(*store.PasswordOverride),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *PasswordOverride) setLibraryId(i string) {
|
||||
o.LibraryId = i
|
||||
}
|
||||
|
||||
func (o *PasswordOverride) sanitize() {
|
||||
if sentinel.Is(o.PasswordAttribute) {
|
||||
o.PasswordAttribute = ""
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (o *PasswordOverride) TableName() string {
|
||||
if o.tableName != "" {
|
||||
return o.tableName
|
||||
}
|
||||
return "credential_vault_library_password_mapping_override"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (o *PasswordOverride) SetTableName(n string) {
|
||||
o.tableName = n
|
||||
}
|
||||
|
||||
// A SshPrivateKeyOverride contains optional values for overriding the
|
||||
// default mappings used to map a Vault secret to a SshPrivateKey credential
|
||||
// type for the credential library that owns it.
|
||||
|
||||
@@ -45,6 +45,11 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
ct: globals.UsernamePasswordDomainCredentialType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: nil,
|
||||
ct: globals.PasswordCredentialType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: unknownMapper(1),
|
||||
ct: globals.UnspecifiedCredentialType,
|
||||
@@ -60,6 +65,11 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
ct: globals.UsernamePasswordDomainCredentialType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: unknownMapper(1),
|
||||
ct: globals.PasswordCredentialType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: allocUsernamePasswordOverride(),
|
||||
ct: globals.UnspecifiedCredentialType,
|
||||
@@ -80,6 +90,16 @@ func TestValidMappingOverrides(t *testing.T) {
|
||||
ct: globals.UsernamePasswordDomainCredentialType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: allocPasswordOverride(),
|
||||
ct: globals.UnspecifiedCredentialType,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
m: allocPasswordOverride(),
|
||||
ct: globals.PasswordCredentialType,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
m: allocSshPrivateKeyOverride(),
|
||||
ct: globals.UnspecifiedCredentialType,
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
ldapv3 "github.com/go-ldap/ldap/v3"
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/internal/password"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/internal/sshprivatekey"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/internal/usernamepassword"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault/internal/usernamepassworddomain"
|
||||
@@ -66,6 +67,8 @@ func convert(ctx context.Context, bc *baseCred) (dynamicCred, error) {
|
||||
return baseToSshPriKey(ctx, bc)
|
||||
case globals.UsernamePasswordDomainCredentialType:
|
||||
return baseToUsrPassDomain(ctx, bc)
|
||||
case globals.PasswordCredentialType:
|
||||
return baseToPass(ctx, bc)
|
||||
}
|
||||
return bc, nil
|
||||
}
|
||||
@@ -166,6 +169,45 @@ func baseToUsrPassDomain(ctx context.Context, bc *baseCred) (*usrPassDomainCred,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ credential.PasswordCredential = (*passCred)(nil)
|
||||
|
||||
type passCred struct {
|
||||
*baseCred
|
||||
password credential.Password
|
||||
}
|
||||
|
||||
func (c *passCred) Password() credential.Password { return c.password }
|
||||
|
||||
func baseToPass(ctx context.Context, bc *baseCred) (*passCred, error) {
|
||||
switch {
|
||||
case bc == nil:
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("nil baseCred"))
|
||||
case bc.lib == nil:
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("nil baseCred.lib"))
|
||||
case bc.Library().CredentialType() != globals.PasswordCredentialType:
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("invalid credential type"))
|
||||
}
|
||||
|
||||
lib, ok := bc.lib.(*genericIssuingCredentialLibrary)
|
||||
if !ok {
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.InvalidParameter), errors.WithMsg("baseCred.lib is not of type genericIssuingCredentialLibrary"))
|
||||
}
|
||||
|
||||
pAttr := lib.PasswordAttribute
|
||||
if pAttr == "" {
|
||||
pAttr = "password"
|
||||
}
|
||||
password := password.Extract(bc.secretData, pAttr)
|
||||
if password == "" {
|
||||
return nil, errors.E(ctx, errors.WithCode(errors.VaultInvalidCredentialMapping))
|
||||
}
|
||||
|
||||
return &passCred{
|
||||
baseCred: bc,
|
||||
password: credential.Password(password),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ credential.SshPrivateKey = (*sshPrivateKeyCred)(nil)
|
||||
|
||||
type sshPrivateKeyCred struct {
|
||||
|
||||
@@ -344,6 +344,37 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
req := credential.Request{SourceId: lib.GetPublicId(), Purpose: credential.BrokeredPurpose}
|
||||
requests = append(requests, req)
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(globals.PasswordCredentialType),
|
||||
}
|
||||
libIn, err := NewCredentialLibrary(origStore.GetPublicId(), "/vault/path", opts...)
|
||||
assert.NoError(err)
|
||||
require.NotNil(libIn)
|
||||
lib, err := repo.CreateCredentialLibrary(ctx, prj.GetPublicId(), libIn)
|
||||
assert.NoError(err)
|
||||
require.NotNil(lib)
|
||||
libs[lib.GetPublicId()] = lib
|
||||
req := credential.Request{SourceId: lib.GetPublicId(), Purpose: credential.BrokeredPurpose}
|
||||
requests = append(requests, req)
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(globals.PasswordCredentialType),
|
||||
WithMappingOverride(NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("test-password"),
|
||||
)),
|
||||
}
|
||||
libIn, err := NewCredentialLibrary(origStore.GetPublicId(), "/vault/path", opts...)
|
||||
assert.NoError(err)
|
||||
require.NotNil(libIn)
|
||||
lib, err := repo.CreateCredentialLibrary(ctx, prj.GetPublicId(), libIn)
|
||||
assert.NoError(err)
|
||||
require.NotNil(lib)
|
||||
libs[lib.GetPublicId()] = lib
|
||||
req := credential.Request{SourceId: lib.GetPublicId(), Purpose: credential.BrokeredPurpose}
|
||||
requests = append(requests, req)
|
||||
}
|
||||
{
|
||||
opts := []Option{
|
||||
WithCredentialType(globals.SshPrivateKeyCredentialType),
|
||||
@@ -460,6 +491,8 @@ func TestRepository_getPrivateLibraries(t *testing.T) {
|
||||
assert.Equal(w.UsernameAttribute, got.UsernameAttribute)
|
||||
assert.Equal(w.PasswordAttribute, got.PasswordAttribute)
|
||||
assert.Equal(w.DomainAttribute, got.DomainAttribute)
|
||||
case *PasswordOverride:
|
||||
assert.Equal(w.PasswordAttribute, got.PasswordAttribute)
|
||||
case *SshPrivateKeyOverride:
|
||||
assert.Equal(w.UsernameAttribute, got.UsernameAttribute)
|
||||
assert.Equal(w.PrivateKeyAttribute, got.PrivateKeyAttribute)
|
||||
@@ -1424,6 +1457,211 @@ func TestBaseToUsrPassDomain(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseToPass(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
given *baseCred
|
||||
want *passCred
|
||||
wantErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "nil-input",
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-library",
|
||||
given: &baseCred{},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "library-not-password-type",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.UnspecifiedCredentialType),
|
||||
},
|
||||
},
|
||||
wantErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "invalid-no-password-attribute",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "valid-default-attributes",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"password": "my-password",
|
||||
},
|
||||
},
|
||||
want: &passCred{
|
||||
password: credential.Password("my-password"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-override-attributes",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"password": "default-password",
|
||||
"test-password": "override-password",
|
||||
},
|
||||
},
|
||||
want: &passCred{
|
||||
password: credential.Password("override-password"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid-password-override",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
PasswordAttribute: "missing-password",
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"password": "default-password",
|
||||
"test-password": "override-password",
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "invalid-kv2-no-metadata-field",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"data": map[string]any{
|
||||
"password": "my-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "invalid-kv2-no-data-field",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"metadata": map[string]any{},
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "invalid-kv2-invalid-metadata-type",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"metadata": "hello",
|
||||
"data": map[string]any{
|
||||
"password": "my-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "invalid-kv2-invalid-metadata-type",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"metadata": map[string]any{},
|
||||
"data": "hello",
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "invalid-kv2-additional-field",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"bad-field": "hello",
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "my-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidCredentialMapping,
|
||||
},
|
||||
{
|
||||
name: "valid-kv2-default-password-attribute",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "my-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &passCred{
|
||||
password: credential.Password("my-password"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-kv2-override-password-attribute",
|
||||
given: &baseCred{
|
||||
lib: &genericIssuingCredentialLibrary{
|
||||
CredType: string(globals.PasswordCredentialType),
|
||||
PasswordAttribute: "test-password",
|
||||
},
|
||||
secretData: map[string]any{
|
||||
"metadata": map[string]any{},
|
||||
"data": map[string]any{
|
||||
"password": "default-password",
|
||||
"test-password": "override-password",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &passCred{
|
||||
password: credential.Password("override-password"),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
got, err := baseToPass(context.Background(), tt.given)
|
||||
if tt.wantErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantErr), err), "want err: %q got: %q", tt.wantErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
want := tt.want
|
||||
want.baseCred = tt.given
|
||||
assert.Equal(want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseToSshPriKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -406,6 +406,14 @@ func (pl *listLookupLibrary) toCredentialLibrary() *CredentialLibrary {
|
||||
upd.sanitize()
|
||||
cl.MappingOverride = upd
|
||||
}
|
||||
case string(globals.PasswordCredentialType):
|
||||
if pl.PasswordAttribute != "" {
|
||||
p := allocPasswordOverride()
|
||||
p.LibraryId = pl.PublicId
|
||||
p.PasswordAttribute = pl.PasswordAttribute
|
||||
p.sanitize()
|
||||
cl.MappingOverride = p
|
||||
}
|
||||
case string(globals.SshPrivateKeyCredentialType):
|
||||
if pl.UsernameAttribute != "" || pl.PrivateKeyAttribute != "" || pl.PrivateKeyPassphraseAttribute != "" {
|
||||
pk := allocSshPrivateKeyOverride()
|
||||
|
||||
@@ -293,6 +293,76 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-password-credential-type",
|
||||
in: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unknown-password-mapping-override-type",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: unknownMapper(1),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "invalid-password-mapping-override-type",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewUsernamePasswordOverride(WithOverrideUsernameAttribute("test")),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "valid-password-credential-type-with-password-override",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("ptest"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
want: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("ptest"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-ssh-private-key-credential-type",
|
||||
in: &CredentialLibrary{
|
||||
@@ -339,7 +409,7 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "valid-ssh-prviate-key-credential-type-with-username-override",
|
||||
name: "valid-ssh-private-key-credential-type-with-username-override",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewSshPrivateKeyOverride(
|
||||
WithOverrideUsernameAttribute("utest"),
|
||||
@@ -486,6 +556,15 @@ func TestRepository_CreateCredentialLibrary(t *testing.T) {
|
||||
override := allocUsernamePasswordOverride()
|
||||
assert.NoError(rw.LookupWhere(ctx, &override, "library_id = ?", []any{got.GetPublicId()}))
|
||||
|
||||
case *PasswordOverride:
|
||||
g, ok := got.MappingOverride.(*PasswordOverride)
|
||||
require.True(ok)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
|
||||
// verify it was persisted in the database
|
||||
override := allocPasswordOverride()
|
||||
assert.NoError(rw.LookupWhere(ctx, &override, "library_id = ?", []any{got.GetPublicId()}))
|
||||
|
||||
case *SshPrivateKeyOverride:
|
||||
g, ok := got.MappingOverride.(*SshPrivateKeyOverride)
|
||||
require.True(ok)
|
||||
@@ -1273,6 +1352,94 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
masks: []string{"MappingOverride"},
|
||||
wantErr: errors.VaultInvalidMappingOverride,
|
||||
},
|
||||
{
|
||||
name: "password-attribute-change-password-attribute",
|
||||
orig: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("orig-password"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("changed-password"),
|
||||
),
|
||||
),
|
||||
masks: []string{"MappingOverride"},
|
||||
want: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("changed-password"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "no-mapping-override-change-password-attributes",
|
||||
orig: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(
|
||||
NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("changed-password"),
|
||||
),
|
||||
),
|
||||
masks: []string{"MappingOverride"},
|
||||
want: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("changed-password"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "password-attributes-delete-mapping-override",
|
||||
orig: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("orig-password"),
|
||||
WithOverridePrivateKeyAttribute("orig-private-key"),
|
||||
WithOverridePrivateKeyPassphraseAttribute("orig-passphrase"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
chgFn: changeMappingOverride(nil),
|
||||
masks: []string{"MappingOverride"},
|
||||
want: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
Name: "test-password-repo",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "ssh-private-key-attributes-change-username-attribute",
|
||||
orig: &CredentialLibrary{
|
||||
@@ -1535,6 +1702,10 @@ func TestRepository_UpdateCredentialLibrary(t *testing.T) {
|
||||
require.True(ok)
|
||||
assert.Equal(w.UsernameAttribute, g.UsernameAttribute)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
case *PasswordOverride:
|
||||
g, ok := got.MappingOverride.(*PasswordOverride)
|
||||
require.True(ok)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
case *SshPrivateKeyOverride:
|
||||
g, ok := got.MappingOverride.(*SshPrivateKeyOverride)
|
||||
require.True(ok)
|
||||
@@ -1800,6 +1971,31 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-password-credential-type",
|
||||
in: &CredentialLibrary{
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-password-credential-type-with-password-override",
|
||||
in: &CredentialLibrary{
|
||||
MappingOverride: NewPasswordOverride(
|
||||
WithOverridePasswordAttribute("ptest"),
|
||||
),
|
||||
CredentialLibrary: &store.CredentialLibrary{
|
||||
StoreId: cs.GetPublicId(),
|
||||
HttpMethod: "GET",
|
||||
VaultPath: "/some/path",
|
||||
CredentialType: string(globals.PasswordCredentialType),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-ssh-private-key-credential-type",
|
||||
in: &CredentialLibrary{
|
||||
@@ -1901,6 +2097,10 @@ func TestRepository_LookupCredentialLibrary(t *testing.T) {
|
||||
require.True(ok)
|
||||
assert.Equal(w.UsernameAttribute, g.UsernameAttribute)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
case *PasswordOverride:
|
||||
g, ok := got.MappingOverride.(*PasswordOverride)
|
||||
require.True(ok)
|
||||
assert.Equal(w.PasswordAttribute, g.PasswordAttribute)
|
||||
case *SshPrivateKeyOverride:
|
||||
g, ok := got.MappingOverride.(*SshPrivateKeyOverride)
|
||||
require.True(ok)
|
||||
|
||||
@@ -1174,6 +1174,68 @@ func (x *UsernamePasswordDomainOverride) GetDomainAttribute() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type PasswordOverride struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// 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"`
|
||||
// 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,2,opt,name=password_attribute,json=passwordAttribute,proto3" json:"password_attribute,omitempty" gorm:"default:null"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *PasswordOverride) Reset() {
|
||||
*x = PasswordOverride{}
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *PasswordOverride) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PasswordOverride) ProtoMessage() {}
|
||||
|
||||
func (x *PasswordOverride) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PasswordOverride.ProtoReflect.Descriptor instead.
|
||||
func (*PasswordOverride) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *PasswordOverride) GetLibraryId() string {
|
||||
if x != nil {
|
||||
return x.LibraryId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *PasswordOverride) GetPasswordAttribute() string {
|
||||
if x != nil {
|
||||
return x.PasswordAttribute
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SshPrivateKeyOverride struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// library_id of the owning vault credential library.
|
||||
@@ -1213,7 +1275,7 @@ type SshPrivateKeyOverride struct {
|
||||
|
||||
func (x *SshPrivateKeyOverride) Reset() {
|
||||
*x = SshPrivateKeyOverride{}
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[8]
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -1225,7 +1287,7 @@ func (x *SshPrivateKeyOverride) String() string {
|
||||
func (*SshPrivateKeyOverride) ProtoMessage() {}
|
||||
|
||||
func (x *SshPrivateKeyOverride) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[8]
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1238,7 +1300,7 @@ func (x *SshPrivateKeyOverride) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use SshPrivateKeyOverride.ProtoReflect.Descriptor instead.
|
||||
func (*SshPrivateKeyOverride) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{8}
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *SshPrivateKeyOverride) GetLibraryId() string {
|
||||
@@ -1306,7 +1368,7 @@ type LdapCredentialLibrary struct {
|
||||
|
||||
func (x *LdapCredentialLibrary) Reset() {
|
||||
*x = LdapCredentialLibrary{}
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[9]
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -1318,7 +1380,7 @@ func (x *LdapCredentialLibrary) String() string {
|
||||
func (*LdapCredentialLibrary) ProtoMessage() {}
|
||||
|
||||
func (x *LdapCredentialLibrary) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[9]
|
||||
mi := &file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes[10]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1331,7 +1393,7 @@ func (x *LdapCredentialLibrary) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use LdapCredentialLibrary.ProtoReflect.Descriptor instead.
|
||||
func (*LdapCredentialLibrary) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{9}
|
||||
return file_controller_storage_credential_vault_store_v1_vault_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *LdapCredentialLibrary) GetPublicId() string {
|
||||
@@ -1546,7 +1608,11 @@ const file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = ""
|
||||
"library_id\x18\x01 \x01(\tR\tlibraryId\x12-\n" +
|
||||
"\x12username_attribute\x18\x02 \x01(\tR\x11usernameAttribute\x12-\n" +
|
||||
"\x12password_attribute\x18\x03 \x01(\tR\x11passwordAttribute\x12)\n" +
|
||||
"\x10domain_attribute\x18\x04 \x01(\tR\x0fdomainAttribute\"\xe2\x01\n" +
|
||||
"\x10domain_attribute\x18\x04 \x01(\tR\x0fdomainAttribute\"`\n" +
|
||||
"\x10PasswordOverride\x12\x1d\n" +
|
||||
"\n" +
|
||||
"library_id\x18\x01 \x01(\tR\tlibraryId\x12-\n" +
|
||||
"\x12password_attribute\x18\x02 \x01(\tR\x11passwordAttribute\"\xe2\x01\n" +
|
||||
"\x15SshPrivateKeyOverride\x12\x1d\n" +
|
||||
"\n" +
|
||||
"library_id\x18\x01 \x01(\tR\tlibraryId\x12-\n" +
|
||||
@@ -1582,7 +1648,7 @@ 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, 10)
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_goTypes = []any{
|
||||
(*CredentialStore)(nil), // 0: controller.storage.credential.vault.store.v1.CredentialStore
|
||||
(*Token)(nil), // 1: controller.storage.credential.vault.store.v1.Token
|
||||
@@ -1592,28 +1658,29 @@ var file_controller_storage_credential_vault_store_v1_vault_proto_goTypes = []an
|
||||
(*Credential)(nil), // 5: controller.storage.credential.vault.store.v1.Credential
|
||||
(*UsernamePasswordOverride)(nil), // 6: controller.storage.credential.vault.store.v1.UsernamePasswordOverride
|
||||
(*UsernamePasswordDomainOverride)(nil), // 7: controller.storage.credential.vault.store.v1.UsernamePasswordDomainOverride
|
||||
(*SshPrivateKeyOverride)(nil), // 8: controller.storage.credential.vault.store.v1.SshPrivateKeyOverride
|
||||
(*LdapCredentialLibrary)(nil), // 9: controller.storage.credential.vault.store.v1.LdapCredentialLibrary
|
||||
(*timestamp.Timestamp)(nil), // 10: controller.storage.timestamp.v1.Timestamp
|
||||
(*PasswordOverride)(nil), // 8: controller.storage.credential.vault.store.v1.PasswordOverride
|
||||
(*SshPrivateKeyOverride)(nil), // 9: controller.storage.credential.vault.store.v1.SshPrivateKeyOverride
|
||||
(*LdapCredentialLibrary)(nil), // 10: controller.storage.credential.vault.store.v1.LdapCredentialLibrary
|
||||
(*timestamp.Timestamp)(nil), // 11: controller.storage.timestamp.v1.Timestamp
|
||||
}
|
||||
var file_controller_storage_credential_vault_store_v1_vault_proto_depIdxs = []int32{
|
||||
10, // 0: controller.storage.credential.vault.store.v1.CredentialStore.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 1: controller.storage.credential.vault.store.v1.CredentialStore.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 2: controller.storage.credential.vault.store.v1.CredentialStore.delete_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 3: controller.storage.credential.vault.store.v1.Token.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 4: controller.storage.credential.vault.store.v1.Token.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 5: controller.storage.credential.vault.store.v1.Token.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 6: controller.storage.credential.vault.store.v1.Token.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 7: controller.storage.credential.vault.store.v1.CredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 8: controller.storage.credential.vault.store.v1.CredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 9: controller.storage.credential.vault.store.v1.SSHCertificateCredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 10: controller.storage.credential.vault.store.v1.SSHCertificateCredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 11: controller.storage.credential.vault.store.v1.Credential.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 12: controller.storage.credential.vault.store.v1.Credential.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 13: controller.storage.credential.vault.store.v1.Credential.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 14: controller.storage.credential.vault.store.v1.Credential.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 15: controller.storage.credential.vault.store.v1.LdapCredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
10, // 16: controller.storage.credential.vault.store.v1.LdapCredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 0: controller.storage.credential.vault.store.v1.CredentialStore.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 1: controller.storage.credential.vault.store.v1.CredentialStore.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 2: controller.storage.credential.vault.store.v1.CredentialStore.delete_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 3: controller.storage.credential.vault.store.v1.Token.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 4: controller.storage.credential.vault.store.v1.Token.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 5: controller.storage.credential.vault.store.v1.Token.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 6: controller.storage.credential.vault.store.v1.Token.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 7: controller.storage.credential.vault.store.v1.CredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 8: controller.storage.credential.vault.store.v1.CredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 9: controller.storage.credential.vault.store.v1.SSHCertificateCredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 10: controller.storage.credential.vault.store.v1.SSHCertificateCredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 11: controller.storage.credential.vault.store.v1.Credential.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 12: controller.storage.credential.vault.store.v1.Credential.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 13: controller.storage.credential.vault.store.v1.Credential.last_renewal_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 14: controller.storage.credential.vault.store.v1.Credential.expiration_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 15: controller.storage.credential.vault.store.v1.LdapCredentialLibrary.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
11, // 16: controller.storage.credential.vault.store.v1.LdapCredentialLibrary.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
17, // [17:17] is the sub-list for method output_type
|
||||
17, // [17:17] is the sub-list for method input_type
|
||||
17, // [17:17] is the sub-list for extension type_name
|
||||
@@ -1632,7 +1699,7 @@ func file_controller_storage_credential_vault_store_v1_vault_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc), len(file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 10,
|
||||
NumMessages: 11,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -499,6 +499,22 @@ message UsernamePasswordDomainOverride {
|
||||
string domain_attribute = 4;
|
||||
}
|
||||
|
||||
message PasswordOverride {
|
||||
// library_id of the owning vault credential library.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string library_id = 1;
|
||||
|
||||
// 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 = 2;
|
||||
}
|
||||
|
||||
message SshPrivateKeyOverride {
|
||||
// library_id of the owning vault credential library.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
|
||||
Reference in new issue
Block a user