feat(credential/static): Implement CRUDL for UsernamePasswordDomain

Co-authored-by: Hugo <10965479+hugoghx@users.noreply.github.com>
Co-authored-by: Andrew Gaffney <109917432+anGaffney@users.noreply.github.com>
This commit is contained in:
authored and irenarindos committed 2025-09-02 15:12:07 -04:00
1 parent 141225baad
commit 34b4028d31
11 files changed
+1417 -20

No files matched your search

+21
View File
@@ -22,6 +22,7 @@ type listCredentialResult struct {
Name string
Description string
Username string
Domain string
KeyId string
Hmac1 string
Hmac2 string
@@ -71,6 +72,26 @@ func (c *listCredentialResult) toCredential(ctx context.Context) (credential.Sta
cred.PasswordHmac = []byte(c.Hmac1)
}
return cred, nil
case "upd":
cred := &UsernamePasswordDomainCredential{
UsernamePasswordDomainCredential: &store.UsernamePasswordDomainCredential{
PublicId: c.PublicId,
StoreId: c.StoreId,
Name: c.Name,
Description: c.Description,
CreateTime: c.CreateTime,
UpdateTime: c.UpdateTime,
Version: uint32(c.Version),
Username: c.Username,
Domain: c.Domain,
KeyId: c.KeyId,
},
}
// Assign byte slices only if the string isn't empty
if c.Hmac1 != "" {
cred.PasswordHmac = []byte(c.Hmac1)
}
return cred, nil
case "ssh":
cred := &SshPrivateKeyCredential{
SshPrivateKeyCredential: &store.SshPrivateKeyCredential{
+1
View File
@@ -9,6 +9,7 @@ const (
descriptionField = "Description"
usernameField = "Username"
passwordField = "Password"
domainField = "Domain"
privateKeyField = "PrivateKey"
PrivateKeyPassphraseField = "PrivateKeyPassphrase"
objectField = "Object"
+97
View File
@@ -55,6 +55,7 @@ select sum(reltuples::bigint) as estimate
where oid in (
'credential_static_json_credential'::regclass,
'credential_static_username_password_credential'::regclass,
'credential_static_username_password_domain_credential'::regclass,
'credential_static_ssh_private_key_credential'::regclass
)
`
@@ -77,6 +78,11 @@ upw_creds as (
from credential_static_username_password_credential
where public_id in (select public_id from credentials)
),
upd_creds as (
select *
from credential_static_username_password_domain_credential
where public_id in (select public_id from credentials)
),
ssh_creds as (
select *
from credential_static_ssh_private_key_credential
@@ -92,6 +98,7 @@ final as (
update_time,
version,
null as username, -- Add this to make the union uniform
null as domain, -- Add this to make the union uniform
key_id,
object_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -107,11 +114,28 @@ final as (
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
'upw' as type
from upw_creds
union
select public_id,
store_id,
project_id,
name,
description,
create_time,
update_time,
version,
username,
domain,
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
'upd' as type
from upd_creds
union
select public_id,
store_id,
@@ -122,6 +146,7 @@ final as (
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
private_key_hmac as hmac1,
private_key_passphrase_hmac as hmac2,
@@ -152,6 +177,11 @@ upw_creds as (
from credential_static_username_password_credential
where public_id in (select public_id from credentials)
),
upd_creds as (
select *
from credential_static_username_password_domain_credential
where public_id in (select public_id from credentials)
),
ssh_creds as (
select *
from credential_static_ssh_private_key_credential
@@ -167,6 +197,7 @@ final as (
update_time,
version,
null as username, -- Add this to make the union uniform
null as domain, -- Add this to make the union uniform
key_id,
object_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -182,6 +213,7 @@ final as (
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -197,6 +229,23 @@ final as (
update_time,
version,
username,
domain,
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
'upd' as type
from upd_creds
union
select public_id,
store_id,
project_id,
name,
description,
create_time,
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
private_key_hmac as hmac1,
private_key_passphrase_hmac as hmac2,
@@ -227,6 +276,11 @@ upw_creds as (
from credential_static_username_password_credential
where public_id in (select public_id from credentials)
),
upd_creds as (
select *
from credential_static_username_password_domain_credential
where public_id in (select public_id from credentials)
),
ssh_creds as (
select *
from credential_static_ssh_private_key_credential
@@ -242,6 +296,7 @@ final as (
update_time,
version,
null as username, -- Add this to make the union uniform
null as domain, -- Add this to make the union uniform
key_id,
object_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -257,6 +312,7 @@ final as (
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -272,6 +328,23 @@ final as (
update_time,
version,
username,
domain,
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
'upd' as type
from upd_creds
union
select public_id,
store_id,
project_id,
name,
description,
create_time,
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
private_key_hmac as hmac1,
private_key_passphrase_hmac as hmac2,
@@ -303,6 +376,11 @@ upw_creds as (
from credential_static_username_password_credential
where public_id in (select public_id from credentials)
),
upd_creds as (
select *
from credential_static_username_password_domain_credential
where public_id in (select public_id from credentials)
),
ssh_creds as (
select *
from credential_static_ssh_private_key_credential
@@ -318,6 +396,7 @@ final as (
update_time,
version,
null as username, -- Add this to make the union uniform
null as domain, -- Add this to make the union uniform
key_id,
object_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -333,6 +412,7 @@ final as (
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
@@ -348,6 +428,23 @@ final as (
update_time,
version,
username,
domain,
key_id,
password_hmac as hmac1,
null::bytea as hmac2, -- Add this to make the union uniform
'upd' as type
from upd_creds
union
select public_id,
store_id,
project_id,
name,
description,
create_time,
update_time,
version,
username,
null as domain, -- Add this to make the union uniform
key_id,
private_key_hmac as hmac1,
private_key_passphrase_hmac as hmac2,
@@ -107,6 +107,95 @@ func (r *Repository) CreateUsernamePasswordCredential(
return newCred, nil
}
// CreateUsernamePasswordDomainCredential inserts c into the repository and returns a new
// UsernamePasswordDomainCredential containing the credential's PublicId. c is not
// changed. c must not contain a PublicId. The PublicId is generated and
// assigned by this method. c must contain a valid StoreId.
//
// The password is encrypted and a HmacSha256 of the password is calculated. Only the
// PasswordHmac is returned, the plain-text and encrypted password is not returned.
//
// Both c.Name and c.Description are optional. If c.Name is set, it must
// be unique within c.ProjectId. Both c.CreateTime and c.UpdateTime are
// ignored.
func (r *Repository) CreateUsernamePasswordDomainCredential(
ctx context.Context,
projectId string,
c *UsernamePasswordDomainCredential,
_ ...Option,
) (*UsernamePasswordDomainCredential, error) {
const op = "static.(Repository).CreateUsernamePasswordDomainCredential"
if c == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing credential")
}
if c.UsernamePasswordDomainCredential == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing embedded credential")
}
if projectId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing project id")
}
if c.Username == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing username")
}
if c.Domain == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing domain")
}
if c.Password == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing password")
}
if c.StoreId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing store id")
}
if c.PublicId != "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "public id not empty")
}
c = c.clone()
id, err := credential.NewUsernamePasswordDomainCredentialId(ctx)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
c.PublicId = id
oplogWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeOplog)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
}
// encrypt
databaseWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
}
if err := c.encrypt(ctx, databaseWrapper); err != nil {
return nil, errors.Wrap(ctx, err, op)
}
var newCred *UsernamePasswordDomainCredential
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
newCred = c.clone()
if err := w.Create(ctx, newCred,
db.WithOplog(oplogWrapper, newCred.oplog(oplog.OpType_OP_TYPE_CREATE))); err != nil {
return errors.Wrap(ctx, err, op)
}
return nil
},
)
if err != nil {
if errors.IsUniqueError(err) {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in store: %s: name %s already exists", c.StoreId, c.Name)))
}
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in store: %s", c.StoreId)))
}
// Clear password fields, only PasswordHmac should be returned
newCred.CtPassword = nil
newCred.Password = nil
return newCred, nil
}
// CreateSshPrivateKeyCredential inserts c into the repository and returns a new
// SshPrivateKeyCredential containing the credential's PublicId. c is not
// changed. c must not contain a PublicId. The PublicId is generated and
@@ -308,6 +397,20 @@ func (r *Repository) LookupCredential(ctx context.Context, publicId string, _ ..
upCred.Password = nil
cred = upCred
case credential.UsernamePasswordDomainSubtype:
updCred := allocUsernamePasswordDomainCredential()
updCred.PublicId = publicId
if err := r.reader.LookupByPublicId(ctx, updCred); err != nil {
if errors.IsNotFoundError(err) {
return nil, nil
}
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for: %s", publicId)))
}
// Clear password fields, only passwordHmac should be returned
updCred.CtPassword = nil
updCred.Password = nil
cred = updCred
case credential.SshPrivateKeySubtype:
spkCred := allocSshPrivateKeyCredential()
spkCred.PublicId = publicId
@@ -457,6 +560,122 @@ func (r *Repository) UpdateUsernamePasswordCredential(ctx context.Context,
return returnedCredential, rowsUpdated, nil
}
// UpdateUsernamePasswordDomainCredential updates the repository entry for c.PublicId with
// the values in c for the fields listed in fieldMaskPaths. It returns a
// new UsernamePasswordDomainCredential containing the updated values and a count of the
// number of records updated. c is not changed.
//
// c must contain a valid PublicId. Only Name, Description, Username, Password, and Domain can be
// changed. If c.Name is set to a non-empty string, it must be unique within c.ProjectId.
//
// An attribute of c will be set to NULL in the database if the attribute
// in c is the zero value and it is included in fieldMaskPaths.
func (r *Repository) UpdateUsernamePasswordDomainCredential(ctx context.Context,
projectId string,
c *UsernamePasswordDomainCredential,
version uint32,
fieldMaskPaths []string,
_ ...Option,
) (*UsernamePasswordDomainCredential, int, error) {
const op = "static.(Repository).UpdateUsernamePasswordDomainCredential"
if c == nil {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing credential")
}
if c.UsernamePasswordDomainCredential == nil {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing embedded credential")
}
if c.PublicId == "" {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidPublicId, op, "missing public id")
}
if version == 0 {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing version")
}
if projectId == "" {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing project id")
}
if c.StoreId == "" {
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidParameter, op, "missing store id")
}
c = c.clone()
for _, f := range fieldMaskPaths {
switch {
case strings.EqualFold(nameField, f):
case strings.EqualFold(descriptionField, f):
case strings.EqualFold(usernameField, f):
case strings.EqualFold(passwordField, f):
case strings.EqualFold(domainField, f):
default:
return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, f)
}
}
dbMask, nullFields := dbw.BuildUpdatePaths(
map[string]any{
nameField: c.Name,
descriptionField: c.Description,
usernameField: c.Username,
passwordField: c.Password,
domainField: c.Domain,
},
fieldMaskPaths,
nil,
)
if len(dbMask) == 0 && len(nullFields) == 0 {
return nil, db.NoRowsAffected, errors.New(ctx, errors.EmptyFieldMask, op, "missing field mask")
}
for _, f := range fieldMaskPaths {
if strings.EqualFold(passwordField, f) {
// Password has been updated, re-encrypt and recalculate hmac
databaseWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
if err != nil {
return nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
}
if err := c.encrypt(ctx, databaseWrapper); err != nil {
return nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
}
// Set PasswordHmac and CtPassword masks for update.
dbMask = append(dbMask, "PasswordHmac", "CtPassword", "KeyId")
}
}
oplogWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeOplog)
if err != nil {
return nil, db.NoRowsAffected,
errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
}
var rowsUpdated int
var returnedCredential *UsernamePasswordDomainCredential
_, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
returnedCredential = c.clone()
var err error
rowsUpdated, err = w.Update(ctx, returnedCredential,
dbMask, nullFields,
db.WithOplog(oplogWrapper, returnedCredential.oplog(oplog.OpType_OP_TYPE_UPDATE)),
db.WithVersion(&version))
if err != nil {
return errors.Wrap(ctx, err, op)
}
if rowsUpdated > 1 {
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been updated")
}
return nil
},
)
if err != nil {
return nil, db.NoRowsAffected, err
}
// Clear password fields, only PasswordHmac should be returned
returnedCredential.CtPassword = nil
returnedCredential.Password = nil
return returnedCredential, rowsUpdated, nil
}
// UpdateSshPrivateKeyCredential updates the repository entry for c.PublicId
// with the values in c for the fields listed in fieldMaskPaths. It returns a
// new SshPrivateKeyCredential containing the updated values and a count of the
@@ -865,6 +1084,11 @@ func (r *Repository) DeleteCredential(ctx context.Context, projectId, id string,
c.PublicId = id
input = c
md = c.oplog(oplog.OpType_OP_TYPE_DELETE)
case credential.UsernamePasswordDomainSubtype:
c := allocUsernamePasswordDomainCredential()
c.PublicId = id
input = c
md = c.oplog(oplog.OpType_OP_TYPE_DELETE)
case credential.SshPrivateKeySubtype:
c := allocSshPrivateKeyCredential()
c.PublicId = id
@@ -946,6 +1170,13 @@ func (r *Repository) ListDeletedCredentialIds(ctx context.Context, since time.Ti
for _, cl := range deletedUsernamePasswordCredentials {
credentialStoreIds = append(credentialStoreIds, cl.PublicId)
}
var deletedUsernamePasswordDomainCredentials []*deletedUsernamePasswordDomainCredential
if err := r.SearchWhere(ctx, &deletedUsernamePasswordDomainCredentials, "delete_time >= ?", []any{since}); err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("failed to query deleted username password domain credentials"))
}
for _, cl := range deletedUsernamePasswordDomainCredentials {
credentialStoreIds = append(credentialStoreIds, cl.PublicId)
}
var deletedSSHPrivateKeyCredentials []*deletedSSHPrivateKeyCredential
if err := r.SearchWhere(ctx, &deletedSSHPrivateKeyCredentials, "delete_time >= ?", []any{since}); err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("failed to query deleted ssh private key credentials"))
File diff suppressed because it is too large. Load diff
@@ -25,6 +25,11 @@ func (r *Repository) Retrieve(ctx context.Context, projectId string, ids []strin
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
var updCreds []*UsernamePasswordDomainCredential
err = r.reader.SearchWhere(ctx, &updCreds, "public_id in (?)", []any{ids})
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
var spkCreds []*SshPrivateKeyCredential
err = r.reader.SearchWhere(ctx, &spkCreds, "public_id in (?)", []any{ids})
if err != nil {
@@ -36,7 +41,7 @@ func (r *Repository) Retrieve(ctx context.Context, projectId string, ids []strin
return nil, errors.Wrap(ctx, err, op)
}
if len(upCreds)+len(spkCreds)+len(jsonCreds) != len(ids) {
if len(upCreds)+len(updCreds)+len(spkCreds)+len(jsonCreds) != len(ids) {
return nil, errors.New(ctx, errors.NotSpecificIntegrity, op,
fmt.Sprintf("mismatch between creds and number of ids requested, expected %d got %d", len(ids), len(upCreds)+len(spkCreds)+len(jsonCreds)))
}
@@ -55,6 +60,19 @@ func (r *Repository) Retrieve(ctx context.Context, projectId string, ids []strin
out = append(out, c)
}
for _, c := range updCreds {
// decrypt credential
databaseWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get database wrapper"))
}
if err := c.decrypt(ctx, databaseWrapper); err != nil {
return nil, errors.Wrap(ctx, err, op)
}
out = append(out, c)
}
for _, c := range spkCreds {
// decrypt credential
databaseWrapper, err := r.kms.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
@@ -37,6 +37,8 @@ func TestRepository_Retrieve(t *testing.T) {
staticStore := TestCredentialStore(t, conn, wrapper, prj.GetPublicId())
upCred1 := TestUsernamePasswordCredential(t, conn, wrapper, "user", "pass", staticStore.GetPublicId(), prj.GetPublicId())
upCred2 := TestUsernamePasswordCredential(t, conn, wrapper, "different user", "better password", staticStore.GetPublicId(), prj.GetPublicId())
updCred1 := TestUsernamePasswordDomainCredential(t, conn, wrapper, "user", "pass", "domain.com", staticStore.GetPublicId(), prj.GetPublicId())
updCred2 := TestUsernamePasswordDomainCredential(t, conn, wrapper, "different user", "better password", "new-domain.com", staticStore.GetPublicId(), prj.GetPublicId())
spkCred1 := TestSshPrivateKeyCredential(t, conn, wrapper, "final user", string(testdata.PEMBytes["ed25519"]), staticStore.GetPublicId(), prj.GetPublicId())
spkCred2 := TestSshPrivateKeyCredential(t, conn, wrapper, "last user", string(testdata.PEMBytes["rsa-openssh-format"]), staticStore.GetPublicId(), prj.GetPublicId())
spkCredWithPass := TestSshPrivateKeyCredential(t, conn, wrapper, "another last user",
@@ -103,6 +105,26 @@ func TestRepository_Retrieve(t *testing.T) {
upCred1, upCred2,
},
},
{
name: "valid-one-upd-cred",
args: args{
projectId: prj.GetPublicId(),
credIds: []string{updCred1.GetPublicId()},
},
wantCreds: []credential.Static{
updCred1,
},
},
{
name: "valid-multiple-upd-creds",
args: args{
projectId: prj.GetPublicId(),
credIds: []string{updCred1.GetPublicId(), updCred2.GetPublicId()},
},
wantCreds: []credential.Static{
updCred1, updCred2,
},
},
{
name: "valid-ssh-pk-cred",
args: args{
@@ -147,10 +169,10 @@ func TestRepository_Retrieve(t *testing.T) {
name: "valid-mixed-creds",
args: args{
projectId: prj.GetPublicId(),
credIds: []string{upCred1.GetPublicId(), spkCred1.GetPublicId(), spkCredWithPass.GetPublicId(), spkCred2.GetPublicId(), upCred2.GetPublicId(), jsonCred1.GetPublicId(), jsonCred2.GetPublicId()},
credIds: []string{upCred1.GetPublicId(), spkCred1.GetPublicId(), spkCredWithPass.GetPublicId(), spkCred2.GetPublicId(), upCred2.GetPublicId(), jsonCred1.GetPublicId(), jsonCred2.GetPublicId(), updCred1.GetPublicId(), updCred2.GetPublicId()},
},
wantCreds: []credential.Static{
upCred1, spkCred1, spkCredWithPass, spkCred2, upCred2, jsonCred1, jsonCred2,
upCred1, spkCred1, spkCredWithPass, spkCred2, upCred2, jsonCred1, jsonCred2, updCred1, updCred2,
},
},
}
@@ -170,6 +192,7 @@ func TestRepository_Retrieve(t *testing.T) {
gotCreds,
cmpopts.IgnoreUnexported(
UsernamePasswordCredential{}, store.UsernamePasswordCredential{},
UsernamePasswordDomainCredential{}, store.UsernamePasswordDomainCredential{},
SshPrivateKeyCredential{}, store.SshPrivateKeyCredential{},
JsonCredential{}, store.JsonCredential{}),
cmpopts.IgnoreTypes(&timestamp.Timestamp{}),
@@ -284,7 +284,8 @@ func TestRewrap_credStaticUsernamePasswordDomainRewrapFn(t *testing.T) {
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
cs := TestCredentialStore(t, conn, wrapper, prj.PublicId)
cred, err := NewUsernamePasswordDomainCredential(cs.GetPublicId(), "username", "domain", "password")
cred, err := NewUsernamePasswordDomainCredential(cs.GetPublicId(), "username", "password", "domain")
assert.NoError(t, err)
cred.PublicId, err = credential.NewUsernamePasswordCredentialId(ctx)
+71
View File
@@ -213,6 +213,77 @@ func TestUsernamePasswordCredentials(
return creds
}
// TestUsernamePasswordDomainCredential creates a username password domain credential in the provided DB with
// the provided project id and any values passed in through.
// If any errors are encountered during the creation of the store, the test will fail.
func TestUsernamePasswordDomainCredential(
t testing.TB,
conn *db.DB,
wrapper wrapping.Wrapper,
username, password, domain, storeId, projectId string,
opts ...Option,
) *UsernamePasswordDomainCredential {
t.Helper()
ctx := context.Background()
kmsCache := kms.TestKms(t, conn, wrapper)
w := db.New(conn)
opt := getOpts(opts...)
databaseWrapper, err := kmsCache.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
assert.NoError(t, err)
require.NotNil(t, databaseWrapper)
cred, err := NewUsernamePasswordDomainCredential(storeId, username, credential.Password(password), domain, opts...)
require.NoError(t, err)
require.NotNil(t, cred)
id := opt.withPublicId
if id == "" {
id, err = credential.NewUsernamePasswordDomainCredentialId(ctx)
require.NoError(t, err)
}
cred.PublicId = id
err = cred.encrypt(ctx, databaseWrapper)
require.NoError(t, err)
_, err2 := w.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{},
func(_ db.Reader, iw db.Writer) error {
require.NoError(t, iw.Create(ctx, cred))
return nil
},
)
require.NoError(t, err2)
return cred
}
// TestUsernamePasswordDomainCredentials creates count number of username password domain credentials in
// the provided DB with the provided project id. If any errors are
// encountered during the creation of the credentials, the test will fail.
func TestUsernamePasswordDomainCredentials(
t testing.TB,
conn *db.DB,
wrapper wrapping.Wrapper,
username, password, domain, storeId, projectId string,
count int,
) []*UsernamePasswordDomainCredential {
t.Helper()
ctx := context.Background()
kmsCache := kms.TestKms(t, conn, wrapper)
databaseWrapper, err := kmsCache.GetWrapper(ctx, projectId, kms.KeyPurposeDatabase)
assert.NoError(t, err)
require.NotNil(t, databaseWrapper)
creds := make([]*UsernamePasswordDomainCredential, 0, count)
for i := 0; i < count; i++ {
creds = append(creds, TestUsernamePasswordDomainCredential(t, conn, wrapper, username, password, domain, storeId, projectId))
}
return creds
}
// TestSshPrivateKeyCredential creates an ssh private key credential in the
// provided DB with the provided project and any values passed in through. If any
// errors are encountered during the creation of the store, the test will fail.
@@ -33,8 +33,9 @@ type UsernamePasswordDomainCredential struct {
func NewUsernamePasswordDomainCredential(
storeId string,
username string,
domain string,
password credential.Password,
domain string,
opt ...Option,
) (*UsernamePasswordDomainCredential, error) {
opts := getOpts(opt...)
@@ -173,7 +173,8 @@ func TestUsernamePasswordDomainCredential_New(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
ctx := context.Background()
got, err := NewUsernamePasswordDomainCredential(tt.args.storeId, tt.args.username, tt.args.domain, tt.args.password, tt.args.options...)
got, err := NewUsernamePasswordDomainCredential(tt.args.storeId, tt.args.username, tt.args.password, tt.args.domain, tt.args.options...)
require.NoError(err)
require.NotNil(got)
assert.Emptyf(got.PublicId, "PublicId set")