Skip to content

Commit 26779f8

Browse files
authored
feat(ec2): change log format in Vpc flow logs (#22430)
refer to #16279 and #16279 (comment). The difference is below - I don't think you need custom for `LogFormatField`. "custom" in the document below does not mean that the user can specify any Key. It means that you can specify any Key of "Available fields" with a space-separated string. https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-logs-fields fixes #19316 ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 65d8e3d commit 26779f8

27 files changed

+5608
-2
lines changed

packages/@aws-cdk/aws-ec2/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,38 @@ vpc.addFlowLog('FlowLogCloudWatch', {
14021402
});
14031403
```
14041404

1405+
### Custom Formatting
1406+
1407+
You can also custom format flow logs.
1408+
1409+
```ts
1410+
const vpc = new ec2.Vpc(this, 'Vpc');
1411+
1412+
vpc.addFlowLog('FlowLog', {
1413+
logFormat: [
1414+
ec2.LogFormat.DST_PORT,
1415+
ec2.LogFormat.SRC_PORT,
1416+
],
1417+
});
1418+
1419+
// If you just want to add a field to the default field
1420+
vpc.addFlowLog('FlowLog', {
1421+
logFormat: [
1422+
ec2.LogFormat.VERSION,
1423+
ec2.LogFormat.ALL_DEFAULT_FIELDS,
1424+
],
1425+
});
1426+
1427+
// If AWS CDK does not support the new fields
1428+
vpc.addFlowLog('FlowLog', {
1429+
logFormat: [
1430+
ec2.LogFormat.SRC_PORT,
1431+
ec2.LogFormat.custom('${new-field}'),
1432+
],
1433+
});
1434+
```
1435+
1436+
14051437
By default, the CDK will create the necessary resources for the destination. For the CloudWatch Logs destination
14061438
it will create a CloudWatch Logs Log Group as well as the IAM role with the necessary permissions to publish to
14071439
the log group. In the case of an S3 destination, it will create the S3 bucket.

packages/@aws-cdk/aws-ec2/lib/vpc-flow-logs.ts

+154
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,141 @@ export enum FlowLogMaxAggregationInterval {
401401

402402
}
403403

404+
/**
405+
* The following table describes all of the available fields for a flow log record.
406+
*/
407+
export class LogFormat {
408+
/**
409+
* The VPC Flow Logs version.
410+
*/
411+
public static readonly VERSION = new LogFormat('${version}');
412+
413+
/**
414+
* The AWS account ID of the owner of the source network interface for which traffic is recorded.
415+
*/
416+
public static readonly ACCOUNT_ID = new LogFormat('${account-id}');
417+
418+
/**
419+
* The ID of the network interface for which the traffic is recorded.
420+
*/
421+
public static readonly INTERFACE_ID = new LogFormat('${interface-id');
422+
423+
/**
424+
* The source address for incoming traffic, or the IPv4 or IPv6 address of the network interface
425+
* for outgoing traffic on the network interface.
426+
*/
427+
public static readonly SRC_ADDR = new LogFormat('${srcaddr}');
428+
429+
/**
430+
* The destination address for outgoing traffic, or the IPv4 or IPv6 address of the network interface
431+
* for incoming traffic on the network interface.
432+
*/
433+
public static readonly DST_ADDR = new LogFormat('${dstaddr}');
434+
435+
/**
436+
* The source port of the traffic.
437+
*/
438+
public static readonly SRC_PORT = new LogFormat('${srcport}');
439+
440+
/**
441+
* The destination port of the traffic.
442+
*/
443+
public static readonly DST_PORT = new LogFormat('${dstport}');
444+
445+
/**
446+
* The IANA protocol number of the traffic.
447+
*/
448+
public static readonly PROTOCOL = new LogFormat('${protocol}');
449+
450+
/**
451+
* The number of packets transferred during the flow.
452+
*/
453+
public static readonly PACKETS = new LogFormat('${packets}');
454+
455+
/**
456+
* The number of bytes transferred during the flow.
457+
*/
458+
public static readonly BYTES = new LogFormat('${bytes}');
459+
460+
/**
461+
* The packet-level (original) source IP address of the traffic.
462+
*/
463+
public static readonly PKT_SRC_ADDR = new LogFormat('${pkt-srcaddr}');
464+
465+
/**
466+
* The packet-level (original) destination IP address for the traffic.
467+
*/
468+
public static readonly PKT_DST_ADDR = new LogFormat('${pkt-dstaddr}');
469+
470+
/**
471+
* The Region that contains the network interface for which traffic is recorded.
472+
*/
473+
public static readonly REGION = new LogFormat('${region}');
474+
475+
/**
476+
* The ID of the Availability Zone that contains the network interface for which traffic is recorded.
477+
*/
478+
public static readonly AZ_ID = new LogFormat('${az-id}');
479+
480+
/**
481+
* The type of sublocation that's returned in the sublocation-id field.
482+
*/
483+
public static readonly SUBLOCATION_TYPE = new LogFormat('${sublocation-type}');
484+
485+
/**
486+
* The ID of the sublocation that contains the network interface for which traffic is recorded.
487+
*/
488+
public static readonly SUBLOCATION_ID = new LogFormat('${sublocation-id}');
489+
490+
/**
491+
* The name of the subset of IP address ranges for the pkt-srcaddr field,
492+
* if the source IP address is for an AWS service.
493+
*/
494+
public static readonly PKT_SRC_AWS_SERVICE = new LogFormat('${pkt-src-aws-service}');
495+
496+
/**
497+
* The name of the subset of IP address ranges for the pkt-dstaddr field,
498+
* if the destination IP address is for an AWS service.
499+
*/
500+
public static readonly PKT_DST_AWS_SERVICE = new LogFormat('${pkt-dst-aws-service}');
501+
502+
/**
503+
* The direction of the flow with respect to the interface where traffic is captured.
504+
*/
505+
public static readonly FLOW_DIRECTION = new LogFormat('${flow-direction}');
506+
507+
/**
508+
* The path that egress traffic takes to the destination.
509+
*/
510+
public static readonly TRAFFIC_PATH = new LogFormat('${traffic-path}');
511+
512+
/**
513+
* The default format.
514+
*/
515+
public static readonly ALL_DEFAULT_FIELDS = new LogFormat('${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}');
516+
517+
/**
518+
* A custom format string.
519+
*
520+
* Gives full control over the format string fragment.
521+
*/
522+
public static custom(formatString: string): LogFormat {
523+
return new LogFormat(formatString);
524+
}
525+
526+
/**
527+
* A custom field name.
528+
*
529+
* If there is no ready-made constant for a new field yet, you can use this.
530+
* The field name will automatically be wrapped in `${ ... }`.
531+
*/
532+
public static field(field: string): LogFormat {
533+
return new LogFormat(`\${${field}}`);
534+
}
535+
536+
protected constructor(public readonly value: string) {}
537+
}
538+
404539
/**
405540
* Options to add a flow log to a VPC
406541
*/
@@ -420,6 +555,18 @@ export interface FlowLogOptions {
420555
*/
421556
readonly destination?: FlowLogDestination;
422557

558+
/**
559+
* The fields to include in the flow log record, in the order in which they should appear.
560+
*
561+
* If multiple fields are specified, they will be separated by spaces. For full control over the literal log format
562+
* string, pass a single field constructed with `LogFormat.custom()`.
563+
*
564+
* See https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records
565+
*
566+
* @default - default log format is used.
567+
*/
568+
readonly logFormat?: LogFormat[];
569+
423570
/**
424571
* The maximum interval of time during which a flow of packets is captured
425572
* and aggregated into a flow log record.
@@ -521,6 +668,12 @@ export class FlowLog extends FlowLogBase {
521668
if (this.bucket) {
522669
logDestination = this.keyPrefix ? this.bucket.arnForObjects(this.keyPrefix) : this.bucket.bucketArn;
523670
}
671+
let customLogFormat: string | undefined = undefined;
672+
if (props.logFormat) {
673+
customLogFormat = props.logFormat.map(elm => {
674+
return elm.value;
675+
}).join(' ');
676+
}
524677

525678
const flowLog = new CfnFlowLog(this, 'FlowLog', {
526679
destinationOptions: destinationConfig.destinationOptions,
@@ -533,6 +686,7 @@ export class FlowLog extends FlowLogBase {
533686
trafficType: props.trafficType
534687
? props.trafficType
535688
: FlowLogTrafficType.ALL,
689+
logFormat: customLogFormat,
536690
logDestination,
537691
});
538692

packages/@aws-cdk/aws-ec2/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@
364364
"docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.SECURITYHUB",
365365
"docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.EMAIL_SMTP",
366366
"docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.WORKSPACES",
367+
"docs-public-apis:@aws-cdk/aws-ec2.LogFormat.value",
367368
"docs-public-apis:@aws-cdk/aws-ec2.Port.toString",
368369
"docs-public-apis:@aws-cdk/aws-ec2.PrivateSubnet.fromPrivateSubnetAttributes",
369370
"docs-public-apis:@aws-cdk/aws-ec2.PublicSubnet.fromPublicSubnetAttributes",
@@ -749,7 +750,8 @@
749750
"props-physical-name:@aws-cdk/aws-ec2.ClientVpnRouteProps",
750751
"duration-prop-type:@aws-cdk/aws-ec2.ClientVpnEndpointOptions.sessionTimeout",
751752
"duration-prop-type:@aws-cdk/aws-ec2.ClientVpnEndpointProps.sessionTimeout",
752-
"resource-attribute:@aws-cdk/aws-ec2.VpnGateway.vpnGatewayId"
753+
"resource-attribute:@aws-cdk/aws-ec2.VpnGateway.vpnGatewayId",
754+
"docs-public-apis:@aws-cdk/aws-ec2.LogFormatField.value"
753755
]
754756
},
755757
"stability": "stable",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
5+
"source": {
6+
"path": "FlowLogsDefaultTestDeployAssert6AFD1854.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Parameters": {
3+
"BootstrapVersion": {
4+
"Type": "AWS::SSM::Parameter::Value<String>",
5+
"Default": "/cdk-bootstrap/hnb659fds/version",
6+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
7+
}
8+
},
9+
"Rules": {
10+
"CheckBootstrapVersion": {
11+
"Assertions": [
12+
{
13+
"Assert": {
14+
"Fn::Not": [
15+
{
16+
"Fn::Contains": [
17+
[
18+
"1",
19+
"2",
20+
"3",
21+
"4",
22+
"5"
23+
],
24+
{
25+
"Ref": "BootstrapVersion"
26+
}
27+
]
28+
}
29+
]
30+
},
31+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
32+
}
33+
]
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": {
5+
"source": {
6+
"path": "asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c",
7+
"packaging": "zip"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c.zip",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
},
17+
"9dcef326beebc49accefb3f0f234ec72b4de2a2aa5f1dc4ed26408fcc22c1dd7": {
18+
"source": {
19+
"path": "FlowLogsTestStack.template.json",
20+
"packaging": "file"
21+
},
22+
"destinations": {
23+
"current_account-current_region": {
24+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
25+
"objectKey": "9dcef326beebc49accefb3f0f234ec72b4de2a2aa5f1dc4ed26408fcc22c1dd7.json",
26+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
27+
}
28+
}
29+
}
30+
},
31+
"dockerImages": {}
32+
}

0 commit comments

Comments
 (0)