Skip to content
New issue

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

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

Already on GitHub? # to your account

elbv2: How to configure a connection log #30708

Closed
jrobbins-LiveData opened this issue Jun 29, 2024 · 6 comments
Closed

elbv2: How to configure a connection log #30708

jrobbins-LiveData opened this issue Jun 29, 2024 · 6 comments
Labels
@aws-cdk/aws-elasticloadbalancingv2 Related to Amazon Elastic Load Balancing V2 documentation This is a problem with documentation. p3

Comments

@jrobbins-LiveData
Copy link
Contributor

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)

@jrobbins-LiveData jrobbins-LiveData added documentation This is a problem with documentation. needs-triage This issue or PR still needs to be triaged. labels Jun 29, 2024
@github-actions github-actions bot added the @aws-cdk/aws-elasticloadbalancingv2 Related to Amazon Elastic Load Balancing V2 label Jun 29, 2024
@pahud pahud self-assigned this Jul 1, 2024
@pahud pahud added investigating This issue is being investigated and/or work is in progress to resolve the issue. and removed needs-triage This issue or PR still needs to be triaged. labels Jul 1, 2024
@pahud
Copy link
Contributor

pahud commented Jul 1, 2024

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 pahud removed their assignment Jul 1, 2024
@pahud pahud added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. p3 and removed investigating This issue is being investigated and/or work is in progress to resolve the issue. labels Jul 1, 2024
@pahud pahud changed the title (aws_elasticloadbalancingv2): (How to configure a connection log) elbv2: How to configure a connection log Jul 1, 2024
@jrobbins-LiveData
Copy link
Contributor Author

@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?

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Jul 1, 2024
@jrobbins-LiveData
Copy link
Contributor Author

@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)

@pahud
Copy link
Contributor

pahud commented Jul 8, 2024

Thank you for your code sharing.

Resolving this issue for now. Feel free to open a new one if it's still relevant.

@pahud pahud closed this as completed Jul 8, 2024
Copy link

github-actions bot commented Jul 8, 2024

⚠️COMMENT VISIBILITY WARNING⚠️

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.

@aws-cdk-automation
Copy link
Collaborator

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.

@aws aws locked as resolved and limited conversation to collaborators Jul 25, 2024
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
@aws-cdk/aws-elasticloadbalancingv2 Related to Amazon Elastic Load Balancing V2 documentation This is a problem with documentation. p3
Projects
None yet
Development

No branches or pull requests

3 participants