-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
b352a24
commit 95f3083
Showing
40 changed files
with
4,991 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "synapse-aws", | ||
"dependencies": { | ||
"@aws-sdk/client-cloudfront": "^3.380.0", | ||
"@aws-sdk/client-cloudwatch": "^3.445.0", | ||
"@aws-sdk/client-cloudwatch-logs": "^3.445.0", | ||
"@aws-sdk/client-dynamodb": "^3.379.1", | ||
"@aws-sdk/client-ec2": "^3.379.1", | ||
"@aws-sdk/client-ecr": "^3.379.1", | ||
"@aws-sdk/client-ecr-public": "^3.388.0", | ||
"@aws-sdk/client-ecs": "^3.379.1", | ||
"@aws-sdk/client-eventbridge": "^3.379.1", | ||
"@aws-sdk/client-kinesis": "^3.379.1", | ||
"@aws-sdk/client-lambda": "^3.379.1", | ||
"@aws-sdk/client-organizations": "^3.379.1", | ||
"@aws-sdk/client-s3": "^3.379.1", | ||
"@aws-sdk/client-secrets-manager": "^3.379.1", | ||
"@aws-sdk/client-sqs": "^3.379.1", | ||
"@aws-sdk/s3-request-presigner": "^3.574.0" | ||
}, | ||
"exports": { | ||
".": "./src/index.ts", | ||
"./*": "./src/services/*.ts" | ||
}, | ||
"types": "./src/index.d.ts", | ||
"synapse": { | ||
"config": { | ||
"sharedLib": true | ||
}, | ||
"providers": { | ||
"aws": "*" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import * as aws from 'synapse-provider:aws' | ||
import * as core from 'synapse:core' | ||
import { Account } from './services/organizations' | ||
import { Role } from './services/iam' | ||
import { Fn } from 'synapse:terraform' | ||
import * as srl from 'synapse:srl' | ||
|
||
// TODO: providers in Terraform should be treated as a special kind of | ||
// resource rather than a separate class entirely. This will solve many | ||
// problems as well as enable all sorts of useful functionality. | ||
export class Provider extends aws.AwsProvider { | ||
static readonly [core.contextType] = 'aws' | ||
|
||
// We need initializers here so that the keys exist on the instance | ||
private identity?: aws.CallerIdentityData = undefined | ||
private regionData?: aws.RegionData = undefined | ||
private partitionData?: aws.PartitionData = undefined | ||
private _assetBucket?: aws.S3Bucket = undefined | ||
|
||
public get arn() { | ||
return (this.identity ??= new aws.CallerIdentityData()).arn | ||
} | ||
|
||
public get regionId() { | ||
return (this.regionData ??= new aws.RegionData()).id | ||
} | ||
|
||
public get accountId() { | ||
return (this.identity ??= new aws.CallerIdentityData()).accountId | ||
} | ||
|
||
public get partition() { | ||
return (this.partitionData ??= new aws.PartitionData()).partition | ||
} | ||
|
||
public get roleArn() { | ||
return this.assumeRole?.[0].roleArn | ||
} | ||
|
||
public get assetBucket() { | ||
// TODO: only create 1 asset bucket per-account (or possibly per-user) | ||
return this._assetBucket ??= new aws.S3Bucket({ | ||
bucketPrefix: 'asset-bucket', | ||
}) | ||
} | ||
|
||
public static fromAccount(account: Account) { | ||
return this.fromRoleArn(getManagementRoleArn(account)) | ||
} | ||
|
||
public static fromRoleArn(roleArn: string) { | ||
return new this({ assumeRole: [{ roleArn }] }) | ||
} | ||
|
||
public static withId(account: Account, id: string) { | ||
const roleName = 'OrganizationAccountAccessRole' | ||
const roleArn = `arn:aws:iam::${account.id}:role/${roleName}` | ||
|
||
return new this(...([{ assumeRole: [{ roleArn }] }, id] as any[])) | ||
} | ||
} | ||
|
||
// TODO: is this still needed? | ||
Object.assign(Provider, { [core.contextType]: 'aws' }) | ||
|
||
core.addTarget(srl.Provider, Provider, 'aws') | ||
|
||
export function getManagementRoleArn(account: Account) { | ||
// TODO: partitions | ||
return `arn:aws:iam::${account.id}:role/${account.managementRoleName}` | ||
} | ||
|
||
|
||
export function createCrossAccountRole(target: Account, principal?: Role) { | ||
const awsPrincipal = principal ? principal.resource.arn : core.getContext(Provider).accountId | ||
const roleName = core.getCurrentId().slice(0, 63) // XXX: we need an independent name to avoid circular deps | ||
const role = core.using(Provider.fromAccount(target), () => { | ||
return new Role({ | ||
name: roleName, | ||
assumeRolePolicy: Fn.jsonencode({ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Action": "sts:AssumeRole", | ||
"Principal": { | ||
"AWS": awsPrincipal | ||
}, | ||
} | ||
] | ||
}) | ||
}) | ||
}) | ||
|
||
principal?.addPolicy({ | ||
name: `Assume-${roleName}`, | ||
policy: Fn.jsonencode({ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Action": "sts:AssumeRole", | ||
"Resource": `arn:${core.getContext(Provider).partition}:iam::${target.id}:role/${roleName}` | ||
} | ||
] | ||
}) | ||
}) | ||
|
||
return role | ||
} |
Oops, something went wrong.