From ebd49c0390d5415665c7de608b62fecb6342cddd Mon Sep 17 00:00:00 2001 From: "Traub, Peter M. (pmt4u)" Date: Thu, 3 Oct 2019 13:18:48 -0400 Subject: [PATCH 1/3] Initial template example --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 9aee25f..e0ecc98 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ # sample-cf A sample AWS CloudFormation template + +## control-tower-client-vpc.yaml +Example of VPC template to replace default VPC created by Control Tower. This is +loosely based on the VPC template used by the Landing Zones solution. It creates +one public and two private subnets, each divided between two AZs, as well as an +Internet Gateway for the public subnet and a VPC Flow Log. Actual VPC CIDR +assignment and subnet IPs are parameterized. This is intended for use as a StackSet +to deploy to multiple client accounts, wherein each client account gets a different +parameter set to define it's VPC IP range. \ No newline at end of file From 19ba50425d50617dbbf02eeb0b85c1fe327fc415 Mon Sep 17 00:00:00 2001 From: "Traub, Peter M. (pmt4u)" Date: Thu, 3 Oct 2019 13:21:04 -0400 Subject: [PATCH 2/3] Forgot to add the actual template --- control-tower-client-vpc.yaml | 327 ++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 control-tower-client-vpc.yaml diff --git a/control-tower-client-vpc.yaml b/control-tower-client-vpc.yaml new file mode 100644 index 0000000..86544b5 --- /dev/null +++ b/control-tower-client-vpc.yaml @@ -0,0 +1,327 @@ +AWSTemplateFormatVersion: 2010-09-09 + +Description: This stack creates the underlying infrastructure for the Control Tower Client Account + +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: VPC and Subnet CIDR configuration + Parameters: + - VPCCIDR + - PublicSubnet1ACIDR + - PublicSubnet1BCIDR + - PrivateSubnet1ACIDR + - PrivateSubnet1BCIDR + - PrivateSubnet2ACIDR + - PrivateSubnet2BCIDR + ParameterLabels: + VPCCIDR: VPC CIDR + PublicSubnet1ACIDR: Public subnet 1A CIDR + PublicSubnet1BCIDR: Public subnet 1A CIDR + PrivateSubnet1ACIDR: Private subnet 1A CIDR + PrivateSubnet1BCIDR: Private subnet 1B CIDR + PrivateSubnet2ACIDR: Private subnet 2A CIDR + PrivateSubnet2BCIDR: Private subnet 2B CIDR + +Parameters: + VPCCIDR: + Default: 172.16.0.0/16 + Description: CIDR block for the Primary VPC + Type: String + PublicSubnet1ACIDR: + Default: 172.16.16.0/20 + Description: CIDR block for public subnet 1A located in Availability Zone 1 + Type: String + PublicSubnet1BCIDR: + Default: 172.16.32.0/20 + Description: CIDR block for public subnet 1A located in Availability Zone 2 + Type: String + PrivateSubnet1ACIDR: + Default: 172.16.48.0/20 + Description: CIDR block for private subnet 1A located in Availability Zone 1 + Type: String + PrivateSubnet1BCIDR: + Default: 172.16.64.0/20 + Description: CIDR block for private subnet 1B located in Availability Zone 2 + Type: String + PrivateSubnet2ACIDR: + Default: 172.16.80.0/20 + Description: CIDR block for private subnet 2A located in Availability Zone 1 + Type: String + PrivateSubnet2BCIDR: + Default: 172.16.96.0/20 + Description: CIDR block for private subnet 2B located in Availability Zone 2 + Type: String + +Resources: + PrimaryVPC: + Type: 'AWS::EC2::VPC' + Properties: + CidrBlock: !Ref VPCCIDR + Tags: + - Key: Name + Value: PrimaryVPC + + PublicSubnet1A: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PublicSubnet1ACIDR + AvailabilityZone: !Select + - '0' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PublicSubnet1A + + PublicSubnet1B: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PublicSubnet1BCIDR + AvailabilityZone: !Select + - '1' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PublicSubnet1B + + PrivateSubnet1A: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PrivateSubnet1ACIDR + AvailabilityZone: !Select + - '0' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PrivateSubnet1A + + PrivateSubnet1B: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PrivateSubnet1BCIDR + AvailabilityZone: !Select + - '1' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PrivateSubnet1B + + PrivateSubnet2A: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PrivateSubnet2ACIDR + AvailabilityZone: !Select + - '0' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PrivateSubnet2A + + PrivateSubnet2B: + Type: 'AWS::EC2::Subnet' + Properties: + VpcId: !Ref PrimaryVPC + CidrBlock: !Ref PrivateSubnet2BCIDR + AvailabilityZone: !Select + - '1' + - !GetAZs + Ref: 'AWS::Region' + Tags: + - Key: Name + Value: PrivateSubnet2B + + PublicRouteTable: + Type: 'AWS::EC2::RouteTable' + Properties: + VpcId: !Ref PrimaryVPC + Tags: + - Key: Name + Value: PublicRouteTable + + PublicSubnetRouteTableAssociationA: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnet1A + + PublicSubnetRouteTableAssociationB: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PublicRouteTable + SubnetId: !Ref PublicSubnet1B + + PrivateRouteTableA: + Type: 'AWS::EC2::RouteTable' + Properties: + VpcId: !Ref PrimaryVPC + Tags: + - Key: Name + Value: PrivateRouteTableA + + PrivateRouteTableB: + Type: 'AWS::EC2::RouteTable' + Properties: + VpcId: !Ref PrimaryVPC + Tags: + - Key: Name + Value: PrivateRouteTableB + + PrivateRouteTableAssociation1A: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PrivateRouteTableA + SubnetId: !Ref PrivateSubnet1A + + PrivateRouteTableAssociation1B: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PrivateRouteTableB + SubnetId: !Ref PrivateSubnet1B + + PrivateRouteTableAssociation2A: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PrivateRouteTableA + SubnetId: !Ref PrivateSubnet2A + + PrivateRouteTableAssociation2B: + Type: 'AWS::EC2::SubnetRouteTableAssociation' + Properties: + RouteTableId: !Ref PrivateRouteTableB + SubnetId: !Ref PrivateSubnet2B + + InternetGateway: + Type: AWS::EC2::InternetGateway + DeletionPolicy: Retain + Properties: + Tags: + - Key: Network + Value: Public + - Key: Name + Value: InternetGateway + + VPCGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + DeletionPolicy: Retain + Properties: + VpcId: !Ref PrimaryVPC + InternetGatewayId: !Ref InternetGateway + + PublicSubnetRoute: + DependsOn: VPCGatewayAttachment + DeletionPolicy: Retain + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref PublicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + + IAMServiceRoleVPCFlowLogs: + Type: 'AWS::IAM::Role' + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - vpc-flow-logs.amazonaws.com + Action: + - 'sts:AssumeRole' + Path: / + RoleName: IAMServiceRoleVPCFlowLogs + Policies: + - PolicyName: aws-iamservicerole-vpcflowlogs-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + - 'logs:DescribeLogGroups' + - 'logs:DescribeLogStreams' + Resource: '*' + Effect: Allow + + VPCFlowLogLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub ${AWS::AccountId}-FlowLog + RetentionInDays: 90 + + VPCFlowLog: + DependsOn: PrimaryVPC + Type: AWS::EC2::FlowLog + Properties: + DeliverLogsPermissionArn: !GetAtt IAMServiceRoleVPCFlowLogs.Arn + LogGroupName: !Ref VPCFlowLogLogGroup + ResourceId: !Ref PrimaryVPC + ResourceType: VPC + TrafficType: ALL + + VPCFlowLogStream: + Type: AWS::Logs::LogStream + Properties: + LogGroupName: !Ref VPCFlowLogLogGroup + +Outputs: + oVPCClient: + Value: !Ref PrimaryVPC + Export: + Name: oVPCClient + + oPublicSubnetRouteTable: + Value: !Ref PublicRouteTable + Export: + Name: oPublicSubnetRouteTable + + oPrivateSubnetRouteTableA: + Value: !Ref PrivateRouteTableA + Export: + Name: oPrivateSubnetRouteTableA + + oPrivateSubnetRouteTableB: + Value: !Ref PrivateRouteTableB + Export: + Name: oPrivateSubnetRouteTableB + + oPublicSubnet1A: + Value: !Ref PublicSubnet1A + Export: + Name: oPublicSubnet1A + + oPublicSubnet1B: + Value: !Ref PublicSubnet1B + Export: + Name: oPublicSubnet1B + + oPrivateSubnet1A: + Value: !Ref PrivateSubnet1A + Export: + Name: oPrivateSubnet1A + + oPrivateSubnet1B: + Value: !Ref PrivateSubnet1B + Export: + Name: oPrivateSubnet1B + + oPrivateSubnet2A: + Value: !Ref PrivateSubnet2A + Export: + Name: oPrivateSubnet2A + + oPrivateSubnet2B: + Value: !Ref PrivateSubnet2B + Export: + Name: oPrivateSubnet2B \ No newline at end of file From 965a63b3f21ee5a1de92d90f3955e1ba439a158a Mon Sep 17 00:00:00 2001 From: "Traub, Peter M. (pmt4u)" Date: Thu, 3 Oct 2019 13:28:24 -0400 Subject: [PATCH 3/3] Add GuardDutyMasterExecutioniRole.yml CFN stack --- GuardDutyMasterExecutionRole.yml | 27 +++++++++++++++++++++++++++ README.md | 10 +++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 GuardDutyMasterExecutionRole.yml diff --git a/GuardDutyMasterExecutionRole.yml b/GuardDutyMasterExecutionRole.yml new file mode 100644 index 0000000..238252e --- /dev/null +++ b/GuardDutyMasterExecutionRole.yml @@ -0,0 +1,27 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Configure the GuardDutyMasterExecutionRole to allow GuardDuty enabling script Assume Role into target accounts from the Guard Duty Master account. + +Parameters: + AdministratorAccountId: + Type: String + Description: AWS Account ID of the administrator account (the account in which StackSet will be created). + MaxLength: 12 + MinLength: 12 + +Resources: + ExecutionRole: + Type: AWS::IAM::Role + Properties: + RoleName: GuardDutyMasterExecutionRole + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: + - !Ref AdministratorAccountId + Action: + - sts:AssumeRole + Path: / + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonGuardDutyFullAccess diff --git a/README.md b/README.md index e0ecc98..7c09bd7 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,12 @@ one public and two private subnets, each divided between two AZs, as well as an Internet Gateway for the public subnet and a VPC Flow Log. Actual VPC CIDR assignment and subnet IPs are parameterized. This is intended for use as a StackSet to deploy to multiple client accounts, wherein each client account gets a different -parameter set to define it's VPC IP range. \ No newline at end of file +parameter set to define it's VPC IP range. + +## GuardDutyMasterExecutionRole.yml +For deployment into all accounts that will run GuardDuty and report findings back +to the Master account. This can be deployed via StackSets from the Master (assuming +you have the necessary StackSet execution roles created on Master and client accounts). +This allows the GuardyDuty setup script to assume role into the client accounts through +the Master account in order to enable GuardDuty in the clients and accept the +invitation from the Master. \ No newline at end of file