Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
aa25315
CCM-11586: initial truststore
masl2 Aug 18, 2025
9bca7cb
CCM-11586: group is invalid prop
masl2 Aug 18, 2025
6e1a983
CCM-11586: missing name
masl2 Aug 18, 2025
2b3ac47
CCM-11586: store ref not indexed
masl2 Aug 18, 2025
d3d31dc
CCM-11586: store ref not indexed
masl2 Aug 18, 2025
1193294
CCM-11586: cert references
masl2 Aug 18, 2025
bfe977e
CCM-11586: domain store refs
masl2 Aug 18, 2025
a54d726
CCM-11586: domain name lifecycles
masl2 Aug 18, 2025
20f4ec2
CCM-11586: more tf refs
masl2 Aug 19, 2025
94e1215
CCM-11586: domain name lifecycles
masl2 Aug 19, 2025
fdde815
CCM-11586: more sensible route53 config
masl2 Aug 20, 2025
235abc7
CCM-11586: correct name reference
masl2 Aug 20, 2025
4397b2c
CCM-11586: correct locals csis3 def
masl2 Aug 20, 2025
911df5d
CCM-11586: change csi to meet s3 naming convention
masl2 Aug 20, 2025
e29e8cc
CCM-11586: remove config variable, reference infra
masl2 Aug 20, 2025
6dbea64
CCM-11586: centralised bucket logging, define a bucket
masl2 Aug 20, 2025
27b2671
CCM-11586: try fix truststore uri
masl2 Aug 20, 2025
f02cafc
CCM-11586: Disable execute-api endpoint
masl2 Aug 20, 2025
1413b02
CCM-11586: secure logging bucket
masl2 Aug 20, 2025
108dfc1
CCM-11586: refine logging bucket policies
masl2 Aug 20, 2025
8d30c4b
CCM-11586: does consolidation make sonar happy
masl2 Aug 20, 2025
00faa97
CCM-11586: consolidation does make sonar happy
masl2 Aug 20, 2025
d3eb513
CCM-11586: forgot to save
masl2 Aug 20, 2025
a23d453
CCM-11586: version log bucket
masl2 Aug 20, 2025
d6a7c30
Merge branch 'main' into feature/CCM-11586_enable-gw-mtls
masl2 Aug 21, 2025
7112ad2
CCM-11586: use shared s3 module; always gen dummy certs
masl2 Aug 21, 2025
dc0ef78
CCM-11586: Correct references to new modules
masl2 Aug 21, 2025
7517345
CCM-11586: Correct references to new modules
masl2 Aug 21, 2025
381eb33
CCM-11586: Correct references to new modules
masl2 Aug 21, 2025
a7a6cae
CCM-11586: SSL module always present for dummies
masl2 Aug 21, 2025
706dbd0
CCM-11586: additional tags not needed
masl2 Aug 21, 2025
f2acd59
Merge branch 'main' into feature/CCM-11586_enable-gw-mtls
masl2 Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions infrastructure/terraform/components/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ No requirements.
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
| <a name="input_component"></a> [component](#input\_component) | The variable encapsulating the name of this component | `string` | `"supapi"` | no |
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | A map of default tags to apply to all taggable resources within the component | `map(string)` | `{}` | no |
| <a name="input_enable_backups"></a> [enable\_backups](#input\_enable\_backups) | Enable backups | `bool` | `false` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
| <a name="input_force_lambda_code_deploy"></a> [force\_lambda\_code\_deploy](#input\_force\_lambda\_code\_deploy) | If the lambda package in s3 has the same commit id tag as the terraform build branch, the lambda will not update automatically. Set to True if making changes to Lambda code from on the same commit for example during development | `bool` | `false` | no |
| <a name="input_group"></a> [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | n/a | yes |
| <a name="input_kms_deletion_window"></a> [kms\_deletion\_window](#input\_kms\_deletion\_window) | When a kms key is deleted, how long should it wait in the pending deletion state? | `string` | `"30"` | no |
| <a name="input_log_level"></a> [log\_level](#input\_log\_level) | The log level to be used in lambda functions within the component. Any log with a lower severity than the configured value will not be logged: https://docs.python.org/3/library/logging.html#levels | `string` | `"INFO"` | no |
| <a name="input_log_retention_in_days"></a> [log\_retention\_in\_days](#input\_log\_retention\_in\_days) | The retention period in days for the Cloudwatch Logs events to be retained, default of 0 is indefinite | `number` | `0` | no |
| <a name="input_manually_configure_mtls_truststore"></a> [manually\_configure\_mtls\_truststore](#input\_manually\_configure\_mtls\_truststore) | Manually manage the truststore used for API Gateway mTLS (e.g. for prod environment) | `bool` | `false` | no |
| <a name="input_parent_acct_environment"></a> [parent\_acct\_environment](#input\_parent\_acct\_environment) | Name of the environment responsible for the acct resources used, affects things like DNS zone. Useful for named dev environments | `string` | `"main"` | no |
| <a name="input_project"></a> [project](#input\_project) | The name of the tfscaffold project | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | The AWS Region | `string` | n/a | yes |
Expand All @@ -27,10 +29,13 @@ No requirements.
| Name | Source | Version |
|------|--------|---------|
| <a name="module_authorizer_lambda"></a> [authorizer\_lambda](#module\_authorizer\_lambda) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/lambda | v2.0.4 |
| <a name="module_domain_truststore"></a> [domain\_truststore](#module\_domain\_truststore) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v2.0.17 |
| <a name="module_get_letters"></a> [get\_letters](#module\_get\_letters) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/lambda | v2.0.10 |
| <a name="module_hello_world"></a> [hello\_world](#module\_hello\_world) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/lambda | v2.0.10 |
| <a name="module_kms"></a> [kms](#module\_kms) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/kms | v2.0.10 |
| <a name="module_logging_bucket"></a> [logging\_bucket](#module\_logging\_bucket) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v2.0.17 |
| <a name="module_patch_letters"></a> [patch\_letters](#module\_patch\_letters) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/lambda | v2.0.10 |
| <a name="module_supplier_ssl"></a> [supplier\_ssl](#module\_supplier\_ssl) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/ssl | v2.0.17 |
## Outputs

| Name | Description |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
resource "aws_api_gateway_base_path_mapping" "main" {
api_id = aws_api_gateway_rest_api.main.id
stage_name = aws_api_gateway_stage.main.stage_name
domain_name = aws_api_gateway_domain_name.main.domain_name
domain_name = var.manually_configure_mtls_truststore ? aws_api_gateway_domain_name.main.0.domain_name : aws_api_gateway_domain_name.main_nonprod.0.domain_name
}
38 changes: 38 additions & 0 deletions infrastructure/terraform/components/api/api_gateway_domain.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,47 @@
resource "aws_api_gateway_domain_name" "main" {
count = var.manually_configure_mtls_truststore ? 1 : 0
regional_certificate_arn = aws_acm_certificate_validation.main.certificate_arn
domain_name = local.root_domain_name
security_policy = "TLS_1_2"

endpoint_configuration {
types = ["REGIONAL"]
}

depends_on = [
module.domain_truststore,
aws_s3_object.placeholder_truststore
]

mutual_tls_authentication {
truststore_uri = "s3://${module.domain_truststore.id}/${aws_s3_object.placeholder_truststore[0].key}"
truststore_version = aws_s3_object.placeholder_truststore[0].version_id
}

lifecycle {
ignore_changes = [
mutual_tls_authentication
]
}
}

resource "aws_api_gateway_domain_name" "main_nonprod" {
count = !var.manually_configure_mtls_truststore ? 1 : 0
regional_certificate_arn = aws_acm_certificate_validation.main.certificate_arn
domain_name = local.root_domain_name
security_policy = "TLS_1_2"

endpoint_configuration {
types = ["REGIONAL"]
}

depends_on = [
module.domain_truststore,
aws_s3_object.placeholder_truststore_nonprod
]

mutual_tls_authentication {
truststore_uri = "s3://${module.domain_truststore.id}/${aws_s3_object.placeholder_truststore_nonprod[0].key}"
truststore_version = aws_s3_object.placeholder_truststore_nonprod[0].version_id
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ resource "aws_api_gateway_rest_api" "main" {
name = local.csi
body = local.openapi_spec
description = "Suppliers API"
disable_execute_api_endpoint = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module "domain_truststore" {
source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket?ref=v2.0.17"

name = "truststore"
aws_account_id = var.aws_account_id
component = var.component
environment = var.environment
project = var.project
region = var.region

default_tags = local.default_tags
kms_key_arn = module.kms.key_id

bucket_logging_target = {
bucket = module.logging_bucket.bucket
prefix = "truststore/"
}

policy_documents = [
]

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module "logging_bucket" {
source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket?ref=v2.0.17"

name = "bucket-logs"
aws_account_id = var.aws_account_id
component = var.component
environment = var.environment
project = var.project
region = var.region

default_tags = local.default_tags
kms_key_arn = module.kms.key_id

policy_documents = [
data.aws_iam_policy_document.logging.json
]
}

data "aws_iam_policy_document" "logging" {
statement {
sid = "s3-log-delivery"
effect = "Allow"

principals {
type = "Service"
identifiers = ["logging.s3.amazonaws.com"]
}

actions = ["s3:PutObject"]

resources = [
"${module.logging_bucket.arn}/*",
]
}
}
12 changes: 12 additions & 0 deletions infrastructure/terraform/components/api/module_supplier_ssl.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module "supplier_ssl" {
source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/ssl?ref=v2.0.17"

name = "sapi_trust"
aws_account_id = var.aws_account_id
default_tags = local.default_tags
component = var.component
environment = var.environment
project = var.project
region = var.region
subject_common_name = local.root_domain_name
}
6 changes: 3 additions & 3 deletions infrastructure/terraform/components/api/route53_record.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
resource "aws_route53_record" "main" {
name = aws_api_gateway_domain_name.main.domain_name
name = var.manually_configure_mtls_truststore ? aws_api_gateway_domain_name.main.0.regional_domain_name : aws_api_gateway_domain_name.main_nonprod.0.regional_domain_name
type = "A"
zone_id = local.root_domain_id

alias {
name = aws_api_gateway_domain_name.main.regional_domain_name
zone_id = aws_api_gateway_domain_name.main.regional_zone_id
name = var.manually_configure_mtls_truststore ? aws_api_gateway_domain_name.main.0.regional_domain_name : aws_api_gateway_domain_name.main_nonprod.0.regional_domain_name
zone_id = var.manually_configure_mtls_truststore ? aws_api_gateway_domain_name.main.0.regional_zone_id : aws_api_gateway_domain_name.main_nonprod.0.regional_zone_id

evaluate_target_health = true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# In manually configured (e.g. dev main, nonprod main, prod main) add lifecycle policy to permit manual management of cert
resource "aws_s3_object" "placeholder_truststore" {
count = var.manually_configure_mtls_truststore ? 1 : 0
bucket = module.domain_truststore.bucket
key = "truststore.pem"
content = module.supplier_ssl.cacert_pem

depends_on = [
module.domain_truststore,
module.supplier_ssl
]

lifecycle {
ignore_changes = [
content
]
}
}

# In non-manually configured env (e.g. PR) exclude lifecycle policy so resources are managed
# Requires duplicate block as lifecycle policies cannot be dynamic
resource "aws_s3_object" "placeholder_truststore_nonprod" {
count = !var.manually_configure_mtls_truststore ? 1 : 0
bucket = module.domain_truststore.bucket
key = "truststore.pem"
content = module.supplier_ssl.cacert_pem

depends_on = [
module.domain_truststore,
module.supplier_ssl
]
}
12 changes: 12 additions & 0 deletions infrastructure/terraform/components/api/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,15 @@ variable "shared_infra_account_id" {
description = "The AWS Account ID of the shared infrastructure account"
default = "000000000000"
}

variable "manually_configure_mtls_truststore" {
type = bool
description = "Manually manage the truststore used for API Gateway mTLS (e.g. for prod environment)"
default = false
}

variable "enable_backups" {
type = bool
description = "Enable backups"
default = false
}
Loading