Skip to content

Commit bb53879

Browse files
committed
feat: Add AWS Role Assumption
1 parent 0db317c commit bb53879

File tree

6 files changed

+8672
-6363
lines changed

6 files changed

+8672
-6363
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
},
6262
"dependencies": {
6363
"@aws-crypto/sha256-js": "^4.0.0",
64+
"@aws-sdk/client-sts": "^3.312.0",
6465
"@aws-sdk/signature-v4": "^3.310.0",
6566
"abort-controller": "^3.0.0",
6667
"axios": "^0.27.2",

src/templates/core/OpenAPI.hbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type OpenAPIConfig = {
99
token?: string | Resolver<string>;
1010
accountSid?: string | Resolver<string>;
1111
authToken?: string | Resolver<string>;
12+
awsRoleArn?: string | Resolver<string>;
1213
}
1314

1415
export type OpenAPIConfig2 = {
@@ -18,4 +19,5 @@ export type OpenAPIConfig2 = {
1819
token?: string | Resolver<string>;
1920
accountSid?: string | Resolver<string>;
2021
authToken?: string | Resolver<string>;
22+
awsRoleArn?: string | Resolver<string>;
2123
}

src/templates/core/axios/request.hbs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { BaseHttpRequest } from './BaseHttpRequest';
1515
{{#if @root.awsSign}}
1616
import { SignatureV4 } from '@aws-sdk/signature-v4';
1717
import { Sha256 } from '@aws-crypto/sha256-js';
18+
import { AssumeRoleCommand, STSClient, AssumeRoleCommandOutput, Credentials } from "@aws-sdk/client-sts";
1819

1920
{{>functions/signAWS}}
2021
{{/if}}
@@ -91,7 +92,37 @@ export class AxiosHttpRequest extends BaseHttpRequest {
9192
const headers = await getHeaders(options, this.openApiConfig, url);
9293

9394
{{#if @root.awsSign}}
94-
const awsSigned = await signAWS({ url, options, headers, body: body ?? formData });
95+
let awsSigned = { headers: {} };
96+
if(this.openApiConfig.awsRoleArn) {
97+
const awsCredentails: AssumeRoleCommandOutput = await assumeAWSRole({ awsRoleArn: this.openApiConfig.awsRoleArn }, options);
98+
99+
if(!awsCredentails.Credentials) {
100+
throw new Error("Invalid AWS Role Arn");
101+
}
102+
103+
awsSigned = await signAWS({
104+
credentials: awsCredentails.Credentials,
105+
url,
106+
options,
107+
headers,
108+
body: body ?? formData
109+
});
110+
}
111+
else {
112+
awsSigned = await signAWS({
113+
credentials: {
114+
AccessKeyId: process.env.AWS_ACCESS_KEY_ID,
115+
SecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
116+
SessionToken: process.env.AWS_SESSION_TOKEN,
117+
Expiration: new Date()
118+
},
119+
url,
120+
options,
121+
headers,
122+
body: body ?? formData
123+
});
124+
}
125+
95126
{{/if}}
96127

97128
if (!onCancel.isCancelled) {
Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1-
async function signAWS({ url, options, headers, body }: { url: URL, options: ApiRequestOptions, headers: { [key: string]: any }, body?: any }): Promise<any> {
2-
if(!process.env.AWS_REGION || !process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY || !process.env.AWS_SESSION_TOKEN) {
1+
interface SignAWSPayload {
2+
credentials: Credentials
3+
url: URL,
4+
options: ApiRequestOptions,
5+
headers: { [key: string]: any },
6+
body?: any
7+
}
8+
9+
async function signAWS({ credentials, url, options, headers, body }: SignAWSPayload): Promise<any> {
10+
if(!process.env.AWS_REGION || !credentials.AccessKeyId || !credentials.SecretAccessKey || !credentials.SessionToken) {
311
throw new Error("Missing AWS Credentials");
412
}
513

614
const sigv4 = new SignatureV4({
715
service: 'execute-api',
816
region: process.env.AWS_REGION,
917
credentials: {
10-
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
11-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
12-
sessionToken: process.env.AWS_SESSION_TOKEN,
18+
accessKeyId: credentials.AccessKeyId,
19+
secretAccessKey: credentials.SecretAccessKey,
20+
sessionToken: credentials.SessionToken,
1321
},
1422
sha256: Sha256,
1523
});
1624

17-
const signed = await sigv4.sign({
25+
return sigv4.sign({
1826
method: options.method,
1927
hostname: url.host,
2028
path: url.pathname,
@@ -23,6 +31,25 @@ async function signAWS({ url, options, headers, body }: { url: URL, options: Api
2331
headers: headers,
2432
body: body
2533
});
34+
}
35+
36+
interface AssumeAWSRolePayload {
37+
awsRoleArn: string | Resolver<string>;
38+
}
39+
40+
async function assumeAWSRole({ awsRoleArn }: AssumeAWSRolePayload, options: ApiRequestOptions): Promise<AssumeRoleCommandOutput> {
41+
const arn = await resolve(options, awsRoleArn);
42+
43+
if(!process.env.AWS_REGION || !arn) {
44+
throw new Error("Missing AWS Credentials");
45+
}
46+
47+
const stsClient = new STSClient({ region: process.env.AWS_REGION });
48+
const command = new AssumeRoleCommand({
49+
RoleArn: arn,
50+
RoleSessionName: "session1",
51+
DurationSeconds: 900
52+
});
2653

27-
return signed;
54+
return stsClient.send(command);
2855
}

src/templates/exportAppClient.hbs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ export class {{{clientName}}} {{#if service}}extends {{{service.name}}} {{/if}}{
2525
version: '{{{version}}}',
2626
token: openApiConfig?.token,
2727
accountSid: openApiConfig?.accountSid,
28-
authToken: openApiConfig?.authToken
28+
authToken: openApiConfig?.authToken,
29+
awsRoleArn: openApiConfig?.awsRoleArn
2930
});
3031
{{#if service}}
3132
super(request);

0 commit comments

Comments
 (0)