Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8f52dc7
Using DynamoDB for tracking Resources created in a stack
naveenkoppula Sep 16, 2020
65b1c95
Adding TODO
naveenkoppula Sep 16, 2020
1f5e8df
fix(core): Setting sleep before SM execution on move account (#391)
naveenkoppula Sep 16, 2020
37e5d90
Create Rulea and Associate Resolver Rule to custom resource
naveenkoppula Sep 16, 2020
3a010dd
Prettier
naveenkoppula Sep 16, 2020
de3aea8
Generating rule name
naveenkoppula Sep 16, 2020
a61ddf7
prettier
naveenkoppula Sep 16, 2020
1d6adca
using name as creatorrequestid
naveenkoppula Sep 16, 2020
710aa4b
adding proper dependency
naveenkoppula Sep 16, 2020
e1a2b8b
Changing name formati
naveenkoppula Sep 17, 2020
cfc65b5
Initiating previous stacks for removing if there are no resources
naveenkoppula Sep 17, 2020
492e3dd
Adding port for rule
naveenkoppula Sep 17, 2020
6d5bcf6
Adding PORT to rule
naveenkoppula Sep 17, 2020
75c768b
prettier
naveenkoppula Sep 17, 2020
75240a4
Adding update for ResolverRule
naveenkoppula Sep 17, 2020
d767f1d
Prettier
naveenkoppula Sep 17, 2020
6cfe471
Changes for max resources
naveenkoppula Sep 17, 2020
9157ec4
Merge remote-tracking branch 'origin/master' into fix/Make-VPC-Relate…
naveenkoppula Sep 17, 2020
46b131c
Fixing Tests
naveenkoppula Sep 17, 2020
cd3b368
Strict Error checking
naveenkoppula Sep 17, 2020
522ac43
Prettier
naveenkoppula Sep 17, 2020
b42a6b1
Fixing CustomResource Delete action
naveenkoppula Sep 17, 2020
9dfa211
Updating documentation
naveenkoppula Sep 17, 2020
593f66d
Nasty Fix for resourceShare
naveenkoppula Sep 17, 2020
e634150
Removing TODOs
naveenkoppula Sep 18, 2020
30f0851
Updating Error messages
naveenkoppula Sep 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/deployments/cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
"@aws-accelerator/custom-resource-ssm-session-manager-document": "workspace:^0.0.1",
"@aws-accelerator/custom-resource-vpc-default-security-group": "workspace:^0.0.1",
"@aws-accelerator/custom-resource-associate-hosted-zones": "workspace:^0.0.1",
"@aws-accelerator/custom-resource-associate-resolver-rules": "workspace:^0.0.1",
"@aws-accelerator/custom-resource-create-resolver-rule": "workspace:^0.0.1",
"@aws-cdk/aws-accessanalyzer": "1.46.0",
"@aws-cdk/aws-autoscaling": "1.46.0",
"@aws-cdk/aws-budgets": "1.46.0",
Expand Down
6 changes: 6 additions & 0 deletions src/deployments/cdk/src/apps/phase--1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,10 @@ export async function deploy({ acceleratorConfig, accountStacks, accounts }: Pha
accountStacks,
accounts,
});

// Creates role for Resource cleanup custom resource
await globalRoles.createCentralEndpointDeploymentRole({
accountStacks,
config: acceleratorConfig,
});
}
1 change: 0 additions & 1 deletion src/deployments/cdk/src/apps/phase-4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { PhaseInput } from './shared';
import * as securityHub from '../deployments/security-hub';
import * as cloudWatchDeployment from '../deployments/cloud-watch';
import * as centralEndpoints from '../deployments/central-endpoints';
import { Context } from '@aws-cdk/aws-stepfunctions';

export interface RdgwArtifactsOutput {
accountKey: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { HostedZoneOutput } from '@aws-accelerator/common-outputs/src/hosted-zone';
import { StaticResourcesOutput } from '@aws-accelerator/common-outputs/src/static-resource';
import { createCfnStructuredOutput } from '../../common/structured-output';
export const CfnHostedZoneOutput = createCfnStructuredOutput(HostedZoneOutput);
export const CfnStaticResourcesOutput = createCfnStructuredOutput(StaticResourcesOutput);
315 changes: 242 additions & 73 deletions src/deployments/cdk/src/deployments/central-endpoints/step-2.ts

Large diffs are not rendered by default.

159 changes: 144 additions & 15 deletions src/deployments/cdk/src/deployments/central-endpoints/step-3.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import { AccountStacks } from '../../common/account-stacks';
import { getStackJsonOutput, ResolversOutput, StackOutput } from '@aws-accelerator/common-outputs/src/stack-output';
import { AssociateResolverRules } from '@aws-accelerator/custom-resource-associate-resolver-rules';
import * as c from '@aws-accelerator/common-config';
import * as route53resolver from '@aws-cdk/aws-route53resolver';
import { IamRoleOutputFinder } from '@aws-accelerator/common-outputs/src/iam-role';
import { VpcOutputFinder } from '@aws-accelerator/common-outputs/src/vpc';
import {
StaticResourcesOutput,
StaticResourcesOutputFinder,
} from '@aws-accelerator/common-outputs/src/static-resource';
import { CfnStaticResourcesOutput } from './outputs';

// Changing these values will lead to redeploying all Phase-4 RuleAssociation stacks
const MAX_RESOURCES_IN_STACK = 190;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Resource per stack (190) for rule association correct? Could you please do a cross check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we only need one resource per associating all rules to VPC

const RESOURCE_TYPE = 'ResolverRulesAssociation';
const STACK_COMMON_SUFFIX = 'RulesAsscociation';

export interface CentralEndpointsStep3Props {
accountStacks: AccountStacks;
Expand All @@ -16,7 +27,28 @@ export interface CentralEndpointsStep3Props {
export async function step3(props: CentralEndpointsStep3Props) {
const { accountStacks, config, outputs } = props;
const allVpcConfigs = config.getVpcConfigs();
const accountRulesCounter: { [accountKey: string]: number } = {};

const allStaticResources: StaticResourcesOutput[] = StaticResourcesOutputFinder.findAll({
outputs,
}).filter(sr => sr.resourceType === RESOURCE_TYPE);

// Initiate previous stacks to handle deletion of previously deployed stack if there are no resources
for (const sr of allStaticResources) {
accountStacks.tryGetOrCreateAccountStack(sr.accountKey, sr.region, `RulesAssc-${sr.suffix}`);
}

const accountStaticResourcesConfig: { [accountKey: string]: StaticResourcesOutput[] } = {};
const accountRegionExistingResources: {
[accountKey: string]: {
[region: string]: string[];
};
} = {};
const accountRegionMaxSuffix: {
[accountKey: string]: {
[region: string]: number;
};
} = {};

for (const { accountKey, vpcConfig } of allVpcConfigs) {
const centralPhzConfig = config['global-options'].zones.find(zc => zc.region === vpcConfig.region);
if (!vpcConfig['use-central-endpoints']) {
Expand Down Expand Up @@ -75,29 +107,126 @@ export async function step3(props: CentralEndpointsStep3Props) {
continue;
}

if (accountRulesCounter[`${accountKey}-${vpcConfig.region}`]) {
accountRulesCounter[`${accountKey}-${vpcConfig.region}`] = ++accountRulesCounter[
`${accountKey}-${vpcConfig.region}`
];
} else {
accountRulesCounter[`${accountKey}-${vpcConfig.region}`] = 1;
let suffix: number;
let stackSuffix: string;
let newResource = true;

// Load all account stacks to object
if (!accountStaticResourcesConfig[accountKey]) {
accountStaticResourcesConfig[accountKey] = allStaticResources.filter(sr => sr.accountKey === accountKey);
}
if (!accountRegionMaxSuffix[accountKey]) {
accountRegionMaxSuffix[accountKey] = {};
}

// Load Max suffix for each region of account to object
if (!accountRegionMaxSuffix[accountKey][vpcConfig.region]) {
const localSuffix = accountStaticResourcesConfig[accountKey]
.filter(sr => sr.region === vpcConfig.region)
.flatMap(r => r.suffix);
accountRegionMaxSuffix[accountKey][vpcConfig.region] = localSuffix.length === 0 ? 1 : Math.max(...localSuffix);
}

if (!accountRegionExistingResources[accountKey]) {
const localRegionalResources = accountStaticResourcesConfig[accountKey]
.filter(sr => sr.region === vpcConfig.region)
.flatMap(sr => sr.resources);
accountRegionExistingResources[accountKey] = {};
accountRegionExistingResources[accountKey][vpcConfig.region] = localRegionalResources;
} else if (!accountRegionExistingResources[accountKey][vpcConfig.region]) {
const localRegionalResources = accountStaticResourcesConfig[accountKey]
.filter(sr => sr.region === vpcConfig.region)
.flatMap(sr => sr.resources);
accountRegionExistingResources[accountKey][vpcConfig.region] = localRegionalResources;
}

// Includes max of 50 VPCs, since we need 3 resource per VPC.
const stackSuffix = `RulesAssc-${Math.ceil(accountRulesCounter[`${accountKey}-${vpcConfig.region}`] / 50)}`;
suffix = accountRegionMaxSuffix[accountKey][vpcConfig.region];
stackSuffix = `${STACK_COMMON_SUFFIX}-${suffix}`;
const constructName = `${STACK_COMMON_SUFFIX}-${vpcConfig.name}`;
if (accountRegionExistingResources[accountKey][vpcConfig.region].includes(constructName)) {
newResource = false;
const regionStacks = accountStaticResourcesConfig[accountKey].filter(sr => sr.region === vpcConfig.region);
for (const rs of regionStacks) {
if (rs.resources.includes(constructName)) {
stackSuffix = `${STACK_COMMON_SUFFIX}-${rs.suffix}`;
break;
}
}
} else {
const existingResources = accountStaticResourcesConfig[accountKey].find(
sr => sr.region === vpcConfig.region && sr.suffix === suffix,
);
if (existingResources && existingResources.resources.length >= MAX_RESOURCES_IN_STACK) {
accountRegionMaxSuffix[accountKey][vpcConfig.region] = ++suffix;
}
stackSuffix = `${STACK_COMMON_SUFFIX}-${suffix}`;
}

const accountStack = accountStacks.tryGetOrCreateAccountStack(accountKey, vpcConfig.region, stackSuffix);
if (!accountStack) {
console.error(`Cannot find account stack ${accountKey}: ${vpcConfig.region}, while Associating Resolver Rules`);
continue;
}

const roleOutput = IamRoleOutputFinder.tryFindOneByName({
outputs,
accountKey,
roleKey: 'CentralEndpointDeployment',
});
if (!roleOutput) {
continue;
}

const ruleIds = [...resolverRegionoutputs.rules?.madRules!, ...resolverRegionoutputs.rules?.onPremRules!];
for (const ruleId of ruleIds) {
new route53resolver.CfnResolverRuleAssociation(accountStack, `Rule-Association-${ruleId}-${vpcConfig.name}`, {
resolverRuleId: ruleId,
vpcId: vpcOutput.vpcId,
});
new AssociateResolverRules(accountStack, constructName, {
resolverRuleIds: ruleIds,
roleArn: roleOutput.roleArn,
vpcId: vpcOutput.vpcId,
});

if (newResource) {
const currentSuffixIndex = allStaticResources.findIndex(
sr => sr.region === vpcConfig.region && sr.suffix === suffix && sr.accountKey === accountKey,
);
const currentAccountSuffixIndex = accountStaticResourcesConfig[accountKey].findIndex(
sr => sr.region === vpcConfig.region && sr.suffix === suffix,
);
if (currentSuffixIndex === -1) {
const currentResourcesObject = {
accountKey,
id: `${STACK_COMMON_SUFFIX}-${vpcConfig.region}-${accountKey}-${suffix}`,
region: vpcConfig.region,
resourceType: RESOURCE_TYPE,
resources: [constructName],
suffix,
};
allStaticResources.push(currentResourcesObject);
accountStaticResourcesConfig[accountKey].push(currentResourcesObject);
} else {
const currentResourcesObject = allStaticResources[currentSuffixIndex];
const currentAccountResourcesObject = accountStaticResourcesConfig[accountKey][currentAccountSuffixIndex];
if (!currentResourcesObject.resources.includes(constructName)) {
currentResourcesObject.resources.push(constructName);
}
if (!currentAccountResourcesObject.resources.includes(constructName)) {
currentAccountResourcesObject.resources.push(constructName);
}
allStaticResources[currentSuffixIndex] = currentResourcesObject;
accountStaticResourcesConfig[accountKey][currentAccountSuffixIndex] = currentAccountResourcesObject;
}
}
}
for (const sr of allStaticResources) {
const accountStack = accountStacks.tryGetOrCreateAccountStack(
sr.accountKey,
sr.region,
`${STACK_COMMON_SUFFIX}-${sr.suffix}`,
);
if (!accountStack) {
throw new Error(
`Not able to get or create stack for ${sr.accountKey}: ${sr.region}: ${STACK_COMMON_SUFFIX}-${sr.suffix}`,
);
}
new CfnStaticResourcesOutput(accountStack, `StaticResourceOutput-${sr.suffix}`, sr);
}
}
Loading