@@ -40,6 +40,7 @@ import {
40
40
hasScopes ,
41
41
scopesSsoAccountAccess ,
42
42
isSsoConnection ,
43
+ IamConnection ,
43
44
} from './connection'
44
45
import { Commands , placeholder } from '../shared/vscode/commands2'
45
46
import { Auth } from './auth'
@@ -79,6 +80,18 @@ export async function promptForConnection(auth: Auth, type?: 'iam' | 'iam-only'
79
80
return globals . awsContextCommands . onCommandEditCredentials ( )
80
81
}
81
82
83
+ // If selected connection is SSO connection and has linked IAM profiles, show second quick pick with the linked IAM profiles
84
+ if ( isSsoConnection ( resp ) ) {
85
+ const linkedProfiles = await getLinkedIamProfiles ( auth , resp )
86
+
87
+ if ( linkedProfiles . length > 0 ) {
88
+ const linkedResp = await showLinkedProfilePicker ( linkedProfiles , resp )
89
+ if ( linkedResp ) {
90
+ return linkedResp
91
+ }
92
+ }
93
+ }
94
+
82
95
return resp
83
96
}
84
97
@@ -340,6 +353,36 @@ export const createDeleteConnectionButton: () => vscode.QuickInputButton = () =>
340
353
return { tooltip : deleteConnection , iconPath : getIcon ( 'vscode-trash' ) }
341
354
}
342
355
356
+ async function getLinkedIamProfiles ( auth : Auth , ssoConnection : SsoConnection ) : Promise < IamConnection [ ] > {
357
+ const allConnections = await auth . listAndTraverseConnections ( ) . promise ( )
358
+
359
+ return allConnections . filter (
360
+ ( conn ) => isIamConnection ( conn ) && conn . id . startsWith ( `sso:${ ssoConnection . id } #` )
361
+ ) as IamConnection [ ]
362
+ }
363
+
364
+ /**
365
+ * Shows a quick pick with linked IAM profiles for a selected SSO connection
366
+ */
367
+ async function showLinkedProfilePicker (
368
+ linkedProfiles : IamConnection [ ] ,
369
+ ssoConnection : SsoConnection
370
+ ) : Promise < IamConnection | undefined > {
371
+ const title = `Select an IAM Role for ${ ssoConnection . label } `
372
+
373
+ const items : DataQuickPickItem < IamConnection > [ ] = linkedProfiles . map ( ( profile ) => ( {
374
+ label : codicon `${ getIcon ( 'vscode-key' ) } ${ profile . label } ` ,
375
+ description : 'IAM Credential, sourced from IAM Identity Center' ,
376
+ data : profile ,
377
+ } ) )
378
+
379
+ return await showQuickPick ( items , {
380
+ title,
381
+ placeholder : 'Select an IAM role' ,
382
+ buttons : [ createRefreshButton ( ) , createExitButton ( ) ] ,
383
+ } )
384
+ }
385
+
343
386
export function createConnectionPrompter ( auth : Auth , type ?: 'iam' | 'iam-only' | 'sso' ) {
344
387
const addNewConnection = {
345
388
label : codicon `${ getIcon ( 'vscode-plus' ) } Add New Connection` ,
@@ -433,22 +476,22 @@ export function createConnectionPrompter(auth: Auth, type?: 'iam' | 'iam-only' |
433
476
for await ( const conn of connections ) {
434
477
if ( conn . label . includes ( 'profile:' ) && ! hasShownEdit ) {
435
478
hasShownEdit = true
436
- yield [ toPickerItem ( conn ) , editCredentials ]
479
+ yield [ await toPickerItem ( conn ) , editCredentials ]
437
480
} else {
438
- yield [ toPickerItem ( conn ) ]
481
+ yield [ await toPickerItem ( conn ) ]
439
482
}
440
483
}
441
484
}
442
485
443
- function toPickerItem ( conn : Connection ) : DataQuickPickItem < Connection > {
486
+ async function toPickerItem ( conn : Connection ) : Promise < DataQuickPickItem < Connection > > {
444
487
const state = auth . getConnectionState ( conn )
445
488
// Only allow SSO connections to be deleted
446
489
const deleteButton : vscode . QuickInputButton [ ] = conn . type === 'sso' ? [ createDeleteConnectionButton ( ) ] : [ ]
447
490
if ( state === 'valid' ) {
448
491
return {
449
492
data : conn ,
450
493
label : codicon `${ getConnectionIcon ( conn ) } ${ conn . label } ` ,
451
- description : getConnectionDescription ( conn ) ,
494
+ description : await getConnectionDescription ( conn ) ,
452
495
buttons : [ ...deleteButton ] ,
453
496
}
454
497
}
@@ -502,7 +545,7 @@ export function createConnectionPrompter(auth: Auth, type?: 'iam' | 'iam-only' |
502
545
}
503
546
}
504
547
505
- function getConnectionDescription ( conn : Connection ) {
548
+ async function getConnectionDescription ( conn : Connection ) {
506
549
if ( conn . type === 'iam' ) {
507
550
// TODO: implement a proper `getConnectionSource` method to discover where a connection came from
508
551
const descSuffix = conn . id . startsWith ( 'profile:' )
@@ -514,6 +557,14 @@ export function createConnectionPrompter(auth: Auth, type?: 'iam' | 'iam-only' |
514
557
return `IAM Credential, ${ descSuffix } `
515
558
}
516
559
560
+ // If this is an SSO connection, check if it has linked IAM profiles
561
+ if ( isSsoConnection ( conn ) ) {
562
+ const linkedProfiles = await getLinkedIamProfiles ( auth , conn )
563
+ if ( linkedProfiles . length > 0 ) {
564
+ return `Has ${ linkedProfiles . length } IAM role${ linkedProfiles . length > 1 ? 's' : '' } (click to select)`
565
+ }
566
+ }
567
+
517
568
const toolAuths = getDependentAuths ( conn )
518
569
if ( toolAuths . length === 0 ) {
519
570
return undefined
0 commit comments