Closed jrobbins-LiveData closed 4 months ago
We need to simplify it with relevant document but this works for me in us-east-1 per the doc.
export class DummyStack extends Stack {
readonly cluster: rds.DatabaseCluster;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const connectionLogBucket = new s3.Bucket(this, 'ConnectionLogBucket', {
removalPolicy: RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
});
const logPrefix = 'MY_PREFIX';
const region = region_info.RegionInfo.get(this.region);
// create a bucket policy for this bucket
const accessPolicy = new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:PutObject'],
resources: [`arn:aws:s3:::${connectionLogBucket.bucketName}/${logPrefix}/AWSLogs/${Aws.ACCOUNT_ID}/*`],
principals: [new iam.AccountPrincipal(region.elbv2Account) ],
});
connectionLogBucket.addToResourcePolicy(accessPolicy);
// create a dummy ALB
const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB', { vpc: ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true }), internetFacing: true });
alb.setAttribute('connection_logs.s3.enabled', 'true');
alb.setAttribute('connection_logs.s3.bucket', connectionLogBucket.bucketName);
alb.setAttribute('connection_logs.s3.prefix', logPrefix);
alb.node.addDependency(connectionLogBucket);
}
}
Let me know if it works for you.
@pahud, this is really great, thank you! We're writing our stacks in Python, so my code below is a little different from your helpful example.
alb_logs_bucket.add_to_resource_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=['s3:PutObject'],
resources=[
f'arn:aws:s3:::{alb_logs_bucket.bucket_name}/access/AWSLogs/{self.account}/*',
f'arn:aws:s3:::{alb_logs_bucket.bucket_name}/connection/AWSLogs/{self.account}/*',
],
principals=[iam.AccountPrincipal(RegionInfo.get(self.region).elbv2_account)]
# principals=[iam.ServicePrincipal('logdelivery.elasticloadbalancing.amazonaws.com')]
)
)
What I'm curious about is what is the difference between the principals=[iam.AccountPrincipal(RegionInfo.get(self.region).elbv2_account)]
(my translation of your example into Python) vs the commented-out # principals=[iam.ServicePrincipal('logdelivery.elasticloadbalancing.amazonaws.com')]
? Either line of code appears to work, but I don't know if either one is "better" from a security point of view? What do you think?
@pahud I was unable to combine my Python conversion of your code the the CDK's built-in ..log_access_logs(bucket)
L2 method. I ended up with permission errors after I destroyed my CDK stack and tried to deploy clean.
The following code works for me to setup both an access_log
and a connection_log
, in case it helps anyone.
alb_logs_bucket.add_to_resource_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=['s3:PutObject'],
resources=[
f'{alb_logs_bucket.bucket_arn}/{ACCESS_LOG_PREFIX}/AWSLogs/{Aws.ACCOUNT_ID}/*',
f'{alb_logs_bucket.bucket_arn}/{CONNECTION_LOG_PREFIX}/AWSLogs/{Aws.ACCOUNT_ID}/*',
],
principals=[iam.ServicePrincipal('logdelivery.elasticloadbalancing.amazonaws.com')]
)
)
alb.set_attribute('access_logs.s3.enabled', 'true')
alb.set_attribute('access_logs.s3.bucket', alb_logs_bucket.bucket_name)
alb.set_attribute('access_logs.s3.prefix', ACCESS_LOG_PREFIX)
alb.set_attribute('connection_logs.s3.enabled', 'true')
alb.set_attribute('connection_logs.s3.bucket', alb_logs_bucket.bucket_name)
alb.set_attribute('connection_logs.s3.prefix', CONNECTION_LOG_PREFIX)
logs_delivery_service_principal = iam.ServicePrincipal('delivery.logs.amazonaws.com')
account = RegionInfo.get(cdk.Stack.of(self).region).elbv2_account
if not account:
account_principal = iam.ServicePrincipal('logdelivery.elasticloadbalancing.amazonaws.com')
else:
account_principal = iam.AccountPrincipal(account)
alb_logs_bucket.add_to_resource_policy(
iam.PolicyStatement(
actions=['s3:PutObject'],
principals=[account_principal],
resources=[
alb_logs_bucket.arn_for_objects(f'{ACCESS_LOG_PREFIX}/AWSLogs/{cdk.Stack.of(self).account}/*'),
alb_logs_bucket.arn_for_objects(f'{CONNECTION_LOG_PREFIX}/AWSLogs/{cdk.Stack.of(self).account}/*')
],
)
)
alb_logs_bucket.add_to_resource_policy(
iam.PolicyStatement(
actions=['s3:PutObject'],
principals=[logs_delivery_service_principal],
resources=[
alb_logs_bucket.arn_for_objects(f'{ACCESS_LOG_PREFIX}/AWSLogs/{self.account}/*'),
alb_logs_bucket.arn_for_objects(f'{CONNECTION_LOG_PREFIX}/AWSLogs/{self.account}/*')
],
conditions={
'StringEquals': {'s3:x-amz-acl': 'bucket-owner-full-control'}
}
)
)
alb_logs_bucket.add_to_resource_policy(
iam.PolicyStatement(
actions=['s3:GetBucketAcl'],
principals=[logs_delivery_service_principal],
resources=[alb_logs_bucket.bucket_arn]
)
)
alb_cfn = alb.node.default_child
bucket_policy_cfn = alb_logs_bucket.policy.node.default_child
alb_cfn.add_dependency(bucket_policy_cfn)
Thank you for your code sharing.
Resolving this issue for now. Feel free to open a new one if it's still relevant.
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.
Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.
Describe the issue
Application Load Balancer has a
connection log
feature (see doc) But the L2 construct doesn't seem to surface it. I tried to use a L1 "escape hatch" to enable it, but failed to do so.I didn't know if this was a doc issue or a feature request, or simply my missing something.
Links
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2-readme.html (which documents the "access log" feature, but not the "connection log" feature)