@@ -11,6 +11,7 @@ import { showConfirmationMessage } from '../../shared/utilities/messages'
1111import globals from '../../shared/extensionGlobals'
1212import { once } from '../../shared/utilities/functionUtils'
1313import CodeWhispererUserClient from '../client/codewhispereruserclient'
14+ import CodeWhispererClient from '../client/codewhispererclient'
1415import { Credentials , Service } from 'aws-sdk'
1516import { ServiceOptions } from '../../shared/awsClientBuilder'
1617import userApiConfig = require( '../client/user-service-2.json' )
@@ -152,30 +153,63 @@ export class RegionProfileManager {
152153 const failedRegions : string [ ] = [ ]
153154
154155 for ( const [ region , endpoint ] of endpoints . entries ( ) ) {
155- const client = await this . _createQClient ( region , endpoint )
156- const requester = async ( request : CodeWhispererUserClient . ListAvailableProfilesRequest ) =>
157- client . listAvailableProfiles ( request ) . promise ( )
158- const request : CodeWhispererUserClient . ListAvailableProfilesRequest = { }
159156 try {
160- const profiles = await pageableToCollection ( requester , request , 'nextToken' , 'profiles' )
161- . flatten ( )
162- . promise ( )
163- const mappedPfs = profiles . map ( ( it ) => {
164- let accntId = ''
165- try {
166- accntId = parse ( it . arn ) . accountId
167- } catch ( e ) { }
168-
169- return {
170- name : it . profileName ,
171- region : region ,
172- arn : it . arn ,
173- description : accntId ,
157+ // Get region profiles (Q developer profiles) from Q client and authenticate with SSO token
158+ if ( this . authProvider . isIdcConnection ( ) ) {
159+ const client = await this . _createQUserClient ( region , endpoint )
160+ const requester = async ( request : CodeWhispererUserClient . ListAvailableProfilesRequest ) => {
161+ return client . listAvailableProfiles ( request ) . promise ( )
174162 }
175- } )
163+ const request : CodeWhispererUserClient . ListAvailableProfilesRequest = { }
164+ const profiles = await pageableToCollection ( requester , request , 'nextToken' , 'profiles' )
165+ . flatten ( )
166+ . promise ( )
167+ const mappedPfs = profiles . map ( ( it ) => {
168+ let accntId = ''
169+ try {
170+ accntId = parse ( it . arn ) . accountId
171+ } catch ( e ) { }
172+
173+ return {
174+ name : it . profileName ,
175+ region : region ,
176+ arn : it . arn ,
177+ description : accntId ,
178+ }
179+ } )
176180
177- availableProfiles . push ( ...mappedPfs )
178- RegionProfileManager . logger . debug ( `Found ${ mappedPfs . length } profiles in region ${ region } ` )
181+ availableProfiles . push ( ...mappedPfs )
182+ RegionProfileManager . logger . debug ( `Found ${ mappedPfs . length } profiles in region ${ region } ` )
183+ }
184+ // Get region profiles (Q developer profiles) from Q client and authenticate with IAM credentials
185+ else if ( this . authProvider . isIamSession ( ) ) {
186+ const client = await this . _createQServiceClient ( region , endpoint )
187+ const requester = async ( request : CodeWhispererClient . ListProfilesRequest ) => {
188+ return client . listProfiles ( request ) . promise ( )
189+ }
190+ const request : CodeWhispererClient . ListProfilesRequest = { }
191+ const profiles = await pageableToCollection ( requester , request , 'nextToken' , 'profiles' )
192+ . flatten ( )
193+ . promise ( )
194+ const mappedPfs = profiles . map ( ( it ) => {
195+ let accntId = ''
196+ try {
197+ accntId = parse ( it . arn ) . accountId
198+ } catch ( e ) { }
199+
200+ return {
201+ name : it . profileName ,
202+ region : region ,
203+ arn : it . arn ,
204+ description : accntId ,
205+ }
206+ } )
207+
208+ availableProfiles . push ( ...mappedPfs )
209+ RegionProfileManager . logger . debug ( `Found ${ mappedPfs . length } profiles in region ${ region } ` )
210+ } else {
211+ throw new ToolkitError ( 'Failed to list profiles when signed out of identity center and IAM credentials' )
212+ }
179213 } catch ( e ) {
180214 const logMsg = isAwsError ( e ) ? `requestId=${ e . requestId } ; message=${ e . message } ` : ( e as Error ) . message
181215 RegionProfileManager . logger . error ( `Failed to list profiles for region ${ region } : ${ logMsg } ` )
@@ -201,7 +235,7 @@ export class RegionProfileManager {
201235 }
202236
203237 async switchRegionProfile ( regionProfile : RegionProfile | undefined , source : ProfileSwitchIntent ) {
204- if ( ! this . authProvider . isConnected ( ) || ! this . authProvider . isIdcConnection ( ) ) {
238+ if ( ! this . authProvider . isConnected ( ) ) {
205239 return
206240 }
207241
@@ -413,55 +447,72 @@ export class RegionProfileManager {
413447 }
414448
415449 // TODO: Should maintain sdk client in a better way
416- async createQClient ( profile : RegionProfile ) : Promise < CodeWhispererUserClient > {
450+ // Create a Q user client compatible with SSO tokens
451+ async createQUserClient ( profile : RegionProfile ) : Promise < CodeWhispererUserClient > {
417452 if ( ! this . authProvider . isConnected ( ) ) {
418453 throw new Error ( 'No valid connection' )
419454 }
420455 const endpoint = endpoints . get ( profile . region )
421456 if ( ! endpoint ) {
422457 throw new Error ( `trying to initiatize Q client with unrecognizable region ${ profile . region } ` )
423458 }
424- return this . _createQClient ( profile . region , endpoint )
459+ return this . _createQUserClient ( profile . region , endpoint )
425460 }
426461
427- // Visible for testing only, do not use this directly, please use createQClient(profile)
428- async _createQClient ( region : string , endpoint : string ) : Promise < CodeWhispererUserClient > {
429- let serviceOption : ServiceOptions = { }
430- if ( this . authProvider . isSsoSession ( ) ) {
431- const token = await this . authProvider . getToken ( )
432- serviceOption = {
433- apiConfig : userApiConfig ,
434- region : region ,
435- endpoint : endpoint ,
436- credentials : new Credentials ( { accessKeyId : 'xxx' , secretAccessKey : 'xxx' } ) ,
437- onRequestSetup : [
438- ( req ) => {
439- req . on ( 'build' , ( { httpRequest } ) => {
440- httpRequest . headers [ 'Authorization' ] = `Bearer ${ token } `
441- } )
442- } ,
443- ] ,
444- } as ServiceOptions
445- } else if ( this . authProvider . isIamSession ( ) ) {
446- const credential = await this . authProvider . getIamCredential ( )
447- serviceOption = {
448- apiConfig : apiConfig ,
449- region : region ,
450- endpoint : endpoint ,
451- credentials : new Credentials ( {
452- accessKeyId : credential . accessKeyId ,
453- secretAccessKey : credential . secretAccessKey ,
454- sessionToken : credential . sessionToken ,
455- } ) ,
456- } as ServiceOptions
462+ // Create a Q service client compatible with IAM credentials
463+ async createQServiceClient ( profile : RegionProfile ) : Promise < CodeWhispererClient > {
464+ if ( ! this . authProvider . isConnected ( ) ) {
465+ throw new Error ( 'No valid connection' )
457466 }
467+ const endpoint = endpoints . get ( profile . region )
468+ if ( ! endpoint ) {
469+ throw new Error ( `trying to initiatize Q client with unrecognizable region ${ profile . region } ` )
470+ }
471+ return this . _createQServiceClient ( profile . region , endpoint )
472+ }
458473
459- const c = ( await globals . sdkClientBuilder . createAwsService (
474+ // Visible for testing only, do not use this directly, please use createQUserClient(profile)
475+ async _createQUserClient ( region : string , endpoint : string ) : Promise < CodeWhispererUserClient > {
476+ const token = await this . authProvider . getToken ( )
477+ const serviceOption : ServiceOptions = {
478+ apiConfig : userApiConfig ,
479+ region : region ,
480+ endpoint : endpoint ,
481+ credentials : new Credentials ( { accessKeyId : 'xxx' , secretAccessKey : 'xxx' } ) ,
482+ onRequestSetup : [
483+ ( req ) => {
484+ req . on ( 'build' , ( { httpRequest } ) => {
485+ httpRequest . headers [ 'Authorization' ] = `Bearer ${ token } `
486+ } )
487+ } ,
488+ ] ,
489+ } as ServiceOptions
490+
491+ return ( await globals . sdkClientBuilder . createAwsService (
460492 Service ,
461493 serviceOption ,
462494 undefined
463495 ) ) as CodeWhispererUserClient
496+ }
464497
465- return c
498+ // Visible for testing only, do not use this directly, please use createQServiceClient(profile)
499+ async _createQServiceClient ( region : string , endpoint : string ) : Promise < CodeWhispererClient > {
500+ const credential = await this . authProvider . getIamCredential ( )
501+ const serviceOption : ServiceOptions = {
502+ apiConfig : apiConfig ,
503+ region : region ,
504+ endpoint : endpoint ,
505+ credentials : new Credentials ( {
506+ accessKeyId : credential . accessKeyId ,
507+ secretAccessKey : credential . secretAccessKey ,
508+ sessionToken : credential . sessionToken ,
509+ } ) ,
510+ } as ServiceOptions
511+
512+ return ( await globals . sdkClientBuilder . createAwsService (
513+ Service ,
514+ serviceOption ,
515+ undefined
516+ ) ) as CodeWhispererClient
466517 }
467518}
0 commit comments