Skip to content

Commit d5011a5

Browse files
authored
chore: release accountId-endpoints credential-provider changes
This reverts commit 3ca8179.
1 parent 0220bd0 commit d5011a5

File tree

15 files changed

+261
-42
lines changed

15 files changed

+261
-42
lines changed

clients/client-sts/src/defaultStsRoleAssumers.ts

+37-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,31 @@ export type RoleAssumer = (
2929

3030
const ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
3131

32+
interface AssumedRoleUser {
33+
/**
34+
* The ARN of the temporary security credentials that are returned from the AssumeRole action.
35+
*/
36+
Arn?: string;
37+
38+
/**
39+
* A unique identifier that contains the role ID and the role session name of the role that is being assumed.
40+
*/
41+
AssumedRoleId?: string;
42+
}
43+
44+
/**
45+
* @internal
46+
*/
47+
const getAccountIdFromAssumedRoleUser = (assumedRoleUser?: AssumedRoleUser) => {
48+
if (typeof assumedRoleUser?.Arn === "string") {
49+
const arnComponents = assumedRoleUser.Arn.split(":");
50+
if (arnComponents.length > 4 && arnComponents[4] !== "") {
51+
return arnComponents[4];
52+
}
53+
}
54+
return undefined;
55+
};
56+
3257
/**
3358
* @internal
3459
*
@@ -84,17 +109,21 @@ export const getDefaultRoleAssumer = (
84109
logger: logger as any,
85110
});
86111
}
87-
const { Credentials } = await stsClient.send(new AssumeRoleCommand(params));
112+
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleCommand(params));
88113
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
89114
throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`);
90115
}
116+
117+
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
118+
91119
return {
92120
accessKeyId: Credentials.AccessKeyId,
93121
secretAccessKey: Credentials.SecretAccessKey,
94122
sessionToken: Credentials.SessionToken,
95123
expiration: Credentials.Expiration,
96124
// TODO(credentialScope): access normally when shape is updated.
97-
credentialScope: (Credentials as any).CredentialScope,
125+
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
126+
...(accountId && { accountId }),
98127
};
99128
};
100129
};
@@ -134,17 +163,21 @@ export const getDefaultRoleAssumerWithWebIdentity = (
134163
logger: logger as any,
135164
});
136165
}
137-
const { Credentials } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
166+
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
138167
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
139168
throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`);
140169
}
170+
171+
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
172+
141173
return {
142174
accessKeyId: Credentials.AccessKeyId,
143175
secretAccessKey: Credentials.SecretAccessKey,
144176
sessionToken: Credentials.SessionToken,
145177
expiration: Credentials.Expiration,
146178
// TODO(credentialScope): access normally when shape is updated.
147-
credentialScope: (Credentials as any).CredentialScope,
179+
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
180+
...(accountId && { accountId }),
148181
};
149182
};
150183
};

clients/client-sts/test/defaultRoleAssumers.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ describe("getDefaultRoleAssumer", () => {
8989
);
9090
});
9191

92+
it("should return accountId in the credentials", async () => {
93+
const roleAssumer = getDefaultRoleAssumer();
94+
const params: AssumeRoleCommandInput = {
95+
RoleArn: "arn:aws:foo",
96+
RoleSessionName: "session",
97+
};
98+
const sourceCred = { accessKeyId: "key", secretAccessKey: "secrete" };
99+
const assumedRole = await roleAssumer(sourceCred, params);
100+
expect(assumedRole.accountId).toEqual("123");
101+
});
102+
92103
it("should use the STS client config", async () => {
93104
const logger = console;
94105
const region = "some-region";
@@ -169,6 +180,10 @@ describe("getDefaultRoleAssumer", () => {
169180
describe("getDefaultRoleAssumerWithWebIdentity", () => {
170181
const assumeRoleResponse = `<Response xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
171182
<AssumeRoleWithWebIdentityResult>
183+
<AssumedRoleUser>
184+
<AssumedRoleId>AROAZOX2IL27GNRBJHWC2:session</AssumedRoleId>
185+
<Arn>arn:aws:sts::123456789012:assumed-role/assume-role-test/session</Arn>
186+
</AssumedRoleUser>
172187
<Credentials>
173188
<AccessKeyId>key</AccessKeyId>
174189
<SecretAccessKey>secrete</SecretAccessKey>
@@ -209,6 +224,17 @@ describe("getDefaultRoleAssumerWithWebIdentity", () => {
209224
});
210225
});
211226

227+
it("should return accountId in the credentials", async () => {
228+
const roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity();
229+
const params: AssumeRoleWithWebIdentityCommandInput = {
230+
RoleArn: "arn:aws:foo",
231+
RoleSessionName: "session",
232+
WebIdentityToken: "token",
233+
};
234+
const assumedRole = await roleAssumerWithWebIdentity(params);
235+
expect(assumedRole.accountId).toEqual("123456789012");
236+
});
237+
212238
it("should use the STS client middleware", async () => {
213239
const customMiddlewareFunction = jest.fn();
214240
const roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity({}, [

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

+26
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ describe("getDefaultRoleAssumer", () => {
8787
);
8888
});
8989

90+
it("should return accountId in the credentials", async () => {
91+
const roleAssumer = getDefaultRoleAssumer();
92+
const params: AssumeRoleCommandInput = {
93+
RoleArn: "arn:aws:foo",
94+
RoleSessionName: "session",
95+
};
96+
const sourceCred = { accessKeyId: "key", secretAccessKey: "secrete" };
97+
const assumedRole = await roleAssumer(sourceCred, params);
98+
expect(assumedRole.accountId).toEqual("123");
99+
});
100+
90101
it("should use the STS client config", async () => {
91102
const logger = console;
92103
const region = "some-region";
@@ -167,6 +178,10 @@ describe("getDefaultRoleAssumer", () => {
167178
describe("getDefaultRoleAssumerWithWebIdentity", () => {
168179
const assumeRoleResponse = `<Response xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
169180
<AssumeRoleWithWebIdentityResult>
181+
<AssumedRoleUser>
182+
<AssumedRoleId>AROAZOX2IL27GNRBJHWC2:session</AssumedRoleId>
183+
<Arn>arn:aws:sts::123456789012:assumed-role/assume-role-test/session</Arn>
184+
</AssumedRoleUser>
170185
<Credentials>
171186
<AccessKeyId>key</AccessKeyId>
172187
<SecretAccessKey>secrete</SecretAccessKey>
@@ -207,6 +222,17 @@ describe("getDefaultRoleAssumerWithWebIdentity", () => {
207222
});
208223
});
209224

225+
it("should return accountId in the credentials", async () => {
226+
const roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity();
227+
const params: AssumeRoleWithWebIdentityCommandInput = {
228+
RoleArn: "arn:aws:foo",
229+
RoleSessionName: "session",
230+
WebIdentityToken: "token",
231+
};
232+
const assumedRole = await roleAssumerWithWebIdentity(params);
233+
expect(assumedRole.accountId).toEqual("123456789012");
234+
});
235+
210236
it("should use the STS client middleware", async () => {
211237
const customMiddlewareFunction = jest.fn();
212238
const roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity({}, [

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

+37-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,31 @@ export type RoleAssumer = (
2626

2727
const ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
2828

29+
interface AssumedRoleUser {
30+
/**
31+
* The ARN of the temporary security credentials that are returned from the AssumeRole action.
32+
*/
33+
Arn?: string;
34+
35+
/**
36+
* A unique identifier that contains the role ID and the role session name of the role that is being assumed.
37+
*/
38+
AssumedRoleId?: string;
39+
}
40+
41+
/**
42+
* @internal
43+
*/
44+
const getAccountIdFromAssumedRoleUser = (assumedRoleUser?: AssumedRoleUser) => {
45+
if (typeof assumedRoleUser?.Arn === "string") {
46+
const arnComponents = assumedRoleUser.Arn.split(":");
47+
if (arnComponents.length > 4 && arnComponents[4] !== "") {
48+
return arnComponents[4];
49+
}
50+
}
51+
return undefined;
52+
};
53+
2954
/**
3055
* @internal
3156
*
@@ -81,17 +106,21 @@ export const getDefaultRoleAssumer = (
81106
logger: logger as any,
82107
});
83108
}
84-
const { Credentials } = await stsClient.send(new AssumeRoleCommand(params));
109+
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleCommand(params));
85110
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
86111
throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`);
87112
}
113+
114+
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
115+
88116
return {
89117
accessKeyId: Credentials.AccessKeyId,
90118
secretAccessKey: Credentials.SecretAccessKey,
91119
sessionToken: Credentials.SessionToken,
92120
expiration: Credentials.Expiration,
93121
// TODO(credentialScope): access normally when shape is updated.
94-
credentialScope: (Credentials as any).CredentialScope,
122+
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
123+
...(accountId && { accountId }),
95124
};
96125
};
97126
};
@@ -131,17 +160,21 @@ export const getDefaultRoleAssumerWithWebIdentity = (
131160
logger: logger as any,
132161
});
133162
}
134-
const { Credentials } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
163+
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
135164
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
136165
throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`);
137166
}
167+
168+
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
169+
138170
return {
139171
accessKeyId: Credentials.AccessKeyId,
140172
secretAccessKey: Credentials.SecretAccessKey,
141173
sessionToken: Credentials.SessionToken,
142174
expiration: Credentials.Expiration,
143175
// TODO(credentialScope): access normally when shape is updated.
144-
credentialScope: (Credentials as any).CredentialScope,
176+
...((Credentials as any).CredentialScope && { credentialScope: (Credentials as any).CredentialScope }),
177+
...(accountId && { accountId }),
145178
};
146179
};
147180
};

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

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { CredentialsProviderError } from "@smithy/property-provider";
22

3-
import { ENV_EXPIRATION, ENV_KEY, ENV_SECRET, ENV_SESSION, fromEnv } from "./fromEnv";
3+
import { ENV_ACCOUNT_ID, ENV_EXPIRATION, ENV_KEY, ENV_SECRET, ENV_SESSION, fromEnv } from "./fromEnv";
44

55
describe(fromEnv.name, () => {
66
const ORIGINAL_ENV = process.env;
77
const mockAccessKeyId = "mockAccessKeyId";
88
const mockSecretAccessKey = "mockSecretAccessKey";
99
const mockSessionToken = "mockSessionToken";
1010
const mockExpiration = new Date().toISOString();
11+
const mockAccountId = "123456789012";
1112

1213
beforeEach(() => {
1314
process.env = {
@@ -16,6 +17,7 @@ describe(fromEnv.name, () => {
1617
[ENV_SECRET]: mockSecretAccessKey,
1718
[ENV_SESSION]: mockSessionToken,
1819
[ENV_EXPIRATION]: mockExpiration,
20+
[ENV_ACCOUNT_ID]: mockAccountId,
1921
};
2022
});
2123

@@ -30,19 +32,33 @@ describe(fromEnv.name, () => {
3032
secretAccessKey: mockSecretAccessKey,
3133
sessionToken: mockSessionToken,
3234
expiration: new Date(mockExpiration),
35+
accountId: mockAccountId,
3336
});
3437
});
3538

36-
it("can create credentials without a session token or expiration", async () => {
39+
it("can create credentials without a session token, accountId, or expiration", async () => {
3740
delete process.env[ENV_SESSION];
3841
delete process.env[ENV_EXPIRATION];
42+
delete process.env[ENV_ACCOUNT_ID];
3943
const receivedCreds = await fromEnv()();
4044
expect(receivedCreds).toStrictEqual({
4145
accessKeyId: mockAccessKeyId,
4246
secretAccessKey: mockSecretAccessKey,
4347
});
4448
});
4549

50+
it("should include accountId when it is provided in environment variables", async () => {
51+
process.env[ENV_ACCOUNT_ID] = mockAccountId;
52+
const receivedCreds = await fromEnv()();
53+
expect(receivedCreds).toHaveProperty("accountId", mockAccountId);
54+
});
55+
56+
it("should not include accountId when it is not provided in environment variables", async () => {
57+
delete process.env[ENV_ACCOUNT_ID]; // Ensure accountId is not set
58+
const receivedCreds = await fromEnv()();
59+
expect(receivedCreds).not.toHaveProperty("accountId");
60+
});
61+
4662
it.each([ENV_KEY, ENV_SECRET])("throws if env['%s'] is not found", async (key) => {
4763
delete process.env[key];
4864
const expectedError = new CredentialsProviderError("Unable to find environment variable credentials.");

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

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export const ENV_EXPIRATION = "AWS_CREDENTIAL_EXPIRATION";
2424
* @internal
2525
*/
2626
export const ENV_CREDENTIAL_SCOPE = "AWS_CREDENTIAL_SCOPE";
27+
/**
28+
* @internal
29+
*/
30+
export const ENV_ACCOUNT_ID = "AWS_ACCOUNT_ID";
2731

2832
/**
2933
* @internal
@@ -41,6 +45,7 @@ export const fromEnv =
4145
const sessionToken: string | undefined = process.env[ENV_SESSION];
4246
const expiry: string | undefined = process.env[ENV_EXPIRATION];
4347
const credentialScope: string | undefined = process.env[ENV_CREDENTIAL_SCOPE];
48+
const accountId: string | undefined = process.env[ENV_ACCOUNT_ID];
4449

4550
if (accessKeyId && secretAccessKey) {
4651
return {
@@ -49,6 +54,7 @@ export const fromEnv =
4954
...(sessionToken && { sessionToken }),
5055
...(expiry && { expiration: new Date(expiry) }),
5156
...(credentialScope && { credentialScope }),
57+
...(accountId && { accountId }),
5258
};
5359
}
5460

packages/credential-provider-ini/src/resolveStaticCredentials.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const getMockStaticCredsProfile = () => ({
55
aws_secret_access_key: "mock_aws_secret_access_key",
66
aws_session_token: "mock_aws_session_token",
77
aws_credential_scope: "mock_aws_credential_scope",
8+
aws_account_id: "mock_aws_account_id",
89
});
910

1011
describe(isStaticCredsProfile.name, () => {
@@ -32,6 +33,12 @@ describe(isStaticCredsProfile.name, () => {
3233
});
3334
});
3435

36+
it.each(["aws_account_id"])("value at '%s' is not of type string | undefined", (key) => {
37+
[true, null, 1, NaN, {}].forEach((value) => {
38+
expect(isStaticCredsProfile({ ...getMockStaticCredsProfile(), [key]: value })).toEqual(false);
39+
});
40+
});
41+
3542
it("returns true for StaticCredentialsProfile", () => {
3643
expect(isStaticCredsProfile(getMockStaticCredsProfile())).toEqual(true);
3744
});
@@ -46,6 +53,7 @@ describe(resolveStaticCredentials.name, () => {
4653
secretAccessKey: mockProfile.aws_secret_access_key,
4754
sessionToken: mockProfile.aws_session_token,
4855
credentialScope: mockProfile.aws_credential_scope,
56+
accountId: mockProfile.aws_account_id,
4957
});
5058
});
5159
});

packages/credential-provider-ini/src/resolveStaticCredentials.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface StaticCredsProfile extends Profile {
1010
aws_secret_access_key: string;
1111
aws_session_token?: string;
1212
aws_credential_scope?: string;
13+
aws_account_id?: string;
1314
}
1415

1516
/**
@@ -20,7 +21,8 @@ export const isStaticCredsProfile = (arg: any): arg is StaticCredsProfile =>
2021
typeof arg === "object" &&
2122
typeof arg.aws_access_key_id === "string" &&
2223
typeof arg.aws_secret_access_key === "string" &&
23-
["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1;
24+
["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1 &&
25+
["undefined", "string"].indexOf(typeof arg.aws_account_id) > -1;
2426

2527
/**
2628
* @internal
@@ -34,6 +36,7 @@ export const resolveStaticCredentials = (
3436
accessKeyId: profile.aws_access_key_id,
3537
secretAccessKey: profile.aws_secret_access_key,
3638
sessionToken: profile.aws_session_token,
37-
credentialScope: profile.aws_credential_scope,
39+
...(profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope }),
40+
...(profile.aws_account_id && { accountId: profile.aws_account_id }),
3841
});
3942
};

0 commit comments

Comments
 (0)