Skip to content

Commit

Permalink
DAC-2765 Security work and IaC release for ingest lambda (#584)
Browse files Browse the repository at this point in the history
Add IaC for cross account lambda, role, VPC and other resources
Minor changes to cross-account-transfer handler code to remove some TypeScript warnings
  • Loading branch information
hdavey-gds authored Feb 27, 2024
1 parent 7b92e38 commit 72db099
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 3 deletions.
6 changes: 6 additions & 0 deletions iac/main/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ Parameters:
Type: String
Description: String of characters to exclude from the redshift password stored in secretsmanager
Default: '"''@/\'
CrossAccountDataSyncRoleName:
Type: String
Description: Name of the role allowing cross account data sync
Default: dap-cross-account-data-sync-role
AllowedValues:
- dap-cross-account-data-sync-role

Conditions:
UseCodeSigning: !Not
Expand Down
191 changes: 191 additions & 0 deletions iac/main/resources/cross-account.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
CrossAccountVPC:
Type: AWS::EC2::VPC
Condition: IsProduction
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Name
Value: dap-cross-account-vpc

CrossAccountSubnet1:
Type: AWS::EC2::Subnet
Condition: IsProduction
Properties:
VpcId: !Ref CrossAccountVPC
AvailabilityZone: !Select
- 0
- !GetAZs
Ref: 'AWS::Region'
CidrBlock: 10.0.1.0/24
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Name
Value: dap-cross-account-subnet-1

CrossAccountSubnet2:
Type: AWS::EC2::Subnet
Condition: IsProduction
Properties:
VpcId: !Ref CrossAccountVPC
AvailabilityZone: !Select
- 1
- !GetAZs
Ref: 'AWS::Region'
CidrBlock: 10.0.2.0/24
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Name
Value: dap-cross-account-subnet-2

CrossAccountSubnet3:
Type: AWS::EC2::Subnet
Condition: IsProduction
Properties:
VpcId: !Ref CrossAccountVPC
AvailabilityZone: !Select
- 2
- !GetAZs
Ref: 'AWS::Region'
CidrBlock: 10.0.3.0/24
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Name
Value: dap-cross-account-subnet-3

CrossAccountRouteTable:
Type: AWS::EC2::RouteTable
Condition: IsProduction
Properties:
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Name
Value: dap-cross-account-route-table
VpcId: !Ref CrossAccountVPC

CrossAccountRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Condition: IsProduction
Properties:
RouteTableId: !Ref CrossAccountRouteTable
SubnetId: !Ref CrossAccountSubnet1

CrossAccountRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Condition: IsProduction
Properties:
RouteTableId: !Ref CrossAccountRouteTable
SubnetId: !Ref CrossAccountSubnet2

CrossAccountRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Condition: IsProduction
Properties:
RouteTableId: !Ref CrossAccountRouteTable
SubnetId: !Ref CrossAccountSubnet3

CrossAccountSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: IsProduction
Properties:
GroupName: cross-account-security-group
GroupDescription: Security group for the cross account VPC
VpcId: !Ref CrossAccountVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: Allow ingress from anywhere within the VPC on 443
SecurityGroupEgress:
- IpProtocol: -1
FromPort: -1
ToPort: -1
CidrIp: 0.0.0.0/0
Description: Allow egress to anywhere

CrossAccountVPCEndpointSQS:
Type: AWS::EC2::VPCEndpoint
Condition: IsProduction
Properties:
VpcEndpointType: Interface
ServiceName: com.amazonaws.eu-west-2.sqs
VpcId: !Ref CrossAccountVPC
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref CrossAccountSecurityGroup
SubnetIds:
- !Ref CrossAccountSubnet1
- !Ref CrossAccountSubnet2
- !Ref CrossAccountSubnet3

CrossAccountDataSyncRole:
Type: AWS::IAM::Role
Condition: IsProduction
Properties:
RoleName: !Ref CrossAccountDataSyncRoleName
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
MaxSessionDuration: 3600
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Policies:
- PolicyName: dap-cross-account-data-sync-policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sqs:SendMessage
Resource:
- !Sub arn:aws:sqs:eu-west-2:*:staging-placeholder-txma-event-queue
- !Sub arn:aws:sqs:eu-west-2:*:production-preview-placeholder-txma-event-queue
- Effect: Allow
Action:
- kms:Decrypt
- kms:Encrypt
- kms:DescribeKey
- kms:GenerateDataKey
Resource: '*'
- Effect: Allow
Action:
- s3:GetObject
- s3:ListBucket
Resource:
- !Sub arn:aws:s3:::${RawLayerBucket}
- !Sub arn:aws:s3:::${RawLayerBucket}/*

CrossAccountDataSyncLambda:
# checkov:skip=CKV_AWS_116: DLQ not needed as this is a manually invoked action
Type: AWS::Serverless::Function
Condition: IsProduction
Properties:
FunctionName: cross-account-transfer
Handler: cross-account-transfer.handler
Role: !GetAtt CrossAccountDataSyncRole.Arn
ReservedConcurrentExecutions: 10
Environment:
# checkov:skip=CKV_AWS_173: These environment variables do not require encryption
Variables:
ENVIRONMENT: !Ref Environment
RAW_BUCKET_NAME: !Ref RawLayerBucket
Tags:
Environment: !Ref Environment
VpcConfig:
SecurityGroupIds:
- !Ref CrossAccountSecurityGroup
SubnetIds:
- !Ref CrossAccountSubnet1
- !Ref CrossAccountSubnet2
- !Ref CrossAccountSubnet3
6 changes: 3 additions & 3 deletions src/handlers/cross-account-transfer/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export const handler = async (event: Event): Promise<{ statusCode: number; body:
const s3Prefix = `txma/${eventName}/year=${date.slice(0, 4)}/month=${date.slice(5, 7)}/day=${date.slice(8, 10)}`;
const s3Params = { Bucket: s3Bucket, Prefix: s3Prefix };

const s3Response = await s3Client.send(new ListObjectsV2Command(s3Params));
const contents = await s3Client.send(new ListObjectsV2Command(s3Params)).then(response => response.Contents);

if (s3Response?.Contents?.length > 0) {
if (contents !== undefined && contents.length > 0) {
const messages = [];
for (const obj of s3Response.Contents) {
for (const obj of contents) {
const getObjectParams = { Bucket: s3Bucket, Key: obj.Key };
const objectResponse = await s3Client.send(new GetObjectCommand(getObjectParams));
const objectContent = await getDecompressedContent(objectResponse);
Expand Down

0 comments on commit 72db099

Please sign in to comment.