Add alias resolution to target service (#4277)
* Add aliases to target resource and alias resolution to target service * Wire up the target alias domain package to the target service handler * Adding alias resolution to target api tests
This commit is contained in:
1 parent
92181e272a
commit
3f3b624b54
12 files changed
+1359
-631
No files matched your search
@@ -0,0 +1,10 @@
|
||||
// Code generated by "make api"; DO NOT EDIT.
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package targets
|
||||
|
||||
type Alias struct {
|
||||
Id string `json:"id,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
@@ -41,6 +41,7 @@ type Target struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
AuthorizedActions []string `json:"authorized_actions,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
Aliases []*Alias `json:"aliases,omitempty"`
|
||||
|
||||
response *api.Response
|
||||
}
|
||||
|
||||
@@ -207,6 +207,23 @@ func (r *Repository) LookupAlias(ctx context.Context, id string, opt ...Option)
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// LookupAliasByValue returns the Alias for the provided value. Returns nil, nil
|
||||
// if no Alias is found for the provided value.
|
||||
func (r *Repository) LookupAliasByValue(ctx context.Context, value string, opt ...Option) (*Alias, error) {
|
||||
const op = "target.(Repository).LookupAliasByValue"
|
||||
if value == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "value is empty")
|
||||
}
|
||||
a := allocAlias()
|
||||
if err := r.reader.LookupWhere(ctx, a, "value = $1", []any{value}); err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %q", value)))
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// DeleteAlias deletes id from the repository returning a count of the
|
||||
// number of records deleted.
|
||||
func (r *Repository) DeleteAlias(ctx context.Context, id string, opt ...Option) (int, error) {
|
||||
|
||||
@@ -979,6 +979,10 @@ var inputStructs = []*structInfo{
|
||||
inProto: &targets.CredentialSource{},
|
||||
outFile: "targets/credential_source.gen.go",
|
||||
},
|
||||
{
|
||||
inProto: &targets.Alias{},
|
||||
outFile: "targets/alias.gen.go",
|
||||
},
|
||||
{
|
||||
inProto: &targets.SessionSecret{},
|
||||
outFile: "targets/session_secret.gen.go",
|
||||
|
||||
@@ -262,6 +262,7 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error {
|
||||
c.StaticHostRepoFn,
|
||||
c.VaultCredentialRepoFn,
|
||||
c.StaticCredentialRepoFn,
|
||||
c.TargetAliasRepoFn,
|
||||
c.downstreamWorkers,
|
||||
c.workerStatusGracePeriod,
|
||||
c.conf.RawConfig.Controller.MaxPageSize,
|
||||
|
||||
@@ -136,7 +136,7 @@ func TestHandleImplementedPaths(t *testing.T) {
|
||||
"v1/storage-buckets",
|
||||
"v1/storage-buckets/someid",
|
||||
"v1/targets",
|
||||
"v1/targets/someid",
|
||||
"v1/targets/some_id",
|
||||
"v1/users",
|
||||
"v1/users/someid",
|
||||
"v1/billing:monthly-active-users",
|
||||
@@ -174,13 +174,13 @@ func TestHandleImplementedPaths(t *testing.T) {
|
||||
"v1/roles/someid:set-principals",
|
||||
"v1/roles/someid:remove-principals",
|
||||
"v1/sessions/someid:cancel",
|
||||
"v1/targets/someid:authorize-session",
|
||||
"v1/targets/someid:add-host-sources",
|
||||
"v1/targets/someid:set-host-sources",
|
||||
"v1/targets/someid:remove-host-sources",
|
||||
"v1/targets/someid:add-credential-sources",
|
||||
"v1/targets/someid:set-credential-sources",
|
||||
"v1/targets/someid:remove-credential-sources",
|
||||
"v1/targets/some_id:authorize-session",
|
||||
"v1/targets/some_id:add-host-sources",
|
||||
"v1/targets/some_id:set-host-sources",
|
||||
"v1/targets/some_id:remove-host-sources",
|
||||
"v1/targets/some_id:add-credential-sources",
|
||||
"v1/targets/some_id:set-credential-sources",
|
||||
"v1/targets/some_id:remove-credential-sources",
|
||||
"v1/users/someid:add-accounts",
|
||||
"v1/users/someid:set-accounts",
|
||||
"v1/users/someid:remove-accounts",
|
||||
@@ -198,7 +198,7 @@ func TestHandleImplementedPaths(t *testing.T) {
|
||||
"v1/roles/someid",
|
||||
"v1/scopes/someid",
|
||||
"v1/storage-buckets/someid",
|
||||
"v1/targets/someid",
|
||||
"v1/targets/some_id",
|
||||
"v1/users/someid",
|
||||
},
|
||||
"PATCH": {
|
||||
@@ -213,7 +213,7 @@ func TestHandleImplementedPaths(t *testing.T) {
|
||||
"v1/roles/someid",
|
||||
"v1/scopes/someid",
|
||||
"v1/storage-buckets/someid",
|
||||
"v1/targets/someid",
|
||||
"v1/targets/some_id",
|
||||
"v1/users/someid",
|
||||
},
|
||||
} {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
talias "github.com/hashicorp/boundary/internal/alias/target"
|
||||
"github.com/hashicorp/boundary/internal/credential"
|
||||
wl "github.com/hashicorp/boundary/internal/daemon/common"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
@@ -118,6 +119,7 @@ type Service struct {
|
||||
pbs.UnsafeTargetServiceServer
|
||||
|
||||
repoFn target.RepositoryFactory
|
||||
aliasRepoFn common.TargetAliasRepoFactory
|
||||
iamRepoFn common.IamRepoFactory
|
||||
serversRepoFn common.ServersRepoFactory
|
||||
sessionRepoFn session.RepositoryFactory
|
||||
@@ -146,38 +148,34 @@ func NewService(
|
||||
staticHostRepoFn common.StaticRepoFactory,
|
||||
vaultCredRepoFn common.VaultCredentialRepoFactory,
|
||||
staticCredRepoFn common.StaticCredentialRepoFactory,
|
||||
aliasRepoFn common.TargetAliasRepoFactory,
|
||||
downstreams common.Downstreamers,
|
||||
workerStatusGracePeriod *atomic.Int64,
|
||||
maxPageSize uint,
|
||||
controllerExt intglobals.ControllerExtension,
|
||||
) (Service, error) {
|
||||
const op = "targets.NewService"
|
||||
if kmsCache == nil {
|
||||
switch {
|
||||
case kmsCache == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing kms repo")
|
||||
}
|
||||
if repoFn == nil {
|
||||
case repoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing target repository")
|
||||
}
|
||||
if iamRepoFn == nil {
|
||||
case iamRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing iam repository")
|
||||
}
|
||||
if serversRepoFn == nil {
|
||||
case serversRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing server repository")
|
||||
}
|
||||
if sessionRepoFn == nil {
|
||||
case sessionRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing session repository")
|
||||
}
|
||||
if pluginHostRepoFn == nil {
|
||||
case pluginHostRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing plugin host repository")
|
||||
}
|
||||
if staticHostRepoFn == nil {
|
||||
case staticHostRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing static host repository")
|
||||
}
|
||||
if vaultCredRepoFn == nil {
|
||||
case vaultCredRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing vault credential repository")
|
||||
}
|
||||
if staticCredRepoFn == nil {
|
||||
case staticCredRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing static credential repository")
|
||||
case aliasRepoFn == nil:
|
||||
return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing target alias repository")
|
||||
}
|
||||
if maxPageSize == 0 {
|
||||
maxPageSize = uint(globals.DefaultMaxPageSize)
|
||||
@@ -191,6 +189,7 @@ func NewService(
|
||||
staticHostRepoFn: staticHostRepoFn,
|
||||
vaultCredRepoFn: vaultCredRepoFn,
|
||||
staticCredRepoFn: staticCredRepoFn,
|
||||
aliasRepoFn: aliasRepoFn,
|
||||
downstreams: downstreams,
|
||||
kmsCache: kmsCache,
|
||||
workerStatusGracePeriod: workerStatusGracePeriod,
|
||||
@@ -356,6 +355,14 @@ func (s Service) ListTargets(ctx context.Context, req *pbs.ListTargetsRequest) (
|
||||
func (s Service) GetTarget(ctx context.Context, req *pbs.GetTargetRequest) (*pbs.GetTargetResponse, error) {
|
||||
const op = "targets.(Service).GetTarget"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateGetRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -436,6 +443,14 @@ func (s Service) CreateTarget(ctx context.Context, req *pbs.CreateTargetRequest)
|
||||
func (s Service) UpdateTarget(ctx context.Context, req *pbs.UpdateTargetRequest) (*pbs.UpdateTargetResponse, error) {
|
||||
const op = "targets.(Service).UpdateTarget"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateUpdateRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -474,6 +489,16 @@ func (s Service) UpdateTarget(ctx context.Context, req *pbs.UpdateTargetRequest)
|
||||
|
||||
// DeleteTarget implements the interface pbs.TargetServiceServer.
|
||||
func (s Service) DeleteTarget(ctx context.Context, req *pbs.DeleteTargetRequest) (*pbs.DeleteTargetResponse, error) {
|
||||
const op = "targets.(Service).DeleteTarget"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateDeleteRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -492,6 +517,14 @@ func (s Service) DeleteTarget(ctx context.Context, req *pbs.DeleteTargetRequest)
|
||||
func (s Service) AddTargetHostSources(ctx context.Context, req *pbs.AddTargetHostSourcesRequest) (*pbs.AddTargetHostSourcesResponse, error) {
|
||||
const op = "targets.(Service).AddTargetHostSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateAddHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -534,6 +567,14 @@ func (s Service) AddTargetHostSources(ctx context.Context, req *pbs.AddTargetHos
|
||||
func (s Service) SetTargetHostSources(ctx context.Context, req *pbs.SetTargetHostSourcesRequest) (*pbs.SetTargetHostSourcesResponse, error) {
|
||||
const op = "targets.(Service).SetTargetHostSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateSetHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -574,6 +615,14 @@ func (s Service) SetTargetHostSources(ctx context.Context, req *pbs.SetTargetHos
|
||||
func (s Service) RemoveTargetHostSources(ctx context.Context, req *pbs.RemoveTargetHostSourcesRequest) (*pbs.RemoveTargetHostSourcesResponse, error) {
|
||||
const op = "targets.(Service).RemoveTargetHostSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateRemoveHostSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -614,6 +663,14 @@ func (s Service) RemoveTargetHostSources(ctx context.Context, req *pbs.RemoveTar
|
||||
func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTargetCredentialSourcesRequest) (*pbs.AddTargetCredentialSourcesResponse, error) {
|
||||
const op = "targets.(Service).AddTargetCredentialSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateAddCredentialSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -655,6 +712,14 @@ func (s Service) AddTargetCredentialSources(ctx context.Context, req *pbs.AddTar
|
||||
func (s Service) SetTargetCredentialSources(ctx context.Context, req *pbs.SetTargetCredentialSourcesRequest) (*pbs.SetTargetCredentialSourcesResponse, error) {
|
||||
const op = "targets.(Service).SetTargetCredentialSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateSetCredentialSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -696,6 +761,14 @@ func (s Service) SetTargetCredentialSources(ctx context.Context, req *pbs.SetTar
|
||||
func (s Service) RemoveTargetCredentialSources(ctx context.Context, req *pbs.RemoveTargetCredentialSourcesRequest) (*pbs.RemoveTargetCredentialSourcesResponse, error) {
|
||||
const op = "targets.(Service).RemoveTargetCredentialSources"
|
||||
|
||||
if maybeAlias(req.GetId()) {
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateRemoveCredentialSourcesRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -781,6 +854,27 @@ func DefaultPostSessionAuthorizationCallback(context.Context, intglobals.Control
|
||||
|
||||
func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSessionRequest) (_ *pbs.AuthorizeSessionResponse, retErr error) {
|
||||
const op = "targets.(Service).AuthorizeSession"
|
||||
|
||||
if maybeAlias(req.GetId()) && len(req.GetScopeId()) == 0 && len(req.GetScopeName()) == 0 {
|
||||
// AuthorizeSession allows passing the target name in the place of an id but
|
||||
// requires that the scope id or scope name is also provided in the request.
|
||||
// If the scope id or the scope name is provided, we will not attempt to
|
||||
// resolve the alias.
|
||||
if a, err := s.resolveAlias(ctx, req.GetId()); err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
} else {
|
||||
req.Id = a.DestinationId
|
||||
if a.HostId != "" {
|
||||
if req.GetHostId() != "" && req.GetHostId() != a.HostId {
|
||||
return nil, handlers.InvalidArgumentErrorf("Errors in provided fields.", map[string]string{
|
||||
"host_id": "The host id specified in the request does not match the one provided by the alias. Consider omiting the host id in the request.",
|
||||
})
|
||||
}
|
||||
req.HostId = a.HostId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateAuthorizeSessionRequest(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1230,6 +1324,38 @@ func (s Service) getFromRepo(ctx context.Context, id string) (target.Target, []t
|
||||
return u, hs, cl, nil
|
||||
}
|
||||
|
||||
// maybeAlias returns true if the input string is a candidate for being an alias.
|
||||
func maybeAlias(s string) bool {
|
||||
return !strings.Contains(s, "_") &&
|
||||
len(s) > 0
|
||||
}
|
||||
|
||||
// resolveAlias returns the alias resource with the specified value.
|
||||
// If the alias does not have a destination id or there is no alias with a
|
||||
// matching value, an error is returned.
|
||||
func (s Service) resolveAlias(ctx context.Context, value string) (*talias.Alias, error) {
|
||||
const op = "targets.(Service).resolveAlias"
|
||||
if value == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "input string is empty")
|
||||
}
|
||||
|
||||
r, err := s.aliasRepoFn()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
a, err := r.LookupAliasByValue(ctx, value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if a == nil {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.NotFound, "alias with value %q not found", value)
|
||||
}
|
||||
if a.DestinationId == "" {
|
||||
return nil, handlers.ApiErrorWithCodeAndMessage(codes.NotFound, "target not found for alias value %q", value)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (s Service) createInRepo(ctx context.Context, item *pb.Target) (target.Target, []target.HostSource, []target.CredentialSource, error) {
|
||||
const op = "targets.(Service).createInRepo"
|
||||
opts := []target.Option{target.WithName(item.GetName().GetValue())}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -6909,6 +6909,20 @@
|
||||
},
|
||||
"title": "StorageBucket manages external object stores"
|
||||
},
|
||||
"controller.api.resources.targets.v1.Alias": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Output only. The ID of the alias referencing this target.",
|
||||
"readOnly": true
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "Ouput only. The value of the alias referencing this target."
|
||||
}
|
||||
}
|
||||
},
|
||||
"controller.api.resources.targets.v1.CredentialSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -7213,6 +7227,15 @@
|
||||
"address": {
|
||||
"type": "string",
|
||||
"description": "Optional string value that represents a network resource and is used when establishing a session."
|
||||
},
|
||||
"aliases": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/controller.api.resources.targets.v1.Alias"
|
||||
},
|
||||
"description": "Output only. The aliases that point to this Target.",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"title": "Target contains all fields related to a Target resource"
|
||||
|
||||
@@ -14,6 +14,14 @@ import "google/protobuf/wrappers.proto";
|
||||
|
||||
option go_package = "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets;targets";
|
||||
|
||||
message Alias {
|
||||
// Output only. The ID of the alias referencing this target.
|
||||
string id = 10; // @gotags: `class:"public" eventstream:"observation"`
|
||||
|
||||
// Ouput only. The value of the alias referencing this target.
|
||||
string value = 20; // @gotags: `class:"public" eventstream:"observation"`
|
||||
}
|
||||
|
||||
message HostSource {
|
||||
// Output only. The ID of the Host Set.
|
||||
string id = 10; // @gotags: `class:"public" eventstream:"observation"`
|
||||
@@ -211,6 +219,9 @@ message Target {
|
||||
}
|
||||
]; // @gotags: `class:"public"`
|
||||
|
||||
// Output only. The aliases that point to this Target.
|
||||
repeated Alias aliases = 550 [json_name = "aliases"]; // @gotags: `class:"public"`
|
||||
|
||||
// Deprecated fields
|
||||
reserved "application_credential_library_ids", "application_credential_libraries";
|
||||
reserved 150, 180;
|
||||
|
||||
@@ -20,9 +20,11 @@ import (
|
||||
"github.com/hashicorp/boundary/api/roles"
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
aliastar "github.com/hashicorp/boundary/internal/alias/target"
|
||||
"github.com/hashicorp/boundary/internal/credential/vault"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller"
|
||||
"github.com/hashicorp/boundary/internal/daemon/worker"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -57,20 +59,44 @@ func TestHostSetASD(t *testing.T) {
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.HostSourceIds)
|
||||
|
||||
tar, err = tarClient.AddHostSources(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet.Item.Id})
|
||||
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet.Item.Id})
|
||||
require.NotNil(aliasedTar)
|
||||
assert.Empty(aliasedTar.Item.HostSourceIds)
|
||||
|
||||
tar, err = tarClient.SetHostSources(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet2.Item.Id})
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet2.Item.Id})
|
||||
rw := db.New(tc.DbConn())
|
||||
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
||||
|
||||
tar, err = tarClient.RemoveHostSources(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet2.Item.Id})
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.HostSourceIds)
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
}{
|
||||
{
|
||||
name: "target id",
|
||||
id: tar.Item.Id,
|
||||
},
|
||||
{
|
||||
name: "aliases",
|
||||
id: al.GetValue(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
tar, err := tarClient.AddHostSources(tc.Context(), c.id, 1, []string{hSet.Item.Id})
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet.Item.Id})
|
||||
|
||||
tar, err = tarClient.SetHostSources(tc.Context(), c.id, tar.Item.Version, []string{hSet2.Item.Id})
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.HostSourceIds, []string{hSet2.Item.Id})
|
||||
|
||||
tar, err = tarClient.RemoveHostSources(tc.Context(), c.id, tar.Item.Version, []string{hSet2.Item.Id})
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.HostSourceIds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCredentialSourcesASD(t *testing.T) {
|
||||
@@ -115,54 +141,78 @@ func TestCredentialSourcesASD(t *testing.T) {
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.BrokeredCredentialSourceIds)
|
||||
|
||||
// Add first Vault library
|
||||
tar, err = tarClient.AddCredentialSources(tc.Context(), tar.Item.Id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib1.Item.Id}))
|
||||
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib1.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: lib1.Item.Id,
|
||||
CredentialStoreId: csVault.Item.Id,
|
||||
},
|
||||
})
|
||||
require.NotNil(aliasedTar)
|
||||
assert.Empty(aliasedTar.Item.BrokeredCredentialSourceIds)
|
||||
|
||||
// Set second Vault library and a static credential
|
||||
tar, err = tarClient.SetCredentialSources(tc.Context(), tar.Item.Id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id, cred.Item.Id}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib2.Item.Id, cred.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: lib2.Item.Id,
|
||||
CredentialStoreId: csVault.Item.Id,
|
||||
},
|
||||
{
|
||||
Id: cred.Item.Id,
|
||||
CredentialStoreId: csStatic.Item.Id,
|
||||
},
|
||||
})
|
||||
// Remove second Vault library
|
||||
tar, err = tarClient.RemoveCredentialSources(tc.Context(), tar.Item.Id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{cred.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: cred.Item.Id,
|
||||
CredentialStoreId: csStatic.Item.Id,
|
||||
},
|
||||
})
|
||||
rw := db.New(tc.DbConn())
|
||||
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
||||
|
||||
// Set empty credential sources
|
||||
tar, err = tarClient.SetCredentialSources(tc.Context(), tar.Item.Id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.BrokeredCredentialSourceIds)
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
}{
|
||||
{
|
||||
name: "target id",
|
||||
id: tar.Item.Id,
|
||||
},
|
||||
{
|
||||
name: "aliases",
|
||||
id: al.GetValue(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
// Add first Vault library
|
||||
tar, err := tarClient.AddCredentialSources(tc.Context(), c.id, 1,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib1.Item.Id}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib1.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: lib1.Item.Id,
|
||||
CredentialStoreId: csVault.Item.Id,
|
||||
},
|
||||
})
|
||||
|
||||
// Set second Vault library and a static credential
|
||||
tar, err = tarClient.SetCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id, cred.Item.Id}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{lib2.Item.Id, cred.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: lib2.Item.Id,
|
||||
CredentialStoreId: csVault.Item.Id,
|
||||
},
|
||||
{
|
||||
Id: cred.Item.Id,
|
||||
CredentialStoreId: csStatic.Item.Id,
|
||||
},
|
||||
})
|
||||
// Remove second Vault library
|
||||
tar, err = tarClient.RemoveCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{lib2.Item.Id}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSourceIds, []string{cred.Item.Id})
|
||||
assert.ElementsMatch(tar.Item.BrokeredCredentialSources, []*targets.CredentialSource{
|
||||
{
|
||||
Id: cred.Item.Id,
|
||||
CredentialStoreId: csStatic.Item.Id,
|
||||
},
|
||||
})
|
||||
|
||||
// Set empty credential sources
|
||||
tar, err = tarClient.SetCredentialSources(tc.Context(), c.id, tar.Item.Version,
|
||||
targets.WithBrokeredCredentialSourceIds([]string{}))
|
||||
require.NoError(err)
|
||||
require.NotNil(tar)
|
||||
assert.Empty(tar.Item.BrokeredCredentialSourceIds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
@@ -467,23 +517,46 @@ func TestUpdateTarget_DeleteAddress(t *testing.T) {
|
||||
require.NotNil(createResp)
|
||||
assert.Equal(addr, createResp.GetItem().Address)
|
||||
|
||||
// Update to delete address (set to null)
|
||||
updateResp, err := tClient.Update(tc.Context(), createResp.Item.Id, createResp.Item.Version, targets.DefaultAddress())
|
||||
aliasedTar, err := tClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
||||
require.NoError(err)
|
||||
require.NotNil(updateResp)
|
||||
assert.Empty(updateResp.GetItem().Address)
|
||||
require.NotNil(aliasedTar)
|
||||
|
||||
// Do it again with same version, should error
|
||||
_, err = tClient.Update(tc.Context(), createResp.Item.Id, createResp.Item.Version, targets.DefaultAddress())
|
||||
require.Error(err)
|
||||
rw := db.New(tc.DbConn())
|
||||
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
||||
|
||||
// Do it again with the correct version, ensure this is not an error.
|
||||
secondUpdateResp, err := tClient.Update(tc.Context(), createResp.Item.Id, updateResp.Item.Version, targets.DefaultAddress())
|
||||
require.NoError(err)
|
||||
require.NotNil(secondUpdateResp)
|
||||
assert.Empty(secondUpdateResp.GetItem().Address)
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
}{
|
||||
{
|
||||
name: "target id",
|
||||
id: createResp.Item.Id,
|
||||
},
|
||||
{
|
||||
name: "aliases",
|
||||
id: al.GetValue(),
|
||||
},
|
||||
}
|
||||
|
||||
assert.NotEqual(updateResp.Item.Version, secondUpdateResp.Item.Version)
|
||||
for _, c := range cases {
|
||||
// Update to delete address (set to null)
|
||||
updateResp, err := tClient.Update(tc.Context(), c.id, 1, targets.DefaultAddress())
|
||||
require.NoError(err)
|
||||
require.NotNil(updateResp)
|
||||
assert.Empty(updateResp.GetItem().Address)
|
||||
|
||||
// Do it again with same version, should error
|
||||
_, err = tClient.Update(tc.Context(), c.id, 1, targets.DefaultAddress())
|
||||
require.Error(err)
|
||||
|
||||
// Do it again with the correct version, ensure this is not an error.
|
||||
secondUpdateResp, err := tClient.Update(tc.Context(), c.id, updateResp.Item.Version, targets.DefaultAddress())
|
||||
require.NoError(err)
|
||||
require.NotNil(secondUpdateResp)
|
||||
assert.Empty(secondUpdateResp.GetItem().Address)
|
||||
|
||||
assert.NotEqual(updateResp.Item.Version, secondUpdateResp.Item.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func comparableSlice(in []*targets.Target) []targets.Target {
|
||||
@@ -528,20 +601,44 @@ func TestCrud(t *testing.T) {
|
||||
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"), targets.WithTcpTargetDefaultPort(2))
|
||||
checkResource(t, "create", tar.Item, err, "foo", 1)
|
||||
|
||||
tar, err = tarClient.Read(tc.Context(), tar.Item.Id)
|
||||
checkResource(t, "read", tar.Item, err, "foo", 1)
|
||||
aliasedTar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("aliased"), targets.WithTcpTargetDefaultPort(2))
|
||||
checkResource(t, "create", aliasedTar.Item, err, "aliased", 1)
|
||||
|
||||
tar, err = tarClient.Update(tc.Context(), tar.Item.Id, tar.Item.Version, targets.WithName("bar"))
|
||||
checkResource(t, "update", tar.Item, err, "bar", 2)
|
||||
rw := db.New(tc.DbConn())
|
||||
al := aliastar.TestAlias(t, rw, "alias.value", aliastar.WithDestinationId(aliasedTar.Item.Id))
|
||||
|
||||
_, err = tarClient.Delete(tc.Context(), tar.Item.Id)
|
||||
assert.NoError(err)
|
||||
cases := []struct {
|
||||
name string
|
||||
id string
|
||||
initialName string
|
||||
}{
|
||||
{
|
||||
name: "target id",
|
||||
id: tar.Item.Id,
|
||||
initialName: "foo",
|
||||
},
|
||||
{
|
||||
name: "aliases",
|
||||
id: al.GetValue(),
|
||||
initialName: "aliased",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
tar, err := tarClient.Read(tc.Context(), c.id)
|
||||
checkResource(t, "read", tar.Item, err, c.initialName, 1)
|
||||
|
||||
_, err = tarClient.Delete(tc.Context(), tar.Item.Id)
|
||||
assert.Error(err)
|
||||
apiErr := api.AsServerError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
||||
tar, err = tarClient.Update(tc.Context(), c.id, tar.Item.Version, targets.WithName("bar"))
|
||||
checkResource(t, "update", tar.Item, err, "bar", 2)
|
||||
|
||||
_, err = tarClient.Delete(tc.Context(), c.id)
|
||||
assert.NoError(err)
|
||||
|
||||
_, err = tarClient.Delete(tc.Context(), c.id)
|
||||
assert.Error(err)
|
||||
apiErr := api.AsServerError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet_Errors(t *testing.T) {
|
||||
@@ -592,7 +689,16 @@ func TestSet_Errors(t *testing.T) {
|
||||
require.Error(err)
|
||||
apiErr = api.AsServerError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
|
||||
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
||||
|
||||
// reading by alias with no destination id should fail
|
||||
rw := db.New(tc.DbConn())
|
||||
al := aliastar.TestAlias(t, rw, "alias.value")
|
||||
_, err = tarClient.Read(tc.Context(), al.GetValue())
|
||||
require.Error(err)
|
||||
apiErr = api.AsServerError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
|
||||
}
|
||||
|
||||
func TestCreateTarget_WhitespaceInAddress(t *testing.T) {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user