Skip to content

Commit

Permalink
feat: add account and region to (I)Resource
Browse files Browse the repository at this point in the history
  • Loading branch information
skinny85 committed Aug 14, 2020
1 parent 4bc8188 commit 4846304
Show file tree
Hide file tree
Showing 40 changed files with 812 additions and 248 deletions.
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-apigateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@
"props-physical-name:@aws-cdk/aws-apigateway.GatewayResponseProps",
"construct-interface-extends-iconstruct:@aws-cdk/aws-apigateway.IModel",
"resource-interface-extends-resource:@aws-cdk/aws-apigateway.IModel",
"attribute-tag:@aws-cdk/aws-apigateway.ProxyResource.resourceEnv",
"attribute-tag:@aws-cdk/aws-apigateway.Resource.resourceEnv",
"docs-public-apis:@aws-cdk/aws-apigateway.JsonSchema.definitions",
"docs-public-apis:@aws-cdk/aws-apigateway.Period.MONTH",
"docs-public-apis:@aws-cdk/aws-apigateway.Period.WEEK",
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-certificatemanager/test/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ describe('getCertificateRegion', () => {
domainName: 'www.example.com',
});

expect(getCertificateRegion(certificate)).toEqual('${Token[AWS::Region.4]}');
expect(getCertificateRegion(certificate)).toEqual('${Token[AWS.Region.4]}');
});

});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, haveResourceLike } from '@aws-cdk/assert';
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as s3 from '@aws-cdk/aws-s3';
import { Duration, SecretValue, Stack } from '@aws-cdk/core';
import { App, Duration, SecretValue, Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import * as cpactions from '../../lib';

Expand Down Expand Up @@ -153,6 +153,38 @@ export = {

test.done();
},

'correctly makes the action cross-region for a Bucket imported with a different region'(test: Test) {
const app = new App();
const stack = new Stack(app, 'PipelineStack', {
env: { account: '123456789012', region: 'us-west-2' },
});
const deployBucket = s3.Bucket.fromBucketAttributes(stack, 'DeployBucket', {
bucketName: 'my-deploy-bucket',
region: 'ap-southeast-1',
});

minimalPipeline(stack, {
bucket: deployBucket,
});

expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', {
Stages: [
{},
{
Name: 'Deploy',
Actions: [
{
Name: 'CopyFiles',
Region: 'ap-southeast-1',
},
],
},
],
}));

test.done();
},
},
};

Expand Down
24 changes: 17 additions & 7 deletions packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as kms from '@aws-cdk/aws-kms';
import * as s3 from '@aws-cdk/aws-s3';
import {
App, BootstraplessSynthesizer, Construct, DefaultStackSynthesizer,
IStackSynthesizer, Lazy, PhysicalName, RemovalPolicy, Resource, Stack, Token,
IStackSynthesizer, Lazy, PhysicalName, RemovalPolicy, Resource, Stack, Token, TokenComparison,
} from '@aws-cdk/core';
import { ActionCategory, IAction, IPipeline, IStage } from './action';
import { CfnPipeline } from './codepipeline.generated';
Expand Down Expand Up @@ -400,12 +400,22 @@ export class Pipeline extends PipelineBase {

const actionResource = action.actionProperties.resource;
if (actionResource) {
const actionResourceStack = Stack.of(actionResource);
if (pipelineStack.region !== actionResourceStack.region) {
actionRegion = actionResourceStack.region;
const pipelineAndActionRegionComparison = Token.compareStrings(this.resourceEnv.region, actionResource.resourceEnv.region);
const pipelineAndActionInDifferentRegions = pipelineAndActionRegionComparison === TokenComparison.ONE_UNRESOLVED ||
pipelineAndActionRegionComparison === TokenComparison.DIFFERENT;
if (pipelineAndActionInDifferentRegions) {
actionRegion = actionResource.resourceEnv.region;

// if the resource is from a different stack in another region but the same account,
// use that stack as home for the cross-region support resources
if (pipelineStack.account === actionResourceStack.account) {
const actionResourceStack = Stack.of(actionResource);
const actionResourceAndItsStackRegionComparison = Token.compareStrings(actionResource.resourceEnv.region, actionResourceStack.region);
const actionResourceInSameRegionAsItsStack = actionResourceAndItsStackRegionComparison === TokenComparison.SAME ||
actionResourceAndItsStackRegionComparison === TokenComparison.BOTH_UNRESOLVED;
const pipelineAndActionResourceStackAccountComparison = Token.compareStrings(this.resourceEnv.account, actionResourceStack.account);
const pipelineAndActionResourceStackInSameAccount = pipelineAndActionResourceStackAccountComparison === TokenComparison.SAME ||
pipelineAndActionResourceStackAccountComparison === TokenComparison.BOTH_UNRESOLVED;
if (pipelineAndActionResourceStackInSameAccount && actionResourceInSameRegionAsItsStack) {
otherStack = actionResourceStack;
}
}
Expand Down Expand Up @@ -850,7 +860,7 @@ export class Pipeline extends PipelineBase {
}

private requireRegion(): string {
const region = Stack.of(this).region;
const region = this.resourceEnv.region;
if (Token.isUnresolved(region)) {
throw new Error('Pipeline stack which uses cross-environment actions must have an explicitly set region');
}
Expand Down Expand Up @@ -932,4 +942,4 @@ class PipelineLocation {
// runOrders are 1-based, so make the stageIndex also 1-based otherwise it's going to be confusing.
return `Stage ${this.stageIndex + 1} Action ${this.action.runOrder} ('${this.stageName}'/'${this.actionName}')`;
}
}
}
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-dynamodb/test/dynamodb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2106,7 +2106,7 @@ describe('import', () => {
'Roles': [{ 'Ref': 'NewRole99763075' }],
});

expect(table.tableArn).toBe('arn:${Token[AWS::Partition.3]}:dynamodb:${Token[AWS::Region.4]}:${Token[AWS::AccountId.0]}:table/MyTable');
expect(table.tableArn).toBe('arn:${Token[AWS.Partition.3]}:dynamodb:${Token[AWS.Region.4]}:${Token[AWS.AccountId.0]}:table/MyTable');
expect(stack.resolve(table.tableName)).toBe(tableName);
});

Expand Down
7 changes: 4 additions & 3 deletions packages/@aws-cdk/aws-ec2/lib/bastion-host.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IPrincipal, IRole, PolicyStatement } from '@aws-cdk/aws-iam';
import { CfnOutput, Construct, Stack } from '@aws-cdk/core';
import { CfnOutput, Construct, Resource, Stack } from '@aws-cdk/core';
import { AmazonLinuxGeneration, InstanceClass, InstanceSize, InstanceType } from '.';
import { Connections } from './connections';
import { IInstance, Instance } from './instance';
Expand Down Expand Up @@ -90,8 +90,9 @@ export interface BastionHostLinuxProps {
* You can also configure this bastion host to allow connections via SSH
*
* @experimental
* @resource AWS::EC2::Instance
*/
export class BastionHostLinux extends Construct implements IInstance {
export class BastionHostLinux extends Resource implements IInstance {
public readonly stack: Stack;

/**
Expand Down Expand Up @@ -192,4 +193,4 @@ export class BastionHostLinux extends Construct implements IInstance {
this.connections.allowFrom(p, Port.tcp(22), 'SSH access');
});
}
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ec2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"props-physical-name:@aws-cdk/aws-ec2.InterfaceVpcEndpointProps",
"from-method:@aws-cdk/aws-ec2.Instance",
"from-method:@aws-cdk/aws-ec2.VpcEndpointService",
"attribute-tag:@aws-cdk/aws-ec2.BastionHostLinux.instance",
"attribute-tag:@aws-cdk/aws-ec2.Instance.instance",
"from-signature:@aws-cdk/aws-ec2.SecurityGroup.fromSecurityGroupId",
"docs-public-apis:@aws-cdk/aws-ec2.WindowsVersion.WINDOWS_SERVER_2016_ENGLISH_DEEP_LEARNING",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
]
}
},
"Instance255F35265e4fe939d8bb9e8f3": {
"Instance255F35265ded5e65f501c2c8c": {
"Type": "AWS::EC2::Instance",
"Properties": {
"AvailabilityZone": "us-east-1a",
Expand Down Expand Up @@ -128,15 +128,15 @@
{
"Ref": "AWS::StackName"
},
" --resource Instance255F35265e4fe939d8bb9e8f3 -c default\n /opt/aws/bin/cfn-signal -e $? --region ",
" --resource Instance255F35265ded5e65f501c2c8c -c default\n /opt/aws/bin/cfn-signal -e $? --region ",
{
"Ref": "AWS::Region"
},
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource Instance255F35265e4fe939d8bb9e8f3\n cat /var/log/cfn-init.log >&2\n)"
" --resource Instance255F35265ded5e65f501c2c8c\n cat /var/log/cfn-init.log >&2\n)"
]
]
}
Expand Down Expand Up @@ -178,4 +178,4 @@
"Default": "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2"
}
}
}
}
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-ec2/test/userdata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ nodeunitShim({

test.equals(rendered, '<powershell>trap {\n' +
'$success=($PSItem.Exception.Message -eq "Success")\n' +
'cfn-signal --stack Default --resource RESOURCE1989552F --region ${Token[AWS::Region.4]} --success ($success.ToString().ToLower())\n' +
'cfn-signal --stack Default --resource RESOURCE1989552F --region ${Token[AWS.Region.4]} --success ($success.ToString().ToLower())\n' +
'break\n' +
'}\n' +
'command1\n' +
Expand Down Expand Up @@ -157,7 +157,7 @@ nodeunitShim({
test.equals(rendered, '#!/bin/bash\n' +
'function exitTrap(){\n' +
'exitCode=$?\n' +
'/opt/aws/bin/cfn-signal --stack Default --resource RESOURCE1989552F --region ${Token[AWS::Region.4]} -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n' +
'/opt/aws/bin/cfn-signal --stack Default --resource RESOURCE1989552F --region ${Token[AWS.Region.4]} -e $exitCode || echo \'Failed to send Cloudformation Signal\'\n' +
'}\n' +
'trap exitTrap EXIT\n' +
'command1');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Vpc } from '@aws-cdk/aws-ec2';
import { Cluster, ContainerImage } from '@aws-cdk/aws-ecs';
import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2';
import * as route53 from '@aws-cdk/aws-route53';
import { App, Stack } from '@aws-cdk/core';

import { ApplicationLoadBalancedFargateService } from '../../lib';
Expand All @@ -20,13 +21,10 @@ new ApplicationLoadBalancedFargateService(stack, 'myService', {
protocol: ApplicationProtocol.HTTPS,
enableECSManagedTags: true,
domainName: 'test.example.com',
domainZone: {
domainZone: route53.HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
hostedZoneId: 'fakeId',
zoneName: 'example.com.',
hostedZoneArn: 'arn:aws:route53:::hostedzone/fakeId',
stack,
node: stack.node,
},
}),
});

app.synth();
app.synth();
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as ec2 from '@aws-cdk/aws-ec2';
import * as ecs from '@aws-cdk/aws-ecs';
import { ApplicationLoadBalancer, ApplicationProtocol, NetworkLoadBalancer } from '@aws-cdk/aws-elasticloadbalancingv2';
import * as iam from '@aws-cdk/aws-iam';
import * as route53 from '@aws-cdk/aws-route53';
import * as cdk from '@aws-cdk/core';
import { Test } from 'nodeunit';
import * as ecsPatterns from '../../lib';
Expand Down Expand Up @@ -370,13 +371,10 @@ export = {
cluster,
protocol: ApplicationProtocol.HTTPS,
domainName: 'domain.com',
domainZone: {
domainZone: route53.HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
hostedZoneId: 'fakeId',
zoneName: 'domain.com',
hostedZoneArn: 'arn:aws:route53:::hostedzone/fakeId',
stack,
node: stack.node,
},
}),
taskImageOptions: {
containerPort: 2015,
image: ecs.ContainerImage.fromRegistry('abiosoft/caddy'),
Expand Down Expand Up @@ -408,13 +406,10 @@ export = {
cluster,
protocol: ApplicationProtocol.HTTPS,
domainName: 'test.domain.com',
domainZone: {
domainZone: route53.HostedZone.fromHostedZoneAttributes(stack, 'HostedZone', {
hostedZoneId: 'fakeId',
zoneName: 'domain.com.',
hostedZoneArn: 'arn:aws:route53:::hostedzone/fakeId',
stack,
node: stack.node,
},
}),
taskImageOptions: {
containerPort: 2015,
image: ecs.ContainerImage.fromRegistry('abiosoft/caddy'),
Expand Down Expand Up @@ -642,4 +637,4 @@ export = {
test.done();
},

};
};
8 changes: 2 additions & 6 deletions packages/@aws-cdk/aws-eks-legacy/lib/kubectl-layer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as lambda from '@aws-cdk/aws-lambda';
import { CfnResource, Construct, Stack, Token } from '@aws-cdk/core';
import { CfnResource, Construct, Resource, Stack, Token } from '@aws-cdk/core';
import * as crypto from 'crypto';

const KUBECTL_APP_ARN = 'arn:aws:serverlessrepo:us-east-1:903779448426:applications/lambda-layer-kubectl';
Expand All @@ -19,7 +19,7 @@ export interface KubectlLayerProps {
*
* @see https://github.com/aws-samples/aws-lambda-layer-kubectl
*/
export class KubectlLayer extends Construct implements lambda.ILayerVersion {
export class KubectlLayer extends Resource implements lambda.ILayerVersion {

/**
* Gets or create a singleton instance of this construct.
Expand Down Expand Up @@ -68,10 +68,6 @@ export class KubectlLayer extends Construct implements lambda.ILayerVersion {
this.layerVersionArn = Token.asString(resource.getAtt('Outputs.LayerVersionArn'));
}

public get stack() {
return Stack.of(this);
}

public addPermission(_id: string, _permission: lambda.LayerVersionPermission): void {
return;
}
Expand Down
8 changes: 2 additions & 6 deletions packages/@aws-cdk/aws-eks/lib/kubectl-layer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as crypto from 'crypto';
import * as lambda from '@aws-cdk/aws-lambda';
import { CfnResource, Construct, Stack, Token } from '@aws-cdk/core';
import { CfnResource, Construct, Resource, Stack, Token } from '@aws-cdk/core';

const KUBECTL_APP_ARN = 'arn:aws:serverlessrepo:us-east-1:903779448426:applications/lambda-layer-kubectl';
const KUBECTL_APP_CN_ARN = 'arn:aws-cn:serverlessrepo:cn-north-1:487369736442:applications/lambda-layer-kubectl';
Expand All @@ -21,7 +21,7 @@ export interface KubectlLayerProps {
*
* @see https://github.com/aws-samples/aws-lambda-layer-kubectl
*/
export class KubectlLayer extends Construct implements lambda.ILayerVersion {
export class KubectlLayer extends Resource implements lambda.ILayerVersion {

/**
* Gets or create a singleton instance of this construct.
Expand Down Expand Up @@ -70,10 +70,6 @@ export class KubectlLayer extends Construct implements lambda.ILayerVersion {
this.layerVersionArn = Token.asString(resource.getAtt('Outputs.LayerVersionArn'));
}

public get stack() {
return Stack.of(this);
}

public addPermission(_id: string, _permission: lambda.LayerVersionPermission): void {
return;
}
Expand Down
21 changes: 18 additions & 3 deletions packages/@aws-cdk/aws-iam/lib/grant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,22 @@ export class Grant implements cdk.IDependable {
scope: options.resource,
});

if (result.success) { return result; }
const resourceAndPrincipalAccountComparison = options.grantee.grantPrincipal.principalAccount
? cdk.Token.compareStrings(options.resource.resourceEnv.account, options.grantee.grantPrincipal.principalAccount)
: undefined;
// if both accounts are tokens, we assume here they are the same
const equalOrBothUnresolved = resourceAndPrincipalAccountComparison === cdk.TokenComparison.SAME
|| resourceAndPrincipalAccountComparison == cdk.TokenComparison.BOTH_UNRESOLVED;
const sameAccount: boolean = resourceAndPrincipalAccountComparison
? equalOrBothUnresolved
// if the principal doesn't have an account (for example, a service principal),
// we should modify the resource's trust policy
: false;
// If we added to the principal AND we're in the same account, then we're done.
// If not, it's a different account and we must also add a trust policy on the resource.
if (result.success && sameAccount) {
return result;
}

const statement = new PolicyStatement({
actions: options.actions,
Expand Down Expand Up @@ -292,7 +307,7 @@ interface GrantProps {
/**
* A resource with a resource policy that can be added to
*/
export interface IResourceWithPolicy extends cdk.IConstruct {
export interface IResourceWithPolicy extends cdk.IResource {
/**
* Add a statement to the resource's resource policy
*/
Expand Down Expand Up @@ -332,4 +347,4 @@ export class CompositeDependable implements cdk.IDependable {
},
});
}
}
}
Loading

0 comments on commit 4846304

Please sign in to comment.