Skip to content

Commit 11d7a1c

Browse files
committed
feat(source-aws): add support for easily assuming roles
1 parent 8a42472 commit 11d7a1c

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

packages/source-aws/src/s3.fs.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,64 @@
11
import { FileInfo, FileSystem, isRecord } from '@chunkd/core';
2+
import S3 from 'aws-sdk/clients/s3.js';
3+
import { Credentials } from 'aws-sdk/lib/credentials.js';
4+
import { ChainableTemporaryCredentials } from 'aws-sdk/lib/credentials/chainable_temporary_credentials.js';
5+
import { EC2MetadataCredentials } from 'aws-sdk/lib/credentials/ec2_metadata_credentials.js';
6+
import { SharedIniFileCredentials } from 'aws-sdk/lib/credentials/shared_ini_file_credentials.js';
27
import type { Readable } from 'stream';
38
import { getCompositeError, SourceAwsS3 } from './s3.source.js';
49
import { ListRes, S3Like } from './type.js';
510

11+
const Ec2 = Symbol();
12+
const x: typeof Ec2 = Ec2;
13+
console.log(x);
14+
615
export class FsAwsS3 implements FileSystem<SourceAwsS3> {
716
static protocol = 's3';
817
protocol = FsAwsS3.protocol;
918
/** Max list requests to run before erroring */
1019
static MaxListCount = 100;
1120

21+
static Ec2Credentials = Ec2;
22+
23+
static credentials: Map<string, Credentials> = new Map();
24+
/**
25+
* Create a aws credential instance from a role arn
26+
*
27+
* if the AWS profile is "FsAwsS3.Ec2Credentials" use EC2MetadataCredentials, otherwise load credentials from the shared ini file
28+
*/
29+
static getCredentials(roleArn: string, profile?: string | typeof Ec2, externalId?: string): Credentials {
30+
const credKey = `${roleArn}::${roleArn}::${externalId}`;
31+
let credentials = FsAwsS3.credentials.get(credKey);
32+
if (credentials == null) {
33+
const masterCredentials =
34+
profile === Ec2 ? new EC2MetadataCredentials() : new SharedIniFileCredentials({ profile });
35+
credentials = new ChainableTemporaryCredentials({
36+
params: {
37+
RoleArn: roleArn,
38+
ExternalId: externalId,
39+
RoleSessionName: 'fsa-' + Math.random().toString(32) + '-' + Date.now(),
40+
},
41+
masterCredentials,
42+
});
43+
FsAwsS3.credentials.set(credKey, credentials);
44+
}
45+
return credentials;
46+
}
47+
48+
/**
49+
* Create a FsS3 instance from a role arn
50+
*
51+
* if the AWS profile is "ec2" use EC2MetadataCredentials, otherwise load credentials from the shared ini file
52+
*
53+
* @example
54+
* Fs3.fromRoleArn('arn:foo', 'ec2');
55+
* FsS3.fromRoleArn('arn:bar', process.env.AWS_PROFILE);
56+
*/
57+
static fromRoleArn(roleArn: string, profile?: string | typeof Ec2, externalId?: string): FsAwsS3 {
58+
const credentials = FsAwsS3.getCredentials(roleArn, profile, externalId);
59+
return new FsAwsS3(new S3({ credentials }));
60+
}
61+
1262
/** AWS-SDK s3 to use */
1363
s3: S3Like;
1464

0 commit comments

Comments
 (0)