aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.65k stars 3.91k forks source link

(aws-route53): Query Logging #29095

Open sniper7kills opened 8 months ago

sniper7kills commented 8 months ago

Describe the feature

There should be a way to enable/disable query logging on hosted zones after they are created.

Currently it appears that this is only possible when creating a hosted zone; but it should be possible to enable/disable Query Logging on an already created Hosted Zone.

Use Case

Attempting to following the guidance provided at: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-route53-hostedzone.html#cfn-route53-hostedzone-queryloggingconfig

We can assume a cdk stack that looks similar to this:

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class InfrastructureStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create a new HostedZone
    const PublicHostedZone = new cdk.aws_route53.HostedZone(this, 'HostedZone', {
      zoneName: 'example.com',
      comment: 'Public Hosted Zone',
    });

    // Create a LogGroup for Hosted Zone Query Logs
    const LogGroup = new cdk.aws_logs.LogGroup(this, 'LogGroup', {
      // Do it after the HostedZone is created as we wantthe Zone ID
      logGroupName: '/aws/route53/' + PublicHostedZone.hostedZoneId,
      retention: cdk.aws_logs.RetentionDays.ONE_WEEK,
    });

    const AWSServiceRoleForRoute53 = new cdk.aws_logs.ResourcePolicy(this, 'ResourcePolicy', {
      resourcePolicyName: 'AWSServiceRoleForRoute53',
      policyStatements: [
        new cdk.aws_iam.PolicyStatement({
          sid: 'Route53LogsToCloudWatchLogs',
          effect: cdk.aws_iam.Effect.ALLOW,
          principals: [
            new cdk.aws_iam.ServicePrincipal('route53.amazonaws.com'),
          ],
          actions: [
            'logs:CreateLogStream',
            'logs:PutLogEvents',
          ],
          resources: [
            'arn:aws:logs:us-east-1:' + this.account + ':log-group:/aws/route53/*:*',
          ],
        })
      ]
    });

    const PublicHostedZoneLoggingEnabled = new cdk.custom_resources.AwsCustomResource(this, 'create-query-logging-config', {
      onCreate: {
        service: 'Route53',
        action: 'createQueryLoggingConfig',
        physicalResourceId: { id: 'create-query-logging-config' },
        parameters: {
          HostedZoneId: PublicHostedZone.hostedZoneId,
          CloudWatchLogsLogGroupArn: LogGroup.logGroupArn,
        },
        region: 'us-east-1',
      },
      policy: cdk.custom_resources.AwsCustomResourcePolicy.fromSdkCalls({ resources: cdk.custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE })
    });
  }
}

Proposed Solution

Something as Simple as PublicHostedZone.enableQueryLogging(LogGroup);

Other Information

Possibly related to #15296 ; and possibly requires a larger RFC as a similar issue exists in CloudFormation.

Acknowledgements

CDK version used

2.127.0 (build 6c90efc)

Environment details (OS name and version, etc.)

Arch Linux

pahud commented 8 months ago

According to this

https://github.com/aws/aws-cdk/blob/a21731c9b1f34525433fbee668ebb2321debf5b8/packages/aws-cdk-lib/aws-route53/lib/hosted-zone.ts#L180

Looks like it would be enabled if queryLogsLogGroupArn is specified?

It's great to have a method like that but you still can enable that when you create the HostedZone, right?

sniper7kills commented 8 months ago

Correct; You can enable it when creating the HostedZone.

The issue comes when trying to follow the recommendation:

When you create log groups for query logging, we recommend that you use a consistent prefix, for example:

/aws/route53/hosted zone name

The HostedZone has to be created; before that value can be set following the recommendations; but because the LogGroup hasn't been created yet, its not possible to set the queryLoggingConfig.

To be clear; I understand I'm changing a setting "after the resource was created" but that is not my intent.


If there is a best practice or something obvious I'm missing please let me know; this is the first time I'm using cdk.

Cameronsplaze commented 7 months ago

If I'm understanding this right, I think I hit a similar use-case. I want my stack to interact with Public Hosted Zones created through the AWS Domain Registration tool. The problem is you can import them, but you can't add logging afterwards, like mentioned above. (And I'd like to add a subscription filter to the logs).

The only way I've found to get around this is to create a second Public Hosted Zone (with logging) in my stack, and add a NsRecord to point queries to the Zone I have direct control over. Something like:

    # The imported one you have no control over :/
    const rootHostedZone = route53.HostedZone.fromLookup(this, 'HostedZone', {
      domainName: <domain-name>,
    });

    # Create a second with logging this time:
    const subdomainHostedZone = new route53.HostedZone(
      this,
      'SubdomainHostedZone',
      {
        zoneName: subdomain,
        queryLogsLogGroupArn: queryLogGroup.logGroupArn,
      }
    );

    # And tie them together with a NsRecord
    const nsRecord = new route53.NsRecord(this, 'NSRecord', {
      zone: rootHostedZone,
      values: subdomainHostedZone.hostedZoneNameServers as string[],
      recordName: subdomain,
    });

Just being able to modify the original "fromLookup" zone would make things much simpler.

Edit: I just realized you linked a issue in the initial post that explains why this isn't possible, Rip. Hopefully the example helps someone out there at least.