Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(controlTower): add validation of status for ControlTower #567

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5dd49da
chore: upgrade github action to node20
johnraws Aug 5, 2024
6fb5259
chore(lza-sample-config): enhance SCP statements for invocation of La…
johnraws Aug 8, 2024
450807b
release/v1.9.1
johnraws Aug 8, 2024
640a9be
fix(validation): fix config validation when enabling SecurityHub in a…
crissupb Jul 31, 2024
4998478
fix(control-tower): skip existing ct identifier check when ct is not …
padebnat Aug 20, 2024
809176a
fix(metadata): fixed config file writes with codecommit
hickeydh-aws Aug 20, 2024
0406a2a
fix(asea): nacl association being updated to LZA created nacl
crissupb Aug 21, 2024
8446a05
chore: add security.md file to repo
johnraws Aug 21, 2024
528f528
fix(control-tower): updated boolean logic to get LZ identifier
erwaxler Aug 23, 2024
a8cd80a
release/v1.9.2
johnraws Aug 23, 2024
338f283
feat(controlTower): add validation of status for ControlTower
richardkeit Sep 13, 2024
c511b0d
Merge remote-tracking branch 'upstream/main' into feature/control-tow…
richardkeit Oct 17, 2024
d084a83
revert yarn changes
richardkeit Oct 17, 2024
76bbb23
updated snapshots
richardkeit Oct 18, 2024
a580bd5
fix(asea): fix duplicate ssm parameter
dustinhaws Oct 23, 2024
dc7f1fa
fix(asea): fixed eni route lookup
dustinhaws Oct 24, 2024
2faa335
fix(migration): fixing broken tgw peering attachment
rycerrat Oct 9, 2024
d50c09a
fix(metadata): accelerator metadata lambda times out without error
StephenBedard Oct 29, 2024
289caaf
fix(docs): resolve broken links in mkdocs
johnraws Oct 17, 2024
9bd4ef6
Fix hosted zone DNS for Sagemaker VPC Endpoints
jbarnet Dec 7, 2023
87294b4
feat: add eks-auth endpoints to hosted-zone
TomasZelenayAWS Nov 8, 2024
65fed13
fix(pipeline): bootstrap stage failed silently
houw22 Nov 11, 2024
2fc45ec
fix(migration): updating replace function with regex to remove multip…
rycerrat Nov 14, 2024
55b95a8
fix(asea): update iam role resource handler to create trust policy fo…
crissupb Nov 15, 2024
a7c5690
feat(asea): support shared security group deletion
crissupb Nov 15, 2024
ad1e986
chore(snapshots): installer snapshot updates
rycerrat Nov 17, 2024
a44748a
fix(organizations): fix enabled controls cfn throttling
dustinhaws Nov 18, 2024
da90d68
fix(asea): security group rule subnet lookup
crissupb Nov 19, 2024
65cf183
fix(asea): iam role with principalarn property
crissupb Nov 19, 2024
d8fe87d
release/v1.10.1
rycerrat Nov 19, 2024
a3bbc9b
Merge branch 'main' into feature/control-tower-error
richardkeit Nov 21, 2024
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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.10.1] - 11-18-2024

### Fixed

- fix(metadata): accelerator metadata lambda times out without error
- fix(docs): resolve broken links in mkdocs
- fix(route53): fix hosted zone DNS for Sagemaker VPC Endpoints
- fix(route53): fix hosted zone DNS for EKS-Auth VPC Endpoints
- fix(pipeline): bootstrap stage failed silently
- fix(organizations): fix enabled controls cfn throttling

## [1.10.0] - 10-16-2024

### Added
Expand All @@ -23,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- fix(bootstrap): batched bootstrap checks
- fix(control-tower): skip existing ct identifier check when ct is not enabled
- fix(control-tower): updated boolean logic to get LZ identifier
- fix(custom-stacks): loaded replacement values during custom stack deployment
- fix(diff): parse error during diff
Expand Down
134 changes: 67 additions & 67 deletions source/mkdocs/docs/user-guide/config.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions source/mkdocs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ nav:
- Architecture and Design Philosophy: developer-guide/design.md
- Feature Development: developer-guide/features.md
- Documentation Guidelines: developer-guide/doc-guidelines.md
- JSON Schema: developer-guide/json-schema.md
- Sample Configurations:
- sample-configurations/index.md
- Standard:
Expand Down
2 changes: 1 addition & 1 deletion source/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "landing-zone-accelerator-on-aws",
"version": "1.10.0",
"version": "1.10.1",
"private": true,
"description": "Landing Zone Accelerator on AWS",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,15 @@ export class FirewallResources extends AseaResource {
const firewallInstance = this.stack.getResource(
existingFirewallInstance.logicalResourceId,
) as cdk.aws_ec2.CfnInstance;
const enis = firewallInstance.networkInterfaces as cdk.aws_ec2.CfnInstance.NetworkInterfaceProperty[];

for (const eni of enis ?? []) {
this.scope.addSsmParameter({
logicalId: pascalCase(`SsmParam${pascalCase(firewallInstanceName)}Eni${eni.deviceIndex}`),
parameterName: this.scope.getSsmPath(SsmResourceType.FIREWALL_ENI, [firewallInstanceName, eni.deviceIndex]),
stringValue: eni.networkInterfaceId!,
});
}
//Leaving as temporary placeholder for deletion handler
firewallInstanceConfig;
firewallInstance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import * as cdk from 'aws-cdk-lib';

import {
AccountPrincipal,
ArnPrincipal,
CfnInstanceProfile,
CfnManagedPolicy,
Effect,
Expand Down Expand Up @@ -83,7 +84,7 @@ export class Roles extends AseaResource {
private getAssumeRolePolicy(roleItem: RoleConfig) {
const statements: PolicyStatement[] = [];
for (const assumedByItem of roleItem.assumedBy ?? []) {
if (assumedByItem.type === 'service') {
if (assumedByItem.type === 'service' || assumedByItem.type === 'account') {
statements.push(
new PolicyStatement({
actions: ['sts:AssumeRole'],
Expand All @@ -92,7 +93,16 @@ export class Roles extends AseaResource {
}),
);
}
if (assumedByItem.type === 'account') {
if (assumedByItem.type === 'principalArn') {
statements.push(
new PolicyStatement({
actions: ['sts:AssumeRole'],
effect: Effect.ALLOW,
principals: [new ArnPrincipal(assumedByItem.principal)],
}),
);
}
if (assumedByItem.type === 'account' && assumedByItem.principal) {
const partition = this.props.partition;
const accountIdRegex = /^\d{12}$/;
const accountArnRegex = new RegExp('^arn:' + partition + ':iam::(\\d{12}):root$');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export class Route53ResolverQueryLoggingAssociation extends AseaResource {
if (!vpcItem.vpcRoute53Resolver?.queryLogs) {
continue;
}
const associationLogicalId = `RqlAssoc${vpcItem.name}`.replace('_vpc', '');
const associationLogicalIdWithReplacedVpc = `RqlAssoc${vpcItem.name}`.replace('_vpc', '');
const associationLogicalId = `${associationLogicalIdWithReplacedVpc}`.replace(/-/g, '');

const importResource = this.scope.importStackResources.getResourceByLogicalId(associationLogicalId);
const cfnResolverQueryLoggingAssociation = this.scope.getResource(
associationLogicalId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { AseaResourceType, VpcConfig, VpcTemplatesConfig } from '@aws-accelerato
import { SsmResourceType } from '@aws-accelerator/utils/lib/ssm-parameter-path';
import { AseaResource, AseaResourceProps } from './resource';
import { ImportAseaResourcesStack, LogLevel } from '../stacks/import-asea-resources-stack';
import { AcceleratorStage } from '../accelerator-stage';
import { pascalCase } from 'pascal-case';

const enum RESOURCE_TYPE {
SECURITY_GROUP = 'AWS::EC2::SecurityGroup',
SECURITY_GROUP_EGRESS = 'AWS::EC2::SecurityGroupEgress',
SECURITY_GROUP_INGRESS = 'AWS::EC2::SecurityGroupIngress',
}

const ASEA_PHASE_NUMBER = '2';
Expand All @@ -22,6 +25,9 @@ export class SharedSecurityGroups extends AseaResource {
}
const vpcsInScope = this.scope.sharedVpcs;
this.updateSecurityGroups(vpcsInScope);
if (this.props.stage === AcceleratorStage.POST_IMPORT_ASEA_RESOURCES) {
this.deleteSharedSecurityGroups(vpcsInScope);
}
}
private updateSecurityGroups(vpcItems: (VpcConfig | VpcTemplatesConfig)[]) {
if (vpcItems.length === 0) {
Expand Down Expand Up @@ -65,4 +71,124 @@ export class SharedSecurityGroups extends AseaResource {
}
return;
}

private deleteSharedSecurityGroups(vpcItems: (VpcConfig | VpcTemplatesConfig)[]) {
if (vpcItems.length === 0) {
return;
}
for (const vpcItem of vpcItems) {
const vpcStackInfo = this.getSecurityGroupResourceByVpc(vpcItem.name);
if (!vpcStackInfo) {
continue;
}
const existingSecurityGroups = vpcStackInfo.nestedStackResources.getResourcesByType(RESOURCE_TYPE.SECURITY_GROUP);

const existingSecurityGroupIngressRules = vpcStackInfo.nestedStackResources.getResourcesByType(
RESOURCE_TYPE.SECURITY_GROUP_INGRESS,
);
const existingSecurityGroupEgressRules = vpcStackInfo.nestedStackResources.getResourcesByType(
RESOURCE_TYPE.SECURITY_GROUP_EGRESS,
);

for (const existingSecurityGroup of existingSecurityGroups) {
const existingSecurityGroupName = existingSecurityGroup.resourceMetadata['Properties']['GroupName'];
const securityGroupConfig = vpcItem.securityGroups?.find(
(securityGroupItem: { name: string }) => securityGroupItem.name === existingSecurityGroupName,
);
// if the security group is still configured skip
if (securityGroupConfig) continue;

// lookup security group by tag name
// if unable to locate, warn and then skip
const securityGroupResource = vpcStackInfo.nestedStackResources.getResourceByTag(existingSecurityGroupName);
if (!securityGroupResource) {
this.scope.addLogs(
LogLevel.WARN,
`Could not locate shared security group resouce by tag name : ${existingSecurityGroupName}, for vpc ${vpcItem.name}`,
);
continue;
}

// remove security group from template
this.scope.addLogs(LogLevel.WARN, `Deleting Shared Security Group: ${existingSecurityGroup.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
securityGroupResource.logicalResourceId,
);

const ssmResource = vpcStackInfo.nestedStackResources.getSSMParameterByName(
this.scope.getSsmPath(SsmResourceType.SECURITY_GROUP, [
vpcItem.name,
existingSecurityGroup.resourceMetadata['Properties'].GroupName,
]),
);
if (ssmResource) {
this.scope.addLogs(LogLevel.WARN, `Deleting SSM Parameter: ${ssmResource.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
ssmResource.logicalResourceId,
);
}

for (const ingressRule of existingSecurityGroupIngressRules) {
try {
if (ingressRule.resourceMetadata['Properties'].GroupId['Ref'] === existingSecurityGroup.logicalResourceId) {
this.scope.addLogs(LogLevel.WARN, `Deleting Ingress Rule: ${ingressRule.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
ingressRule.logicalResourceId,
);
}
} catch (error) {
// continue the ref may not exits
}

try {
if (
ingressRule.resourceMetadata['Properties'].SourceSecurityGroupId['Ref'] ===
existingSecurityGroup.logicalResourceId
) {
this.scope.addLogs(LogLevel.WARN, `Deleting Ingress Rule: ${ingressRule.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
ingressRule.logicalResourceId,
);
}
} catch (error) {
// the ref may not exist
}

for (const egressRule of existingSecurityGroupEgressRules) {
try {
if (
egressRule.resourceMetadata['Properties'].GroupId['Ref'] === existingSecurityGroup.logicalResourceId
) {
this.scope.addLogs(LogLevel.WARN, `Deleting Egress Rule: ${egressRule.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
egressRule.logicalResourceId,
);
}
} catch (error) {
// continue the ref may not exist
}
try {
if (
egressRule.resourceMetadata['Properties'].DestinationSecurityGroupId['Ref'] ===
existingSecurityGroup.logicalResourceId
) {
this.scope.addLogs(LogLevel.WARN, `Deleting Egress Rule: ${egressRule.logicalResourceId}`);
this.scope.addDeleteFlagForNestedResource(
vpcStackInfo.nestedStackResources.getStackKey(),
egressRule.logicalResourceId,
);
}
} catch (error) {
// continue the ref may not exist
}
}
}
}
}
}
}
Loading