Skip to content

Commit d1ce6de

Browse files
authored
Credentials: partial migration to SDK v3 #1766
## Problem SDK v2 has some known issues in regards to credentials from source_profile. SDK v3 does not fix them out-right, however, it does expose some functionality that allows us to fix the bugs. ## Solution Migrate the credentials subsystem to use SDK v3, then add additional logic to handle source_profile resolution. The new SDK credentials API allows us to 'pre-load' credentials when calling relevant APIs. We can use this functionality to load source profile credentials ourselves, letting the SDK treat them as static credentials. Any valid profile should now be usable as a base profile as well (e.g. processes, SSO, MFA, etc.)
1 parent 740c4bb commit d1ce6de

File tree

53 files changed

+4734
-2647
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4734
-2647
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Credentials: correctly handle different `source_profile` combinations"
4+
}

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ src/shared/telemetry/clienttelemetry.d.ts
2727

2828
# Generated by tests
2929
src/testFixtures/**/bin
30-
src/testFixtures/**/obj
30+
src/testFixtures/**/obj

.gitpod.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
tasks:
2-
- init: npm install
2+
- init: npm install
33

44
vscode:
5-
extensions:
6-
- dbaeumer.vscode-eslint
7-
- eg2.vscode-npm-script
8-
5+
extensions:
6+
- dbaeumer.vscode-eslint
7+
- eg2.vscode-npm-script

package-lock.json

Lines changed: 4182 additions & 2344 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,11 @@
21162116
"webpack-cli": "^4.7.2"
21172117
},
21182118
"dependencies": {
2119+
"@aws-sdk/client-sso": "^3.16.0",
2120+
"@aws-sdk/client-sso-oidc": "^3.16.0",
2121+
"@aws-sdk/credential-provider-ini": "^3.15.0",
2122+
"@aws-sdk/credential-provider-process": "^3.15.0",
2123+
"@aws-sdk/credential-provider-sso": "^3.16.0",
21192124
"adm-zip": "^0.4.13",
21202125
"amazon-states-language-service": "^1.6.4",
21212126
"async-lock": "^1.3.0",

src/awsexplorer/awsExplorer.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ export class AwsExplorer implements vscode.TreeDataProvider<AWSTreeNodeBase>, Re
3737
localize('AWS.explorerNode.addRegion', 'Add a region to {0} Explorer...', getIdeProperties().company),
3838
'aws.showRegion',
3939
undefined,
40-
localize('AWS.explorerNode.addRegion.tooltip', 'Click here to add a region to {0} Explorer.', getIdeProperties().company)
40+
localize(
41+
'AWS.explorerNode.addRegion.tooltip',
42+
'Click here to add a region to {0} Explorer.',
43+
getIdeProperties().company
44+
)
4145
)
4246

4347
public constructor(
@@ -51,7 +55,11 @@ export class AwsExplorer implements vscode.TreeDataProvider<AWSTreeNodeBase>, Re
5155
this.extContext.subscriptions.push(
5256
this.awsContext.onDidChangeContext(e => {
5357
if (!e.accountId) {
54-
this.ROOT_NODE_SIGN_IN.label = localize('AWS.explorerNode.signIn', 'Connect to {0}...', getIdeProperties().company)
58+
this.ROOT_NODE_SIGN_IN.label = localize(
59+
'AWS.explorerNode.signIn',
60+
'Connect to {0}...',
61+
getIdeProperties().company
62+
)
5563
this.ROOT_NODE_SIGN_IN.tooltip = localize(
5664
'AWS.explorerNode.signIn.tooltip',
5765
'Click here to select credentials for the {0} Toolkit',

src/awsexplorer/commands/copyArn.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ export async function copyArnCommand(
4242
const logsItem = localize('AWS.generic.message.viewLogs', 'View Logs...')
4343
window
4444
.showErrorMessage(
45-
localize('AWS.explorerNode.noArnFound', 'Could not find an ARN for selected {0} Explorer node', getIdeProperties().company),
45+
localize(
46+
'AWS.explorerNode.noArnFound',
47+
'Could not find an ARN for selected {0} Explorer node',
48+
getIdeProperties().company
49+
),
4650
logsItem
4751
)
4852
.then(selection => {

src/credentials/awsCredentialsStatusBarItem.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,22 @@ export async function initializeAwsCredentialsStatusBarItem(
4242
}
4343

4444
// Resolves when the status bar reaches its final state
45-
export async function updateCredentialsStatusBarItem(statusBarItem: vscode.StatusBarItem, credentialsId?: string): Promise<void> {
45+
export async function updateCredentialsStatusBarItem(
46+
statusBarItem: vscode.StatusBarItem,
47+
credentialsId?: string
48+
): Promise<void> {
4649
clearTimeout(timeoutID)
4750

4851
// Shows confirmation text in the status bar message
4952
let delay = 0
5053
if (credentialsId) {
5154
delay = STATUSBAR_CONNECTED_DELAY
52-
statusBarItem.text = localize('AWS.credentials.statusbar.text', '{0}: {1}', getIdeProperties().company, STATUSBAR_TEXT_CONNECTED)
55+
statusBarItem.text = localize(
56+
'AWS.credentials.statusbar.text',
57+
'{0}: {1}',
58+
getIdeProperties().company,
59+
STATUSBAR_TEXT_CONNECTED
60+
)
5361
}
5462

5563
return new Promise<void>(

src/credentials/credentialsCreator.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ const ERROR_MESSAGE_USER_CANCELLED = localize(
2525
*/
2626
export async function getMfaTokenFromUser(
2727
mfaSerial: string,
28-
profileName: string,
29-
callback: (err?: Error, token?: string) => void
30-
): Promise<void> {
28+
profileName: string
29+
): Promise<string> {
3130
try {
3231
const inputBox = createInputBox({
3332
options: {
@@ -45,9 +44,8 @@ export async function getMfaTokenFromUser(
4544
throw new Error(ERROR_MESSAGE_USER_CANCELLED)
4645
}
4746

48-
callback(undefined, token)
47+
return token
4948
} catch (err) {
50-
const error = err as Error
51-
callback(error)
49+
throw err as Error
5250
}
5351
}

src/credentials/credentialsStore.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import * as AWS from 'aws-sdk'
6+
import * as AWS from '@aws-sdk/types'
77
import { getLogger } from '../shared/logger/logger'
88
import { asString, CredentialsProvider, CredentialsId } from './providers/credentials'
99
import { CredentialsProviderManager } from './providers/credentialsProviderManager'
@@ -23,14 +23,25 @@ export class CredentialsStore {
2323
this.credentialsCache = {}
2424
}
2525

26+
/**
27+
* Checks if the stored credentials are valid. Non-existent or expired credentials returns false.
28+
*
29+
* If the expiration property does not exist, it is assumed to never expire.
30+
*/
31+
public isValid(key: string): boolean {
32+
if (this.credentialsCache[key]) {
33+
const expiration = this.credentialsCache[key].credentials.expiration
34+
return expiration !== undefined ? expiration >= new Date() : true
35+
}
36+
37+
return false
38+
}
39+
2640
/**
2741
* Returns undefined if the specified credentials are expired or not found.
2842
*/
2943
public async getCredentials(credentials: CredentialsId): Promise<CachedCredentials | undefined> {
30-
if (
31-
this.credentialsCache[asString(credentials)] &&
32-
!this.credentialsCache[asString(credentials)].credentials.expired
33-
) {
44+
if (this.isValid(asString(credentials))) {
3445
return this.credentialsCache[asString(credentials)]
3546
} else {
3647
return undefined

0 commit comments

Comments
 (0)