Skip to content

Commit

Permalink
fix(elasticloadbalancingv2): dependency between ALB and logging bucket (
Browse files Browse the repository at this point in the history
#2221)

When access logs are enabled for an ALB, a dependency is added between
the ALB and the logging bucket and it's policy to avoid a race condition
where the ALB can't access the bucket.

Fixes #1633
  • Loading branch information
Elad Ben-Israel authored Apr 11, 2019
1 parent 81fa7ba commit 99e085d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic
throw new Error(`Cannot enable access logging; don't know ELBv2 account for region ${region}`);
}

// FIXME: can't use grantPut() here because that only takes IAM objects, not arbitrary principals
bucket.addToResourcePolicy(new iam.PolicyStatement()
.addPrincipal(new iam.AccountPrincipal(account))
.addAction('s3:PutObject')
.addResource(bucket.arnForObjects(prefix || '', '*')));
prefix = prefix || '';
bucket.grantPut(new iam.AccountPrincipal(account), prefix + '*');

// make sure the bucket's policy is created before the ALB (see https://github.com/awslabs/aws-cdk/issues/1633)
this.node.addDependency(bucket);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ export = {
lb.logAccessLogs(bucket);

// THEN

// verify that the LB attributes reference the bucket
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
LoadBalancerAttributes: [
{
Expand All @@ -134,12 +136,14 @@ export = {
}
],
}));

// verify the bucket policy allows the ALB to put objects in the bucket
expect(stack).to(haveResource('AWS::S3::BucketPolicy', {
PolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: "s3:PutObject",
Action: [ "s3:PutObject*", "s3:Abort*" ],
Effect: 'Allow',
Principal: { AWS: { "Fn::Join": [ "", [ "arn:", { Ref: "AWS::Partition" }, ":iam::127311923021:root" ] ] } },
Resource: { "Fn::Join": [ "", [ { "Fn::GetAtt": [ "AccessLoggingBucketA6D88F29", "Arn" ] }, "/*" ] ] }
Expand All @@ -148,6 +152,58 @@ export = {
}
}));

// verify the ALB depends on the bucket *and* the bucket policy
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
DependsOn: [ 'AccessLoggingBucketPolicy700D7CC6', 'AccessLoggingBucketA6D88F29' ]
}, ResourcePart.CompleteDefinition));

test.done();
},

'access logging with prefix'(test: Test) {
// GIVEN
const stack = new cdk.Stack(undefined, undefined, { env: { region: 'us-east-1' }});
const vpc = new ec2.VpcNetwork(stack, 'Stack');
const bucket = new s3.Bucket(stack, 'AccessLoggingBucket');
const lb = new elbv2.ApplicationLoadBalancer(stack, 'LB', { vpc });

// WHEN
lb.logAccessLogs(bucket, 'prefix-of-access-logs');

// THEN
// verify that the LB attributes reference the bucket
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
LoadBalancerAttributes: [
{
Key: "access_logs.s3.enabled",
Value: "true"
},
{
Key: "access_logs.s3.bucket",
Value: { Ref: "AccessLoggingBucketA6D88F29" }
},
{
Key: "access_logs.s3.prefix",
Value: "prefix-of-access-logs"
}
],
}));

// verify the bucket policy allows the ALB to put objects in the bucket
expect(stack).to(haveResource('AWS::S3::BucketPolicy', {
PolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: [ "s3:PutObject*", "s3:Abort*" ],
Effect: 'Allow',
Principal: { AWS: { "Fn::Join": [ "", [ "arn:", { Ref: "AWS::Partition" }, ":iam::127311923021:root" ] ] } },
Resource: { "Fn::Join": [ "", [ { "Fn::GetAtt": [ "AccessLoggingBucketA6D88F29", "Arn" ] }, "/prefix-of-access-logs*" ] ] }
}
]
}
}));

test.done();
},

Expand Down

0 comments on commit 99e085d

Please sign in to comment.