@aws/nx-plugin 1.0.0-rc.31 → 1.0.0-rc.32

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.
@@ -295,6 +295,30 @@ variable "asset_bucket_name" {
295
295
  type = string
296
296
  }
297
297
 
298
+ # VPC Configuration (optional)
299
+ variable "enable_vpc" {
300
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
301
+ type = bool
302
+ default = false
303
+ }
304
+
305
+ variable "vpc_id" {
306
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
307
+ type = string
308
+ default = null
309
+
310
+ validation {
311
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
312
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
313
+ }
314
+ }
315
+
316
+ variable "subnet_ids" {
317
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
318
+ type = list(string)
319
+ default = null
320
+ }
321
+
298
322
  # CORS Configuration (passed to core module)
299
323
  variable "cors_allow_credentials" {
300
324
  description = "Whether to allow credentials in CORS requests"
@@ -381,10 +405,32 @@ module "http_api" {
381
405
  tags = var.tags
382
406
  }
383
407
 
408
+ # Security group for the API Lambda function, used when deployed into a VPC
409
+ resource "aws_security_group" "api_lambda" {
410
+ count = var.enable_vpc ? 1 : 0
411
+
412
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
413
+ name_prefix = "test-api-lambda-"
414
+ description = "Security group for the TestApi API Lambda function"
415
+ vpc_id = var.vpc_id
416
+ tags = var.tags
417
+ }
418
+
419
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
420
+ count = var.enable_vpc ? 1 : 0
421
+
422
+ security_group_id = aws_security_group.api_lambda[0].id
423
+ cidr_ipv4 = "0.0.0.0/0"
424
+ from_port = 443
425
+ to_port = 443
426
+ ip_protocol = "tcp"
427
+ description = "Allow outbound HTTPS to AWS service endpoints"
428
+ }
429
+
384
430
  # Lambda function
385
431
  # This configures a single "router" lambda to serve all requests
386
432
  resource "aws_lambda_function" "api_lambda" {
387
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
433
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
388
434
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
389
435
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
390
436
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -408,6 +454,14 @@ resource "aws_lambda_function" "api_lambda" {
408
454
  mode = "Active"
409
455
  }
410
456
 
457
+ dynamic "vpc_config" {
458
+ for_each = var.enable_vpc ? [1] : []
459
+ content {
460
+ subnet_ids = var.subnet_ids
461
+ security_group_ids = [aws_security_group.api_lambda[0].id]
462
+ }
463
+ }
464
+
411
465
  # Enable SnapStart for faster cold starts
412
466
  snap_start {
413
467
  apply_on = "PublishedVersions"
@@ -422,6 +476,8 @@ resource "aws_lambda_function" "api_lambda" {
422
476
  }
423
477
 
424
478
  tags = var.tags
479
+
480
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
425
481
  }
426
482
 
427
483
  # IAM role for Lambda execution
@@ -456,6 +512,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
456
512
  role = aws_iam_role.lambda_execution_role.name
457
513
  }
458
514
 
515
+ # Attach VPC access policy to Lambda role when deployed into a VPC
516
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
517
+ count = var.enable_vpc ? 1 : 0
518
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
519
+ role = aws_iam_role.lambda_execution_role.name
520
+ }
521
+
459
522
  # Additional IAM policies for Lambda (if provided)
460
523
  resource "aws_iam_role_policy" "lambda_additional_policies" {
461
524
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -635,6 +698,11 @@ output "lambda_execution_role_name" {
635
698
  value = aws_iam_role.lambda_execution_role.name
636
699
  }
637
700
 
701
+ output "security_group_id" {
702
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
703
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
704
+ }
705
+
638
706
  # Integration Outputs
639
707
  output "integration_id" {
640
708
  description = "ID of the Lambda integration"
@@ -949,6 +1017,30 @@ variable "asset_bucket_name" {
949
1017
  type = string
950
1018
  }
951
1019
 
1020
+ # VPC Configuration (optional)
1021
+ variable "enable_vpc" {
1022
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
1023
+ type = bool
1024
+ default = false
1025
+ }
1026
+
1027
+ variable "vpc_id" {
1028
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
1029
+ type = string
1030
+ default = null
1031
+
1032
+ validation {
1033
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
1034
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
1035
+ }
1036
+ }
1037
+
1038
+ variable "subnet_ids" {
1039
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
1040
+ type = list(string)
1041
+ default = null
1042
+ }
1043
+
952
1044
  # CORS Configuration (passed to core module)
953
1045
  variable "cors_allow_credentials" {
954
1046
  description = "Whether to allow credentials in CORS requests"
@@ -1035,10 +1127,32 @@ module "http_api" {
1035
1127
  tags = var.tags
1036
1128
  }
1037
1129
 
1130
+ # Security group for the API Lambda function, used when deployed into a VPC
1131
+ resource "aws_security_group" "api_lambda" {
1132
+ count = var.enable_vpc ? 1 : 0
1133
+
1134
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
1135
+ name_prefix = "test-api-lambda-"
1136
+ description = "Security group for the TestApi API Lambda function"
1137
+ vpc_id = var.vpc_id
1138
+ tags = var.tags
1139
+ }
1140
+
1141
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
1142
+ count = var.enable_vpc ? 1 : 0
1143
+
1144
+ security_group_id = aws_security_group.api_lambda[0].id
1145
+ cidr_ipv4 = "0.0.0.0/0"
1146
+ from_port = 443
1147
+ to_port = 443
1148
+ ip_protocol = "tcp"
1149
+ description = "Allow outbound HTTPS to AWS service endpoints"
1150
+ }
1151
+
1038
1152
  # Lambda function
1039
1153
  # This configures a single "router" lambda to serve all requests
1040
1154
  resource "aws_lambda_function" "api_lambda" {
1041
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
1155
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
1042
1156
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
1043
1157
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
1044
1158
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -1062,6 +1176,14 @@ resource "aws_lambda_function" "api_lambda" {
1062
1176
  mode = "Active"
1063
1177
  }
1064
1178
 
1179
+ dynamic "vpc_config" {
1180
+ for_each = var.enable_vpc ? [1] : []
1181
+ content {
1182
+ subnet_ids = var.subnet_ids
1183
+ security_group_ids = [aws_security_group.api_lambda[0].id]
1184
+ }
1185
+ }
1186
+
1065
1187
  # Enable SnapStart for faster cold starts
1066
1188
  snap_start {
1067
1189
  apply_on = "PublishedVersions"
@@ -1076,6 +1198,8 @@ resource "aws_lambda_function" "api_lambda" {
1076
1198
  }
1077
1199
 
1078
1200
  tags = var.tags
1201
+
1202
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
1079
1203
  }
1080
1204
 
1081
1205
  # IAM role for Lambda execution
@@ -1110,6 +1234,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
1110
1234
  role = aws_iam_role.lambda_execution_role.name
1111
1235
  }
1112
1236
 
1237
+ # Attach VPC access policy to Lambda role when deployed into a VPC
1238
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
1239
+ count = var.enable_vpc ? 1 : 0
1240
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
1241
+ role = aws_iam_role.lambda_execution_role.name
1242
+ }
1243
+
1113
1244
  # Additional IAM policies for Lambda (if provided)
1114
1245
  resource "aws_iam_role_policy" "lambda_additional_policies" {
1115
1246
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -1371,6 +1502,11 @@ output "lambda_execution_role_name" {
1371
1502
  value = aws_iam_role.lambda_execution_role.name
1372
1503
  }
1373
1504
 
1505
+ output "security_group_id" {
1506
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
1507
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
1508
+ }
1509
+
1374
1510
  # Integration Outputs
1375
1511
  output "integration_id" {
1376
1512
  description = "ID of the Lambda integration"
@@ -1685,6 +1821,30 @@ variable "asset_bucket_name" {
1685
1821
  type = string
1686
1822
  }
1687
1823
 
1824
+ # VPC Configuration (optional)
1825
+ variable "enable_vpc" {
1826
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
1827
+ type = bool
1828
+ default = false
1829
+ }
1830
+
1831
+ variable "vpc_id" {
1832
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
1833
+ type = string
1834
+ default = null
1835
+
1836
+ validation {
1837
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
1838
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
1839
+ }
1840
+ }
1841
+
1842
+ variable "subnet_ids" {
1843
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
1844
+ type = list(string)
1845
+ default = null
1846
+ }
1847
+
1688
1848
  # CORS Configuration (passed to core module)
1689
1849
  variable "cors_allow_credentials" {
1690
1850
  description = "Whether to allow credentials in CORS requests"
@@ -1771,10 +1931,32 @@ module "http_api" {
1771
1931
  tags = var.tags
1772
1932
  }
1773
1933
 
1934
+ # Security group for the API Lambda function, used when deployed into a VPC
1935
+ resource "aws_security_group" "api_lambda" {
1936
+ count = var.enable_vpc ? 1 : 0
1937
+
1938
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
1939
+ name_prefix = "test-api-lambda-"
1940
+ description = "Security group for the TestApi API Lambda function"
1941
+ vpc_id = var.vpc_id
1942
+ tags = var.tags
1943
+ }
1944
+
1945
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
1946
+ count = var.enable_vpc ? 1 : 0
1947
+
1948
+ security_group_id = aws_security_group.api_lambda[0].id
1949
+ cidr_ipv4 = "0.0.0.0/0"
1950
+ from_port = 443
1951
+ to_port = 443
1952
+ ip_protocol = "tcp"
1953
+ description = "Allow outbound HTTPS to AWS service endpoints"
1954
+ }
1955
+
1774
1956
  # Lambda function
1775
1957
  # This configures a single "router" lambda to serve all requests
1776
1958
  resource "aws_lambda_function" "api_lambda" {
1777
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
1959
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
1778
1960
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
1779
1961
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
1780
1962
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -1798,6 +1980,14 @@ resource "aws_lambda_function" "api_lambda" {
1798
1980
  mode = "Active"
1799
1981
  }
1800
1982
 
1983
+ dynamic "vpc_config" {
1984
+ for_each = var.enable_vpc ? [1] : []
1985
+ content {
1986
+ subnet_ids = var.subnet_ids
1987
+ security_group_ids = [aws_security_group.api_lambda[0].id]
1988
+ }
1989
+ }
1990
+
1801
1991
  # Enable SnapStart for faster cold starts
1802
1992
  snap_start {
1803
1993
  apply_on = "PublishedVersions"
@@ -1812,6 +2002,8 @@ resource "aws_lambda_function" "api_lambda" {
1812
2002
  }
1813
2003
 
1814
2004
  tags = var.tags
2005
+
2006
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
1815
2007
  }
1816
2008
 
1817
2009
  # IAM role for Lambda execution
@@ -1846,6 +2038,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
1846
2038
  role = aws_iam_role.lambda_execution_role.name
1847
2039
  }
1848
2040
 
2041
+ # Attach VPC access policy to Lambda role when deployed into a VPC
2042
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
2043
+ count = var.enable_vpc ? 1 : 0
2044
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
2045
+ role = aws_iam_role.lambda_execution_role.name
2046
+ }
2047
+
1849
2048
  # Additional IAM policies for Lambda (if provided)
1850
2049
  resource "aws_iam_role_policy" "lambda_additional_policies" {
1851
2050
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -2012,6 +2211,11 @@ output "lambda_execution_role_name" {
2012
2211
  value = aws_iam_role.lambda_execution_role.name
2013
2212
  }
2014
2213
 
2214
+ output "security_group_id" {
2215
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
2216
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
2217
+ }
2218
+
2015
2219
  # Integration Outputs
2016
2220
  output "integration_id" {
2017
2221
  description = "ID of the Lambda integration"
@@ -2345,6 +2549,30 @@ variable "asset_bucket_name" {
2345
2549
  type = string
2346
2550
  }
2347
2551
 
2552
+ # VPC Configuration (optional)
2553
+ variable "enable_vpc" {
2554
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
2555
+ type = bool
2556
+ default = false
2557
+ }
2558
+
2559
+ variable "vpc_id" {
2560
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
2561
+ type = string
2562
+ default = null
2563
+
2564
+ validation {
2565
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
2566
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
2567
+ }
2568
+ }
2569
+
2570
+ variable "subnet_ids" {
2571
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
2572
+ type = list(string)
2573
+ default = null
2574
+ }
2575
+
2348
2576
  # CORS Configuration (passed to core module)
2349
2577
 
2350
2578
  variable "cors_allow_headers" {
@@ -2441,9 +2669,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
2441
2669
  depends_on = [aws_api_gateway_stage.api_stage]
2442
2670
  }
2443
2671
 
2672
+ # Security group for the API Lambda function, used when deployed into a VPC
2673
+ resource "aws_security_group" "api_lambda" {
2674
+ count = var.enable_vpc ? 1 : 0
2675
+
2676
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
2677
+ name_prefix = "test-api-lambda-"
2678
+ description = "Security group for the TestApi API Lambda function"
2679
+ vpc_id = var.vpc_id
2680
+ tags = var.tags
2681
+ }
2682
+
2683
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
2684
+ count = var.enable_vpc ? 1 : 0
2685
+
2686
+ security_group_id = aws_security_group.api_lambda[0].id
2687
+ cidr_ipv4 = "0.0.0.0/0"
2688
+ from_port = 443
2689
+ to_port = 443
2690
+ ip_protocol = "tcp"
2691
+ description = "Allow outbound HTTPS to AWS service endpoints"
2692
+ }
2693
+
2444
2694
  # Lambda function
2445
2695
  resource "aws_lambda_function" "api_lambda" {
2446
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
2696
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
2447
2697
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
2448
2698
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
2449
2699
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -2467,6 +2717,14 @@ resource "aws_lambda_function" "api_lambda" {
2467
2717
  mode = "Active"
2468
2718
  }
2469
2719
 
2720
+ dynamic "vpc_config" {
2721
+ for_each = var.enable_vpc ? [1] : []
2722
+ content {
2723
+ subnet_ids = var.subnet_ids
2724
+ security_group_ids = [aws_security_group.api_lambda[0].id]
2725
+ }
2726
+ }
2727
+
2470
2728
  # Enable SnapStart for faster cold starts
2471
2729
  snap_start {
2472
2730
  apply_on = "PublishedVersions"
@@ -2481,6 +2739,8 @@ resource "aws_lambda_function" "api_lambda" {
2481
2739
  }
2482
2740
 
2483
2741
  tags = var.tags
2742
+
2743
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
2484
2744
  }
2485
2745
 
2486
2746
  # IAM role for Lambda execution
@@ -2515,6 +2775,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
2515
2775
  role = aws_iam_role.lambda_execution_role.name
2516
2776
  }
2517
2777
 
2778
+ # Attach VPC access policy to Lambda role when deployed into a VPC
2779
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
2780
+ count = var.enable_vpc ? 1 : 0
2781
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
2782
+ role = aws_iam_role.lambda_execution_role.name
2783
+ }
2784
+
2518
2785
  # Additional IAM policies for Lambda (if provided)
2519
2786
  resource "aws_iam_role_policy" "lambda_additional_policies" {
2520
2787
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -2921,6 +3188,11 @@ output "lambda_execution_role_name" {
2921
3188
  value = aws_iam_role.lambda_execution_role.name
2922
3189
  }
2923
3190
 
3191
+ output "security_group_id" {
3192
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
3193
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
3194
+ }
3195
+
2924
3196
  # Integration Outputs
2925
3197
  output "integration_id" {
2926
3198
  description = "ID of the Lambda integration"
@@ -3245,6 +3517,30 @@ variable "asset_bucket_name" {
3245
3517
  type = string
3246
3518
  }
3247
3519
 
3520
+ # VPC Configuration (optional)
3521
+ variable "enable_vpc" {
3522
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
3523
+ type = bool
3524
+ default = false
3525
+ }
3526
+
3527
+ variable "vpc_id" {
3528
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
3529
+ type = string
3530
+ default = null
3531
+
3532
+ validation {
3533
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
3534
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
3535
+ }
3536
+ }
3537
+
3538
+ variable "subnet_ids" {
3539
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
3540
+ type = list(string)
3541
+ default = null
3542
+ }
3543
+
3248
3544
  # CORS Configuration (passed to core module)
3249
3545
 
3250
3546
  variable "cors_allow_headers" {
@@ -3341,9 +3637,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
3341
3637
  depends_on = [aws_api_gateway_stage.api_stage]
3342
3638
  }
3343
3639
 
3640
+ # Security group for the API Lambda function, used when deployed into a VPC
3641
+ resource "aws_security_group" "api_lambda" {
3642
+ count = var.enable_vpc ? 1 : 0
3643
+
3644
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
3645
+ name_prefix = "test-api-lambda-"
3646
+ description = "Security group for the TestApi API Lambda function"
3647
+ vpc_id = var.vpc_id
3648
+ tags = var.tags
3649
+ }
3650
+
3651
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
3652
+ count = var.enable_vpc ? 1 : 0
3653
+
3654
+ security_group_id = aws_security_group.api_lambda[0].id
3655
+ cidr_ipv4 = "0.0.0.0/0"
3656
+ from_port = 443
3657
+ to_port = 443
3658
+ ip_protocol = "tcp"
3659
+ description = "Allow outbound HTTPS to AWS service endpoints"
3660
+ }
3661
+
3344
3662
  # Lambda function
3345
3663
  resource "aws_lambda_function" "api_lambda" {
3346
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
3664
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
3347
3665
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
3348
3666
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
3349
3667
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -3367,6 +3685,14 @@ resource "aws_lambda_function" "api_lambda" {
3367
3685
  mode = "Active"
3368
3686
  }
3369
3687
 
3688
+ dynamic "vpc_config" {
3689
+ for_each = var.enable_vpc ? [1] : []
3690
+ content {
3691
+ subnet_ids = var.subnet_ids
3692
+ security_group_ids = [aws_security_group.api_lambda[0].id]
3693
+ }
3694
+ }
3695
+
3370
3696
  # Enable SnapStart for faster cold starts
3371
3697
  snap_start {
3372
3698
  apply_on = "PublishedVersions"
@@ -3381,6 +3707,8 @@ resource "aws_lambda_function" "api_lambda" {
3381
3707
  }
3382
3708
 
3383
3709
  tags = var.tags
3710
+
3711
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
3384
3712
  }
3385
3713
 
3386
3714
  # IAM role for Lambda execution
@@ -3415,6 +3743,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
3415
3743
  role = aws_iam_role.lambda_execution_role.name
3416
3744
  }
3417
3745
 
3746
+ # Attach VPC access policy to Lambda role when deployed into a VPC
3747
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
3748
+ count = var.enable_vpc ? 1 : 0
3749
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
3750
+ role = aws_iam_role.lambda_execution_role.name
3751
+ }
3752
+
3418
3753
  # Additional IAM policies for Lambda (if provided)
3419
3754
  resource "aws_iam_role_policy" "lambda_additional_policies" {
3420
3755
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -3820,6 +4155,11 @@ output "lambda_execution_role_name" {
3820
4155
  value = aws_iam_role.lambda_execution_role.name
3821
4156
  }
3822
4157
 
4158
+ output "security_group_id" {
4159
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
4160
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
4161
+ }
4162
+
3823
4163
  # Integration Outputs
3824
4164
  output "integration_id" {
3825
4165
  description = "ID of the Lambda integration"
@@ -4144,6 +4484,30 @@ variable "asset_bucket_name" {
4144
4484
  type = string
4145
4485
  }
4146
4486
 
4487
+ # VPC Configuration (optional)
4488
+ variable "enable_vpc" {
4489
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
4490
+ type = bool
4491
+ default = false
4492
+ }
4493
+
4494
+ variable "vpc_id" {
4495
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
4496
+ type = string
4497
+ default = null
4498
+
4499
+ validation {
4500
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
4501
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
4502
+ }
4503
+ }
4504
+
4505
+ variable "subnet_ids" {
4506
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
4507
+ type = list(string)
4508
+ default = null
4509
+ }
4510
+
4147
4511
  # CORS Configuration (passed to core module)
4148
4512
 
4149
4513
  variable "cors_allow_headers" {
@@ -4240,9 +4604,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
4240
4604
  depends_on = [aws_api_gateway_stage.api_stage]
4241
4605
  }
4242
4606
 
4607
+ # Security group for the API Lambda function, used when deployed into a VPC
4608
+ resource "aws_security_group" "api_lambda" {
4609
+ count = var.enable_vpc ? 1 : 0
4610
+
4611
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
4612
+ name_prefix = "test-api-lambda-"
4613
+ description = "Security group for the TestApi API Lambda function"
4614
+ vpc_id = var.vpc_id
4615
+ tags = var.tags
4616
+ }
4617
+
4618
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
4619
+ count = var.enable_vpc ? 1 : 0
4620
+
4621
+ security_group_id = aws_security_group.api_lambda[0].id
4622
+ cidr_ipv4 = "0.0.0.0/0"
4623
+ from_port = 443
4624
+ to_port = 443
4625
+ ip_protocol = "tcp"
4626
+ description = "Allow outbound HTTPS to AWS service endpoints"
4627
+ }
4628
+
4243
4629
  # Lambda function
4244
4630
  resource "aws_lambda_function" "api_lambda" {
4245
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
4631
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
4246
4632
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
4247
4633
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
4248
4634
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -4266,6 +4652,14 @@ resource "aws_lambda_function" "api_lambda" {
4266
4652
  mode = "Active"
4267
4653
  }
4268
4654
 
4655
+ dynamic "vpc_config" {
4656
+ for_each = var.enable_vpc ? [1] : []
4657
+ content {
4658
+ subnet_ids = var.subnet_ids
4659
+ security_group_ids = [aws_security_group.api_lambda[0].id]
4660
+ }
4661
+ }
4662
+
4269
4663
  # Enable SnapStart for faster cold starts
4270
4664
  snap_start {
4271
4665
  apply_on = "PublishedVersions"
@@ -4280,6 +4674,8 @@ resource "aws_lambda_function" "api_lambda" {
4280
4674
  }
4281
4675
 
4282
4676
  tags = var.tags
4677
+
4678
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
4283
4679
  }
4284
4680
 
4285
4681
  # IAM role for Lambda execution
@@ -4314,6 +4710,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
4314
4710
  role = aws_iam_role.lambda_execution_role.name
4315
4711
  }
4316
4712
 
4713
+ # Attach VPC access policy to Lambda role when deployed into a VPC
4714
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
4715
+ count = var.enable_vpc ? 1 : 0
4716
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
4717
+ role = aws_iam_role.lambda_execution_role.name
4718
+ }
4719
+
4317
4720
  # Additional IAM policies for Lambda (if provided)
4318
4721
  resource "aws_iam_role_policy" "lambda_additional_policies" {
4319
4722
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -4802,6 +5205,11 @@ output "lambda_execution_role_name" {
4802
5205
  value = aws_iam_role.lambda_execution_role.name
4803
5206
  }
4804
5207
 
5208
+ output "security_group_id" {
5209
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
5210
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
5211
+ }
5212
+
4805
5213
  # Integration Outputs
4806
5214
  output "integration_id" {
4807
5215
  description = "ID of the Lambda integration"