Merge branch 'main' into plugin-hostcatalogs
This commit is contained in:
commit
80d41b9044
79 files changed
+3965
-927
No files matched your search
@@ -140,6 +140,9 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
|
||||
v.ctx = ctx
|
||||
|
||||
ea := &event.Auth{}
|
||||
defer event.WriteAudit(ctx, op, event.WithAuth(ea))
|
||||
|
||||
opts := getOpts(opt...)
|
||||
|
||||
ret.Scope = new(scopes.ScopeInfo)
|
||||
@@ -160,6 +163,8 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
// In tests we often simply disable auth so we can test the service handlers
|
||||
// without fuss
|
||||
if v.requestInfo.DisableAuthEntirely {
|
||||
yes := true
|
||||
ea.DisabledAuthEntirely = &yes
|
||||
const op = "auth.(disabled).lookupScope"
|
||||
ret.Scope.Id = v.requestInfo.ScopeIdOverride
|
||||
if ret.Scope.Id == "" {
|
||||
@@ -205,6 +210,7 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
if reqInfo != nil {
|
||||
reqInfo.UserId = ret.UserId
|
||||
}
|
||||
ea.UserInfo = &event.UserInfo{UserId: ret.UserId}
|
||||
ret.Error = nil
|
||||
return
|
||||
}
|
||||
@@ -226,8 +232,10 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
}
|
||||
|
||||
var authResults perms.ACLResults
|
||||
var grantTuples []perms.GrantTuple
|
||||
var accountId, userName, userEmail string
|
||||
var err error
|
||||
authResults, ret.UserId, ret.Scope, v.acl, err = v.performAuthCheck(ctx)
|
||||
authResults, ret.UserId, accountId, userName, userEmail, ret.Scope, v.acl, grantTuples, err = v.performAuthCheck(ctx)
|
||||
if err != nil {
|
||||
event.WriteError(ctx, op, err, event.WithInfoMsg("error performing authn/authz check"))
|
||||
return
|
||||
@@ -262,10 +270,31 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
if ret.UserId == AnonymousUserId {
|
||||
ret.Error = handlers.UnauthenticatedError()
|
||||
}
|
||||
ea.UserInfo = &event.UserInfo{
|
||||
UserId: ret.UserId,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
grants := make([]event.Grant, 0, len(grantTuples))
|
||||
for _, g := range grantTuples {
|
||||
grants = append(grants, event.Grant{
|
||||
Grant: g.Grant,
|
||||
RoleId: g.RoleId,
|
||||
ScopeId: g.ScopeId,
|
||||
})
|
||||
}
|
||||
ea.UserInfo = &event.UserInfo{
|
||||
UserId: ret.UserId,
|
||||
AuthAccountId: accountId,
|
||||
}
|
||||
ea.GrantsInfo = &event.GrantsInfo{
|
||||
Grants: grants,
|
||||
}
|
||||
ea.UserName = userName
|
||||
ea.UserEmail = userEmail
|
||||
|
||||
if reqInfo != nil {
|
||||
reqInfo.UserId = ret.UserId
|
||||
reqInfo.OutputFields = authResults.OutputFields
|
||||
@@ -401,15 +430,23 @@ func (v *verifier) decryptToken(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLResults, userId string, scopeInfo *scopes.ScopeInfo, retAcl perms.ACL, retErr error) {
|
||||
func (v verifier) performAuthCheck(ctx context.Context) (
|
||||
aclResults perms.ACLResults,
|
||||
userId string,
|
||||
accountId string,
|
||||
userName string,
|
||||
userEmail string,
|
||||
scopeInfo *scopes.ScopeInfo,
|
||||
retAcl perms.ACL,
|
||||
grantTuples []perms.GrantTuple,
|
||||
retErr error) {
|
||||
const op = "auth.(verifier).performAuthCheck"
|
||||
// Ensure we return an error by default if we forget to set this somewhere
|
||||
retErr = errors.NewDeprecated(errors.Unknown, op, "default auth error", errors.WithoutEvent())
|
||||
retErr = errors.New(ctx, errors.Unknown, op, "default auth error", errors.WithoutEvent())
|
||||
// Make the linter happy
|
||||
_ = retErr
|
||||
scopeInfo = new(scopes.ScopeInfo)
|
||||
userId = AnonymousUserId
|
||||
var accountId string
|
||||
|
||||
// Validate the token and fetch the corresponding user ID
|
||||
switch v.requestInfo.TokenFormat {
|
||||
@@ -428,7 +465,7 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
|
||||
}
|
||||
tokenRepo, err := v.authTokenRepoFn()
|
||||
if err != nil {
|
||||
retErr = errors.WrapDeprecated(err, op)
|
||||
retErr = errors.Wrap(ctx, err, op)
|
||||
return
|
||||
}
|
||||
at, err := tokenRepo.ValidateToken(v.ctx, v.requestInfo.PublicId, v.requestInfo.Token)
|
||||
@@ -451,10 +488,18 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
|
||||
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
retErr = errors.WrapDeprecated(err, op, errors.WithMsg("failed to get iam repo"))
|
||||
retErr = errors.Wrap(ctx, err, op, errors.WithMsg("failed to get iam repo"))
|
||||
return
|
||||
}
|
||||
|
||||
u, _, err := iamRepo.LookupUser(ctx, userId)
|
||||
if err != nil {
|
||||
retErr = errors.Wrap(ctx, err, op, errors.WithMsg("failed to lookup user"))
|
||||
return
|
||||
}
|
||||
userEmail = u.Email
|
||||
userName = u.FullName
|
||||
|
||||
// Look up scope details to return. We can skip a lookup when using the
|
||||
// global scope
|
||||
switch v.res.ScopeId {
|
||||
@@ -470,11 +515,11 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
|
||||
default:
|
||||
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
|
||||
if err != nil {
|
||||
retErr = errors.WrapDeprecated(err, op)
|
||||
retErr = errors.Wrap(ctx, err, op)
|
||||
return
|
||||
}
|
||||
if scp == nil {
|
||||
retErr = errors.NewDeprecated(errors.InvalidParameter, op, fmt.Sprint("non-existent scope $q", v.res.ScopeId))
|
||||
retErr = errors.New(ctx, errors.InvalidParameter, op, fmt.Sprint("non-existent scope $q", v.res.ScopeId))
|
||||
return
|
||||
}
|
||||
scopeInfo = &scopes.ScopeInfo{
|
||||
@@ -495,13 +540,12 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
|
||||
}
|
||||
|
||||
var parsedGrants []perms.Grant
|
||||
var grantTuples []perms.GrantTuple
|
||||
|
||||
// Fetch and parse grants for this user ID (which may include grants for
|
||||
// u_anon and u_auth)
|
||||
grantTuples, err = iamRepo.GrantsForUser(v.ctx, userId)
|
||||
if err != nil {
|
||||
retErr = errors.WrapDeprecated(err, op)
|
||||
retErr = errors.Wrap(ctx, err, op)
|
||||
return
|
||||
}
|
||||
parsedGrants = make([]perms.Grant, 0, len(grantTuples))
|
||||
@@ -516,7 +560,7 @@ func (v verifier) performAuthCheck(ctx context.Context) (aclResults perms.ACLRes
|
||||
perms.WithAccountId(accountId),
|
||||
perms.WithSkipFinalValidation(true))
|
||||
if err != nil {
|
||||
retErr = errors.WrapDeprecated(err, op, errors.WithMsg(fmt.Sprintf("failed to parse grant %#v", pair.Grant)))
|
||||
retErr = errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed to parse grant %#v", pair.Grant)))
|
||||
return
|
||||
}
|
||||
parsedGrants = append(parsedGrants, parsed)
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
@@ -12,8 +14,12 @@ import (
|
||||
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
"github.com/hashicorp/boundary/internal/servers"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/tests/api"
|
||||
"github.com/hashicorp/eventlogger/filters/encrypt"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -132,3 +138,125 @@ func TestAuthTokenAuthenticator(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerify_AuditEvent(t *testing.T) {
|
||||
// this cannot run in parallel because it relies on envvar
|
||||
// globals.BOUNDARY_DEVELOPER_ENABLE_EVENTS
|
||||
event.TestEnableEventing(t, true)
|
||||
eventConfig := event.TestEventerConfig(t, "Test_Verify", event.TestWithAuditSink(t))
|
||||
testLock := &sync.Mutex{}
|
||||
testLogger := hclog.New(&hclog.LoggerOptions{
|
||||
Mutex: testLock,
|
||||
Name: "test",
|
||||
})
|
||||
require.NoError(t, event.InitSysEventer(testLogger, testLock, "Test_Verify", event.WithEventerConfig(&eventConfig.EventerConfig)))
|
||||
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
testKms := kms.TestKms(t, conn, wrapper)
|
||||
tokenRepo, err := authtoken.NewRepository(rw, rw, testKms)
|
||||
require.NoError(t, err)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
tokenRepoFn := func() (*authtoken.Repository, error) {
|
||||
return tokenRepo, nil
|
||||
}
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
serversRepoFn := func() (*servers.Repository, error) {
|
||||
return servers.NewRepository(rw, rw, testKms)
|
||||
}
|
||||
|
||||
o, _ := iam.TestScopes(t, iamRepo)
|
||||
at := authtoken.TestAuthToken(t, conn, testKms, o.GetPublicId())
|
||||
encToken, err := authtoken.EncryptToken(context.Background(), testKms, o.GetPublicId(), at.GetPublicId(), at.GetToken())
|
||||
require.NoError(t, err)
|
||||
|
||||
tokValue := at.GetPublicId() + "_" + encToken
|
||||
jsCookieVal, httpCookieVal := tokValue[:len(tokValue)/2], tokValue[len(tokValue)/2:]
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
headers map[string]string
|
||||
cookies []http.Cookie
|
||||
opt []Option
|
||||
disableAuth bool
|
||||
wantResults VerifyResults
|
||||
wantAuthAuditData bool
|
||||
wantUserId string
|
||||
}{
|
||||
{
|
||||
name: "bearer-token",
|
||||
headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", tokValue)},
|
||||
opt: []Option{WithScopeId(o.PublicId)},
|
||||
wantAuthAuditData: true,
|
||||
wantUserId: at.IamUserId,
|
||||
},
|
||||
{
|
||||
name: "split-cookie-token",
|
||||
cookies: []http.Cookie{
|
||||
{Name: handlers.HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: handlers.JsVisibleCookieName, Value: jsCookieVal},
|
||||
},
|
||||
opt: []Option{WithScopeId(o.PublicId)},
|
||||
wantAuthAuditData: true,
|
||||
wantUserId: at.IamUserId,
|
||||
},
|
||||
{
|
||||
name: "no-auth-data",
|
||||
opt: []Option{WithScopeId(o.PublicId)},
|
||||
wantAuthAuditData: true,
|
||||
wantUserId: "u_anon",
|
||||
},
|
||||
{
|
||||
name: "disable-auth",
|
||||
opt: []Option{WithScopeId(o.PublicId)},
|
||||
disableAuth: true,
|
||||
wantAuthAuditData: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
req := httptest.NewRequest("GET", "http://127.0.0.1/v1/scopes/o_1", nil)
|
||||
for k, v := range tt.headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
for _, c := range tt.cookies {
|
||||
req.AddCookie(&c)
|
||||
}
|
||||
|
||||
// Add values for authn/authz checking
|
||||
requestInfo := authpb.RequestInfo{
|
||||
Path: req.URL.Path,
|
||||
Method: req.Method,
|
||||
DisableAuthEntirely: tt.disableAuth,
|
||||
}
|
||||
requestInfo.PublicId, requestInfo.EncryptedToken, requestInfo.TokenFormat = GetTokenFromRequest(context.TODO(), testKms, req)
|
||||
|
||||
ctx := NewVerifierContext(context.Background(), iamRepoFn, tokenRepoFn, serversRepoFn, testKms, &requestInfo)
|
||||
|
||||
_ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls
|
||||
_ = Verify(ctx, tt.opt...)
|
||||
got := api.CloudEventFromFile(t, eventConfig.AuditEvents.Name())
|
||||
|
||||
if tt.wantAuthAuditData {
|
||||
auth, ok := got.Data.(map[string]interface{})["auth"].(map[string]interface{})
|
||||
require.True(ok)
|
||||
assert.Equal(encrypt.RedactedData, auth["email"])
|
||||
assert.Equal(encrypt.RedactedData, auth["name"])
|
||||
|
||||
if tt.disableAuth {
|
||||
assert.Equal(true, auth["disabled_auth_entirely"])
|
||||
}
|
||||
if tt.wantUserId != "" {
|
||||
userInfo, ok := auth["user_info"].(map[string]interface{})
|
||||
require.True(ok)
|
||||
assert.Equal(tt.wantUserId, userInfo["id"])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -592,7 +592,7 @@ func (s Service) AddTargetCredentialLibraries(ctx context.Context, req *pbs.AddT
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -630,7 +630,7 @@ func (s Service) SetTargetCredentialLibraries(ctx context.Context, req *pbs.SetT
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -668,7 +668,7 @@ func (s Service) RemoveTargetCredentialLibraries(ctx context.Context, req *pbs.R
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialLibraryIds(), nil, req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -706,7 +706,7 @@ func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTar
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.addCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -744,7 +744,7 @@ func (s Service) SetTargetCredentialSources(ctx context.Context, req *pbs.SetTar
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.setCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -782,7 +782,7 @@ func (s Service) RemoveTargetCredentialSources(ctx context.Context, req *pbs.Rem
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetVersion())
|
||||
t, ts, cl, err := s.removeCredentialSourcesInRepo(ctx, req.GetId(), req.GetApplicationCredentialSourceIds(), req.GetEgressCredentialSourceIds(), req.GetVersion())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1352,12 +1352,17 @@ func (s Service) removeHostSourcesInRepo(ctx context.Context, targetId string, h
|
||||
return out, hs, cl, nil
|
||||
}
|
||||
|
||||
func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
}
|
||||
|
||||
out, hs, credSources, err := repo.AddTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to add credential sources to target: %v.", err)
|
||||
@@ -1368,13 +1373,19 @@ func (s Service) addCredentialSourcesInRepo(ctx context.Context, targetId string
|
||||
return out, hs, credSources, nil
|
||||
}
|
||||
|
||||
func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
const op = "targets.(Service).setCredentialSourcesInRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
|
||||
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
}
|
||||
|
||||
_, _, _, err = repo.SetTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
@@ -1390,13 +1401,18 @@ func (s Service) setCredentialSourcesInRepo(ctx context.Context, targetId string
|
||||
return out, hs, credSources, nil
|
||||
}
|
||||
|
||||
func (s Service) removeCredentialSourcesInRepo(ctx context.Context, targetId string, ids []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
func (s Service) removeCredentialSourcesInRepo(ctx context.Context, targetId string, applicationIds []string, egressIds []string, version uint32) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
const op = "targets.(Service).removeCredentialSourcesInRepo"
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, strutil.RemoveDuplicates(ids, false))
|
||||
|
||||
credLibs, err := createCredLibs(targetId, applicationIds, egressIds, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to set credential sources in target: %v.", err)
|
||||
}
|
||||
_, err = repo.DeleteTargetCredentialSources(ctx, targetId, version, credLibs)
|
||||
if err != nil {
|
||||
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
|
||||
return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to remove credential sources from target: %v.", err)
|
||||
@@ -1917,8 +1933,9 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ
|
||||
if req.GetVersion() == 0 {
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
if len(req.GetApplicationCredentialSourceIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = "Must be non-empty."
|
||||
if len(req.GetApplicationCredentialSourceIds())+len(req.GetEgressCredentialSourceIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
@@ -1926,6 +1943,12 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
@@ -1946,6 +1969,12 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
@@ -1960,8 +1989,9 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc
|
||||
if req.GetVersion() == 0 {
|
||||
badFields[globals.VersionField] = "Required field."
|
||||
}
|
||||
if len(req.GetApplicationCredentialSourceIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialLibraryIdsField] = "Must be non-empty."
|
||||
if len(req.GetApplicationCredentialSourceIds())+len(req.GetEgressCredentialSourceIds()) == 0 {
|
||||
badFields[globals.ApplicationCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
badFields[globals.EgressCredentialSourceIdsField] = "Application or Egress Credential Source IDs must be provided."
|
||||
}
|
||||
for _, cl := range req.GetApplicationCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
@@ -1969,6 +1999,12 @@ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourc
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, cl := range req.GetEgressCredentialSourceIds() {
|
||||
if !handlers.ValidId(handlers.Id(cl), vault.CredentialLibraryPrefix) {
|
||||
badFields[globals.EgressCredentialSourceIdsField] = fmt.Sprintf("Incorrectly formatted credential source identifier %q.", cl)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Errors in provided fields.", badFields)
|
||||
}
|
||||
@@ -2015,3 +2051,23 @@ func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createCredLibs(targetId string, applicationIds, ingressIds, egressIds []string) ([]*target.CredentialLibrary, error) {
|
||||
credLibs := make([]*target.CredentialLibrary, 0, len(applicationIds)+len(ingressIds)+len(egressIds))
|
||||
|
||||
byPurpose := map[credential.Purpose][]string{
|
||||
credential.ApplicationPurpose: strutil.RemoveDuplicates(applicationIds, false),
|
||||
credential.IngressPurpose: strutil.RemoveDuplicates(ingressIds, false),
|
||||
credential.EgressPurpose: strutil.RemoveDuplicates(egressIds, false),
|
||||
}
|
||||
for purpose, ids := range byPurpose {
|
||||
for _, id := range ids {
|
||||
l, err := target.NewCredentialLibrary(targetId, id, purpose)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credLibs = append(credLibs, l)
|
||||
}
|
||||
}
|
||||
return credLibs, nil
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
@@ -293,7 +294,16 @@ func TestList(t *testing.T) {
|
||||
return
|
||||
}
|
||||
require.NoError(gErr)
|
||||
assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListTargets(%q) scope %q, got response %q, wanted %q", tc.name, tc.req.GetScopeId(), got, tc.res)
|
||||
assert.Equal(len(tc.res.Items), len(got.Items))
|
||||
wantById := make(map[string]*pb.Target, len(tc.res.Items))
|
||||
for _, t := range tc.res.Items {
|
||||
wantById[t.Id] = t
|
||||
}
|
||||
for _, t := range got.Items {
|
||||
want, ok := wantById[t.Id]
|
||||
assert.True(ok, "Got unexpected target with id: %s", t.Id)
|
||||
assert.Empty(cmp.Diff(t, want, protocmp.Transform()), "got %v, wanted %v", t, want)
|
||||
}
|
||||
|
||||
// Test with anon user
|
||||
got, gErr = s.ListTargets(auth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId(), auth.WithUserId(auth.AnonymousUserId)), tc.req)
|
||||
@@ -1806,13 +1816,13 @@ func TestAddTargetLibraries(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Add library on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
addLibraries: []string{cls[1].GetPublicId()},
|
||||
resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Add duplicated libraries on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
addLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
|
||||
resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
|
||||
},
|
||||
@@ -1942,19 +1952,19 @@ func TestSetTargetLibraries(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Set on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setLibraries: []string{cls[1].GetPublicId()},
|
||||
resultLibraryIds: []string{cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Set duplicate libraries on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
|
||||
resultLibraryIds: []string{cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Set empty on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setLibraries: []string{},
|
||||
resultLibraryIds: nil,
|
||||
},
|
||||
@@ -2068,13 +2078,13 @@ func TestRemoveTargetLibraries(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Remove 1 of 2 libraries",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeLibs: []string{cls[1].GetPublicId()},
|
||||
resultLibIds: []string{cls[0].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Remove 1 duplicate set of 2 libraries",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeLibs: []string{
|
||||
cls[1].GetPublicId(), cls[1].GetPublicId(),
|
||||
},
|
||||
@@ -2082,7 +2092,7 @@ func TestRemoveTargetLibraries(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Remove all libraries from target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeLibs: []string{
|
||||
cls[0].GetPublicId(), cls[1].GetPublicId(),
|
||||
},
|
||||
@@ -2203,13 +2213,13 @@ func TestAddTargetSources(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Add source on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
addSources: []string{cls[1].GetPublicId()},
|
||||
resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Add duplicated sources on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
addSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
|
||||
resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()},
|
||||
},
|
||||
@@ -2339,19 +2349,19 @@ func TestSetTargetCredentialSources(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Set on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setCredentialSources: []string{cls[1].GetPublicId()},
|
||||
resultCredentialSourceIds: []string{cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Set duplicate sources on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setCredentialSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()},
|
||||
resultCredentialSourceIds: []string{cls[1].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Set empty on populated target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialSources([]string{cls[0].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
setCredentialSources: []string{},
|
||||
resultCredentialSourceIds: nil,
|
||||
},
|
||||
@@ -2465,13 +2475,13 @@ func TestRemoveTargetCredentialSources(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Remove 1 of 2 sources",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeCredentialSources: []string{cls[1].GetPublicId()},
|
||||
resultCredentialSourceIds: []string{cls[0].GetPublicId()},
|
||||
},
|
||||
{
|
||||
name: "Remove 1 duplicate set of 2 sources",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeCredentialSources: []string{
|
||||
cls[1].GetPublicId(), cls[1].GetPublicId(),
|
||||
},
|
||||
@@ -2479,7 +2489,7 @@ func TestRemoveTargetCredentialSources(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Remove all sources from target",
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialSources([]string{cls[0].GetPublicId(), cls[1].GetPublicId()})),
|
||||
tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})),
|
||||
removeCredentialSources: []string{
|
||||
cls[0].GetPublicId(), cls[1].GetPublicId(),
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user