@@ -62,6 +62,10 @@ export function createSsoProfile(startUrl: string, region = 'us-east-1'): SsoPro
62
62
}
63
63
}
64
64
65
+ export function hasScopes ( target : SsoConnection | SsoProfile , scopes : string [ ] ) : boolean {
66
+ return scopes ?. every ( s => target . scopes ?. includes ( s ) )
67
+ }
68
+
65
69
export interface SsoConnection {
66
70
readonly type : 'sso'
67
71
readonly id : string
@@ -343,6 +347,8 @@ export class Auth implements AuthService, ConnectionManager {
343
347
}
344
348
}
345
349
350
+ public async useConnection ( { id } : Pick < SsoConnection , 'id' > ) : Promise < SsoConnection >
351
+ public async useConnection ( { id } : Pick < Connection , 'id' > ) : Promise < Connection >
346
352
public async useConnection ( { id } : Pick < Connection , 'id' > ) : Promise < Connection > {
347
353
const profile = this . store . getProfile ( id )
348
354
if ( profile === undefined ) {
@@ -522,14 +528,21 @@ export class Auth implements AuthService, ConnectionManager {
522
528
523
529
// XXX: always read from the same location in a dev environment
524
530
private getSsoSessionName = once ( ( ) => {
525
- const configFile = getConfigFilename ( )
526
- const contents : string = require ( 'fs' ) . readFileSync ( configFile , 'utf-8' )
527
- const identifier = contents . match ( / \[ s s o \- s e s s i o n ( .* ) \] / ) ?. [ 1 ]
528
- if ( ! identifier ) {
529
- throw new ToolkitError ( 'No sso-session name found in ~/.aws/config' , { code : 'NoSsoSessionName' } )
530
- }
531
+ try {
532
+ const configFile = getConfigFilename ( )
533
+ const contents : string = require ( 'fs' ) . readFileSync ( configFile , 'utf-8' )
534
+ const identifier = contents . match ( / \[ s s o \- s e s s i o n ( .* ) \] / ) ?. [ 1 ]
535
+ if ( ! identifier ) {
536
+ throw new ToolkitError ( 'No sso-session name found in ~/.aws/config' , { code : 'NoSsoSessionName' } )
537
+ }
531
538
532
- return identifier
539
+ return identifier
540
+ } catch ( err ) {
541
+ const defaultName = 'codecatalyst'
542
+ getLogger ( ) . warn ( `auth: unable to get an sso session name, defaulting to "${ defaultName } ": %s` , err )
543
+
544
+ return defaultName
545
+ }
533
546
} )
534
547
535
548
private getTokenProvider ( id : Connection [ 'id' ] , profile : StoredProfile < SsoProfile > ) {
@@ -659,20 +672,6 @@ export class Auth implements AuthService, ConnectionManager {
659
672
return
660
673
}
661
674
662
- // Remove connections that do not have the required scopes
663
- const requiredScopes = createBuilderIdProfile ( ) . scopes
664
- for ( const [ id , profile ] of this . store . listProfiles ( ) ) {
665
- if (
666
- profile . type === 'sso' &&
667
- profile . startUrl === builderIdStartUrl &&
668
- ! requiredScopes ?. every ( s => profile . scopes ?. includes ( s ) )
669
- ) {
670
- await this . store . deleteProfile ( id ) . catch ( err => {
671
- getLogger ( ) . warn ( `auth: failed to remove profile ${ id } : %s` , err )
672
- } )
673
- }
674
- }
675
-
676
675
// Use the environment token if available
677
676
if ( getCodeCatalystDevEnvId ( ) !== undefined ) {
678
677
const profile = createBuilderIdProfile ( )
@@ -880,7 +879,7 @@ export async function createStartUrlPrompter(title: string, ignoreScopes = true)
880
879
a . authority . toLowerCase ( ) === b . authority . toLowerCase ( )
881
880
const oldConn = existingConnections . find ( conn => isSameAuthority ( vscode . Uri . parse ( conn . startUrl ) , uri ) )
882
881
883
- if ( oldConn && ( ignoreScopes || requiredScopes ?. every ( s => oldConn . scopes ?. includes ( s ) ) ) ) {
882
+ if ( oldConn && ( ignoreScopes || hasScopes ( oldConn , requiredScopes ) ) ) {
884
883
return 'A connection for this start URL already exists. Sign out before creating a new one.'
885
884
}
886
885
} catch ( err ) {
@@ -897,14 +896,13 @@ export async function createStartUrlPrompter(title: string, ignoreScopes = true)
897
896
}
898
897
899
898
export async function createBuilderIdConnection ( auth : Auth ) {
899
+ const newProfile = createBuilderIdProfile ( )
900
900
const existingConn = ( await auth . listConnections ( ) ) . find ( isBuilderIdConnection )
901
-
902
- // Right now users can only have 1 builder id connection
903
- if ( existingConn !== undefined ) {
904
- await auth . deleteConnection ( existingConn )
901
+ if ( existingConn && ! hasScopes ( existingConn , newProfile . scopes ) ) {
902
+ return migrateBuilderId ( auth , existingConn , newProfile )
905
903
}
906
904
907
- return Auth . instance . createConnection ( createBuilderIdProfile ( ) )
905
+ return existingConn ?? ( await auth . createConnection ( newProfile ) )
908
906
}
909
907
910
908
Commands . register ( 'aws.auth.help' , async ( ) => {
@@ -916,6 +914,23 @@ Commands.register('aws.auth.signout', () => {
916
914
917
915
return signout ( Auth . instance )
918
916
} )
917
+
918
+ // XXX: right now users can only have 1 builder id connection, so de-dupe
919
+ // This logic can be removed or re-purposed once we have access to identities
920
+ async function migrateBuilderId ( auth : Auth , existingConn : SsoConnection , newProfile : SsoProfile ) {
921
+ const newConn = await auth . createConnection ( newProfile )
922
+ const shouldUseConnection = auth . activeConnection ?. id === existingConn . id
923
+ await auth . deleteConnection ( existingConn ) . catch ( err => {
924
+ getLogger ( ) . warn ( `auth: failed to remove old connection "${ existingConn . id } ": %s` , err )
925
+ } )
926
+
927
+ if ( shouldUseConnection ) {
928
+ return auth . useConnection ( newConn )
929
+ }
930
+
931
+ return newConn
932
+ }
933
+
919
934
const addConnection = Commands . register ( 'aws.auth.addConnection' , async ( ) => {
920
935
const c9IamItem = createIamItem ( )
921
936
c9IamItem . detail =
@@ -948,11 +963,7 @@ const addConnection = Commands.register('aws.auth.addConnection', async () => {
948
963
return Auth . instance . useConnection ( conn )
949
964
}
950
965
case 'builderId' : {
951
- const existingConn = ( await Auth . instance . listConnections ( ) ) . find ( isBuilderIdConnection )
952
- // Right now users can only have 1 builder id connection
953
- const conn = existingConn ?? ( await Auth . instance . createConnection ( createBuilderIdProfile ( ) ) )
954
-
955
- return Auth . instance . useConnection ( conn )
966
+ return createBuilderIdConnection ( Auth . instance )
956
967
}
957
968
}
958
969
} )
0 commit comments