@@ -9,14 +9,12 @@ import {
99    getIamCredentialOptionsDefaults , 
1010    GetSsoTokenParams , 
1111    GetSsoTokenResult , 
12-     IamCredentials , 
1312    IamIdentityCenterSsoTokenSource , 
1413    InvalidateSsoTokenParams , 
1514    InvalidateSsoTokenResult , 
1615    MetricEvent , 
1716    SsoSession , 
1817    SsoTokenSourceKind , 
19-     ProfileKind , 
2018}  from  '@aws/language-server-runtimes/server-interface' 
2119
2220import  {  normalizeSettingList ,  ProfileStore  }  from  './profiles/profileService' 
@@ -28,45 +26,31 @@ import {
2826    throwOnInvalidSsoSession , 
2927    throwOnInvalidSsoSessionName , 
3028    SsoFlowParams , 
29+     SsoHandlers , 
3130}  from  '../sso/utils' 
31+ import  {  IamHandlers ,  simulatePermissions  }  from  '../iam/utils' 
3232import  {  AwsError ,  Observability  }  from  '@aws/lsp-core' 
33- import  {  GetCallerIdentityCommand ,  STSClient  }  from  '@aws-sdk/client-sts' 
3433import  {  __ServiceException  }  from  '@aws-sdk/client-sso-oidc/dist-types/models/SSOOIDCServiceException' 
3534import  {  deviceCodeFlow  }  from  '../sso/deviceCode/deviceCodeFlow' 
3635import  {  SSOToken  }  from  '@smithy/shared-ini-file-loader' 
37- import  {  IAMClient ,   SimulatePrincipalPolicyCommand ,   SimulatePrincipalPolicyCommandOutput   }  from  '@aws-sdk/client- iam' 
36+ import  {  IamProvider   }  from  '../ iam/iamProvider ' 
3837
3938type  SsoTokenSource  =  IamIdentityCenterSsoTokenSource  |  AwsBuilderIdSsoTokenSource 
4039type  AuthFlows  =  Record < AuthorizationFlowKind ,  ( params : SsoFlowParams )  =>  Promise < SSOToken > > 
40+ type  Handlers  =  SsoHandlers  &  IamHandlers 
4141
4242const  flows : AuthFlows  =  { 
4343    [ AuthorizationFlowKind . DeviceCode ] : deviceCodeFlow , 
4444    [ AuthorizationFlowKind . Pkce ] : authorizationCodePkceFlow , 
4545} 
46- const  qPermissions  =  [ 
47-     'q:StartConversation' , 
48-     'q:SendMessage' , 
49-     'q:GetConversation' , 
50-     'q:ListConversations' , 
51-     'q:UpdateConversation' , 
52-     'q:DeleteConversation' , 
53-     'q:PassRequest' , 
54-     'q:StartTroubleshootingAnalysis' , 
55-     'q:StartTroubleshootingResolutionExplanation' , 
56-     'q:GetTroubleshootingResults' , 
57-     'q:UpdateTroubleshootingCommandResult' , 
58-     'q:GetIdentityMetaData' , 
59-     'q:GenerateCodeFromCommands' , 
60-     'q:UsePlugin' , 
61-     'codewhisperer:GenerateRecommendations' , 
62- ] 
6346
6447export  class  IdentityService  { 
6548    constructor ( 
6649        private  readonly  profileStore : ProfileStore , 
6750        private  readonly  ssoCache : SsoCache , 
6851        private  readonly  autoRefresher : SsoTokenAutoRefresher , 
69-         private  readonly  handlers : SsoFlowParams [ 'handlers' ] , 
52+         private  readonly  iamProvider : IamProvider , 
53+         private  readonly  handlers : Handlers , 
7054        private  readonly  clientName : string , 
7155        private  readonly  observability : Observability , 
7256        private  readonly  authFlows : AuthFlows  =  flows 
@@ -119,7 +103,7 @@ export class IdentityService {
119103                    clientName : this . clientName , 
120104                    clientRegistration, 
121105                    ssoSession, 
122-                     handlers : this . handlers , 
106+                     handlers : this . handlers   as   Pick < Handlers ,   keyof   SsoHandlers > , 
123107                    token, 
124108                    observability : this . observability , 
125109                } 
@@ -173,9 +157,7 @@ export class IdentityService {
173157            const  options  =  {  ...getIamCredentialOptionsDefaults ,  ...params . options  } 
174158
175159            token . onCancellationRequested ( _  =>  { 
176-                 if  ( options . callStsOnInvalidIamCredential )  { 
177-                     emitMetric ( 'Cancelled' ,  null ) 
178-                 } 
160+                 emitMetric ( 'Cancelled' ,  null ) 
179161            } ) 
180162
181163            // Get the profile with provided name 
@@ -186,33 +168,20 @@ export class IdentityService {
186168                throw  new  AwsError ( 'Profile not found.' ,  AwsErrorCodes . E_PROFILE_NOT_FOUND ) 
187169            } 
188170
189-             let  credentials : IamCredentials 
190-             // Get the credentials directly from the profile 
191-             if  ( profile . kinds . includes ( ProfileKind . IamCredentialsProfile ) )  { 
192-                 credentials  =  { 
193-                     accessKeyId : profile . settings ! . aws_access_key_id ! , 
194-                     secretAccessKey : profile . settings ! . aws_secret_access_key ! , 
195-                     sessionToken : profile . settings ! . aws_session_token ! , 
196-                 } 
197-             }  else  { 
198-                 throw  new  AwsError ( 'Credentials could not be found for profile' ,  AwsErrorCodes . E_INVALID_PROFILE ) 
199-             } 
171+             const  credentials  =  await  this . iamProvider . getCredential ( profile ,  options . callStsOnInvalidIamCredential ) 
200172
201173            // Validate permissions 
202-             if  ( options . validatePermissions )  { 
203-                 const  response  =  await  this . simulatePermissions ( credentials ,  qPermissions ,  profile . settings ?. region ) 
174+             if  ( options . permissionSet . length   >   0 )  { 
175+                 const  response  =  await  simulatePermissions ( credentials ,  options . permissionSet ,  profile . settings ?. region ) 
204176                if  ( ! response ?. EvaluationResults ?. every ( result  =>  result . EvalDecision  ===  'allowed' ) )  { 
205-                     throw  new  AwsError ( 
206-                         `User or assumed role has insufficient permissions.` , 
207-                         AwsErrorCodes . E_INVALID_PROFILE 
208-                     ) 
177+                     throw  new  AwsError ( `Credentials have insufficient permissions.` ,  AwsErrorCodes . E_INVALID_PROFILE ) 
209178                } 
210179            } 
211180
212181            emitMetric ( 'Succeeded' ) 
182+ 
213183            return  { 
214-                 id : profile . name , 
215-                 credentials : credentials , 
184+                 credential : {  id : params . profileName ,  credentials : credentials  } , 
216185                updateCredentialsParams : {  data : credentials ,  encrypted : false  } , 
217186            } 
218187        }  catch  ( e )  { 
@@ -332,27 +301,4 @@ export class IdentityService {
332301
333302        return  ssoSession 
334303    } 
335- 
336-     // Simulate permissions on the identity associated with the credentials 
337-     private  async  simulatePermissions ( 
338-         credentials : IamCredentials , 
339-         permissions : string [ ] , 
340-         region ?: string 
341-     ) : Promise < SimulatePrincipalPolicyCommandOutput >  { 
342-         // Convert the credentials into an identity 
343-         const  stsClient  =  new  STSClient ( {  region : region  ||  'us-east-1' ,  credentials : credentials  } ) 
344-         const  identity  =  await  stsClient . send ( new  GetCallerIdentityCommand ( { } ) ) 
345-         if  ( ! identity . Arn )  { 
346-             throw  new  AwsError ( 'Caller identity ARN not found.' ,  AwsErrorCodes . E_INVALID_PROFILE ) 
347-         } 
348- 
349-         // Simulate permissions on the identity 
350-         const  iamClient  =  new  IAMClient ( {  region : region  ||  'us-east-1' ,  credentials : credentials  } ) 
351-         return  await  iamClient . send ( 
352-             new  SimulatePrincipalPolicyCommand ( { 
353-                 PolicySourceArn : identity . Arn , 
354-                 ActionNames : permissions , 
355-             } ) 
356-         ) 
357-     } 
358304} 
0 commit comments