Skip to content

Commit 089f1a4

Browse files
authored
chore(credential-providers): add credential attribution (#6546)
* chore(credential-providers): add credential attribution * chore(credential-providers): attribute credential feature sources * test(credential-provider-node): add credential source assertions * test: fix unit test * test(credential-providers): fix unit tests * chore(core): separate function files * chore: undo script change * chore: change Promise.resolve to async fn
1 parent 7a98e5f commit 089f1a4

38 files changed

+326
-63
lines changed

clients/client-sts/src/defaultStsRoleAssumers.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// smithy-typescript generated code
22
// Please do not touch this file. It's generated from template in:
33
// https://github.com/aws/aws-sdk-js-v3/blob/main/codegen/smithy-aws-typescript-codegen/src/main/resources/software/amazon/smithy/aws/typescript/codegen/sts-client-defaultStsRoleAssumers.ts
4+
import { setCredentialFeature } from "@aws-sdk/core/client";
45
import type { CredentialProviderOptions } from "@aws-sdk/types";
56
import { AwsCredentialIdentity, Logger, Provider } from "@smithy/types";
67

@@ -118,7 +119,7 @@ export const getDefaultRoleAssumer = (
118119

119120
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
120121

121-
return {
122+
const credentials = {
122123
accessKeyId: Credentials.AccessKeyId,
123124
secretAccessKey: Credentials.SecretAccessKey,
124125
sessionToken: Credentials.SessionToken,
@@ -127,6 +128,8 @@ export const getDefaultRoleAssumer = (
127128
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
128129
...(accountId && { accountId }),
129130
};
131+
setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE", "i");
132+
return credentials;
130133
};
131134
};
132135

@@ -174,7 +177,7 @@ export const getDefaultRoleAssumerWithWebIdentity = (
174177

175178
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
176179

177-
return {
180+
const credentials = {
178181
accessKeyId: Credentials.AccessKeyId,
179182
secretAccessKey: Credentials.SecretAccessKey,
180183
sessionToken: Credentials.SessionToken,
@@ -183,6 +186,11 @@ export const getDefaultRoleAssumerWithWebIdentity = (
183186
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
184187
...(accountId && { accountId }),
185188
};
189+
if (accountId) {
190+
setCredentialFeature(credentials, "RESOLVED_ACCOUNT_ID", "T");
191+
}
192+
setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k");
193+
return credentials;
186194
};
187195
};
188196

codegen/smithy-aws-typescript-codegen/src/main/resources/software/amazon/smithy/aws/typescript/codegen/sts-client-defaultStsRoleAssumers.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { setCredentialFeature } from "@aws-sdk/core/client";
12
import type { CredentialProviderOptions } from "@aws-sdk/types";
23
import { AwsCredentialIdentity, Logger, Provider } from "@smithy/types";
34

@@ -115,7 +116,7 @@ export const getDefaultRoleAssumer = (
115116

116117
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
117118

118-
return {
119+
const credentials = {
119120
accessKeyId: Credentials.AccessKeyId,
120121
secretAccessKey: Credentials.SecretAccessKey,
121122
sessionToken: Credentials.SessionToken,
@@ -124,6 +125,8 @@ export const getDefaultRoleAssumer = (
124125
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
125126
...(accountId && { accountId }),
126127
};
128+
setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE", "i");
129+
return credentials;
127130
};
128131
};
129132

@@ -171,7 +174,7 @@ export const getDefaultRoleAssumerWithWebIdentity = (
171174

172175
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
173176

174-
return {
177+
const credentials = {
175178
accessKeyId: Credentials.AccessKeyId,
176179
secretAccessKey: Credentials.SecretAccessKey,
177180
sessionToken: Credentials.SessionToken,
@@ -180,6 +183,11 @@ export const getDefaultRoleAssumerWithWebIdentity = (
180183
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
181184
...(accountId && { accountId }),
182185
};
186+
if (accountId) {
187+
setCredentialFeature(credentials, "RESOLVED_ACCOUNT_ID", "T");
188+
}
189+
setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k");
190+
return credentials;
183191
};
184192
};
185193

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from "./emitWarningIfUnsupportedVersion";
2+
export * from "./setCredentialFeature";
23
export * from "./setFeature";
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { AttributedAwsCredentialIdentity } from "@aws-sdk/types";
2+
3+
import { setCredentialFeature } from "./setCredentialFeature";
4+
5+
describe(setCredentialFeature.name, () => {
6+
it("should create the data path if it does't exist", () => {
7+
const credentials = {
8+
accessKeyId: "",
9+
secretAccessKey: "",
10+
} as AttributedAwsCredentialIdentity;
11+
expect(setCredentialFeature(credentials, "CREDENTIALS_CODE", "e")).toEqual({
12+
accessKeyId: "",
13+
secretAccessKey: "",
14+
$source: {
15+
CREDENTIALS_CODE: "e",
16+
},
17+
});
18+
});
19+
20+
it("should track a set of features", () => {
21+
const credentials = {
22+
accessKeyId: "",
23+
secretAccessKey: "",
24+
} as AttributedAwsCredentialIdentity;
25+
26+
setCredentialFeature(credentials, "CREDENTIALS_CODE", "e");
27+
setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS", "g");
28+
// it ignores duplicates.
29+
setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS", "g");
30+
31+
expect(setCredentialFeature(credentials, "CREDENTIALS_CODE", "e")).toEqual({
32+
accessKeyId: "",
33+
secretAccessKey: "",
34+
$source: {
35+
CREDENTIALS_CODE: "e",
36+
CREDENTIALS_ENV_VARS: "g",
37+
},
38+
});
39+
});
40+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { AttributedAwsCredentialIdentity, AwsSdkCredentialsFeatures } from "@aws-sdk/types";
2+
3+
/**
4+
* @internal
5+
*
6+
* @returns the credentials with source feature attribution.
7+
*/
8+
export function setCredentialFeature<F extends keyof AwsSdkCredentialsFeatures>(
9+
credentials: AttributedAwsCredentialIdentity,
10+
feature: F,
11+
value: AwsSdkCredentialsFeatures[F]
12+
): AttributedAwsCredentialIdentity {
13+
if (!credentials.$source) {
14+
credentials.$source = {};
15+
}
16+
credentials.$source![feature] = value;
17+
return credentials;
18+
}

packages/core/src/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4Config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { setCredentialFeature } from "@aws-sdk/core/client";
2+
import { AttributedAwsCredentialIdentity } from "@aws-sdk/types";
13
import {
24
doesIdentityRequireRefresh,
35
isIdentityExpired,
@@ -102,9 +104,11 @@ export interface AwsSdkSigV4AuthResolvedConfig {
102104
export const resolveAwsSdkSigV4Config = <T>(
103105
config: T & AwsSdkSigV4AuthInputConfig & AwsSdkSigV4PreviouslyResolved
104106
): T & AwsSdkSigV4AuthResolvedConfig => {
107+
let isUserSupplied = false;
105108
// Normalize credentials
106109
let normalizedCreds: AwsCredentialIdentityProvider | undefined;
107110
if (config.credentials) {
111+
isUserSupplied = true;
108112
normalizedCreds = memoizeIdentityProvider(config.credentials, isIdentityExpired, doesIdentityRequireRefresh);
109113
}
110114
if (!normalizedCreds) {
@@ -218,7 +222,12 @@ export const resolveAwsSdkSigV4Config = <T>(
218222
...config,
219223
systemClockOffset,
220224
signingEscapePath,
221-
credentials: normalizedCreds!,
225+
credentials: isUserSupplied
226+
? async () =>
227+
normalizedCreds!().then((creds: AttributedAwsCredentialIdentity) =>
228+
setCredentialFeature(creds, "CREDENTIALS_CODE", "e")
229+
)
230+
: normalizedCreds!,
222231
signer,
223232
};
224233
};

packages/credential-provider-env/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
},
2525
"license": "Apache-2.0",
2626
"dependencies": {
27+
"@aws-sdk/core": "*",
2728
"@aws-sdk/types": "*",
2829
"@smithy/property-provider": "^3.1.7",
2930
"@smithy/types": "^3.5.0",

packages/credential-provider-env/src/fromEnv.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ describe(fromEnv.name, () => {
3333
sessionToken: mockSessionToken,
3434
expiration: new Date(mockExpiration),
3535
accountId: mockAccountId,
36+
$source: {
37+
CREDENTIALS_ENV_VARS: "g",
38+
},
3639
});
3740
});
3841

@@ -44,6 +47,9 @@ describe(fromEnv.name, () => {
4447
expect(receivedCreds).toStrictEqual({
4548
accessKeyId: mockAccessKeyId,
4649
secretAccessKey: mockSecretAccessKey,
50+
$source: {
51+
CREDENTIALS_ENV_VARS: "g",
52+
},
4753
});
4854
});
4955

packages/credential-provider-env/src/fromEnv.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { CredentialProviderOptions } from "@aws-sdk/types";
1+
import { setCredentialFeature } from "@aws-sdk/core/client";
2+
import type { AttributedAwsCredentialIdentity, CredentialProviderOptions } from "@aws-sdk/types";
23
import { CredentialsProviderError } from "@smithy/property-provider";
34
import { AwsCredentialIdentityProvider } from "@smithy/types";
45

@@ -48,14 +49,16 @@ export const fromEnv =
4849
const accountId: string | undefined = process.env[ENV_ACCOUNT_ID];
4950

5051
if (accessKeyId && secretAccessKey) {
51-
return {
52+
const credentials = {
5253
accessKeyId,
5354
secretAccessKey,
5455
...(sessionToken && { sessionToken }),
5556
...(expiry && { expiration: new Date(expiry) }),
5657
...(credentialScope && { credentialScope }),
5758
...(accountId && { accountId }),
58-
};
59+
} as AttributedAwsCredentialIdentity;
60+
setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS", "g");
61+
return credentials;
5962
}
6063

6164
throw new CredentialsProviderError("Unable to find environment variable credentials.", { logger: init?.logger });

packages/credential-provider-http/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"license": "Apache-2.0",
2828
"dependencies": {
29+
"@aws-sdk/core": "*",
2930
"@aws-sdk/types": "*",
3031
"@smithy/fetch-http-handler": "^3.2.9",
3132
"@smithy/node-http-handler": "^3.2.4",

0 commit comments

Comments
 (0)