Skip to content

Commit aa25315

Browse files
committed
CCM-11586: initial truststore
1 parent 08be1f1 commit aa25315

File tree

7 files changed

+183
-0
lines changed

7 files changed

+183
-0
lines changed

infrastructure/terraform/components/api/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ No requirements.
1212
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
1313
| <a name="input_component"></a> [component](#input\_component) | The variable encapsulating the name of this component | `string` | `"supapi"` | no |
1414
| <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 |
15+
| <a name="input_enable_backups"></a> [enable\_backups](#input\_enable\_backups) | Enable backups | `bool` | `false` | no |
1516
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
1617
| <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 |
1718
| <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 |
1819
| <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 |
1920
| <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 |
2021
| <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 |
22+
| <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 |
2123
| <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 |
2224
| <a name="input_project"></a> [project](#input\_project) | The name of the tfscaffold project | `string` | n/a | yes |
2325
| <a name="input_region"></a> [region](#input\_region) | The AWS Region | `string` | n/a | yes |
2426
| <a name="input_shared_infra_account_id"></a> [shared\_infra\_account\_id](#input\_shared\_infra\_account\_id) | The AWS Account ID of the shared infrastructure account | `string` | `"000000000000"` | no |
27+
| <a name="input_truststore_s3_bucket_config"></a> [truststore\_s3\_bucket\_config](#input\_truststore\_s3\_bucket\_config) | Parameters for configuring the Notify Supplier API truststore bucket | <pre>object({<br/> kms_key_id = string<br/> kms_key_arn = string<br/> bucket_logs_bucket_name = string<br/> })</pre> | <pre>{<br/> "bucket_logs_bucket_name": "",<br/> "kms_key_arn": "",<br/> "kms_key_id": ""<br/>}</pre> | no |
2528
## Modules
2629

2730
| Name | Source | Version |
@@ -31,6 +34,7 @@ No requirements.
3134
| <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 |
3235
| <a name="module_kms"></a> [kms](#module\_kms) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/kms | v2.0.10 |
3336
| <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 |
37+
| <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 |
3438
## Outputs
3539

3640
| Name | Description |

infrastructure/terraform/components/api/api_gateway_domain.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,19 @@ resource "aws_api_gateway_domain_name" "main" {
66
endpoint_configuration {
77
types = ["REGIONAL"]
88
}
9+
10+
depends_on = [
11+
aws_s3_bucket.truststore
12+
]
13+
14+
mutual_tls_authentication {
15+
truststore_uri = "s3://${aws_s3_bucket.truststore[0].id}/${aws_s3_object.placeholder_truststore[0].id}"
16+
truststore_version = aws_s3_object.placeholder_truststore[0].version_id
17+
}
18+
19+
lifecycle {
20+
ignore_changes = [
21+
mutual_tls_authentication
22+
]
23+
}
924
}

infrastructure/terraform/components/api/locals.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,15 @@ locals {
1414
})
1515

1616
destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs"
17+
18+
csi_s3 = replace(
19+
format(
20+
"%s-%s-%s-%s",
21+
var.project,
22+
var.aws_account_id,
23+
var.environment
24+
),
25+
"_",
26+
"",
27+
)
1728
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module "supplier_ssl" {
2+
source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/ssl?ref=v2.0.17"
3+
4+
count = var.manually_configure_mtls_truststore ? 0 : 1
5+
6+
aws_account_id = var.aws_account_id
7+
default_tags = local.default_tags
8+
component = var.component
9+
environment = var.environment
10+
project = var.project
11+
region = var.region
12+
group = var.group
13+
subject_common_name = local.root_domain_name
14+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
resource "aws_s3_bucket_policy" "truststore" {
2+
bucket = aws_s3_bucket.truststore[0].id
3+
policy = data.aws_iam_policy_document.truststore[0].json
4+
}
5+
6+
data "aws_iam_policy_document" "truststore" {
7+
statement {
8+
effect = "Deny"
9+
actions = ["s3:*"]
10+
resources = [
11+
aws_s3_bucket.truststore[0].arn,
12+
"${aws_s3_bucket.truststore[0].arn}/*",
13+
]
14+
15+
principals {
16+
type = "AWS"
17+
identifiers = ["*"]
18+
}
19+
20+
condition {
21+
test = "Bool"
22+
variable = "aws:SecureTransport"
23+
values = [
24+
false
25+
]
26+
}
27+
}
28+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
resource "aws_s3_bucket" "truststore" {
2+
bucket = "${local.csi_s3}-truststore"
3+
tags = merge(local.default_tags, { "Enable-Backup" = var.enable_backups }, { "Enable-S3-Continuous-Backup" = var.enable_backups }, { "SKIP_S3_AUDIT" = "true" })
4+
}
5+
6+
resource "aws_s3_bucket_ownership_controls" "truststore" {
7+
bucket = aws_s3_bucket.truststore[0].id
8+
9+
rule {
10+
object_ownership = "BucketOwnerPreferred"
11+
}
12+
}
13+
14+
resource "aws_s3_bucket_server_side_encryption_configuration" "truststore" {
15+
bucket = aws_s3_bucket.truststore[0].id
16+
17+
rule {
18+
apply_server_side_encryption_by_default {
19+
sse_algorithm = "aws:kms"
20+
kms_master_key_id = var.truststore_s3_bucket_config.kms_key_id
21+
}
22+
bucket_key_enabled = true
23+
}
24+
}
25+
26+
resource "aws_s3_bucket_versioning" "truststore" {
27+
bucket = aws_s3_bucket.truststore[0].id
28+
29+
versioning_configuration {
30+
status = "Enabled"
31+
}
32+
}
33+
34+
resource "aws_s3_bucket_public_access_block" "truststore" {
35+
depends_on = [
36+
aws_s3_bucket_policy.truststore
37+
]
38+
39+
bucket = aws_s3_bucket.truststore[0].id
40+
41+
block_public_acls = true
42+
block_public_policy = true
43+
ignore_public_acls = true
44+
restrict_public_buckets = true
45+
}
46+
47+
resource "aws_s3_bucket_logging" "truststore" {
48+
bucket = aws_s3_bucket.truststore[0].id
49+
50+
target_bucket = var.truststore_s3_bucket_config.bucket_logs_bucket_name
51+
target_prefix = "truststore/${aws_s3_bucket.truststore[0].bucket}/"
52+
}
53+
54+
# If Environment is to be Manually configured, need to create a placeholder truststore file for mtls
55+
resource "aws_s3_object" "placeholder_truststore" {
56+
count = var.manually_configure_mtls_truststore ? 1 : 0
57+
bucket = aws_s3_bucket.truststore[0].bucket
58+
key = "truststore.pem"
59+
content = tls_self_signed_cert.placeholder_cert[0].cert_pem
60+
61+
depends_on = [
62+
aws_s3_bucket_versioning.truststore
63+
]
64+
65+
lifecycle {
66+
ignore_changes = [
67+
content
68+
]
69+
}
70+
}
71+
72+
# If env is not manually configured, use the certs generated from the ssl module
73+
# Having a duplicate resource here as lifcycle rules can't be dynamic or variable
74+
# We don't want to ignore content in nonprod, but we do for prod as we will manually update certs and not via ssl module
75+
resource "aws_s3_object" "placeholder_truststore_nonprod" {
76+
count = var.manually_configure_mtls_truststore ? 0 : 1
77+
bucket = aws_s3_bucket.truststore[0].bucket
78+
key = "truststore.pem"
79+
content = module.supplier_ssl.cacert_pem
80+
81+
depends_on = [
82+
aws_s3_bucket_versioning.truststore,
83+
module.supplier_ssl
84+
]
85+
}

infrastructure/terraform/components/api/variables.tf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,29 @@ variable "shared_infra_account_id" {
8686
description = "The AWS Account ID of the shared infrastructure account"
8787
default = "000000000000"
8888
}
89+
90+
variable "manually_configure_mtls_truststore" {
91+
type = bool
92+
description = "Manually manage the truststore used for API Gateway mTLS (e.g. for prod environment)"
93+
default = false
94+
}
95+
96+
variable "enable_backups" {
97+
type = bool
98+
description = "Enable backups"
99+
default = false
100+
}
101+
102+
variable "truststore_s3_bucket_config" {
103+
type = object({
104+
kms_key_id = string
105+
kms_key_arn = string
106+
bucket_logs_bucket_name = string
107+
})
108+
description = "Parameters for configuring the Notify Supplier API truststore bucket"
109+
default = {
110+
bucket_logs_bucket_name = ""
111+
kms_key_arn = ""
112+
kms_key_id = ""
113+
}
114+
}

0 commit comments

Comments
 (0)