@aws/nx-plugin 0.101.0 → 0.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-THIRD-PARTY +207 -0
- package/package.json +1 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +510 -1
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +12 -1
- package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +12 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +437 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +522 -1
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +12 -1
- package/src/ts/strands-agent/__snapshots__/generator.spec.ts.snap +12 -1
- package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +9 -1
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +6 -0
- package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +99 -1
- package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +20 -0
- package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +115 -0
|
@@ -16,6 +16,7 @@ export * from './workspace.js';
|
|
|
16
16
|
exports[`py#mcp-server generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > mcp-server-construct.ts 1`] = `
|
|
17
17
|
"import { Lazy, Names } from 'aws-cdk-lib';
|
|
18
18
|
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
|
|
19
|
+
import { Connections, IConnectable } from 'aws-cdk-lib/aws-ec2';
|
|
19
20
|
import { Construct } from 'constructs';
|
|
20
21
|
import * as path from 'path';
|
|
21
22
|
import * as url from 'url';
|
|
@@ -37,7 +38,10 @@ export type SnapshotBedrockServerProps = Omit<
|
|
|
37
38
|
| 'authorizerConfiguration'
|
|
38
39
|
>;
|
|
39
40
|
|
|
40
|
-
export class SnapshotBedrockServer
|
|
41
|
+
export class SnapshotBedrockServer
|
|
42
|
+
extends Construct
|
|
43
|
+
implements IGrantable, IConnectable
|
|
44
|
+
{
|
|
41
45
|
public readonly dockerImage: AgentRuntimeArtifact;
|
|
42
46
|
public readonly agentCoreRuntime: Runtime;
|
|
43
47
|
|
|
@@ -89,6 +93,13 @@ export class SnapshotBedrockServer extends Construct implements IGrantable {
|
|
|
89
93
|
return this.agentCoreRuntime.grantPrincipal;
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Network connections for this agent runtime.
|
|
98
|
+
*/
|
|
99
|
+
public get connections(): Connections {
|
|
100
|
+
return this.agentCoreRuntime.connections;
|
|
101
|
+
}
|
|
102
|
+
|
|
92
103
|
/**
|
|
93
104
|
* Grants IAM permissions to invoke this agent runtime.
|
|
94
105
|
*
|
|
@@ -22,6 +22,7 @@ CMD ["python", "bin/opentelemetry-instrument", "python", "-m", "proj_test_projec
|
|
|
22
22
|
exports[`py#strands-agent generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > agent-construct.ts 1`] = `
|
|
23
23
|
"import { Lazy, Names } from 'aws-cdk-lib';
|
|
24
24
|
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
|
|
25
|
+
import { Connections, IConnectable } from 'aws-cdk-lib/aws-ec2';
|
|
25
26
|
import { Construct } from 'constructs';
|
|
26
27
|
import * as path from 'path';
|
|
27
28
|
import * as url from 'url';
|
|
@@ -48,7 +49,10 @@ export type SnapshotBedrockAgentProps = Omit<
|
|
|
48
49
|
| 'authorizerConfiguration'
|
|
49
50
|
>;
|
|
50
51
|
|
|
51
|
-
export class SnapshotBedrockAgent
|
|
52
|
+
export class SnapshotBedrockAgent
|
|
53
|
+
extends Construct
|
|
54
|
+
implements IGrantable, IConnectable
|
|
55
|
+
{
|
|
52
56
|
public readonly dockerImage: AgentRuntimeArtifact;
|
|
53
57
|
public readonly agentCoreRuntime: Runtime;
|
|
54
58
|
|
|
@@ -110,6 +114,13 @@ export class SnapshotBedrockAgent extends Construct implements IGrantable {
|
|
|
110
114
|
return this.agentCoreRuntime.grantPrincipal;
|
|
111
115
|
}
|
|
112
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Network connections for this agent runtime.
|
|
119
|
+
*/
|
|
120
|
+
public get connections(): Connections {
|
|
121
|
+
return this.agentCoreRuntime.connections;
|
|
122
|
+
}
|
|
123
|
+
|
|
113
124
|
/**
|
|
114
125
|
* Grants IAM permissions to invoke this agent runtime.
|
|
115
126
|
*
|
|
@@ -85,6 +85,12 @@ export interface TestApiProps<
|
|
|
85
85
|
identity: {
|
|
86
86
|
userPool: IUserPool;
|
|
87
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Whether to enable AWS WAFv2 with the default managed ruleset on the API's default stage.
|
|
90
|
+
*
|
|
91
|
+
* @default true
|
|
92
|
+
*/
|
|
93
|
+
enableWaf?: boolean;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
/**
|
|
@@ -259,6 +265,12 @@ export interface TestApiProps<
|
|
|
259
265
|
* Map of operation names to their API Gateway integrations
|
|
260
266
|
*/
|
|
261
267
|
integrations: TIntegrations;
|
|
268
|
+
/**
|
|
269
|
+
* Whether to enable AWS WAFv2 with the default managed ruleset on the API's default stage.
|
|
270
|
+
*
|
|
271
|
+
* @default true
|
|
272
|
+
*/
|
|
273
|
+
enableWaf?: boolean;
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
/**
|
|
@@ -419,6 +431,10 @@ terraform {
|
|
|
419
431
|
source = "hashicorp/aws"
|
|
420
432
|
version = "~> 6.33"
|
|
421
433
|
}
|
|
434
|
+
random = {
|
|
435
|
+
source = "hashicorp/random"
|
|
436
|
+
version = "~> 3.1"
|
|
437
|
+
}
|
|
422
438
|
}
|
|
423
439
|
}
|
|
424
440
|
|
|
@@ -447,6 +463,12 @@ variable "stage_auto_deploy" {
|
|
|
447
463
|
default = true
|
|
448
464
|
}
|
|
449
465
|
|
|
466
|
+
variable "enable_waf" {
|
|
467
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset (AWSManagedRulesCommonRuleSet and AWSManagedRulesKnownBadInputsRuleSet). The Web ACL is created here and associated with the stage in the consuming module."
|
|
468
|
+
type = bool
|
|
469
|
+
default = true
|
|
470
|
+
}
|
|
471
|
+
|
|
450
472
|
# CORS Configuration
|
|
451
473
|
|
|
452
474
|
variable "cors_allow_headers" {
|
|
@@ -528,6 +550,106 @@ resource "aws_api_gateway_gateway_response" "cors_5xx" {
|
|
|
528
550
|
}
|
|
529
551
|
}
|
|
530
552
|
|
|
553
|
+
resource "aws_wafv2_web_acl" "api_waf" {
|
|
554
|
+
#checkov:skip=CKV2_AWS_31:Logging configuration is defined below in aws_wafv2_web_acl_logging_configuration.api_waf_logging; Checkov does not resolve the separate resource
|
|
555
|
+
count = var.enable_waf ? 1 : 0
|
|
556
|
+
|
|
557
|
+
name = "\${var.api_name}-waf"
|
|
558
|
+
scope = "REGIONAL"
|
|
559
|
+
|
|
560
|
+
default_action {
|
|
561
|
+
allow {}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
rule {
|
|
565
|
+
name = "CRSRule"
|
|
566
|
+
priority = 0
|
|
567
|
+
|
|
568
|
+
override_action {
|
|
569
|
+
none {}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
statement {
|
|
573
|
+
managed_rule_group_statement {
|
|
574
|
+
name = "AWSManagedRulesCommonRuleSet"
|
|
575
|
+
vendor_name = "AWS"
|
|
576
|
+
|
|
577
|
+
# Count instead of Block: the CRS 8 KB body limit is too restrictive for most APIs.
|
|
578
|
+
rule_action_override {
|
|
579
|
+
name = "SizeRestrictions_BODY"
|
|
580
|
+
action_to_use {
|
|
581
|
+
count {}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
visibility_config {
|
|
588
|
+
cloudwatch_metrics_enabled = true
|
|
589
|
+
metric_name = "\${var.api_name}WebAcl-CRS"
|
|
590
|
+
sampled_requests_enabled = true
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
rule {
|
|
595
|
+
name = "KnownBadInputsRule"
|
|
596
|
+
priority = 1
|
|
597
|
+
|
|
598
|
+
override_action {
|
|
599
|
+
none {}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
statement {
|
|
603
|
+
managed_rule_group_statement {
|
|
604
|
+
name = "AWSManagedRulesKnownBadInputsRuleSet"
|
|
605
|
+
vendor_name = "AWS"
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
visibility_config {
|
|
610
|
+
cloudwatch_metrics_enabled = true
|
|
611
|
+
metric_name = "\${var.api_name}WebAcl-KnownBadInputs"
|
|
612
|
+
sampled_requests_enabled = true
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
visibility_config {
|
|
617
|
+
cloudwatch_metrics_enabled = true
|
|
618
|
+
metric_name = "\${var.api_name}WebAcl"
|
|
619
|
+
sampled_requests_enabled = true
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
tags = var.tags
|
|
623
|
+
|
|
624
|
+
lifecycle {
|
|
625
|
+
create_before_destroy = true
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
# CloudWatch Log Group for WAF request logs. Name must start with \`aws-waf-logs-\`.
|
|
630
|
+
resource "aws_cloudwatch_log_group" "api_waf_logs" {
|
|
631
|
+
#checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
|
|
632
|
+
#checkov:skip=CKV_AWS_338:Log retention set to one month which is sufficient for WAF logs
|
|
633
|
+
count = var.enable_waf ? 1 : 0
|
|
634
|
+
|
|
635
|
+
name = "aws-waf-logs-\${var.api_name}-\${random_id.waf_log_suffix[0].hex}"
|
|
636
|
+
retention_in_days = 30
|
|
637
|
+
tags = var.tags
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
resource "random_id" "waf_log_suffix" {
|
|
641
|
+
count = var.enable_waf ? 1 : 0
|
|
642
|
+
byte_length = 4
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
resource "aws_wafv2_web_acl_logging_configuration" "api_waf_logging" {
|
|
646
|
+
count = var.enable_waf ? 1 : 0
|
|
647
|
+
|
|
648
|
+
log_destination_configs = [aws_cloudwatch_log_group.api_waf_logs[0].arn]
|
|
649
|
+
resource_arn = aws_wafv2_web_acl.api_waf[0].arn
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
|
|
531
653
|
# Outputs
|
|
532
654
|
|
|
533
655
|
output "api_id" {
|
|
@@ -555,6 +677,11 @@ output "api_root_resource_id" {
|
|
|
555
677
|
value = aws_api_gateway_rest_api.rest_api.root_resource_id
|
|
556
678
|
}
|
|
557
679
|
|
|
680
|
+
output "waf_web_acl_arn" {
|
|
681
|
+
description = "ARN of the WAFv2 Web ACL associated with the API, or null if WAF is disabled"
|
|
682
|
+
value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
|
|
683
|
+
}
|
|
684
|
+
|
|
558
685
|
# Note: Stage and deployment outputs are provided by the consuming module
|
|
559
686
|
|
|
560
687
|
# Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement"
|
|
@@ -609,6 +736,13 @@ variable "cors_allow_origins" {
|
|
|
609
736
|
default = ["*"]
|
|
610
737
|
}
|
|
611
738
|
|
|
739
|
+
# WAF Configuration
|
|
740
|
+
variable "enable_waf" {
|
|
741
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset on the API stage"
|
|
742
|
+
type = bool
|
|
743
|
+
default = true
|
|
744
|
+
}
|
|
745
|
+
|
|
612
746
|
# Tags
|
|
613
747
|
variable "tags" {
|
|
614
748
|
description = "Tags to apply to all resources"
|
|
@@ -638,6 +772,9 @@ module "rest_api" {
|
|
|
638
772
|
stage_name = "prod"
|
|
639
773
|
stage_auto_deploy = true
|
|
640
774
|
|
|
775
|
+
# WAF Configuration
|
|
776
|
+
enable_waf = var.enable_waf
|
|
777
|
+
|
|
641
778
|
# CORS Configuration
|
|
642
779
|
cors_allow_headers = var.cors_allow_headers
|
|
643
780
|
cors_allow_methods = var.cors_allow_methods
|
|
@@ -647,6 +784,15 @@ module "rest_api" {
|
|
|
647
784
|
tags = var.tags
|
|
648
785
|
}
|
|
649
786
|
|
|
787
|
+
resource "aws_wafv2_web_acl_association" "api_waf_association" {
|
|
788
|
+
count = var.enable_waf ? 1 : 0
|
|
789
|
+
|
|
790
|
+
resource_arn = aws_api_gateway_stage.api_stage.arn
|
|
791
|
+
web_acl_arn = module.rest_api.waf_web_acl_arn
|
|
792
|
+
|
|
793
|
+
depends_on = [aws_api_gateway_stage.api_stage]
|
|
794
|
+
}
|
|
795
|
+
|
|
650
796
|
# Lambda function
|
|
651
797
|
resource "aws_lambda_function" "api_lambda" {
|
|
652
798
|
#checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
|
|
@@ -855,6 +1001,7 @@ resource "aws_api_gateway_stage" "api_stage" {
|
|
|
855
1001
|
#checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
|
|
856
1002
|
#checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
|
|
857
1003
|
#checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
|
|
1004
|
+
#checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
|
|
858
1005
|
deployment_id = aws_api_gateway_deployment.api_deployment.id
|
|
859
1006
|
rest_api_id = module.rest_api.api_id
|
|
860
1007
|
stage_name = "prod"
|
|
@@ -1446,6 +1593,10 @@ terraform {
|
|
|
1446
1593
|
source = "hashicorp/aws"
|
|
1447
1594
|
version = "~> 6.33"
|
|
1448
1595
|
}
|
|
1596
|
+
random = {
|
|
1597
|
+
source = "hashicorp/random"
|
|
1598
|
+
version = "~> 3.1"
|
|
1599
|
+
}
|
|
1449
1600
|
}
|
|
1450
1601
|
}
|
|
1451
1602
|
|
|
@@ -1474,6 +1625,12 @@ variable "stage_auto_deploy" {
|
|
|
1474
1625
|
default = true
|
|
1475
1626
|
}
|
|
1476
1627
|
|
|
1628
|
+
variable "enable_waf" {
|
|
1629
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset (AWSManagedRulesCommonRuleSet and AWSManagedRulesKnownBadInputsRuleSet). The Web ACL is created here and associated with the stage in the consuming module."
|
|
1630
|
+
type = bool
|
|
1631
|
+
default = true
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1477
1634
|
# CORS Configuration
|
|
1478
1635
|
|
|
1479
1636
|
variable "cors_allow_headers" {
|
|
@@ -1555,6 +1712,106 @@ resource "aws_api_gateway_gateway_response" "cors_5xx" {
|
|
|
1555
1712
|
}
|
|
1556
1713
|
}
|
|
1557
1714
|
|
|
1715
|
+
resource "aws_wafv2_web_acl" "api_waf" {
|
|
1716
|
+
#checkov:skip=CKV2_AWS_31:Logging configuration is defined below in aws_wafv2_web_acl_logging_configuration.api_waf_logging; Checkov does not resolve the separate resource
|
|
1717
|
+
count = var.enable_waf ? 1 : 0
|
|
1718
|
+
|
|
1719
|
+
name = "\${var.api_name}-waf"
|
|
1720
|
+
scope = "REGIONAL"
|
|
1721
|
+
|
|
1722
|
+
default_action {
|
|
1723
|
+
allow {}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
rule {
|
|
1727
|
+
name = "CRSRule"
|
|
1728
|
+
priority = 0
|
|
1729
|
+
|
|
1730
|
+
override_action {
|
|
1731
|
+
none {}
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
statement {
|
|
1735
|
+
managed_rule_group_statement {
|
|
1736
|
+
name = "AWSManagedRulesCommonRuleSet"
|
|
1737
|
+
vendor_name = "AWS"
|
|
1738
|
+
|
|
1739
|
+
# Count instead of Block: the CRS 8 KB body limit is too restrictive for most APIs.
|
|
1740
|
+
rule_action_override {
|
|
1741
|
+
name = "SizeRestrictions_BODY"
|
|
1742
|
+
action_to_use {
|
|
1743
|
+
count {}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
visibility_config {
|
|
1750
|
+
cloudwatch_metrics_enabled = true
|
|
1751
|
+
metric_name = "\${var.api_name}WebAcl-CRS"
|
|
1752
|
+
sampled_requests_enabled = true
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
rule {
|
|
1757
|
+
name = "KnownBadInputsRule"
|
|
1758
|
+
priority = 1
|
|
1759
|
+
|
|
1760
|
+
override_action {
|
|
1761
|
+
none {}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
statement {
|
|
1765
|
+
managed_rule_group_statement {
|
|
1766
|
+
name = "AWSManagedRulesKnownBadInputsRuleSet"
|
|
1767
|
+
vendor_name = "AWS"
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
visibility_config {
|
|
1772
|
+
cloudwatch_metrics_enabled = true
|
|
1773
|
+
metric_name = "\${var.api_name}WebAcl-KnownBadInputs"
|
|
1774
|
+
sampled_requests_enabled = true
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
visibility_config {
|
|
1779
|
+
cloudwatch_metrics_enabled = true
|
|
1780
|
+
metric_name = "\${var.api_name}WebAcl"
|
|
1781
|
+
sampled_requests_enabled = true
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
tags = var.tags
|
|
1785
|
+
|
|
1786
|
+
lifecycle {
|
|
1787
|
+
create_before_destroy = true
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
# CloudWatch Log Group for WAF request logs. Name must start with \`aws-waf-logs-\`.
|
|
1792
|
+
resource "aws_cloudwatch_log_group" "api_waf_logs" {
|
|
1793
|
+
#checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
|
|
1794
|
+
#checkov:skip=CKV_AWS_338:Log retention set to one month which is sufficient for WAF logs
|
|
1795
|
+
count = var.enable_waf ? 1 : 0
|
|
1796
|
+
|
|
1797
|
+
name = "aws-waf-logs-\${var.api_name}-\${random_id.waf_log_suffix[0].hex}"
|
|
1798
|
+
retention_in_days = 30
|
|
1799
|
+
tags = var.tags
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
resource "random_id" "waf_log_suffix" {
|
|
1803
|
+
count = var.enable_waf ? 1 : 0
|
|
1804
|
+
byte_length = 4
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
resource "aws_wafv2_web_acl_logging_configuration" "api_waf_logging" {
|
|
1808
|
+
count = var.enable_waf ? 1 : 0
|
|
1809
|
+
|
|
1810
|
+
log_destination_configs = [aws_cloudwatch_log_group.api_waf_logs[0].arn]
|
|
1811
|
+
resource_arn = aws_wafv2_web_acl.api_waf[0].arn
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
|
|
1558
1815
|
# Outputs
|
|
1559
1816
|
|
|
1560
1817
|
output "api_id" {
|
|
@@ -1582,6 +1839,11 @@ output "api_root_resource_id" {
|
|
|
1582
1839
|
value = aws_api_gateway_rest_api.rest_api.root_resource_id
|
|
1583
1840
|
}
|
|
1584
1841
|
|
|
1842
|
+
output "waf_web_acl_arn" {
|
|
1843
|
+
description = "ARN of the WAFv2 Web ACL associated with the API, or null if WAF is disabled"
|
|
1844
|
+
value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1585
1847
|
# Note: Stage and deployment outputs are provided by the consuming module
|
|
1586
1848
|
|
|
1587
1849
|
# Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement",
|
|
@@ -1643,6 +1905,13 @@ variable "cors_allow_origins" {
|
|
|
1643
1905
|
default = ["*"]
|
|
1644
1906
|
}
|
|
1645
1907
|
|
|
1908
|
+
# WAF Configuration
|
|
1909
|
+
variable "enable_waf" {
|
|
1910
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset on the API stage"
|
|
1911
|
+
type = bool
|
|
1912
|
+
default = true
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1646
1915
|
# Tags
|
|
1647
1916
|
variable "tags" {
|
|
1648
1917
|
description = "Tags to apply to all resources"
|
|
@@ -1672,6 +1941,9 @@ module "rest_api" {
|
|
|
1672
1941
|
stage_name = "prod"
|
|
1673
1942
|
stage_auto_deploy = true
|
|
1674
1943
|
|
|
1944
|
+
# WAF Configuration
|
|
1945
|
+
enable_waf = var.enable_waf
|
|
1946
|
+
|
|
1675
1947
|
# CORS Configuration
|
|
1676
1948
|
cors_allow_headers = var.cors_allow_headers
|
|
1677
1949
|
cors_allow_methods = var.cors_allow_methods
|
|
@@ -1681,6 +1953,15 @@ module "rest_api" {
|
|
|
1681
1953
|
tags = var.tags
|
|
1682
1954
|
}
|
|
1683
1955
|
|
|
1956
|
+
resource "aws_wafv2_web_acl_association" "api_waf_association" {
|
|
1957
|
+
count = var.enable_waf ? 1 : 0
|
|
1958
|
+
|
|
1959
|
+
resource_arn = aws_api_gateway_stage.api_stage.arn
|
|
1960
|
+
web_acl_arn = module.rest_api.waf_web_acl_arn
|
|
1961
|
+
|
|
1962
|
+
depends_on = [aws_api_gateway_stage.api_stage]
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1684
1965
|
# Lambda function
|
|
1685
1966
|
resource "aws_lambda_function" "api_lambda" {
|
|
1686
1967
|
#checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
|
|
@@ -1896,6 +2177,7 @@ resource "aws_api_gateway_stage" "api_stage" {
|
|
|
1896
2177
|
#checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
|
|
1897
2178
|
#checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
|
|
1898
2179
|
#checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
|
|
2180
|
+
#checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
|
|
1899
2181
|
deployment_id = aws_api_gateway_deployment.api_deployment.id
|
|
1900
2182
|
rest_api_id = module.rest_api.api_id
|
|
1901
2183
|
stage_name = "prod"
|
|
@@ -2093,6 +2375,10 @@ terraform {
|
|
|
2093
2375
|
source = "hashicorp/aws"
|
|
2094
2376
|
version = "~> 6.33"
|
|
2095
2377
|
}
|
|
2378
|
+
random = {
|
|
2379
|
+
source = "hashicorp/random"
|
|
2380
|
+
version = "~> 3.1"
|
|
2381
|
+
}
|
|
2096
2382
|
}
|
|
2097
2383
|
}
|
|
2098
2384
|
|
|
@@ -2121,6 +2407,12 @@ variable "stage_auto_deploy" {
|
|
|
2121
2407
|
default = true
|
|
2122
2408
|
}
|
|
2123
2409
|
|
|
2410
|
+
variable "enable_waf" {
|
|
2411
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset (AWSManagedRulesCommonRuleSet and AWSManagedRulesKnownBadInputsRuleSet). The Web ACL is created here and associated with the stage in the consuming module."
|
|
2412
|
+
type = bool
|
|
2413
|
+
default = true
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2124
2416
|
# CORS Configuration
|
|
2125
2417
|
|
|
2126
2418
|
variable "cors_allow_headers" {
|
|
@@ -2202,6 +2494,106 @@ resource "aws_api_gateway_gateway_response" "cors_5xx" {
|
|
|
2202
2494
|
}
|
|
2203
2495
|
}
|
|
2204
2496
|
|
|
2497
|
+
resource "aws_wafv2_web_acl" "api_waf" {
|
|
2498
|
+
#checkov:skip=CKV2_AWS_31:Logging configuration is defined below in aws_wafv2_web_acl_logging_configuration.api_waf_logging; Checkov does not resolve the separate resource
|
|
2499
|
+
count = var.enable_waf ? 1 : 0
|
|
2500
|
+
|
|
2501
|
+
name = "\${var.api_name}-waf"
|
|
2502
|
+
scope = "REGIONAL"
|
|
2503
|
+
|
|
2504
|
+
default_action {
|
|
2505
|
+
allow {}
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
rule {
|
|
2509
|
+
name = "CRSRule"
|
|
2510
|
+
priority = 0
|
|
2511
|
+
|
|
2512
|
+
override_action {
|
|
2513
|
+
none {}
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
statement {
|
|
2517
|
+
managed_rule_group_statement {
|
|
2518
|
+
name = "AWSManagedRulesCommonRuleSet"
|
|
2519
|
+
vendor_name = "AWS"
|
|
2520
|
+
|
|
2521
|
+
# Count instead of Block: the CRS 8 KB body limit is too restrictive for most APIs.
|
|
2522
|
+
rule_action_override {
|
|
2523
|
+
name = "SizeRestrictions_BODY"
|
|
2524
|
+
action_to_use {
|
|
2525
|
+
count {}
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
visibility_config {
|
|
2532
|
+
cloudwatch_metrics_enabled = true
|
|
2533
|
+
metric_name = "\${var.api_name}WebAcl-CRS"
|
|
2534
|
+
sampled_requests_enabled = true
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
rule {
|
|
2539
|
+
name = "KnownBadInputsRule"
|
|
2540
|
+
priority = 1
|
|
2541
|
+
|
|
2542
|
+
override_action {
|
|
2543
|
+
none {}
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
statement {
|
|
2547
|
+
managed_rule_group_statement {
|
|
2548
|
+
name = "AWSManagedRulesKnownBadInputsRuleSet"
|
|
2549
|
+
vendor_name = "AWS"
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
visibility_config {
|
|
2554
|
+
cloudwatch_metrics_enabled = true
|
|
2555
|
+
metric_name = "\${var.api_name}WebAcl-KnownBadInputs"
|
|
2556
|
+
sampled_requests_enabled = true
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
visibility_config {
|
|
2561
|
+
cloudwatch_metrics_enabled = true
|
|
2562
|
+
metric_name = "\${var.api_name}WebAcl"
|
|
2563
|
+
sampled_requests_enabled = true
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
tags = var.tags
|
|
2567
|
+
|
|
2568
|
+
lifecycle {
|
|
2569
|
+
create_before_destroy = true
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
# CloudWatch Log Group for WAF request logs. Name must start with \`aws-waf-logs-\`.
|
|
2574
|
+
resource "aws_cloudwatch_log_group" "api_waf_logs" {
|
|
2575
|
+
#checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
|
|
2576
|
+
#checkov:skip=CKV_AWS_338:Log retention set to one month which is sufficient for WAF logs
|
|
2577
|
+
count = var.enable_waf ? 1 : 0
|
|
2578
|
+
|
|
2579
|
+
name = "aws-waf-logs-\${var.api_name}-\${random_id.waf_log_suffix[0].hex}"
|
|
2580
|
+
retention_in_days = 30
|
|
2581
|
+
tags = var.tags
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
resource "random_id" "waf_log_suffix" {
|
|
2585
|
+
count = var.enable_waf ? 1 : 0
|
|
2586
|
+
byte_length = 4
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
resource "aws_wafv2_web_acl_logging_configuration" "api_waf_logging" {
|
|
2590
|
+
count = var.enable_waf ? 1 : 0
|
|
2591
|
+
|
|
2592
|
+
log_destination_configs = [aws_cloudwatch_log_group.api_waf_logs[0].arn]
|
|
2593
|
+
resource_arn = aws_wafv2_web_acl.api_waf[0].arn
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
|
|
2205
2597
|
# Outputs
|
|
2206
2598
|
|
|
2207
2599
|
output "api_id" {
|
|
@@ -2229,6 +2621,11 @@ output "api_root_resource_id" {
|
|
|
2229
2621
|
value = aws_api_gateway_rest_api.rest_api.root_resource_id
|
|
2230
2622
|
}
|
|
2231
2623
|
|
|
2624
|
+
output "waf_web_acl_arn" {
|
|
2625
|
+
description = "ARN of the WAFv2 Web ACL associated with the API, or null if WAF is disabled"
|
|
2626
|
+
value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2232
2629
|
# Note: Stage and deployment outputs are provided by the consuming module
|
|
2233
2630
|
|
|
2234
2631
|
# Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement",
|
|
@@ -2280,6 +2677,13 @@ variable "cors_allow_origins" {
|
|
|
2280
2677
|
default = ["*"]
|
|
2281
2678
|
}
|
|
2282
2679
|
|
|
2680
|
+
# WAF Configuration
|
|
2681
|
+
variable "enable_waf" {
|
|
2682
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset on the API stage"
|
|
2683
|
+
type = bool
|
|
2684
|
+
default = true
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2283
2687
|
# Tags
|
|
2284
2688
|
variable "tags" {
|
|
2285
2689
|
description = "Tags to apply to all resources"
|
|
@@ -2309,6 +2713,9 @@ module "rest_api" {
|
|
|
2309
2713
|
stage_name = "prod"
|
|
2310
2714
|
stage_auto_deploy = true
|
|
2311
2715
|
|
|
2716
|
+
# WAF Configuration
|
|
2717
|
+
enable_waf = var.enable_waf
|
|
2718
|
+
|
|
2312
2719
|
# CORS Configuration
|
|
2313
2720
|
cors_allow_headers = var.cors_allow_headers
|
|
2314
2721
|
cors_allow_methods = var.cors_allow_methods
|
|
@@ -2318,6 +2725,15 @@ module "rest_api" {
|
|
|
2318
2725
|
tags = var.tags
|
|
2319
2726
|
}
|
|
2320
2727
|
|
|
2728
|
+
resource "aws_wafv2_web_acl_association" "api_waf_association" {
|
|
2729
|
+
count = var.enable_waf ? 1 : 0
|
|
2730
|
+
|
|
2731
|
+
resource_arn = aws_api_gateway_stage.api_stage.arn
|
|
2732
|
+
web_acl_arn = module.rest_api.waf_web_acl_arn
|
|
2733
|
+
|
|
2734
|
+
depends_on = [aws_api_gateway_stage.api_stage]
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2321
2737
|
# Lambda function
|
|
2322
2738
|
resource "aws_lambda_function" "api_lambda" {
|
|
2323
2739
|
#checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
|
|
@@ -2524,6 +2940,7 @@ resource "aws_api_gateway_stage" "api_stage" {
|
|
|
2524
2940
|
#checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
|
|
2525
2941
|
#checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
|
|
2526
2942
|
#checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
|
|
2943
|
+
#checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
|
|
2527
2944
|
deployment_id = aws_api_gateway_deployment.api_deployment.id
|
|
2528
2945
|
rest_api_id = module.rest_api.api_id
|
|
2529
2946
|
stage_name = "prod"
|
|
@@ -2768,6 +3185,13 @@ variable "cors_allow_origins" {
|
|
|
2768
3185
|
default = ["*"]
|
|
2769
3186
|
}
|
|
2770
3187
|
|
|
3188
|
+
# WAF Configuration
|
|
3189
|
+
variable "enable_waf" {
|
|
3190
|
+
description = "Whether to enable AWS WAFv2 with the default managed ruleset on the API stage"
|
|
3191
|
+
type = bool
|
|
3192
|
+
default = true
|
|
3193
|
+
}
|
|
3194
|
+
|
|
2771
3195
|
# Tags
|
|
2772
3196
|
variable "tags" {
|
|
2773
3197
|
description = "Tags to apply to all resources"
|
|
@@ -2797,6 +3221,9 @@ module "rest_api" {
|
|
|
2797
3221
|
stage_name = "prod"
|
|
2798
3222
|
stage_auto_deploy = true
|
|
2799
3223
|
|
|
3224
|
+
# WAF Configuration
|
|
3225
|
+
enable_waf = var.enable_waf
|
|
3226
|
+
|
|
2800
3227
|
# CORS Configuration
|
|
2801
3228
|
cors_allow_headers = var.cors_allow_headers
|
|
2802
3229
|
cors_allow_methods = var.cors_allow_methods
|
|
@@ -2806,6 +3233,15 @@ module "rest_api" {
|
|
|
2806
3233
|
tags = var.tags
|
|
2807
3234
|
}
|
|
2808
3235
|
|
|
3236
|
+
resource "aws_wafv2_web_acl_association" "api_waf_association" {
|
|
3237
|
+
count = var.enable_waf ? 1 : 0
|
|
3238
|
+
|
|
3239
|
+
resource_arn = aws_api_gateway_stage.api_stage.arn
|
|
3240
|
+
web_acl_arn = module.rest_api.waf_web_acl_arn
|
|
3241
|
+
|
|
3242
|
+
depends_on = [aws_api_gateway_stage.api_stage]
|
|
3243
|
+
}
|
|
3244
|
+
|
|
2809
3245
|
# Lambda function
|
|
2810
3246
|
resource "aws_lambda_function" "api_lambda" {
|
|
2811
3247
|
#checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
|
|
@@ -3014,6 +3450,7 @@ resource "aws_api_gateway_stage" "api_stage" {
|
|
|
3014
3450
|
#checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
|
|
3015
3451
|
#checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
|
|
3016
3452
|
#checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
|
|
3453
|
+
#checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
|
|
3017
3454
|
deployment_id = aws_api_gateway_deployment.api_deployment.id
|
|
3018
3455
|
rest_api_id = module.rest_api.api_id
|
|
3019
3456
|
stage_name = "prod"
|