2020-09-19 00:18:17 -04:00
// Copyright (c) HashiCorp, Inc.
2021-07-27 12:48:36 -04:00
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2020-09-01 15:05:46 -07:00
package targets
import (
"context"
2020-11-05 16:54:03 -05:00
stderrors "errors"
2020-09-01 15:05:46 -07:00
"fmt"
2020-09-19 00:18:17 -04:00
"math/rand"
2022-06-13 08:26:24 -07:00
"net"
2020-09-19 00:18:17 -04:00
"net/url"
2022-06-13 08:26:24 -07:00
"strconv"
2020-10-22 08:40:00 -04:00
"strings"
2022-11-10 13:14:57 -05:00
"sync/atomic"
"time"
2020-09-01 15:05:46 -07:00
2021-05-04 19:57:35 -05:00
"github.com/hashicorp/boundary/globals"
2024-02-13 09:17:41 -08:00
"github.com/hashicorp/boundary/internal/alias"
2024-02-01 08:58:56 -08:00
talias "github.com/hashicorp/boundary/internal/alias/target"
2021-06-22 22:26:26 -04:00
"github.com/hashicorp/boundary/internal/credential"
2022-05-09 12:45:10 -07:00
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
"github.com/hashicorp/boundary/internal/daemon/controller/common"
2025-01-08 15:18:03 +00:00
"github.com/hashicorp/boundary/internal/daemon/controller/downstream"
2022-05-09 12:45:10 -07:00
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
2020-09-19 10:31:49 -04:00
"github.com/hashicorp/boundary/internal/db/timestamp"
2020-11-05 16:54:03 -05:00
"github.com/hashicorp/boundary/internal/errors"
2024-04-06 13:48:47 -07:00
"github.com/hashicorp/boundary/internal/event"
2020-09-01 15:05:46 -07:00
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
2023-04-23 22:07:22 -07:00
intglobals "github.com/hashicorp/boundary/internal/globals"
2020-09-19 00:18:17 -04:00
"github.com/hashicorp/boundary/internal/host"
2023-11-02 16:03:47 -04:00
"github.com/hashicorp/boundary/internal/host/plugin"
2020-10-02 16:45:32 -07:00
"github.com/hashicorp/boundary/internal/host/static"
2020-09-19 00:18:17 -04:00
"github.com/hashicorp/boundary/internal/kms"
2023-11-24 17:27:15 -08:00
"github.com/hashicorp/boundary/internal/listtoken"
2023-10-24 09:41:11 -07:00
"github.com/hashicorp/boundary/internal/pagination"
2021-01-13 14:42:37 -05:00
"github.com/hashicorp/boundary/internal/perms"
2021-05-04 19:57:35 -05:00
"github.com/hashicorp/boundary/internal/requests"
2020-09-19 00:18:17 -04:00
"github.com/hashicorp/boundary/internal/session"
2020-09-01 15:05:46 -07:00
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/types/action"
2020-09-04 14:48:11 -07:00
"github.com/hashicorp/boundary/internal/types/resource"
2020-09-01 15:05:46 -07:00
"github.com/hashicorp/boundary/internal/types/scope"
2022-04-13 12:56:31 -04:00
"github.com/hashicorp/boundary/internal/types/subtypes"
2024-11-01 13:27:40 -04:00
"github.com/hashicorp/boundary/internal/util"
2022-08-23 17:32:36 +01:00
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
2021-08-26 10:44:41 -04:00
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
2023-02-07 10:14:01 -08:00
fm "github.com/hashicorp/boundary/version"
2021-01-21 16:27:20 -05:00
"github.com/hashicorp/go-bexpr"
2021-07-14 17:37:40 -07:00
"github.com/hashicorp/go-secure-stdlib/strutil"
2020-09-26 14:01:49 -04:00
"github.com/mr-tron/base58"
2020-09-01 15:05:46 -07:00
"google.golang.org/grpc/codes"
2020-09-19 00:18:17 -04:00
"google.golang.org/protobuf/proto"
2020-09-19 10:31:49 -04:00
"google.golang.org/protobuf/types/known/timestamppb"
2020-09-01 15:05:46 -07:00
"google.golang.org/protobuf/types/known/wrapperspb"
)
2021-01-13 14:42:37 -05:00
var (
2021-01-20 10:53:01 -05:00
// IdActions contains the set of actions that can be performed on
// individual resources
2023-10-31 13:44:17 +00:00
IdActions = action . NewActionSet (
2021-04-23 09:13:37 -05:00
action . NoOp ,
2021-01-13 14:42:37 -05:00
action . Read ,
action . Update ,
action . Delete ,
2021-12-15 10:06:35 -08:00
action . AddHostSources ,
action . SetHostSources ,
action . RemoveHostSources ,
2021-07-27 12:48:36 -04:00
action . AddCredentialSources ,
action . SetCredentialSources ,
action . RemoveCredentialSources ,
2021-01-13 14:42:37 -05:00
action . AuthorizeSession ,
2023-10-31 13:44:17 +00:00
)
2021-01-20 10:53:01 -05:00
// CollectionActions contains the set of actions that can be performed on
// this collection
2023-10-31 13:44:17 +00:00
CollectionActions = action . NewActionSet (
2021-01-20 10:53:01 -05:00
action . Create ,
action . List ,
2023-10-31 13:44:17 +00:00
)
2022-11-30 15:23:37 -05:00
2024-04-03 17:54:37 -07:00
validateCredentialSourcesFn = func ( context . Context , globals . Subtype , [] target . CredentialSource ) error { return nil }
ValidateIngressWorkerFilterFn = IngressWorkerFilterUnsupported
SessionRecordingFn = NoSessionRecording
WorkerFilterDeprecationMessage = fmt . Sprintf ( "This field is deprecated. Use %s instead." , globals . EgressWorkerFilterField )
2025-01-08 15:18:03 +00:00
StorageBucketFilterCredIdFn = noStorageBucket
2025-01-23 11:55:11 -08:00
ValidateLicenseFn = noOpValidateLicense
2021-01-13 14:42:37 -05:00
)
2020-09-01 15:05:46 -07:00
2023-10-11 18:26:16 +00:00
func init () {
// TODO: refactor to remove IdActions and CollectionActions package variables
action . RegisterResource ( resource . Target , IdActions , CollectionActions )
}
2022-11-30 15:23:37 -05:00
func IngressWorkerFilterUnsupported ( string ) error {
return fmt . Errorf ( "Ingress Worker Filter field is not supported in OSS" )
}
2020-09-01 15:05:46 -07:00
// Service handles request as described by the pbs.TargetServiceServer interface.
type Service struct {
2022-08-30 14:22:10 -04:00
pbs . UnsafeTargetServiceServer
2020-11-11 14:41:05 -05:00
2025-01-09 10:26:37 -08:00
repoFn target . RepositoryFactory
aliasRepoFn common . TargetAliasRepoFactory
iamRepoFn common . IamRepoFactory
serversRepoFn common . ServersRepoFactory
sessionRepoFn session . RepositoryFactory
pluginHostRepoFn common . PluginHostRepoFactory
staticHostRepoFn common . StaticRepoFactory
vaultCredRepoFn common . VaultCredentialRepoFactory
staticCredRepoFn common . StaticCredentialRepoFactory
downstreams downstream . Graph
kmsCache * kms . Kms
workerRPCGracePeriod * atomic . Int64
maxPageSize uint
controllerExt intglobals . ControllerExtension
2020-09-01 15:05:46 -07:00
}
2022-08-30 14:22:10 -04:00
var _ pbs . TargetServiceServer = ( * Service )( nil )
2020-09-01 15:05:46 -07:00
// NewService returns a target service which handles target related requests to boundary.
2020-09-19 00:18:17 -04:00
func NewService (
2021-09-26 08:17:21 -07:00
ctx context . Context ,
2020-09-19 00:18:17 -04:00
kmsCache * kms . Kms ,
2022-08-23 14:57:38 +01:00
repoFn target . RepositoryFactory ,
2020-09-19 00:18:17 -04:00
iamRepoFn common . IamRepoFactory ,
serversRepoFn common . ServersRepoFactory ,
2022-08-24 13:22:03 +00:00
sessionRepoFn session . RepositoryFactory ,
2021-09-26 08:17:21 -07:00
pluginHostRepoFn common . PluginHostRepoFactory ,
2021-06-22 22:26:26 -04:00
staticHostRepoFn common . StaticRepoFactory ,
2022-04-01 16:32:20 -04:00
vaultCredRepoFn common . VaultCredentialRepoFactory ,
2022-06-09 15:35:55 -07:00
staticCredRepoFn common . StaticCredentialRepoFactory ,
2024-02-01 08:58:56 -08:00
aliasRepoFn common . TargetAliasRepoFactory ,
2025-01-08 15:18:03 +00:00
downstreams downstream . Graph ,
2025-01-09 10:26:37 -08:00
workerRPCGracePeriod * atomic . Int64 ,
2023-10-24 09:41:11 -07:00
maxPageSize uint ,
2023-04-23 22:07:22 -07:00
controllerExt intglobals . ControllerExtension ,
2022-04-01 16:32:20 -04:00
) ( Service , error ) {
2021-04-16 12:06:03 -05:00
const op = "targets.NewService"
2024-02-01 08:58:56 -08:00
switch {
case kmsCache == nil :
2023-04-23 22:07:22 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing kms repo" )
2024-02-01 08:58:56 -08:00
case repoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing target repository" )
2024-02-01 08:58:56 -08:00
case iamRepoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing iam repository" )
2024-02-01 08:58:56 -08:00
case serversRepoFn == nil :
2022-06-20 18:20:17 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing server repository" )
2024-02-01 08:58:56 -08:00
case sessionRepoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing session repository" )
2024-02-01 08:58:56 -08:00
case pluginHostRepoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing plugin host repository" )
2024-02-01 08:58:56 -08:00
case staticHostRepoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing static host repository" )
2024-02-01 08:58:56 -08:00
case vaultCredRepoFn == nil :
2021-09-26 08:17:21 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing vault credential repository" )
2024-02-01 08:58:56 -08:00
case staticCredRepoFn == nil :
2022-06-09 15:35:55 -07:00
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing static credential repository" )
2024-02-01 08:58:56 -08:00
case aliasRepoFn == nil :
return Service {}, errors . New ( ctx , errors . InvalidParameter , op , "missing target alias repository" )
2022-06-09 15:35:55 -07:00
}
2023-10-24 09:41:11 -07:00
if maxPageSize == 0 {
maxPageSize = uint ( globals . DefaultMaxPageSize )
}
2020-09-19 00:18:17 -04:00
return Service {
2025-01-09 10:26:37 -08:00
repoFn : repoFn ,
iamRepoFn : iamRepoFn ,
serversRepoFn : serversRepoFn ,
sessionRepoFn : sessionRepoFn ,
pluginHostRepoFn : pluginHostRepoFn ,
staticHostRepoFn : staticHostRepoFn ,
vaultCredRepoFn : vaultCredRepoFn ,
staticCredRepoFn : staticCredRepoFn ,
aliasRepoFn : aliasRepoFn ,
downstreams : downstreams ,
kmsCache : kmsCache ,
workerRPCGracePeriod : workerRPCGracePeriod ,
maxPageSize : maxPageSize ,
controllerExt : controllerExt ,
2020-09-19 00:18:17 -04:00
}, nil
2020-09-01 15:05:46 -07:00
}
// ListTargets implements the interface pbs.TargetServiceServer.
func ( s Service ) ListTargets ( ctx context . Context , req * pbs . ListTargetsRequest ) ( * pbs . ListTargetsResponse , error ) {
2023-10-24 09:41:11 -07:00
const op = "targets.(Service).ListTargets"
2022-04-29 15:55:27 -04:00
2023-06-06 17:09:08 -04:00
if err := validateListRequest ( ctx , req ); err != nil {
2020-09-01 15:05:46 -07:00
return nil , err
}
2020-09-04 14:48:11 -07:00
authResults := s . authResult ( ctx , req . GetScopeId (), action . List )
2020-09-01 15:05:46 -07:00
if authResults . Error != nil {
2021-03-24 15:33:04 -04:00
// If it's forbidden, and it's a recursive request, and they're
// successfully authenticated but just not authorized, keep going as we
2021-09-02 12:55:04 -04:00
// may have authorization on downstream scopes. Or, if they've not
// authenticated, still process in case u_anon has permissions.
if ( authResults . Error == handlers . ForbiddenError () || authResults . Error == handlers . UnauthenticatedError ()) &&
2021-03-24 15:33:04 -04:00
req . GetRecursive () &&
2021-04-13 16:55:40 -05:00
authResults . AuthenticationFinished {
2021-03-24 15:33:04 -04:00
} else {
return nil , authResults . Error
}
2020-09-01 15:05:46 -07:00
}
2021-01-25 19:37:40 -05:00
2022-08-23 17:32:36 +01:00
var err error
var authzScopes map [ string ] * scopes . ScopeInfo
if req . GetRecursive () {
authzScopes , err = authResults . ScopesAuthorizedForList ( ctx , req . GetScopeId (), resource . Target )
} else {
authzScopes = map [ string ] * scopes . ScopeInfo { authResults . Scope . Id : authResults . Scope }
}
2021-01-25 19:37:40 -05:00
if err != nil {
return nil , err
}
2022-04-29 15:55:27 -04:00
2022-08-23 17:32:36 +01:00
// Get all user permissions for the requested scope(s).
2022-10-28 11:17:33 -04:00
userPerms := authResults . ACL (). ListPermissions ( authzScopes , resource . Target , IdActions , authResults . UserId )
2022-08-23 17:32:36 +01:00
if len ( userPerms ) == 0 {
2024-02-15 09:26:29 -08:00
return & pbs . ListTargetsResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
}, nil
2021-03-24 15:33:04 -04:00
}
2021-01-25 19:37:40 -05:00
2023-10-24 09:41:11 -07:00
pageSize := int ( s . maxPageSize )
// Use the requested page size only if it is smaller than
// the configured max.
if req . GetPageSize () != 0 && uint ( req . GetPageSize ()) < s . maxPageSize {
pageSize = int ( req . GetPageSize ())
}
2023-11-24 17:27:15 -08:00
var filterItemFn func ( ctx context . Context , item target . Target ) ( bool , error )
switch {
case req . GetFilter () != "" :
// Only use a filter if we need to
filter , err := handlers . NewFilter ( ctx , req . GetFilter ())
if err != nil {
return nil , err
}
// TODO: replace the need for this function with some way to convert the `filter`
// to a domain type. This would allow filtering to happen in the domain, and we could
// remove this callback altogether.
filterItemFn = func ( ctx context . Context , item target . Target ) ( bool , error ) {
pbItem , err := toProto ( ctx , item , newOutputOpts ( ctx , item , authResults , authzScopes ) ... )
if err != nil {
return false , err
}
filterable , err := subtypes . Filterable ( ctx , pbItem )
if err != nil {
return false , err
}
return filter . Match ( filterable ), nil
}
default :
filterItemFn = func ( ctx context . Context , item target . Target ) ( bool , error ) {
return true , nil
}
2020-09-01 15:05:46 -07:00
}
2021-01-25 19:37:40 -05:00
2023-10-24 09:41:11 -07:00
repo , err := s . repoFn ( target . WithPermissions ( userPerms ))
2021-02-22 10:09:25 -07:00
if err != nil {
return nil , err
}
2023-10-24 09:41:11 -07:00
grantsHash , err := authResults . GrantsHash ( ctx )
if err != nil {
return nil , err
}
2022-08-23 17:32:36 +01:00
2023-10-24 09:41:11 -07:00
var listResp * pagination . ListResponse [ target . Target ]
2023-11-24 17:27:15 -08:00
var sortBy string
if req . GetListToken () == "" {
sortBy = "created_time"
2023-10-24 09:41:11 -07:00
listResp , err = target . List ( ctx , grantsHash , pageSize , filterItemFn , repo )
if err != nil {
return nil , err
2021-05-04 19:57:35 -05:00
}
2023-10-24 09:41:11 -07:00
} else {
2023-11-30 10:06:47 -08:00
listToken , err := handlers . ParseListToken ( ctx , req . GetListToken (), resource . Target , grantsHash )
2023-10-24 09:41:11 -07:00
if err != nil {
return nil , err
}
2023-11-30 10:06:47 -08:00
switch st := listToken . Subtype .( type ) {
case * listtoken . PaginationToken :
2023-11-24 17:27:15 -08:00
sortBy = "created_time"
listResp , err = target . ListPage ( ctx , grantsHash , pageSize , filterItemFn , listToken , repo )
if err != nil {
return nil , err
}
2023-11-30 10:06:47 -08:00
case * listtoken . StartRefreshToken :
2023-11-24 17:27:15 -08:00
sortBy = "updated_time"
listResp , err = target . ListRefresh ( ctx , grantsHash , pageSize , filterItemFn , listToken , repo )
if err != nil {
return nil , err
}
2023-11-30 10:06:47 -08:00
case * listtoken . RefreshToken :
2023-11-24 17:27:15 -08:00
sortBy = "updated_time"
listResp , err = target . ListRefreshPage ( ctx , grantsHash , pageSize , filterItemFn , listToken , repo )
if err != nil {
return nil , err
}
default :
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . InvalidArgument , "unexpected list token subtype: %T" , st )
2021-05-04 19:57:35 -05:00
}
2023-10-24 09:41:11 -07:00
}
2021-05-04 19:57:35 -05:00
2023-10-24 09:41:11 -07:00
finalItems := make ([] * pb . Target , 0 , len ( listResp . Items ))
for _ , item := range listResp . Items {
item , err := toProto ( ctx , item , newOutputOpts ( ctx , item , authResults , authzScopes ) ... )
2022-04-13 16:27:48 -04:00
if err != nil {
return nil , err
}
2023-10-24 09:41:11 -07:00
finalItems = append ( finalItems , item )
}
respType := "delta"
if listResp . CompleteListing {
respType = "complete"
}
resp := & pbs . ListTargetsResponse {
Items : finalItems ,
EstItemCount : uint32 ( listResp . EstimatedItemCount ),
RemovedIds : listResp . DeletedIds ,
ResponseType : respType ,
2023-11-24 17:27:15 -08:00
SortBy : sortBy ,
SortDir : "desc" ,
2023-10-24 09:41:11 -07:00
}
2023-11-24 17:27:15 -08:00
if listResp . ListToken != nil {
resp . ListToken , err = handlers . MarshalListToken ( ctx , listResp . ListToken , pbs . ResourceType_RESOURCE_TYPE_TARGET )
2023-10-24 09:41:11 -07:00
if err != nil {
return nil , err
2021-01-13 14:42:37 -05:00
}
2020-09-01 15:05:46 -07:00
}
2022-08-23 17:32:36 +01:00
2023-10-24 09:41:11 -07:00
return resp , nil
2020-09-01 15:05:46 -07:00
}
2022-04-13 16:27:48 -04:00
// GetTarget implements the interface pbs.TargetServiceServer.
2020-09-01 15:05:46 -07:00
func ( s Service ) GetTarget ( ctx context . Context , req * pbs . GetTargetRequest ) ( * pbs . GetTargetResponse , error ) {
2021-05-04 19:57:35 -05:00
const op = "targets.(Service).GetTarget"
2020-09-01 15:05:46 -07:00
if err := validateGetRequest ( req ); err != nil {
return nil , err
}
2020-09-04 14:48:11 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . Read )
2020-09-01 15:05:46 -07:00
if authResults . Error != nil {
return nil , authResults . Error
}
2021-06-22 22:26:26 -04:00
t , ts , cl , err := s . getFromRepo ( ctx , req . GetId ())
2021-05-04 19:57:35 -05:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-05-04 19:57:35 -05:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-05-04 19:57:35 -05:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
return nil , err
}
2021-05-04 19:57:35 -05:00
return & pbs . GetTargetResponse { Item : item }, nil
2020-09-01 15:05:46 -07:00
}
// CreateTarget implements the interface pbs.TargetServiceServer.
func ( s Service ) CreateTarget ( ctx context . Context , req * pbs . CreateTargetRequest ) ( * pbs . CreateTargetResponse , error ) {
2021-05-04 19:57:35 -05:00
const op = "targets.(Service).CreateTarget"
2020-09-01 15:05:46 -07:00
if err := validateCreateRequest ( req ); err != nil {
return nil , err
}
2020-09-04 14:48:11 -07:00
authResults := s . authResult ( ctx , req . GetItem (). GetScopeId (), action . Create )
2020-09-01 15:05:46 -07:00
if authResults . Error != nil {
return nil , authResults . Error
}
2024-03-12 13:57:47 -07:00
for _ , a := range req . GetItem (). WithAliases {
authResults := s . aliasCreateAuthResult ( ctx , a . GetScopeId ())
if authResults . Error != nil {
return nil , authResults . Error
}
}
2021-06-22 22:26:26 -04:00
t , ts , cl , err := s . createInRepo ( ctx , req . GetItem ())
2021-05-04 19:57:35 -05:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-05-04 19:57:35 -05:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-05-04 19:57:35 -05:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
return nil , err
}
2021-05-04 19:57:35 -05:00
return & pbs . CreateTargetResponse { Item : item , Uri : fmt . Sprintf ( "targets/%s" , item . GetId ())}, nil
2020-09-01 15:05:46 -07:00
}
// UpdateTarget implements the interface pbs.TargetServiceServer.
func ( s Service ) UpdateTarget ( ctx context . Context , req * pbs . UpdateTargetRequest ) ( * pbs . UpdateTargetResponse , error ) {
2021-05-04 19:57:35 -05:00
const op = "targets.(Service).UpdateTarget"
2020-09-01 15:05:46 -07:00
if err := validateUpdateRequest ( req ); err != nil {
return nil , err
}
2020-09-04 14:48:11 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . Update )
2020-09-01 15:05:46 -07:00
if authResults . Error != nil {
return nil , authResults . Error
}
2021-06-22 22:26:26 -04:00
t , ts , cl , err := s . updateInRepo ( ctx , authResults . Scope . GetId (), req . GetId (), req . GetUpdateMask (). GetPaths (), req . GetItem ())
2021-05-04 19:57:35 -05:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-05-04 19:57:35 -05:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-05-04 19:57:35 -05:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
return nil , err
}
2021-05-04 19:57:35 -05:00
return & pbs . UpdateTargetResponse { Item : item }, nil
2020-09-01 15:05:46 -07:00
}
// DeleteTarget implements the interface pbs.TargetServiceServer.
func ( s Service ) DeleteTarget ( ctx context . Context , req * pbs . DeleteTargetRequest ) ( * pbs . DeleteTargetResponse , error ) {
2024-02-01 08:58:56 -08:00
const op = "targets.(Service).DeleteTarget"
2020-09-01 15:05:46 -07:00
if err := validateDeleteRequest ( req ); err != nil {
return nil , err
}
2020-09-04 14:48:11 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . Delete )
2020-09-01 15:05:46 -07:00
if authResults . Error != nil {
return nil , authResults . Error
}
2020-09-08 23:57:26 -04:00
_ , err := s . deleteFromRepo ( ctx , req . GetId ())
2020-09-01 15:05:46 -07:00
if err != nil {
return nil , err
}
2021-04-26 19:38:55 -05:00
return nil , nil
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
// AddTargetHostSources implements the interface pbs.TargetServiceServer.
func ( s Service ) AddTargetHostSources ( ctx context . Context , req * pbs . AddTargetHostSourcesRequest ) ( * pbs . AddTargetHostSourcesResponse , error ) {
const op = "targets.(Service).AddTargetHostSources"
if err := validateAddHostSourcesRequest ( req ); err != nil {
return nil , err
}
2022-06-15 08:56:24 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . AddHostSources )
2021-07-30 08:48:03 -04:00
if authResults . Error != nil {
return nil , authResults . Error
}
2023-03-30 15:19:30 -04:00
t , err := s . addHostSourcesInRepo ( ctx , req . GetId (), req . GetHostSourceIds (), req . GetVersion ())
2021-07-30 08:48:03 -04:00
if err != nil {
return nil , err
}
2023-03-30 15:19:30 -04:00
ts := t . GetHostSources ()
cl := t . GetCredentialSources ()
2021-07-30 08:48:03 -04:00
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-30 08:48:03 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-30 08:48:03 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-30 08:48:03 -04:00
if err != nil {
return nil , err
}
return & pbs . AddTargetHostSourcesResponse { Item : item }, nil
}
// SetTargetHostSources implements the interface pbs.TargetServiceServer.
func ( s Service ) SetTargetHostSources ( ctx context . Context , req * pbs . SetTargetHostSourcesRequest ) ( * pbs . SetTargetHostSourcesResponse , error ) {
const op = "targets.(Service).SetTargetHostSources"
if err := validateSetHostSourcesRequest ( req ); err != nil {
return nil , err
}
2022-06-15 08:56:24 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . SetHostSources )
2021-07-30 08:48:03 -04:00
if authResults . Error != nil {
return nil , authResults . Error
}
t , ts , cl , err := s . setHostSourcesInRepo ( ctx , req . GetId (), req . GetHostSourceIds (), req . GetVersion ())
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-30 08:48:03 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-30 08:48:03 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-30 08:48:03 -04:00
if err != nil {
return nil , err
}
return & pbs . SetTargetHostSourcesResponse { Item : item }, nil
}
// RemoveTargetHostSources implements the interface pbs.TargetServiceServer.
func ( s Service ) RemoveTargetHostSources ( ctx context . Context , req * pbs . RemoveTargetHostSourcesRequest ) ( * pbs . RemoveTargetHostSourcesResponse , error ) {
2022-06-15 08:56:24 -07:00
const op = "targets.(Service).RemoveTargetHostSources"
2021-07-30 08:48:03 -04:00
if err := validateRemoveHostSourcesRequest ( req ); err != nil {
return nil , err
}
2022-06-15 08:56:24 -07:00
authResults := s . authResult ( ctx , req . GetId (), action . RemoveHostSources )
2021-07-30 08:48:03 -04:00
if authResults . Error != nil {
return nil , authResults . Error
}
t , ts , cl , err := s . removeHostSourcesInRepo ( ctx , req . GetId (), req . GetHostSourceIds (), req . GetVersion ())
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-30 08:48:03 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-30 08:48:03 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-30 08:48:03 -04:00
if err != nil {
return nil , err
}
return & pbs . RemoveTargetHostSourcesResponse { Item : item }, nil
}
2021-07-27 12:48:36 -04:00
// AddTargetCredentialSources implements the interface pbs.TargetServiceServer.
func ( s Service ) AddTargetCredentialSources ( ctx context . Context , req * pbs . AddTargetCredentialSourcesRequest ) ( * pbs . AddTargetCredentialSourcesResponse , error ) {
const op = "targets.(Service).AddTargetCredentialSources"
if err := validateAddCredentialSourcesRequest ( req ); err != nil {
return nil , err
}
authResults := s . authResult ( ctx , req . GetId (), action . AddCredentialSources )
if authResults . Error != nil {
2022-09-15 09:20:08 -04:00
return nil , authResults . Error
2021-07-27 12:48:36 -04:00
}
2022-07-19 15:16:24 -07:00
2023-09-22 15:58:18 -04:00
t , ts , cl , err := s . addCredentialSourcesInRepo ( ctx , req . GetId (), req . GetBrokeredCredentialSourceIds (), req . GetInjectedApplicationCredentialSourceIds (), req . GetVersion ())
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-07-27 12:48:36 -04:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-27 12:48:36 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-27 12:48:36 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
return & pbs . AddTargetCredentialSourcesResponse { Item : item }, nil
}
// SetTargetCredentialSources implements the interface pbs.TargetServiceServer.
func ( s Service ) SetTargetCredentialSources ( ctx context . Context , req * pbs . SetTargetCredentialSourcesRequest ) ( * pbs . SetTargetCredentialSourcesResponse , error ) {
const op = "targets.(Service).SetTargetCredentialSources"
if err := validateSetCredentialSourcesRequest ( req ); err != nil {
return nil , err
}
authResults := s . authResult ( ctx , req . GetId (), action . SetCredentialSources )
if authResults . Error != nil {
2022-09-15 09:20:08 -04:00
return nil , authResults . Error
2021-07-27 12:48:36 -04:00
}
2022-07-19 15:16:24 -07:00
2023-09-22 15:58:18 -04:00
t , ts , cl , err := s . setCredentialSourcesInRepo ( ctx , req . GetId (), req . GetBrokeredCredentialSourceIds (), req . GetInjectedApplicationCredentialSourceIds (), req . GetVersion ())
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-07-27 12:48:36 -04:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-27 12:48:36 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-27 12:48:36 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
return & pbs . SetTargetCredentialSourcesResponse { Item : item }, nil
}
// RemoveTargetCredentialSources implements the interface pbs.TargetServiceServer.
func ( s Service ) RemoveTargetCredentialSources ( ctx context . Context , req * pbs . RemoveTargetCredentialSourcesRequest ) ( * pbs . RemoveTargetCredentialSourcesResponse , error ) {
const op = "targets.(Service).RemoveTargetCredentialSources"
if err := validateRemoveCredentialSourcesRequest ( req ); err != nil {
return nil , err
}
authResults := s . authResult ( ctx , req . GetId (), action . RemoveCredentialSources )
if authResults . Error != nil {
2022-09-15 09:20:08 -04:00
return nil , authResults . Error
2021-07-27 12:48:36 -04:00
}
2022-07-19 15:16:24 -07:00
2023-09-22 15:58:18 -04:00
t , ts , cl , err := s . removeCredentialSourcesInRepo ( ctx , req . GetId (), req . GetBrokeredCredentialSourceIds (), req . GetInjectedApplicationCredentialSourceIds (), req . GetVersion ())
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
outputFields , ok := requests . OutputFields ( ctx )
if ! ok {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . Internal , op , "no request context found" )
2021-07-27 12:48:36 -04:00
}
outputOpts := make ([] handlers . Option , 0 , 3 )
2023-01-06 17:27:19 -06:00
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
2021-07-27 12:48:36 -04:00
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authResults . Scope ))
}
if outputFields . Has ( globals . AuthorizedActionsField ) {
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authResults . FetchActionSetForId ( ctx , t . GetPublicId (), IdActions ). Strings ()))
}
2023-03-30 15:19:30 -04:00
t . SetHostSources ( ts )
t . SetCredentialSources ( cl )
2021-07-27 12:48:36 -04:00
2023-03-30 15:19:30 -04:00
item , err := toProto ( ctx , t , outputOpts ... )
2021-07-27 12:48:36 -04:00
if err != nil {
return nil , err
}
return & pbs . RemoveTargetCredentialSourcesResponse { Item : item }, nil
}
2025-01-08 15:18:03 +00:00
func NoSessionRecording ( context . Context , intglobals . ControllerExtension , * kms . Kms , target . Target , * session . Session , string ) ( string , error ) {
2024-04-03 17:54:37 -07:00
return "" , nil
2023-04-23 22:16:08 -07:00
}
2023-04-23 22:15:20 -07:00
func ( s Service ) AuthorizeSession ( ctx context . Context , req * pbs . AuthorizeSessionRequest ) ( _ * pbs . AuthorizeSessionResponse , retErr error ) {
2021-04-16 12:06:03 -05:00
const op = "targets.(Service).AuthorizeSession"
2024-02-01 08:58:56 -08:00
2025-01-23 11:55:11 -08:00
if err := ValidateLicenseFn ( ctx ); err != nil {
return nil , err
}
2024-02-13 09:17:41 -08:00
if ctxAlias := alias . FromContext ( ctx ); ctxAlias != nil {
a , err := s . resolveAlias ( ctx , ctxAlias . PublicId )
if err != nil {
2024-02-01 08:58:56 -08:00
return nil , errors . Wrap ( ctx , err , op )
2024-02-13 09:17:41 -08:00
}
if a . HostId != "" {
if req . GetHostId () != "" && req . GetHostId () != a . HostId {
return nil , handlers . InvalidArgumentErrorf ( "Errors in provided fields." , map [ string ] string {
2024-02-29 14:56:11 -08:00
"host_id" : "The host id specified in the request does not match the one provided by the alias. Consider omitting the host id in the request." ,
2024-02-13 09:17:41 -08:00
})
2024-02-01 08:58:56 -08:00
}
2024-02-13 09:17:41 -08:00
req . HostId = a . HostId
2024-02-01 08:58:56 -08:00
}
}
2020-10-05 11:02:23 -04:00
if err := validateAuthorizeSessionRequest ( req ); err != nil {
2020-09-19 00:18:17 -04:00
return nil , err
}
2020-10-22 08:40:00 -04:00
authResults := s . authResult ( ctx , req . GetId (), action . AuthorizeSession ,
target . WithName ( req . GetName ()),
2022-07-20 16:24:46 -07:00
target . WithProjectId ( req . GetScopeId ()),
target . WithProjectName ( req . GetScopeName ()),
2020-10-22 08:40:00 -04:00
)
2020-09-19 00:18:17 -04:00
if authResults . Error != nil {
return nil , authResults . Error
}
2024-04-06 13:48:47 -07:00
correlationId , ok := event . CorrelationIdFromContext ( ctx )
if ! ok {
return nil , stderrors . New ( "authorize session: missing correlation id" )
}
2020-10-22 08:40:00 -04:00
if authResults . RoundTripValue == nil {
2020-11-05 16:54:03 -05:00
return nil , stderrors . New ( "authorize session: expected to get a target back from auth results" )
2020-10-22 08:40:00 -04:00
}
2025-03-13 16:20:17 -07:00
roundTripTarget , ok := authResults . RoundTripValue .( target . Target )
2020-10-22 08:40:00 -04:00
if ! ok {
2020-11-05 16:54:03 -05:00
return nil , stderrors . New ( "authorize session: round tripped auth results value is not a target" )
2020-10-22 08:40:00 -04:00
}
2025-03-13 16:20:17 -07:00
if roundTripTarget == nil {
2020-11-05 16:54:03 -05:00
return nil , stderrors . New ( "authorize session: round tripped target is nil" )
2020-10-22 08:40:00 -04:00
}
2020-09-19 00:18:17 -04:00
// This could happen if, say, u_recovery was used or u_anon was granted. But
// don't allow it. It's one thing if grants give access to resources within
// Boundary, even if those could eventually be used to provide an unintended
// user access to a remote system. It's quite another to enable anonymous
// access directly to a remote system.
//
// Note that even if u_anon or u_auth are given grants we can still validate
// a token! So this is just checking that a valid token was provided. The
// actual reality of this works out to excluding:
//
// * True anonymous access (no token provided and u_anon)
//
// * u_recovery access (which is fine, recovery is meant for recovering
// system state, no real reason to allow it to then connect to systems)
if authResults . AuthTokenId == "" {
return nil , handlers . ForbiddenError ()
}
2025-03-13 16:20:17 -07:00
if roundTripTarget . GetDefaultPort () == 0 {
2023-01-26 10:35:29 -08:00
return nil , handlers . ConflictErrorf ( "Target does not have default port defined." )
}
2020-09-19 00:18:17 -04:00
// Get the target information
repo , err := s . repoFn ()
if err != nil {
return nil , err
}
2025-03-13 16:20:17 -07:00
t , err := repo . LookupTarget ( ctx , roundTripTarget . GetPublicId ())
2020-09-19 00:18:17 -04:00
if err != nil {
2020-12-21 10:07:34 -08:00
if errors . IsNotFoundError ( err ) {
2025-03-13 16:20:17 -07:00
return nil , handlers . NotFoundErrorf ( "Target %q not found." , roundTripTarget . GetPublicId ())
2020-09-19 00:18:17 -04:00
}
return nil , err
}
if t == nil {
2025-03-13 16:20:17 -07:00
return nil , handlers . NotFoundErrorf ( "Target %q not found." , roundTripTarget . GetPublicId ())
2020-09-19 00:18:17 -04:00
}
2023-07-20 11:01:20 -04:00
hostSources := t . GetHostSources ()
credSources := t . GetCredentialSources ()
2023-03-07 16:29:34 -05:00
if len ( credSources ) > 0 {
if err := validateCredentialSourcesFn ( ctx , t . GetType (), credSources ); err != nil {
return nil , err
}
}
2020-09-19 00:18:17 -04:00
// Instantiate some repos
sessionRepo , err := s . sessionRepoFn ()
if err != nil {
return nil , err
}
serversRepo , err := s . serversRepoFn ()
if err != nil {
return nil , err
}
2023-01-26 10:35:29 -08:00
p := strconv . FormatUint ( uint64 ( t . GetDefaultPort ()), 10 )
var h , hostId , hostSetId string
switch {
case t . GetAddress () != "" :
h = t . GetAddress ()
default :
requestedId := req . GetHostId ()
staticHostRepo , err := s . staticHostRepoFn ()
if err != nil {
return nil , err
}
pluginHostRepo , err := s . pluginHostRepoFn ()
if err != nil {
return nil , err
}
2020-09-19 00:18:17 -04:00
2023-01-26 10:35:29 -08:00
var pluginHostSetIds [] string
var endpoints [] * host . Endpoint
for _ , hSource := range hostSources {
hsId := hSource . Id ()
2023-11-15 19:55:46 -05:00
switch globals . ResourceInfoFromPrefix ( hsId ). Subtype {
2023-11-02 16:03:47 -04:00
case static . Subtype :
2023-01-26 10:35:29 -08:00
eps , err := staticHostRepo . Endpoints ( ctx , hsId )
if err != nil {
return nil , err
}
endpoints = append ( endpoints , eps ... )
default :
// Batch the plugin host set ids since each round trip to the plugin
// has the potential to be expensive.
pluginHostSetIds = append ( pluginHostSetIds , hsId )
}
}
if len ( pluginHostSetIds ) > 0 {
eps , err := pluginHostRepo . Endpoints ( ctx , pluginHostSetIds )
2020-09-19 00:18:17 -04:00
if err != nil {
return nil , err
}
2021-09-26 08:17:21 -07:00
endpoints = append ( endpoints , eps ... )
}
2023-01-26 10:35:29 -08:00
if len ( endpoints ) == 0 {
return nil , handlers . NotFoundErrorf ( "No host sources or address found for given target." )
}
2022-12-06 12:33:28 -08:00
2023-01-26 10:35:29 -08:00
var chosenEndpoint * host . Endpoint
if requestedId != "" {
for _ , ep := range endpoints {
if ep . HostId == requestedId {
chosenEndpoint = ep
}
}
if chosenEndpoint == nil {
// We didn't find it
return nil , handlers . InvalidArgumentErrorf (
"Errors in provided fields." ,
map [ string ] string {
"host_id" : "The requested host id is not available." ,
})
2021-09-26 08:17:21 -07:00
}
}
2023-01-26 10:35:29 -08:00
2021-09-26 08:17:21 -07:00
if chosenEndpoint == nil {
2023-01-26 10:35:29 -08:00
chosenEndpoint = endpoints [ rand . Intn ( len ( endpoints ))]
2021-09-26 08:17:21 -07:00
}
2020-09-19 00:18:17 -04:00
2022-12-06 12:33:28 -08:00
hostId = chosenEndpoint . HostId
hostSetId = chosenEndpoint . SetId
2023-01-26 10:35:29 -08:00
h = chosenEndpoint . Address
2022-12-06 12:33:28 -08:00
}
2023-01-26 10:35:29 -08:00
if h == "" {
return nil , handlers . ApiErrorWithCodeAndMessage (
codes . FailedPrecondition ,
"No host was discovered after checking target address and host sources." )
}
2024-11-01 13:27:40 -04:00
// Ensure we don't have a port from the address
_ , err = util . ParseAddress ( ctx , h )
if err != nil {
2023-01-26 10:35:29 -08:00
return nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "error when parsing the chosen endpoint host address" ))
2022-06-13 08:26:24 -07:00
}
2022-12-06 12:33:28 -08:00
2020-09-19 00:18:17 -04:00
// Generate the endpoint URL
endpointUrl := & url . URL {
2021-09-29 13:13:49 -04:00
Scheme : t . GetType (). String (),
2022-06-13 08:26:24 -07:00
Host : net . JoinHostPort ( h , p ),
2020-09-19 00:18:17 -04:00
}
2023-02-03 11:40:41 -05:00
// Get workers and filter down to ones that can service this request
2025-01-08 15:18:03 +00:00
selectedWorkers , protoWorkerId , err := serversRepo . SelectSessionWorkers (
ctx ,
2025-01-09 10:26:37 -08:00
time . Duration ( s . workerRPCGracePeriod . Load ()),
2025-01-08 15:18:03 +00:00
t ,
h ,
s . controllerExt ,
StorageBucketFilterCredIdFn ,
s . downstreams ,
)
2023-02-03 11:40:41 -05:00
if err != nil {
return nil , err
2022-07-22 11:22:37 -07:00
}
2023-05-01 14:20:27 -04:00
if len ( selectedWorkers ) == 0 {
return nil , handlers . ApiErrorWithCodeAndMessage (
codes . FailedPrecondition ,
"No workers are available to handle this session." )
}
2023-02-03 11:40:41 -05:00
// Randomize the workers
rand . Shuffle ( len ( selectedWorkers ), func ( i , j int ) {
selectedWorkers [ i ], selectedWorkers [ j ] = selectedWorkers [ j ], selectedWorkers [ i ]
})
2022-06-09 15:35:55 -07:00
var vaultReqs [] credential . Request
var staticIds [] string
2021-06-22 22:26:26 -04:00
var dynCreds [] * session . DynamicCredential
2022-06-09 15:35:55 -07:00
var staticCreds [] * session . StaticCredential
for _ , cs := range credSources {
switch cs . Type () {
case target . LibraryCredentialSourceType :
vaultReqs = append ( vaultReqs , credential . Request {
SourceId : cs . Id (),
Purpose : cs . CredentialPurpose (),
})
dynCreds = append ( dynCreds , session . NewDynamicCredential ( cs . Id (), cs . CredentialPurpose ()))
case target . StaticCredentialSourceType :
staticIds = append ( staticIds , cs . Id ())
staticCreds = append ( staticCreds , session . NewStaticCredential ( cs . Id (), cs . CredentialPurpose ()))
}
2021-06-22 22:26:26 -04:00
}
2020-09-19 10:31:49 -04:00
expTime := timestamppb . Now ()
2020-09-19 11:32:38 -04:00
expTime . Seconds += int64 ( t . GetSessionMaxSeconds ())
2020-09-19 00:18:17 -04:00
sessionComposition := session . ComposedOf {
2022-11-30 15:23:37 -05:00
UserId : authResults . UserId ,
2022-12-06 12:33:28 -08:00
HostId : hostId ,
2022-11-30 15:23:37 -05:00
TargetId : t . GetPublicId (),
2022-12-06 12:33:28 -08:00
HostSetId : hostSetId ,
2022-11-30 15:23:37 -05:00
AuthTokenId : authResults . AuthTokenId ,
ProjectId : authResults . Scope . Id ,
Endpoint : endpointUrl . String (),
ExpirationTime : & timestamp . Timestamp { Timestamp : expTime },
ConnectionLimit : t . GetSessionConnectionLimit (),
WorkerFilter : t . GetWorkerFilter (),
EgressWorkerFilter : t . GetEgressWorkerFilter (),
IngressWorkerFilter : t . GetIngressWorkerFilter (),
DynamicCredentials : dynCreds ,
StaticCredentials : staticCreds ,
2024-04-06 13:48:47 -07:00
CorrelationId : correlationId ,
2025-01-08 15:18:03 +00:00
ProtocolWorkerId : protoWorkerId ,
2023-05-05 09:22:54 -04:00
}
2023-06-06 17:09:08 -04:00
sess , err := session . New ( ctx , sessionComposition )
2020-09-19 00:18:17 -04:00
if err != nil {
return nil , err
}
wrapper , err := s . kmsCache . GetWrapper ( ctx , authResults . Scope . Id , kms . KeyPurposeSessions )
if err != nil {
return nil , err
}
2025-01-08 15:18:03 +00:00
workerAddresses := make ([] string , 0 , len ( selectedWorkers ))
for _ , sw := range selectedWorkers {
workerAddresses = append ( workerAddresses , sw . Address )
}
sess , err = sessionRepo . CreateSession ( ctx , wrapper , sess , workerAddresses )
2020-09-19 00:18:17 -04:00
if err != nil {
return nil , err
}
2023-04-23 22:15:20 -07:00
defer func () {
if retErr != nil {
// Delete created session in case of errors.
// Use new context for deletion in case error is because of context cancellation.
deleteCtx , cancel := context . WithTimeout ( context . Background (), 5 * time . Second )
defer cancel ()
_ , err := sessionRepo . DeleteSession ( deleteCtx , sess . PublicId )
2023-09-17 19:35:43 -04:00
retErr = stderrors . Join ( retErr , err )
2023-04-23 22:15:20 -07:00
}
}()
2020-09-19 00:18:17 -04:00
2023-05-31 11:25:03 -04:00
subtype := target . SubtypeFromId ( t . GetPublicId ())
2023-05-25 15:52:03 -07:00
subtypeEntry , err := subtypeRegistry . get ( subtype )
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
if err := subtypeEntry . validateSessionStateFunc ( ctx , sess ); err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
2022-06-09 15:35:55 -07:00
var dynamic [] credential . Dynamic
var staticCredsById map [ string ] credential . Static
if len ( vaultReqs ) > 0 {
2021-06-22 22:26:26 -04:00
credRepo , err := s . vaultCredRepoFn ()
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , errors . Wrap ( ctx , err , op )
2021-06-22 22:26:26 -04:00
}
2022-10-27 09:01:05 -04:00
dynamic , err = credRepo . Issue ( ctx , sess . GetPublicId (), vaultReqs , credential . WithTemplateData ( authResults . UserData ))
2022-06-09 15:35:55 -07:00
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
2023-04-23 22:15:20 -07:00
defer func () {
if retErr != nil {
// Revoke issued credentials in case of errors.
// Use new context for deletion in case error is because of context cancellation.
2023-04-23 22:16:08 -07:00
deleteCtx , cancel := context . WithTimeout ( context . Background (), time . Minute )
2023-04-23 22:15:20 -07:00
defer cancel ()
err := credRepo . Revoke ( deleteCtx , sess . PublicId )
2023-09-17 19:35:43 -04:00
retErr = stderrors . Join ( retErr , err )
2023-04-23 22:15:20 -07:00
// This leaves the credential in a state which will allow it to be cleaned up
// by the periodic credential cleanup job.
}
}()
2022-06-09 15:35:55 -07:00
}
if len ( staticIds ) > 0 {
credRepo , err := s . staticCredRepoFn ()
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
// Remove duplicate requests
staticIds = strutil . RemoveDuplicates ( staticIds , false )
2022-07-20 16:24:46 -07:00
creds , err := credRepo . Retrieve ( ctx , t . GetProjectId (), staticIds )
2021-06-22 22:26:26 -04:00
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , errors . Wrap ( ctx , err , op )
2021-06-22 22:26:26 -04:00
}
2022-06-09 15:35:55 -07:00
staticCredsById = make ( map [ string ] credential . Static )
for _ , c := range creds {
staticCredsById [ c . GetPublicId ()] = c
}
2021-06-22 22:26:26 -04:00
}
var creds [] * pb . SessionCredential
2021-12-17 11:26:42 -08:00
var workerCreds [] session . Credential
2022-06-09 15:35:55 -07:00
for _ , cred := range dynamic {
2022-01-05 14:15:38 -08:00
switch cred . Purpose () {
2022-07-19 15:16:24 -07:00
case credential . InjectedApplicationPurpose :
2022-06-09 15:35:55 -07:00
c , err := dynamicToWorkerCredential ( ctx , cred )
2021-12-17 11:26:42 -08:00
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
2021-06-30 18:02:03 -04:00
}
2022-06-09 15:35:55 -07:00
workerCreds = append ( workerCreds , c )
2021-12-17 11:26:42 -08:00
2022-07-19 15:16:24 -07:00
case credential . BrokeredPurpose :
2022-06-09 15:35:55 -07:00
c , err := dynamicToSessionCredential ( ctx , cred )
2021-12-17 11:26:42 -08:00
if err != nil {
2022-06-09 15:35:55 -07:00
return nil , errors . Wrap ( ctx , err , op )
2021-12-17 11:26:42 -08:00
}
2022-06-09 15:35:55 -07:00
creds = append ( creds , c )
2022-01-05 14:15:38 -08:00
2022-06-09 15:35:55 -07:00
default :
return nil , errors . New ( ctx , errors . Unknown , op , fmt . Sprintf ( "unsupported credential purpose %s" , cred . Purpose ()))
}
}
2022-01-05 14:15:38 -08:00
2022-06-09 15:35:55 -07:00
for _ , sc := range staticCreds {
switch sc . CredentialPurpose {
2022-07-19 15:16:24 -07:00
case string ( credential . InjectedApplicationPurpose ):
2022-06-09 15:35:55 -07:00
c , err := staticToWorkerCredential ( ctx , staticCredsById [ sc . CredentialStaticId ])
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
2022-01-05 14:15:38 -08:00
}
2022-06-09 15:35:55 -07:00
workerCreds = append ( workerCreds , c )
2022-01-05 14:15:38 -08:00
2022-07-19 15:16:24 -07:00
case string ( credential . BrokeredPurpose ):
2022-06-09 15:35:55 -07:00
c , err := staticToSessionCredential ( ctx , staticCredsById [ sc . CredentialStaticId ])
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
creds = append ( creds , c )
2021-12-17 11:26:42 -08:00
default :
2022-06-09 15:35:55 -07:00
return nil , errors . New ( ctx , errors . Unknown , op , fmt . Sprintf ( "unsupported credential purpose %s" , sc . CredentialPurpose ))
2021-12-17 11:26:42 -08:00
}
}
if len ( workerCreds ) > 0 {
// store credentials in repo, worker will request creds when a connection is established
2023-04-23 22:15:20 -07:00
// These credentials are deleted with the session, so nothing extra to cleanup in case of errors.
2022-07-20 16:24:46 -07:00
err = sessionRepo . AddSessionCredentials ( ctx , sess . ProjectId , sess . PublicId , workerCreds )
2021-12-17 11:26:42 -08:00
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
2021-06-30 18:02:03 -04:00
}
2021-06-22 22:26:26 -04:00
}
2023-02-07 10:14:01 -08:00
// this is an edge case issue where the hostId cannot be empty when trying to execute an ssh connection
// on a tcp target type. By setting the hostId to the targetId value, this will enable support of previous
// boundary cli versions.
if fm . SupportsFeature ( fm . Binary , fm . UseTargetIdForHostId ) && t . GetAddress () != "" {
hostId = t . GetPublicId ()
}
2025-01-08 15:18:03 +00:00
workerInfos := make ([] * pb . WorkerInfo , 0 , len ( selectedWorkers ))
for _ , sw := range selectedWorkers {
workerInfos = append ( workerInfos , & pb . WorkerInfo { Address : sw . Address })
}
2020-09-19 00:18:17 -04:00
sad := & pb . SessionAuthorizationData {
2023-04-21 06:50:53 -04:00
SessionId : sess . PublicId ,
TargetId : t . GetPublicId (),
Scope : authResults . Scope ,
CreatedTime : sess . CreateTime . GetTimestamp (),
2023-10-22 17:48:54 -07:00
Expiration : sess . ExpirationTime . GetTimestamp (),
EndpointPort : t . GetDefaultPort (),
2023-04-21 06:50:53 -04:00
Type : t . GetType (). String (),
Certificate : sess . Certificate ,
PrivateKey : sess . CertificatePrivateKey ,
HostId : hostId ,
Endpoint : endpointUrl . String (),
2025-01-08 15:18:03 +00:00
WorkerInfo : workerInfos ,
2023-04-21 06:50:53 -04:00
ConnectionLimit : t . GetSessionConnectionLimit (),
DefaultClientPort : t . GetDefaultClientPort (),
2020-09-19 00:18:17 -04:00
}
marshaledSad , err := proto . Marshal ( sad )
if err != nil {
return nil , err
}
2020-09-26 14:01:49 -04:00
encodedMarshaledSad := base58 . FastBase58Encoding ( marshaledSad )
2020-09-19 00:18:17 -04:00
ret := & pb . SessionAuthorization {
SessionId : sess . PublicId ,
TargetId : t . GetPublicId (),
Scope : authResults . Scope ,
CreatedTime : sess . CreateTime . GetTimestamp (),
2023-10-22 17:48:54 -07:00
Expiration : sess . ExpirationTime . GetTimestamp (),
EndpointPort : t . GetDefaultPort (),
2021-09-29 13:13:49 -04:00
Type : t . GetType (). String (),
2022-06-09 15:35:55 -07:00
AuthorizationToken : encodedMarshaledSad ,
2020-09-24 14:12:34 -04:00
UserId : authResults . UserId ,
2022-12-06 12:33:28 -08:00
HostId : hostId ,
HostSetId : hostSetId ,
2020-12-09 14:45:53 -05:00
Endpoint : endpointUrl . String (),
2021-06-22 22:26:26 -04:00
Credentials : creds ,
2024-12-30 14:16:39 -05:00
ConnectionLimit : t . GetSessionConnectionLimit (),
2020-09-19 00:18:17 -04:00
}
2023-04-23 22:16:08 -07:00
2024-04-03 17:54:37 -07:00
ret . SessionRecordingId , err = SessionRecordingFn (
2023-04-23 22:16:08 -07:00
ctx ,
s . controllerExt ,
2023-05-02 13:55:54 -07:00
s . kmsCache ,
2023-04-23 22:16:08 -07:00
t ,
sess ,
2025-01-08 15:18:03 +00:00
protoWorkerId ,
2024-04-03 17:54:37 -07:00
)
if err != nil {
2023-04-23 22:16:08 -07:00
// Errors here will automatically delete the session and associated resources
// using deferred statements above.
return nil , errors . Wrap ( ctx , err , op )
}
2020-09-19 00:18:17 -04:00
return & pbs . AuthorizeSessionResponse { Item : ret }, nil
}
2021-07-30 08:48:03 -04:00
func ( s Service ) getFromRepo ( ctx context . Context , id string ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2020-09-01 15:05:46 -07:00
repo , err := s . repoFn ()
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
u , err := repo . LookupTarget ( ctx , id )
2020-09-01 15:05:46 -07:00
if err != nil {
2020-12-21 10:07:34 -08:00
if errors . IsNotFoundError ( err ) {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . NotFoundErrorf ( "Target %q doesn't exist." , id )
2020-09-01 15:05:46 -07:00
}
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
hs := u . GetHostSources ()
cl := u . GetCredentialSources ()
2020-09-01 15:05:46 -07:00
if u == nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . NotFoundErrorf ( "Target %q doesn't exist." , id )
2020-09-01 15:05:46 -07:00
}
2021-06-22 22:26:26 -04:00
return u , hs , cl , nil
2020-09-01 15:05:46 -07:00
}
2024-02-13 09:17:41 -08:00
// resolveAlias returns the alias resource with the specified public id.
func ( s Service ) resolveAlias ( ctx context . Context , id string ) ( * talias . Alias , error ) {
2024-02-01 08:58:56 -08:00
const op = "targets.(Service).resolveAlias"
2024-02-13 09:17:41 -08:00
if id == "" {
return nil , errors . New ( ctx , errors . InvalidParameter , op , "alias id is empty" )
2024-02-01 08:58:56 -08:00
}
r , err := s . aliasRepoFn ()
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
2024-02-13 09:17:41 -08:00
a , err := r . LookupAlias ( ctx , id )
2024-02-01 08:58:56 -08:00
if err != nil {
return nil , errors . Wrap ( ctx , err , op )
}
if a == nil {
2024-02-13 09:17:41 -08:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . NotFound , "alias with id %q not found" , id )
2024-02-01 08:58:56 -08:00
}
return a , nil
}
2021-07-30 08:48:03 -04:00
func ( s Service ) createInRepo ( ctx context . Context , item * pb . Target ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2021-04-16 12:06:03 -05:00
const op = "targets.(Service).createInRepo"
2020-09-01 15:05:46 -07:00
opts := [] target . Option { target . WithName ( item . GetName (). GetValue ())}
if item . GetDescription () != nil {
opts = append ( opts , target . WithDescription ( item . GetDescription (). GetValue ()))
}
2020-09-19 11:32:38 -04:00
if item . GetSessionMaxSeconds () != nil {
opts = append ( opts , target . WithSessionMaxSeconds ( item . GetSessionMaxSeconds (). GetValue ()))
2020-09-19 10:31:49 -04:00
}
if item . GetSessionConnectionLimit () != nil {
opts = append ( opts , target . WithSessionConnectionLimit ( item . GetSessionConnectionLimit (). GetValue ()))
}
2022-11-30 15:23:37 -05:00
if item . GetEgressWorkerFilter () != nil {
opts = append ( opts , target . WithEgressWorkerFilter ( item . GetEgressWorkerFilter (). GetValue ()))
}
if item . GetIngressWorkerFilter () != nil {
opts = append ( opts , target . WithIngressWorkerFilter ( item . GetIngressWorkerFilter (). GetValue ()))
2021-01-21 16:27:20 -05:00
}
2022-12-06 12:33:28 -08:00
if item . GetAddress () != nil {
2023-02-02 18:51:39 +00:00
opts = append ( opts , target . WithAddress ( strings . TrimSpace ( item . GetAddress (). GetValue ())))
2022-12-06 12:33:28 -08:00
}
2021-11-04 11:44:22 -04:00
2022-04-13 16:27:48 -04:00
attr , err := subtypeRegistry . newAttribute ( target . SubtypeFromType ( item . GetType ()), item . GetAttrs ())
2021-11-04 11:44:22 -04:00
if err != nil {
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . InvalidArgument , err . Error ())
2020-09-01 15:05:46 -07:00
}
2021-11-04 11:44:22 -04:00
opts = append ( opts , attr . Options () ... )
u , err := target . New ( ctx , target . SubtypeFromType ( item . GetType ()), item . GetScopeId (), opts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to build target for creation: %v." , err )
2020-09-01 15:05:46 -07:00
}
repo , err := s . repoFn ()
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2024-03-12 13:57:47 -07:00
createOptions := [] target . Option {}
if len ( item . GetWithAliases ()) > 0 {
writeAliases := make ([] * talias . Alias , 0 , len ( item . GetWithAliases ()))
for _ , a := range item . GetWithAliases () {
na , err := talias . NewAlias ( ctx , a . GetScopeId (), a . GetValue (), talias . WithHostId ( a . GetAttributes (). GetAuthorizeSessionArguments (). GetHostId ()))
if err != nil {
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "converting from proto to storage alias" ))
}
writeAliases = append ( writeAliases , na )
}
createOptions = append ( createOptions , target . WithAliases ( writeAliases ))
}
out , err := repo . CreateTarget ( ctx , u , createOptions ... )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to create target" ))
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
cl := out . GetCredentialSources ()
2020-09-01 15:05:46 -07:00
if out == nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to create target but no error returned from repository." )
2020-09-01 15:05:46 -07:00
}
2021-06-22 22:26:26 -04:00
return out , hs , cl , nil
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
func ( s Service ) updateInRepo ( ctx context . Context , scopeId , id string , mask [] string , item * pb . Target ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2021-04-16 12:06:03 -05:00
const op = "targets.(Service).updateInRepo"
2022-12-06 12:33:28 -08:00
var dbMask [] string
2020-09-01 15:05:46 -07:00
var opts [] target . Option
if desc := item . GetDescription (); desc != nil {
opts = append ( opts , target . WithDescription ( desc . GetValue ()))
}
if name := item . GetName (); name != nil {
opts = append ( opts , target . WithName ( name . GetValue ()))
}
2020-09-19 11:32:38 -04:00
if item . GetSessionMaxSeconds () != nil {
opts = append ( opts , target . WithSessionMaxSeconds ( item . GetSessionMaxSeconds (). GetValue ()))
2020-09-19 10:31:49 -04:00
}
if item . GetSessionConnectionLimit () != nil {
opts = append ( opts , target . WithSessionConnectionLimit ( item . GetSessionConnectionLimit (). GetValue ()))
}
2022-11-30 15:23:37 -05:00
// worker_filter is deprecated, but we allow users who have migrated with a worker_filter value to update it.
if workerFilter := item . GetWorkerFilter (); workerFilter != nil {
2021-01-21 16:27:20 -05:00
opts = append ( opts , target . WithWorkerFilter ( item . GetWorkerFilter (). GetValue ()))
}
2022-11-30 15:23:37 -05:00
if egressFilter := item . GetEgressWorkerFilter (); egressFilter != nil {
opts = append ( opts , target . WithEgressWorkerFilter ( item . GetEgressWorkerFilter (). GetValue ()))
}
if ingressFilter := item . GetIngressWorkerFilter (); ingressFilter != nil {
opts = append ( opts , target . WithIngressWorkerFilter ( item . GetIngressWorkerFilter (). GetValue ()))
}
2022-12-06 12:33:28 -08:00
if item . GetAddress () != nil {
dbMask = append ( dbMask , "Address" )
2023-02-02 18:51:39 +00:00
opts = append ( opts , target . WithAddress ( strings . TrimSpace ( item . GetAddress (). GetValue ())))
2022-12-06 12:33:28 -08:00
}
2021-11-04 11:44:22 -04:00
subtype := target . SubtypeFromId ( id )
2022-04-13 16:27:48 -04:00
attr , err := subtypeRegistry . newAttribute ( subtype , item . GetAttrs ())
2021-11-04 11:44:22 -04:00
if err != nil {
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . InvalidArgument , err . Error ())
2020-09-15 02:15:33 -04:00
}
2021-11-04 11:44:22 -04:00
opts = append ( opts , attr . Options () ... )
2020-09-01 15:05:46 -07:00
version := item . GetVersion ()
2021-11-04 11:44:22 -04:00
u , err := target . New ( ctx , subtype , scopeId , opts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to build target for update: %v." , err )
2020-09-01 15:05:46 -07:00
}
2022-06-09 15:35:55 -07:00
if err := u . SetPublicId ( ctx , id ); err != nil {
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to set target id: %v." , err )
}
2021-11-04 11:44:22 -04:00
maskManager , err := subtypeRegistry . maskManager ( subtype )
if err != nil {
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to update target" ))
}
2022-12-06 12:33:28 -08:00
dbMask = append ( dbMask , maskManager . Translate ( mask ) ... )
2020-09-01 15:05:46 -07:00
if len ( dbMask ) == 0 {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . InvalidArgumentErrorf ( "No valid fields included in the update mask." , map [ string ] string { "update_mask" : "No valid paths provided in the update mask." })
2020-09-01 15:05:46 -07:00
}
repo , err := s . repoFn ()
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
out , rowsUpdated , err := repo . UpdateTarget ( ctx , u , version , dbMask , opts ... )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to update target" ))
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
cl := out . GetCredentialSources ()
2020-09-01 15:05:46 -07:00
if rowsUpdated == 0 {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , handlers . NotFoundErrorf ( "Target %q not found or incorrect version provided." , id )
2020-09-01 15:05:46 -07:00
}
2021-06-22 22:26:26 -04:00
return out , hs , cl , nil
2020-09-01 15:05:46 -07:00
}
func ( s Service ) deleteFromRepo ( ctx context . Context , id string ) ( bool , error ) {
2021-04-16 12:06:03 -05:00
const op = "targets.(Service).deleteFromRepo"
2020-09-01 15:05:46 -07:00
repo , err := s . repoFn ()
if err != nil {
return false , err
}
rows , err := repo . DeleteTarget ( ctx , id )
if err != nil {
2020-12-21 10:07:34 -08:00
if errors . IsNotFoundError ( err ) {
2020-09-01 15:05:46 -07:00
return false , nil
}
2021-07-29 18:52:56 -06:00
return false , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to delete target" ))
2020-09-01 15:05:46 -07:00
}
return rows > 0 , nil
}
2023-03-30 15:19:30 -04:00
func ( s Service ) addHostSourcesInRepo ( ctx context . Context , targetId string , hostSourceIds [] string , version uint32 ) ( target . Target , error ) {
2020-09-01 15:05:46 -07:00
repo , err := s . repoFn ()
if err != nil {
2023-03-30 15:19:30 -04:00
return nil , err
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . AddTargetHostSources ( ctx , targetId , version , strutil . RemoveDuplicates ( hostSourceIds , false ))
2020-09-01 15:05:46 -07:00
if err != nil {
2022-12-06 12:33:28 -08:00
var internalErr * errors . Err
if stderrors . As ( err , & internalErr ) && internalErr . Code == errors . Conflict {
// The conflict error is surfaced directly as it's correctly
// converted all the way down to the HTTP status.
2023-03-30 15:19:30 -04:00
return nil , err
2022-12-06 12:33:28 -08:00
}
2020-09-25 13:41:20 -07:00
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2023-03-30 15:19:30 -04:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Failed to add target host sources" )
2020-09-01 15:05:46 -07:00
}
if out == nil {
2023-03-30 15:19:30 -04:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after adding host sources to it." )
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
return out , nil
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
func ( s Service ) setHostSourcesInRepo ( ctx context . Context , targetId string , hostSourceIds [] string , version uint32 ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
const op = "targets.(Service).setSourcesInRepo"
2020-09-01 15:05:46 -07:00
repo , err := s . repoFn ()
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
_ , _ , _ , err = repo . SetTargetHostSources ( ctx , targetId , version , strutil . RemoveDuplicates ( hostSourceIds , false ))
2020-09-01 15:05:46 -07:00
if err != nil {
2022-12-06 12:33:28 -08:00
var internalErr * errors . Err
if stderrors . As ( err , & internalErr ) && internalErr . Code == errors . Conflict {
// The conflict error is surfaced directly as it's correctly
// converted all the way down to the HTTP status.
return nil , nil , nil , err
}
2020-09-25 13:41:20 -07:00
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2022-12-06 12:33:28 -08:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Failed to set target host sources" )
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . LookupTarget ( ctx , targetId )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-07-30 08:48:03 -04:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to look up target after setting host sources" ))
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
cl := out . GetCredentialSources ()
2020-09-01 15:05:46 -07:00
if out == nil {
2021-07-30 08:48:03 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after setting host sources for it." )
2020-09-01 15:05:46 -07:00
}
2021-06-22 22:26:26 -04:00
return out , hs , cl , nil
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
func ( s Service ) removeHostSourcesInRepo ( ctx context . Context , targetId string , hostSourceIds [] string , version uint32 ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
const op = "targets.(Service).removeHostSourcesInRepo"
2020-09-01 15:05:46 -07:00
repo , err := s . repoFn ()
if err != nil {
2021-06-22 22:26:26 -04:00
return nil , nil , nil , err
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
_ , err = repo . DeleteTargetHostSources ( ctx , targetId , version , strutil . RemoveDuplicates ( hostSourceIds , false ))
2020-09-01 15:05:46 -07:00
if err != nil {
2020-09-25 13:41:20 -07:00
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2021-07-30 08:48:03 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to remove host sources from target: %v." , err )
2021-06-22 22:26:26 -04:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . LookupTarget ( ctx , targetId )
2021-06-22 22:26:26 -04:00
if err != nil {
2021-07-30 08:48:03 -04:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to look up target after removing host sources" ))
2021-06-22 22:26:26 -04:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
cl := out . GetCredentialSources ()
2021-06-22 22:26:26 -04:00
if out == nil {
2021-07-30 08:48:03 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after removing host sources from it." )
2021-06-22 22:26:26 -04:00
}
return out , hs , cl , nil
}
2022-07-19 15:16:24 -07:00
func ( s Service ) addCredentialSourcesInRepo ( ctx context . Context , targetId string , brokeredIds [] string , injectedAppIds [] string , version uint32 ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2021-06-22 22:26:26 -04:00
repo , err := s . repoFn ()
if err != nil {
return nil , nil , nil , err
}
2022-06-08 13:51:56 -07:00
var creds target . CredentialSources
2022-07-19 15:16:24 -07:00
if len ( brokeredIds ) > 0 {
creds . BrokeredCredentialIds = strutil . RemoveDuplicates ( brokeredIds , false )
2022-06-08 13:51:56 -07:00
}
2022-07-19 15:16:24 -07:00
if len ( injectedAppIds ) > 0 {
creds . InjectedApplicationCredentialIds = strutil . RemoveDuplicates ( injectedAppIds , false )
2021-10-26 09:57:22 -04:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . AddTargetCredentialSources ( ctx , targetId , version , creds )
2021-06-22 22:26:26 -04:00
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to add credential sources to target: %v." , err )
2021-06-22 22:26:26 -04:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
credSources := out . GetCredentialSources ()
2021-06-22 22:26:26 -04:00
if out == nil {
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after adding credential sources to it." )
2021-06-22 22:26:26 -04:00
}
2021-07-27 12:48:36 -04:00
return out , hs , credSources , nil
2021-06-22 22:26:26 -04:00
}
2022-07-19 15:16:24 -07:00
func ( s Service ) setCredentialSourcesInRepo ( ctx context . Context , targetId string , brokeredIds [] string , injectedAppIds [] string , version uint32 ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2021-07-27 12:48:36 -04:00
const op = "targets.(Service).setCredentialSourcesInRepo"
2021-06-22 22:26:26 -04:00
repo , err := s . repoFn ()
if err != nil {
return nil , nil , nil , err
}
2021-10-26 09:57:22 -04:00
2022-06-08 13:51:56 -07:00
var ids target . CredentialSources
2022-07-19 15:16:24 -07:00
if len ( brokeredIds ) > 0 {
ids . BrokeredCredentialIds = strutil . RemoveDuplicates ( brokeredIds , false )
2022-06-08 13:51:56 -07:00
}
2022-07-19 15:16:24 -07:00
if len ( injectedAppIds ) > 0 {
ids . InjectedApplicationCredentialIds = strutil . RemoveDuplicates ( injectedAppIds , false )
2021-10-26 09:57:22 -04:00
}
2022-06-08 13:51:56 -07:00
_ , _ , _ , err = repo . SetTargetCredentialSources ( ctx , targetId , version , ids )
2021-06-22 22:26:26 -04:00
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to set credential sources in target: %v." , err )
2021-06-22 22:26:26 -04:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . LookupTarget ( ctx , targetId )
2021-06-22 22:26:26 -04:00
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to look up target after setting credential sources" ))
2021-06-22 22:26:26 -04:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
credSources := out . GetCredentialSources ()
2021-06-22 22:26:26 -04:00
if out == nil {
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after setting credential sources for it." )
2021-06-22 22:26:26 -04:00
}
2021-07-27 12:48:36 -04:00
return out , hs , credSources , nil
2021-06-22 22:26:26 -04:00
}
2022-07-19 15:16:24 -07:00
func ( s Service ) removeCredentialSourcesInRepo ( ctx context . Context , targetId string , brokeredIds [] string , injectedAppIds [] string , version uint32 ) ( target . Target , [] target . HostSource , [] target . CredentialSource , error ) {
2021-07-27 12:48:36 -04:00
const op = "targets.(Service).removeCredentialSourcesInRepo"
2021-06-22 22:26:26 -04:00
repo , err := s . repoFn ()
if err != nil {
return nil , nil , nil , err
}
2021-10-26 09:57:22 -04:00
2022-06-08 13:51:56 -07:00
var ids target . CredentialSources
2022-07-19 15:16:24 -07:00
if len ( brokeredIds ) > 0 {
ids . BrokeredCredentialIds = strutil . RemoveDuplicates ( brokeredIds , false )
2022-06-08 13:51:56 -07:00
}
2022-07-19 15:16:24 -07:00
if len ( injectedAppIds ) > 0 {
ids . InjectedApplicationCredentialIds = strutil . RemoveDuplicates ( injectedAppIds , false )
2021-10-26 09:57:22 -04:00
}
2022-06-08 13:51:56 -07:00
_ , err = repo . DeleteTargetCredentialSources ( ctx , targetId , version , ids )
2021-06-22 22:26:26 -04:00
if err != nil {
// TODO: Figure out a way to surface more helpful error info beyond the Internal error.
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to remove credential sources from target: %v." , err )
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
out , err := repo . LookupTarget ( ctx , targetId )
2020-09-01 15:05:46 -07:00
if err != nil {
2021-07-29 18:52:56 -06:00
return nil , nil , nil , errors . Wrap ( ctx , err , op , errors . WithMsg ( "unable to look up target after removing credential sources" ))
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
hs := out . GetHostSources ()
credSources := out . GetCredentialSources ()
2020-09-01 15:05:46 -07:00
if out == nil {
2021-07-27 12:48:36 -04:00
return nil , nil , nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to lookup target after removing credential sources from it." )
2020-09-01 15:05:46 -07:00
}
2021-07-27 12:48:36 -04:00
return out , hs , credSources , nil
2020-09-01 15:05:46 -07:00
}
2024-03-12 13:57:47 -07:00
// aliasCreateAuthResult verifies authorization for creating an alias
func ( s Service ) aliasCreateAuthResult ( ctx context . Context , parentId string ) auth . VerifyResults {
res := auth . VerifyResults {}
a := action . Create
opts := [] auth . Option { auth . WithType ( resource . Alias ), auth . WithAction ( a )}
iamRepo , err := s . iamRepoFn ()
if err != nil {
res . Error = err
return res
}
scp , err := iamRepo . LookupScope ( ctx , parentId )
if err != nil {
res . Error = err
return res
}
if scp == nil {
res . Error = handlers . NotFoundError ()
return res
}
opts = append ( opts , auth . WithScopeId ( parentId ))
ret := auth . Verify ( ctx , opts ... )
return ret
}
2020-10-22 08:40:00 -04:00
func ( s Service ) authResult ( ctx context . Context , id string , a action . Type , lookupOpt ... target . Option ) auth . VerifyResults {
2020-09-04 14:48:11 -07:00
res := auth . VerifyResults {}
2020-09-01 15:05:46 -07:00
2020-09-04 14:48:11 -07:00
var parentId string
2020-10-22 08:40:00 -04:00
var t target . Target
2020-09-04 14:48:11 -07:00
opts := [] auth . Option { auth . WithType ( resource . Target ), auth . WithAction ( a )}
switch a {
case action . List , action . Create :
parentId = id
iamRepo , err := s . iamRepoFn ()
if err != nil {
res . Error = err
return res
}
scp , err := iamRepo . LookupScope ( ctx , parentId )
if err != nil {
res . Error = err
return res
}
if scp == nil {
2020-09-08 23:57:26 -04:00
res . Error = handlers . NotFoundError ()
2020-09-04 14:48:11 -07:00
return res
}
default :
repo , err := s . repoFn ()
if err != nil {
res . Error = err
return res
}
2023-03-30 15:19:30 -04:00
t , err = repo . LookupTarget ( ctx , id , lookupOpt ... )
2020-09-04 14:48:11 -07:00
if err != nil {
2020-10-22 08:40:00 -04:00
// TODO: Fix this with new/better error handling
if strings . Contains ( err . Error (), "more than one row returned by a subquery" ) {
res . Error = handlers . ApiErrorWithCodeAndMessage ( codes . FailedPrecondition , "Scope name is ambiguous (matches more than one scope), use scope ID with target name instead, or use target ID." )
} else {
res . Error = err
}
2020-09-04 14:48:11 -07:00
return res
}
if t == nil {
2020-09-08 23:57:26 -04:00
res . Error = handlers . NotFoundError ()
2020-09-04 14:48:11 -07:00
return res
}
2020-10-22 08:40:00 -04:00
id = t . GetPublicId ()
2022-07-20 16:24:46 -07:00
parentId = t . GetProjectId ()
2020-09-04 14:48:11 -07:00
opts = append ( opts , auth . WithId ( id ))
2020-09-01 15:05:46 -07:00
}
2020-09-04 14:48:11 -07:00
opts = append ( opts , auth . WithScopeId ( parentId ))
2020-10-22 08:40:00 -04:00
ret := auth . Verify ( ctx , opts ... )
ret . RoundTripValue = t
return ret
2020-09-01 15:05:46 -07:00
}
2023-03-30 15:19:30 -04:00
func toProto ( ctx context . Context , in target . Target , opt ... handlers . Option ) ( * pb . Target , error ) {
2021-06-25 14:06:31 -04:00
const op = "target_service.toProto"
2021-05-04 19:57:35 -05:00
opts := handlers . GetOpts ( opt ... )
if opts . WithOutputFields == nil {
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "output fields not found when building target proto" )
}
outputFields := * opts . WithOutputFields
2023-03-30 15:19:30 -04:00
hostSources := in . GetHostSources ()
credSources := in . GetCredentialSources ()
2024-02-01 14:36:58 -05:00
aliases := in . GetAliases ()
2021-05-04 19:57:35 -05:00
out := pb . Target {}
if outputFields . Has ( globals . IdField ) {
out . Id = in . GetPublicId ()
}
if outputFields . Has ( globals . ScopeIdField ) {
2022-07-20 16:24:46 -07:00
out . ScopeId = in . GetProjectId ()
2021-05-04 19:57:35 -05:00
}
if outputFields . Has ( globals . TypeField ) {
2021-10-20 08:35:33 -04:00
out . Type = in . GetType (). String ()
2021-05-04 19:57:35 -05:00
}
if outputFields . Has ( globals . DescriptionField ) && in . GetDescription () != "" {
2020-09-01 15:05:46 -07:00
out . Description = wrapperspb . String ( in . GetDescription ())
}
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . NameField ) && in . GetName () != "" {
2020-09-01 15:05:46 -07:00
out . Name = wrapperspb . String ( in . GetName ())
}
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . CreatedTimeField ) {
out . CreatedTime = in . GetCreateTime (). GetTimestamp ()
}
if outputFields . Has ( globals . UpdatedTimeField ) {
out . UpdatedTime = in . GetUpdateTime (). GetTimestamp ()
}
if outputFields . Has ( globals . VersionField ) {
out . Version = in . GetVersion ()
}
if outputFields . Has ( globals . SessionMaxSecondsField ) {
out . SessionMaxSeconds = wrapperspb . UInt32 ( in . GetSessionMaxSeconds ())
}
if outputFields . Has ( globals . SessionConnectionLimitField ) {
out . SessionConnectionLimit = wrapperspb . Int32 ( in . GetSessionConnectionLimit ())
}
if outputFields . Has ( globals . WorkerFilterField ) && in . GetWorkerFilter () != "" {
2021-01-21 16:27:20 -05:00
out . WorkerFilter = wrapperspb . String ( in . GetWorkerFilter ())
}
2022-11-30 15:23:37 -05:00
if outputFields . Has ( globals . EgressWorkerFilterField ) && in . GetEgressWorkerFilter () != "" {
out . EgressWorkerFilter = wrapperspb . String ( in . GetEgressWorkerFilter ())
}
if outputFields . Has ( globals . IngressWorkerFilterField ) && in . GetIngressWorkerFilter () != "" {
out . IngressWorkerFilter = wrapperspb . String ( in . GetIngressWorkerFilter ())
}
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . ScopeField ) {
out . Scope = opts . WithScope
2020-09-15 15:20:49 -04:00
}
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . AuthorizedActionsField ) {
out . AuthorizedActions = opts . WithAuthorizedActions
}
2021-07-30 08:48:03 -04:00
if outputFields . Has ( globals . HostSourceIdsField ) {
for _ , hs := range hostSources {
out . HostSourceIds = append ( out . HostSourceIds , hs . Id ())
2021-05-04 19:57:35 -05:00
}
2020-09-01 15:05:46 -07:00
}
2021-07-30 08:48:03 -04:00
if outputFields . Has ( globals . HostSourcesField ) {
for _ , hs := range hostSources {
out . HostSources = append ( out . HostSources , & pb . HostSource {
Id : hs . Id (),
HostCatalogId : hs . HostCatalogId (),
2021-05-04 19:57:35 -05:00
})
}
}
2024-02-01 14:36:58 -05:00
if outputFields . Has ( globals . AliasesField ) {
for _ , a := range aliases {
2024-03-12 13:57:47 -07:00
// Even though pb.Alias has more than just these 2 fields, we only
// want to return these 2 fields to the client. Any more information
// may be sharing more than the client should know.
2024-02-01 14:36:58 -05:00
out . Aliases = append ( out . Aliases , & pb . Alias {
Id : a . PublicId ,
Value : a . Value ,
})
}
}
2022-12-06 12:33:28 -08:00
if outputFields . Has ( globals . AddressField ) {
out . Address = wrapperspb . String ( in . GetAddress ())
}
2022-06-10 12:26:19 -07:00
2022-07-19 15:16:24 -07:00
var brokeredSources , injectedAppSources [] * pb . CredentialSource
var brokeredSourceIds , injectedAppSourceIds [] string
2022-06-10 12:26:19 -07:00
for _ , cs := range credSources {
switch cs . CredentialPurpose () {
2022-07-19 15:16:24 -07:00
case credential . BrokeredPurpose :
brokeredSourceIds = append ( brokeredSourceIds , cs . Id ())
brokeredSources = append ( brokeredSources , & pb . CredentialSource {
2022-06-10 12:26:19 -07:00
Id : cs . Id (),
CredentialStoreId : cs . CredentialStoreId (),
})
2022-07-19 15:16:24 -07:00
case credential . InjectedApplicationPurpose :
injectedAppSources = append ( injectedAppSources , & pb . CredentialSource {
2022-06-10 12:26:19 -07:00
Id : cs . Id (),
CredentialStoreId : cs . CredentialStoreId (),
})
2022-07-19 15:16:24 -07:00
injectedAppSourceIds = append ( injectedAppSourceIds , cs . Id ())
2022-06-10 12:26:19 -07:00
default :
return nil , errors . New ( ctx , errors . Internal , op , fmt . Sprintf ( "unrecognized purpose %q for credential source on target" , cs . CredentialPurpose ()))
2021-07-27 12:48:36 -04:00
}
}
2022-06-10 12:26:19 -07:00
2022-07-19 15:16:24 -07:00
if outputFields . Has ( globals . BrokeredCredentialSourceIdsField ) {
out . BrokeredCredentialSourceIds = brokeredSourceIds
2022-06-10 12:26:19 -07:00
}
2022-07-19 15:16:24 -07:00
if outputFields . Has ( globals . BrokeredCredentialSourcesField ) {
out . BrokeredCredentialSources = brokeredSources
2022-06-10 12:26:19 -07:00
}
2022-07-19 15:16:24 -07:00
if outputFields . Has ( globals . InjectedApplicationCredentialSourceIdsField ) {
out . InjectedApplicationCredentialSourceIds = injectedAppSourceIds
}
if outputFields . Has ( globals . InjectedApplicationCredentialSourcesField ) {
out . InjectedApplicationCredentialSources = injectedAppSources
2021-06-22 22:26:26 -04:00
}
2021-05-04 19:57:35 -05:00
if outputFields . Has ( globals . AttributesField ) {
2022-04-13 16:27:48 -04:00
if err := subtypeRegistry . setAttributes ( in . GetType (), in , & out ); err != nil {
2021-11-04 11:44:22 -04:00
return nil , errors . Wrap ( ctx , err , op )
2021-05-04 19:57:35 -05:00
}
2020-09-01 15:05:46 -07:00
}
2020-09-15 15:20:49 -04:00
return & out , nil
2020-09-01 15:05:46 -07:00
}
// A validateX method should exist for each method above. These methods do not make calls to any backing service but enforce
// requirements on the structure of the request. They verify that:
2022-08-25 09:12:24 -07:00
// - The path passed in is correctly formatted
// - All required parameters are set
// - There are no conflicting parameters provided
2020-09-01 15:05:46 -07:00
func validateGetRequest ( req * pbs . GetTargetRequest ) error {
2021-11-04 11:44:22 -04:00
return handlers . ValidateGetRequest ( handlers . NoopValidatorFn , req , target . Prefixes () ... )
2020-09-01 15:05:46 -07:00
}
func validateCreateRequest ( req * pbs . CreateTargetRequest ) error {
2024-02-14 17:14:31 -05:00
item := req . GetItem ()
return handlers . ValidateCreateRequest ( item , func () map [ string ] string {
2020-09-01 15:05:46 -07:00
badFields := map [ string ] string {}
2024-02-14 17:14:31 -05:00
if ! handlers . ValidId ( handlers . Id ( item . GetScopeId ()), scope . Project . Prefix ()) {
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "This field is required to have a properly formatted project scope id."
2020-09-01 15:05:46 -07:00
}
2024-02-14 17:14:31 -05:00
if item . GetName () == nil || item . GetName (). GetValue () == "" {
2021-06-22 22:26:26 -04:00
badFields [ globals . NameField ] = "This field is required."
2020-09-01 15:05:46 -07:00
}
2024-03-12 13:57:47 -07:00
for _ , a := range item . GetWithAliases () {
pa := proto . Clone ( a ).( * pb . Alias )
pa . Value = ""
pa . ScopeId = ""
pa . Attributes = nil
if ! proto . Equal ( pa , & pb . Alias {}) {
badFields [ globals . WithAliasesField ] = "Included aliases can only specify a value, a scope id, and attributes."
}
}
2024-02-14 17:14:31 -05:00
if item . GetSessionConnectionLimit () != nil {
val := item . GetSessionConnectionLimit (). GetValue ()
2020-09-20 15:53:49 -04:00
switch {
case val == - 1 :
case val > 0 :
default :
2021-06-22 22:26:26 -04:00
badFields [ globals . SessionConnectionLimitField ] = "This must be -1 (unlimited) or greater than zero."
2020-09-20 15:53:49 -04:00
}
}
2024-02-14 17:14:31 -05:00
if item . GetSessionMaxSeconds () != nil && item . GetSessionMaxSeconds (). GetValue () == 0 {
2021-06-22 22:26:26 -04:00
badFields [ globals . SessionMaxSecondsField ] = "This must be greater than zero."
2020-09-20 15:53:49 -04:00
}
2024-02-14 17:14:31 -05:00
if item . GetType () == "" {
2021-06-22 22:26:26 -04:00
badFields [ globals . TypeField ] = "This is a required field."
2024-02-14 17:14:31 -05:00
} else if target . SubtypeFromType ( item . GetType ()) == "" {
2021-06-22 22:26:26 -04:00
badFields [ globals . TypeField ] = "Unknown type provided."
2020-09-01 15:05:46 -07:00
}
2024-02-14 17:14:31 -05:00
if workerFilter := item . GetWorkerFilter (); workerFilter != nil {
2023-02-16 14:56:18 -08:00
badFields [ globals . WorkerFilterField ] = WorkerFilterDeprecationMessage
2022-11-30 15:23:37 -05:00
}
2024-02-14 17:14:31 -05:00
if egressFilter := item . GetEgressWorkerFilter (); egressFilter != nil {
2022-11-30 15:23:37 -05:00
if _ , err := bexpr . CreateEvaluator ( egressFilter . GetValue ()); err != nil {
badFields [ globals . EgressWorkerFilterField ] = "Unable to successfully parse egress filter expression."
}
}
2024-02-14 17:14:31 -05:00
if ingressFilter := item . GetIngressWorkerFilter (); ingressFilter != nil {
2022-11-30 15:23:37 -05:00
err := ValidateIngressWorkerFilterFn ( ingressFilter . GetValue ())
if err != nil {
badFields [ globals . IngressWorkerFilterField ] = err . Error ()
2021-01-21 16:27:20 -05:00
}
}
2024-02-14 17:14:31 -05:00
if address := item . GetAddress (); address != nil {
2022-12-06 12:33:28 -08:00
if len ( address . GetValue ()) < static . MinHostAddressLength ||
len ( address . GetValue ()) > static . MaxHostAddressLength {
badFields [ globals . AddressField ] = fmt . Sprintf ( "Address length must be between %d and %d characters." , static . MinHostAddressLength , static . MaxHostAddressLength )
}
_ , _ , err := net . SplitHostPort ( address . GetValue ())
switch {
case err == nil :
badFields [ globals . AddressField ] = "Address does not support a port."
2023-01-26 10:35:29 -08:00
case strings . Contains ( err . Error (), globals . MissingPortErrStr ):
2022-12-06 12:33:28 -08:00
default :
badFields [ globals . AddressField ] = fmt . Sprintf ( "Error parsing address: %v." , err )
}
}
2024-02-14 17:14:31 -05:00
subtype := target . SubtypeFromType ( item . GetType ())
2021-11-04 11:44:22 -04:00
_ , err := subtypeRegistry . get ( subtype )
if err != nil {
badFields [ globals . TypeField ] = "Unknown type provided."
} else {
2024-02-14 17:14:31 -05:00
a , err := subtypeRegistry . newAttribute ( subtype , item . GetAttrs ())
2021-11-04 11:44:22 -04:00
if err != nil {
badFields [ globals . AttributesField ] = "Attribute fields do not match the expected format."
} else {
for k , v := range a . Vet () {
badFields [ k ] = v
}
}
}
2020-09-01 15:05:46 -07:00
return badFields
})
}
func validateUpdateRequest ( req * pbs . UpdateTargetRequest ) error {
2024-02-14 17:14:31 -05:00
item := req . GetItem ()
2021-04-08 20:54:32 -04:00
return handlers . ValidateUpdateRequest ( req , req . GetItem (), func () map [ string ] string {
2020-09-01 15:05:46 -07:00
badFields := map [ string ] string {}
2022-06-13 08:26:24 -07:00
paths := req . GetUpdateMask (). GetPaths ()
2024-02-14 17:14:31 -05:00
if handlers . MaskContains ( paths , globals . NameField ) && item . GetName (). GetValue () == "" {
2021-06-22 22:26:26 -04:00
badFields [ globals . NameField ] = "This field cannot be set to empty."
2020-09-01 15:05:46 -07:00
}
2024-02-14 17:14:31 -05:00
if item . GetSessionConnectionLimit () != nil {
val := item . GetSessionConnectionLimit (). GetValue ()
2020-09-20 15:53:49 -04:00
switch {
case val == - 1 :
case val > 0 :
default :
2021-06-22 22:26:26 -04:00
badFields [ globals . SessionConnectionLimitField ] = "This must be -1 (unlimited) or greater than zero."
2020-09-20 15:53:49 -04:00
}
}
2024-02-14 17:14:31 -05:00
if item . GetSessionMaxSeconds () != nil && item . GetSessionMaxSeconds (). GetValue () == 0 {
2021-06-22 22:26:26 -04:00
badFields [ globals . SessionMaxSecondsField ] = "This must be greater than zero."
2020-09-20 15:53:49 -04:00
}
2024-03-12 13:57:47 -07:00
if len ( item . GetWithAliases ()) > 0 {
badFields [ globals . WithAliasesField ] = "This field can only be set at target creation time."
}
2022-11-30 15:23:37 -05:00
// worker_filter is mutually exclusive from ingress and egress filter
workerFilterFound := false
2024-02-14 17:14:31 -05:00
if workerFilter := item . GetWorkerFilter (); workerFilter != nil {
2022-11-30 15:23:37 -05:00
if _ , err := bexpr . CreateEvaluator ( workerFilter . GetValue ()); err != nil {
2021-06-22 22:26:26 -04:00
badFields [ globals . WorkerFilterField ] = "Unable to successfully parse filter expression."
2021-01-21 16:27:20 -05:00
}
2022-11-30 15:23:37 -05:00
workerFilterFound = true
}
2024-02-14 17:14:31 -05:00
if egressFilter := item . GetEgressWorkerFilter (); egressFilter != nil {
2022-11-30 15:23:37 -05:00
if workerFilterFound {
2023-02-16 11:36:23 -08:00
badFields [ globals . EgressWorkerFilterField ] = fmt . Sprintf ( "Cannot set %s and %s; they are mutually exclusive fields." , globals . WorkerFilterField , globals . EgressWorkerFilterField )
2022-11-30 15:23:37 -05:00
}
if _ , err := bexpr . CreateEvaluator ( egressFilter . GetValue ()); err != nil {
badFields [ globals . EgressWorkerFilterField ] = "Unable to successfully parse egress filter expression."
}
}
2024-02-14 17:14:31 -05:00
if ingressFilter := item . GetIngressWorkerFilter (); ingressFilter != nil {
2022-11-30 15:23:37 -05:00
if workerFilterFound {
2023-02-16 11:36:23 -08:00
badFields [ globals . IngressWorkerFilterField ] = fmt . Sprintf ( "Cannot set %s and %s; they are mutually exclusive fields." , globals . WorkerFilterField , globals . IngressWorkerFilterField )
2022-11-30 15:23:37 -05:00
}
err := ValidateIngressWorkerFilterFn ( ingressFilter . GetValue ())
if err != nil {
badFields [ globals . IngressWorkerFilterField ] = err . Error ()
}
2021-01-21 16:27:20 -05:00
}
2024-02-14 17:14:31 -05:00
if address := item . GetAddress (); address != nil {
2022-12-06 12:33:28 -08:00
if len ( address . GetValue ()) < static . MinHostAddressLength ||
len ( address . GetValue ()) > static . MaxHostAddressLength {
badFields [ globals . AddressField ] = fmt . Sprintf ( "Address length must be between %d and %d characters." , static . MinHostAddressLength , static . MaxHostAddressLength )
}
_ , _ , err := net . SplitHostPort ( address . GetValue ())
switch {
case err == nil :
badFields [ globals . AddressField ] = "Address does not support a port."
2023-01-26 10:35:29 -08:00
case strings . Contains ( err . Error (), globals . MissingPortErrStr ):
2022-12-06 12:33:28 -08:00
default :
badFields [ globals . AddressField ] = fmt . Sprintf ( "Error parsing address: %v." , err )
}
}
2021-11-04 11:44:22 -04:00
subtype := target . SubtypeFromId ( req . GetId ())
_ , err := subtypeRegistry . get ( subtype )
if err != nil {
badFields [ globals . TypeField ] = "Unknown type provided."
} else {
2024-02-14 17:14:31 -05:00
if item . GetType () != "" && target . SubtypeFromType ( item . GetType ()) != subtype {
2021-11-04 11:44:22 -04:00
badFields [ globals . TypeField ] = "Cannot modify the resource type."
}
2024-02-14 17:14:31 -05:00
a , err := subtypeRegistry . newAttribute ( subtype , item . GetAttrs ())
2021-11-04 11:44:22 -04:00
if err != nil {
badFields [ globals . AttributesField ] = "Attribute fields do not match the expected format."
} else {
2022-06-13 08:26:24 -07:00
for k , v := range a . VetForUpdate ( paths ) {
2021-11-04 11:44:22 -04:00
badFields [ k ] = v
}
}
}
2020-09-01 15:05:46 -07:00
return badFields
2021-11-04 11:44:22 -04:00
}, target . Prefixes () ... )
2020-09-01 15:05:46 -07:00
}
func validateDeleteRequest ( req * pbs . DeleteTargetRequest ) error {
2021-11-04 11:44:22 -04:00
return handlers . ValidateDeleteRequest ( handlers . NoopValidatorFn , req , target . Prefixes () ... )
2020-09-01 15:05:46 -07:00
}
2023-06-06 17:09:08 -04:00
func validateListRequest ( ctx context . Context , req * pbs . ListTargetsRequest ) error {
2020-09-01 15:05:46 -07:00
badFields := map [ string ] string {}
2021-04-08 20:54:32 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetScopeId ()), scope . Project . Prefix ()) &&
2021-01-25 19:37:40 -05:00
! req . GetRecursive () {
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "This field must be a valid project scope ID or the list operation must be recursive."
2020-09-01 15:05:46 -07:00
}
2023-06-06 17:09:08 -04:00
if _ , err := handlers . NewFilter ( ctx , req . GetFilter ()); err != nil {
2021-02-22 10:09:25 -07:00
badFields [ "filter" ] = fmt . Sprintf ( "This field could not be parsed. %v" , err )
}
2020-09-01 15:05:46 -07:00
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Improperly formatted identifier." , badFields )
}
return nil
}
2023-10-24 09:41:11 -07:00
func newOutputOpts ( ctx context . Context , item target . Target , authResults auth . VerifyResults , authzScopes map [ string ] * scopes . ScopeInfo ) [] handlers . Option {
2024-09-17 10:07:43 -04:00
pr := perms . Resource { Id : item . GetPublicId (), ScopeId : item . GetProjectId (), Type : resource . Target , ParentScopeId : authzScopes [ item . GetProjectId ()]. GetParentScopeId ()}
2023-10-24 09:41:11 -07:00
outputFields := authResults . FetchOutputFields ( pr , action . List ). SelfOrDefaults ( authResults . UserId )
outputOpts := make ([] handlers . Option , 0 , 3 )
outputOpts = append ( outputOpts , handlers . WithOutputFields ( outputFields ))
if outputFields . Has ( globals . ScopeField ) {
outputOpts = append ( outputOpts , handlers . WithScope ( authzScopes [ item . GetProjectId ()]))
}
2025-01-24 10:23:33 -08:00
pr . ParentScopeId = authzScopes [ item . GetProjectId ()]. GetParentScopeId ()
2023-10-24 09:41:11 -07:00
if outputFields . Has ( globals . AuthorizedActionsField ) {
authorizedActions := authResults . FetchActionSetForId ( ctx , item . GetPublicId (), IdActions , auth . WithResource ( & pr )). Strings ()
outputOpts = append ( outputOpts , handlers . WithAuthorizedActions ( authorizedActions ))
}
return outputOpts
}
2021-07-30 08:48:03 -04:00
func validateAddHostSourcesRequest ( req * pbs . AddTargetHostSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
if len ( req . GetHostSourceIds ()) == 0 {
badFields [ globals . HostSourceIdsField ] = "Must be non-empty."
}
for _ , id := range req . GetHostSourceIds () {
2023-03-10 15:06:39 -05:00
if ! handlers . ValidId ( handlers . Id ( id ), globals . StaticHostSetPrefix , globals . PluginHostSetPrefix , globals . PluginHostSetPreviousPrefix ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . HostSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted host source identifier %q." , id )
break
}
}
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
func validateSetHostSourcesRequest ( req * pbs . SetTargetHostSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
for _ , id := range req . GetHostSourceIds () {
2023-03-10 15:06:39 -05:00
if ! handlers . ValidId ( handlers . Id ( id ), globals . StaticHostSetPrefix , globals . PluginHostSetPrefix , globals . PluginHostSetPreviousPrefix ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . HostSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted host source identifier %q." , id )
break
}
}
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
func validateRemoveHostSourcesRequest ( req * pbs . RemoveTargetHostSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
if len ( req . GetHostSourceIds ()) == 0 {
badFields [ globals . HostSourceIdsField ] = "Must be non-empty."
}
for _ , id := range req . GetHostSourceIds () {
2023-03-10 15:06:39 -05:00
if ! handlers . ValidId ( handlers . Id ( id ), globals . StaticHostSetPrefix , globals . PluginHostSetPrefix , globals . PluginHostSetPreviousPrefix ) {
2021-07-30 08:48:03 -04:00
badFields [ globals . HostSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted host source identifier %q." , id )
break
}
}
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
2021-07-27 12:48:36 -04:00
func validateAddCredentialSourcesRequest ( req * pbs . AddTargetCredentialSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-27 12:48:36 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
2023-09-22 15:58:18 -04:00
if len ( req . GetBrokeredCredentialSourceIds ()) + len ( req . GetInjectedApplicationCredentialSourceIds ()) == 0 {
2022-07-19 15:16:24 -07:00
badFields [ globals . BrokeredCredentialSourceIdsField ] = "Brokered or Injected Application Credential Source IDs must be provided."
badFields [ globals . InjectedApplicationCredentialSourceIdsField ] = "Brokered or Injected Application Credential Source IDs must be provided."
2021-07-27 12:48:36 -04:00
}
2022-07-19 15:16:24 -07:00
for _ , cl := range req . GetBrokeredCredentialSourceIds () {
2022-07-19 10:31:53 -07:00
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ,
globals . JsonCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . BrokeredCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
break
}
}
for _ , cl := range req . GetInjectedApplicationCredentialSourceIds () {
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . VaultSshCertificateCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . InjectedApplicationCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
2021-10-28 14:24:40 -04:00
break
}
}
2021-07-27 12:48:36 -04:00
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
func validateSetCredentialSourcesRequest ( req * pbs . SetTargetCredentialSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-27 12:48:36 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
2022-07-19 15:16:24 -07:00
for _ , cl := range req . GetBrokeredCredentialSourceIds () {
2022-07-19 10:31:53 -07:00
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ,
globals . JsonCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . BrokeredCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
break
}
}
for _ , cl := range req . GetInjectedApplicationCredentialSourceIds () {
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . VaultSshCertificateCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . InjectedApplicationCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
2021-10-28 14:24:40 -04:00
break
}
}
2021-07-27 12:48:36 -04:00
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
func validateRemoveCredentialSourcesRequest ( req * pbs . RemoveTargetCredentialSourcesRequest ) error {
badFields := map [ string ] string {}
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-07-27 12:48:36 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
}
if req . GetVersion () == 0 {
badFields [ globals . VersionField ] = "Required field."
}
2023-09-22 15:58:18 -04:00
if len ( req . GetBrokeredCredentialSourceIds ()) + len ( req . GetInjectedApplicationCredentialSourceIds ()) == 0 {
2022-07-19 15:16:24 -07:00
badFields [ globals . BrokeredCredentialSourceIdsField ] = "Brokered or Injected Application Credential Source IDs must be provided."
badFields [ globals . InjectedApplicationCredentialSourceIdsField ] = "Brokered or Injected Application Credential Source IDs must be provided."
2021-07-27 12:48:36 -04:00
}
2022-07-19 15:16:24 -07:00
for _ , cl := range req . GetBrokeredCredentialSourceIds () {
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ,
globals . JsonCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . BrokeredCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
break
}
}
for _ , cl := range req . GetInjectedApplicationCredentialSourceIds () {
2022-07-19 10:31:53 -07:00
if ! handlers . ValidId ( handlers . Id ( cl ),
2023-03-10 15:06:39 -05:00
globals . VaultCredentialLibraryPrefix ,
globals . VaultSshCertificateCredentialLibraryPrefix ,
globals . UsernamePasswordCredentialPrefix ,
globals . UsernamePasswordCredentialPreviousPrefix ,
globals . SshPrivateKeyCredentialPrefix ,
globals . JsonCredentialPrefix ) {
2022-07-19 15:16:24 -07:00
badFields [ globals . InjectedApplicationCredentialSourceIdsField ] = fmt . Sprintf ( "Incorrectly formatted credential source identifier %q." , cl )
2021-10-28 14:24:40 -04:00
break
}
}
2021-07-27 12:48:36 -04:00
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
2020-10-05 11:02:23 -04:00
func validateAuthorizeSessionRequest ( req * pbs . AuthorizeSessionRequest ) error {
2020-09-19 00:18:17 -04:00
badFields := map [ string ] string {}
2020-10-22 08:40:00 -04:00
nameEmpty := req . GetName () == ""
scopeIdEmpty := req . GetScopeId () == ""
scopeNameEmpty := req . GetScopeName () == ""
if nameEmpty {
2021-11-04 11:44:22 -04:00
if ! handlers . ValidId ( handlers . Id ( req . GetId ()), target . Prefixes () ... ) {
2021-06-22 22:26:26 -04:00
badFields [ globals . IdField ] = "Incorrectly formatted identifier."
2020-10-22 08:40:00 -04:00
}
if ! scopeIdEmpty {
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "Scope ID provided when target name was empty."
2020-10-22 08:40:00 -04:00
}
if ! scopeNameEmpty {
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "Scope name provided when target name was empty."
2020-10-22 08:40:00 -04:00
}
} else {
if req . GetName () != req . GetId () {
2021-06-22 22:26:26 -04:00
badFields [ globals . NameField ] = "Target name provided but does not match the given ID value from the URL."
2020-10-22 08:40:00 -04:00
}
switch {
case scopeIdEmpty && scopeNameEmpty :
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "Scope ID or scope name must be provided when target name is used."
2020-10-22 08:40:00 -04:00
badFields [ "scope_name" ] = "Scope ID or scope name must be provided when target name is used."
case ! scopeIdEmpty && ! scopeNameEmpty :
2021-06-22 22:26:26 -04:00
badFields [ globals . ScopeIdField ] = "Scope ID and scope name cannot both be provided when target name is used."
2020-10-22 08:40:00 -04:00
badFields [ "scope_name" ] = "Scope ID and scope name cannot both be provided when target name is used."
}
2020-09-19 00:18:17 -04:00
}
if req . GetHostId () != "" {
2023-11-15 19:55:46 -05:00
switch globals . ResourceInfoFromPrefix ( req . GetHostId ()). Subtype {
2023-11-02 16:03:47 -04:00
case static . Subtype , plugin . Subtype :
2020-09-19 00:18:17 -04:00
default :
2021-06-22 22:26:26 -04:00
badFields [ globals . HostIdField ] = "Incorrectly formatted identifier."
2020-09-19 00:18:17 -04:00
}
}
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Errors in provided fields." , badFields )
}
return nil
}
2025-01-08 15:18:03 +00:00
func noStorageBucket ( _ context . Context , _ intglobals . ControllerExtension , _ string ) ( string , string , error ) {
return "" , "" , fmt . Errorf ( "not supported" )
}
2025-01-23 11:55:11 -08:00
func noOpValidateLicense ( ctx context . Context ) error {
return nil
}