Skip to content

Commit 2ffc611

Browse files
committed
feat(credential-providers): pass caller client options to fromTemporaryCredentials inner STSClient
1 parent 84d6c18 commit 2ffc611

File tree

8 files changed

+155
-316
lines changed

8 files changed

+155
-316
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ CHANGELOG.md
44
**/*.hbs
55
**/*/report.md
66
clients/*/src/endpoint/ruleset.ts
7+
packages/nested-clients/src/submodules/*/endpoint/ruleset.ts
78
**/*.java

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const resolveRegion = async (
8181
*/
8282
export const getDefaultRoleAssumer = (
8383
stsOptions: STSRoleAssumerOptions,
84-
stsClientCtor: new (options: STSClientConfig) => STSClient
84+
STSClient: new (options: STSClientConfig) => STSClient
8585
): RoleAssumer => {
8686
let stsClient: STSClient;
8787
let closureSourceCreds: AwsCredentialIdentity;
@@ -101,7 +101,8 @@ export const getDefaultRoleAssumer = (
101101
);
102102
const isCompatibleRequestHandler = !isH2(requestHandler);
103103

104-
stsClient = new stsClientCtor({
104+
stsClient = new STSClient({
105+
profile: stsOptions?.parentClientConfig?.profile,
105106
// A hack to make sts client uses the credential in current closure.
106107
credentialDefaultProvider: () => async () => closureSourceCreds,
107108
region: resolvedRegion,
@@ -143,7 +144,7 @@ export type RoleAssumerWithWebIdentity = (
143144
*/
144145
export const getDefaultRoleAssumerWithWebIdentity = (
145146
stsOptions: STSRoleAssumerOptions,
146-
stsClientCtor: new (options: STSClientConfig) => STSClient
147+
STSClient: new (options: STSClientConfig) => STSClient
147148
): RoleAssumerWithWebIdentity => {
148149
let stsClient: STSClient;
149150
return async (params) => {
@@ -161,7 +162,8 @@ export const getDefaultRoleAssumerWithWebIdentity = (
161162
);
162163
const isCompatibleRequestHandler = !isH2(requestHandler);
163164

164-
stsClient = new stsClientCtor({
165+
stsClient = new STSClient({
166+
profile: stsOptions?.parentClientConfig?.profile,
165167
region: resolvedRegion,
166168
requestHandler: isCompatibleRequestHandler ? (requestHandler as any) : undefined,
167169
logger: logger as any,

packages/credential-providers/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"@aws-sdk/credential-provider-web-identity": "*",
4343
"@aws-sdk/nested-clients": "*",
4444
"@aws-sdk/types": "*",
45+
"@smithy/core": "^3.0.0",
4546
"@smithy/credential-provider-imds": "^4.0.0",
4647
"@smithy/property-provider": "^4.0.0",
4748
"@smithy/types": "^4.0.0",

packages/credential-providers/src/fromTemporaryCredentials.base.ts

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ import type {
44
CredentialProviderOptions,
55
RuntimeConfigAwsCredentialIdentityProvider,
66
} from "@aws-sdk/types";
7+
import { normalizeProvider } from "@smithy/core";
78
import { CredentialsProviderError } from "@smithy/property-provider";
8-
import { AwsCredentialIdentity, AwsCredentialIdentityProvider, Pluggable } from "@smithy/types";
9+
import { AwsCredentialIdentity, AwsCredentialIdentityProvider, Logger, Pluggable, RequestHandler } from "@smithy/types";
910

1011
export interface FromTemporaryCredentialsOptions extends CredentialProviderOptions {
1112
params: Omit<AssumeRoleCommandInput, "RoleSessionName"> & { RoleSessionName?: string };
1213
masterCredentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
1314
clientConfig?: STSClientConfig;
15+
logger?: Logger;
1416
clientPlugins?: Pluggable<any, any>[];
1517
mfaCodeProvider?: (mfaSerial: string) => Promise<string>;
1618
}
1719

20+
const ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
21+
1822
export const fromTemporaryCredentials = (
1923
options: FromTemporaryCredentialsOptions,
2024
credentialDefaultProvider?: () => AwsCredentialIdentityProvider
@@ -41,15 +45,59 @@ export const fromTemporaryCredentials = (
4145
if (!stsClient) {
4246
const defaultCredentialsOrError =
4347
typeof credentialDefaultProvider === "function" ? credentialDefaultProvider() : undefined;
44-
4548
const { callerClientConfig } = awsIdentityProperties;
49+
50+
const credentialSources = [
51+
options.masterCredentials,
52+
options.clientConfig?.credentials,
53+
callerClientConfig?.credentials,
54+
callerClientConfig?.credentialDefaultProvider?.(),
55+
defaultCredentialsOrError,
56+
];
57+
let credentialSource = "STS client default credentials";
58+
if (credentialSources[0]) {
59+
credentialSource = "options.masterCredentials";
60+
} else if (credentialSources[1]) {
61+
credentialSource = "options.clientConfig.credentials";
62+
} else if (credentialSources[2]) {
63+
credentialSource = "caller client's credentials";
64+
} else if (credentialSources[3]) {
65+
credentialSource = "caller client's credentialDefaultProvider";
66+
}
67+
68+
const regionSources = [options.clientConfig?.region, callerClientConfig?.region, ASSUME_ROLE_DEFAULT_REGION];
69+
let regionSource = "default partition's default region";
70+
if (regionSources[0]) {
71+
regionSource = "options.clientConfig.region";
72+
} else if (regionSources[1]) {
73+
regionSource = "caller client's region";
74+
}
75+
76+
const requestHandlerSources = [
77+
filterRequestHandler(options.clientConfig?.requestHandler),
78+
filterRequestHandler(callerClientConfig?.requestHandler),
79+
];
80+
let requestHandlerSource = "STS default requestHandler";
81+
if (requestHandlerSources[0]) {
82+
requestHandlerSource = "options.clientConfig.requestHandler";
83+
} else if (requestHandlerSources[1]) {
84+
requestHandlerSource = "caller client's requestHandler";
85+
}
86+
87+
options.logger?.debug?.(
88+
`@aws-sdk/credential-providers - fromTemporaryCredentials STS client init with ` +
89+
`${regionSource}=${await normalizeProvider(
90+
coalesce(regionSources)
91+
)()}, ${credentialSource}, ${requestHandlerSource}.`
92+
);
93+
4694
stsClient = new STSClient({
4795
...options.clientConfig,
48-
credentials:
49-
options.masterCredentials ??
50-
options.clientConfig?.credentials ??
51-
callerClientConfig?.credentialDefaultProvider?.() ??
52-
defaultCredentialsOrError,
96+
credentials: coalesce(credentialSources),
97+
logger: options.logger,
98+
profile: options.clientConfig?.profile ?? callerClientConfig?.profile,
99+
region: coalesce(regionSources),
100+
requestHandler: coalesce(requestHandlerSources),
53101
});
54102
}
55103
if (options.clientPlugins) {
@@ -73,3 +121,21 @@ export const fromTemporaryCredentials = (
73121
};
74122
};
75123
};
124+
125+
/**
126+
* @internal
127+
*/
128+
const filterRequestHandler = (requestHandler: STSClientConfig["requestHandler"]): undefined | typeof requestHandler => {
129+
return (requestHandler as RequestHandler<any, any>)?.metadata?.handlerProtocol === "h2" ? undefined : requestHandler;
130+
};
131+
132+
/**
133+
* @internal
134+
*/
135+
const coalesce = (...args: any) => {
136+
for (const item of args) {
137+
if (item !== undefined) {
138+
return item;
139+
}
140+
}
141+
};

packages/nested-clients/src/submodules/sso-oidc/endpoint/ruleset.ts

Lines changed: 25 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -6,128 +6,29 @@ import { RuleSetObject } from "@smithy/types";
66
or see "smithy.rules#endpointRuleSet"
77
in codegen/sdk-codegen/aws-models/sso-oidc.json */
88

9-
const u = "required",
10-
v = "fn",
11-
w = "argv",
12-
x = "ref";
13-
const a = true,
14-
b = "isSet",
15-
c = "booleanEquals",
16-
d = "error",
17-
e = "endpoint",
18-
f = "tree",
19-
g = "PartitionResult",
20-
h = "getAttr",
21-
i = { [u]: false, type: "String" },
22-
j = { [u]: true, default: false, type: "Boolean" },
23-
k = { [x]: "Endpoint" },
24-
l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] },
25-
m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] },
26-
n = {},
27-
o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] },
28-
p = { [x]: g },
29-
q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] },
30-
r = [l],
31-
s = [m],
32-
t = [{ [x]: "Region" }];
33-
const _data = {
34-
version: "1.0",
35-
parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i },
36-
rules: [
37-
{
38-
conditions: [{ [v]: b, [w]: [k] }],
39-
rules: [
40-
{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d },
41-
{ conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d },
42-
{ endpoint: { url: k, properties: n, headers: n }, type: e },
43-
],
44-
type: f,
45-
},
46-
{
47-
conditions: [{ [v]: b, [w]: t }],
48-
rules: [
49-
{
50-
conditions: [{ [v]: "aws.partition", [w]: t, assign: g }],
51-
rules: [
52-
{
53-
conditions: [l, m],
54-
rules: [
55-
{
56-
conditions: [{ [v]: c, [w]: [a, o] }, q],
57-
rules: [
58-
{
59-
endpoint: {
60-
url: "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}",
61-
properties: n,
62-
headers: n,
63-
},
64-
type: e,
65-
},
66-
],
67-
type: f,
68-
},
69-
{ error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d },
70-
],
71-
type: f,
72-
},
73-
{
74-
conditions: r,
75-
rules: [
76-
{
77-
conditions: [{ [v]: c, [w]: [o, a] }],
78-
rules: [
79-
{
80-
conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }],
81-
endpoint: { url: "https://oidc.{Region}.amazonaws.com", properties: n, headers: n },
82-
type: e,
83-
},
84-
{
85-
endpoint: {
86-
url: "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}",
87-
properties: n,
88-
headers: n,
89-
},
90-
type: e,
91-
},
92-
],
93-
type: f,
94-
},
95-
{ error: "FIPS is enabled but this partition does not support FIPS", type: d },
96-
],
97-
type: f,
98-
},
99-
{
100-
conditions: s,
101-
rules: [
102-
{
103-
conditions: [q],
104-
rules: [
105-
{
106-
endpoint: {
107-
url: "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}",
108-
properties: n,
109-
headers: n,
110-
},
111-
type: e,
112-
},
113-
],
114-
type: f,
115-
},
116-
{ error: "DualStack is enabled but this partition does not support DualStack", type: d },
117-
],
118-
type: f,
119-
},
120-
{
121-
endpoint: { url: "https://oidc.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n },
122-
type: e,
123-
},
124-
],
125-
type: f,
126-
},
127-
],
128-
type: f,
129-
},
130-
{ error: "Invalid Configuration: Missing Region", type: d },
131-
],
132-
};
9+
const u="required",
10+
v="fn",
11+
w="argv",
12+
x="ref";
13+
const a=true,
14+
b="isSet",
15+
c="booleanEquals",
16+
d="error",
17+
e="endpoint",
18+
f="tree",
19+
g="PartitionResult",
20+
h="getAttr",
21+
i={[u]:false,"type":"String"},
22+
j={[u]:true,"default":false,"type":"Boolean"},
23+
k={[x]:"Endpoint"},
24+
l={[v]:c,[w]:[{[x]:"UseFIPS"},true]},
25+
m={[v]:c,[w]:[{[x]:"UseDualStack"},true]},
26+
n={},
27+
o={[v]:h,[w]:[{[x]:g},"supportsFIPS"]},
28+
p={[x]:g},
29+
q={[v]:c,[w]:[true,{[v]:h,[w]:[p,"supportsDualStack"]}]},
30+
r=[l],
31+
s=[m],
32+
t=[{[x]:"Region"}];
33+
const _data={version:"1.0",parameters:{Region:i,UseDualStack:j,UseFIPS:j,Endpoint:i},rules:[{conditions:[{[v]:b,[w]:[k]}],rules:[{conditions:r,error:"Invalid Configuration: FIPS and custom endpoint are not supported",type:d},{conditions:s,error:"Invalid Configuration: Dualstack and custom endpoint are not supported",type:d},{endpoint:{url:k,properties:n,headers:n},type:e}],type:f},{conditions:[{[v]:b,[w]:t}],rules:[{conditions:[{[v]:"aws.partition",[w]:t,assign:g}],rules:[{conditions:[l,m],rules:[{conditions:[{[v]:c,[w]:[a,o]},q],rules:[{endpoint:{url:"https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}",properties:n,headers:n},type:e}],type:f},{error:"FIPS and DualStack are enabled, but this partition does not support one or both",type:d}],type:f},{conditions:r,rules:[{conditions:[{[v]:c,[w]:[o,a]}],rules:[{conditions:[{[v]:"stringEquals",[w]:[{[v]:h,[w]:[p,"name"]},"aws-us-gov"]}],endpoint:{url:"https://oidc.{Region}.amazonaws.com",properties:n,headers:n},type:e},{endpoint:{url:"https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}",properties:n,headers:n},type:e}],type:f},{error:"FIPS is enabled but this partition does not support FIPS",type:d}],type:f},{conditions:s,rules:[{conditions:[q],rules:[{endpoint:{url:"https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}",properties:n,headers:n},type:e}],type:f},{error:"DualStack is enabled but this partition does not support DualStack",type:d}],type:f},{endpoint:{url:"https://oidc.{Region}.{PartitionResult#dnsSuffix}",properties:n,headers:n},type:e}],type:f}],type:f},{error:"Invalid Configuration: Missing Region",type:d}]};
13334
export const ruleSet: RuleSetObject = _data;

packages/nested-clients/src/submodules/sts/defaultStsRoleAssumers.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const resolveRegion = async (
8484
*/
8585
export const getDefaultRoleAssumer = (
8686
stsOptions: STSRoleAssumerOptions,
87-
stsClientCtor: new (options: STSClientConfig) => STSClient
87+
STSClient: new (options: STSClientConfig) => STSClient
8888
): RoleAssumer => {
8989
let stsClient: STSClient;
9090
let closureSourceCreds: AwsCredentialIdentity;
@@ -104,7 +104,8 @@ export const getDefaultRoleAssumer = (
104104
);
105105
const isCompatibleRequestHandler = !isH2(requestHandler);
106106

107-
stsClient = new stsClientCtor({
107+
stsClient = new STSClient({
108+
profile: stsOptions?.parentClientConfig?.profile,
108109
// A hack to make sts client uses the credential in current closure.
109110
credentialDefaultProvider: () => async () => closureSourceCreds,
110111
region: resolvedRegion,
@@ -146,7 +147,7 @@ export type RoleAssumerWithWebIdentity = (
146147
*/
147148
export const getDefaultRoleAssumerWithWebIdentity = (
148149
stsOptions: STSRoleAssumerOptions,
149-
stsClientCtor: new (options: STSClientConfig) => STSClient
150+
STSClient: new (options: STSClientConfig) => STSClient
150151
): RoleAssumerWithWebIdentity => {
151152
let stsClient: STSClient;
152153
return async (params) => {
@@ -164,7 +165,8 @@ export const getDefaultRoleAssumerWithWebIdentity = (
164165
);
165166
const isCompatibleRequestHandler = !isH2(requestHandler);
166167

167-
stsClient = new stsClientCtor({
168+
stsClient = new STSClient({
169+
profile: stsOptions?.parentClientConfig?.profile,
168170
region: resolvedRegion,
169171
requestHandler: isCompatibleRequestHandler ? (requestHandler as any) : undefined,
170172
logger: logger as any,

0 commit comments

Comments
 (0)