Skip to content

Commit d1c0a37

Browse files
CCM-12615: APIM Authentication (#116)
* CCM-12615: APIM Authentication * CCM-12615: Ignore secrets for test keys * CCM-12615: Updated APIM URL variable definition * CCM-12615: Address review comments * CCM-12615: Address review comments
1 parent e91851a commit d1c0a37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3579
-62
lines changed

.gitleaksignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ f8546e35b77b69ba7b15dbe3174d2d7e375200ef:utils/utils/src/__tests__/key-generatio
1616
f8546e35b77b69ba7b15dbe3174d2d7e375200ef:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:23
1717
f8546e35b77b69ba7b15dbe3174d2d7e375200ef:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:30
1818
f8546e35b77b69ba7b15dbe3174d2d7e375200ef:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:46
19+
39af95d4a48f3f2f4e5404da6cfe4a1350f25abe:utils/utils/src/__tests__/key-generation/validate-private-key.test.ts:private-key:7
20+
39af95d4a48f3f2f4e5404da6cfe4a1350f25abe:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:23
21+
39af95d4a48f3f2f4e5404da6cfe4a1350f25abe:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:30
22+
39af95d4a48f3f2f4e5404da6cfe4a1350f25abe:utils/utils/src/__tests__/key-generation/get-private-key.test.ts:private-key:46

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ export default defineConfig([
253253
'no-await-in-loop': 0,
254254
'no-plusplus': [2, { allowForLoopAfterthoughts: true }],
255255
'unicorn/prefer-top-level-await': 0, // top level await is not available in commonjs
256+
'import-x/prefer-default-export': "off"
256257
},
257258
},
258259
]);

infrastructure/terraform/components/dl/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@ No requirements.
99

1010
| Name | Description | Type | Default | Required |
1111
|------|-------------|------|---------|:--------:|
12+
| <a name="input_apim_auth_token_schedule"></a> [apim\_auth\_token\_schedule](#input\_apim\_auth\_token\_schedule) | Schedule to renew the APIM auth token | `string` | `"rate(9 minutes)"` | no |
13+
| <a name="input_apim_auth_token_url"></a> [apim\_auth\_token\_url](#input\_apim\_auth\_token\_url) | URL to generate an APIM auth token | `string` | `"https://int.api.service.nhs.uk/oauth2/token"` | no |
14+
| <a name="input_apim_base_url"></a> [apim\_base\_url](#input\_apim\_base\_url) | The URL used to send requests to Notify and PDM | `string` | `"https://sandbox.api.service.nhs.uk"` | no |
15+
| <a name="input_apim_keygen_schedule"></a> [apim\_keygen\_schedule](#input\_apim\_keygen\_schedule) | Schedule to refresh key pairs if necessary | `string` | `"cron(0 14 * * ? *)"` | no |
1216
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
1317
| <a name="input_component"></a> [component](#input\_component) | The variable encapsulating the name of this component | `string` | `"dl"` | no |
1418
| <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 |
1519
| <a name="input_enable_dynamodb_delete_protection"></a> [enable\_dynamodb\_delete\_protection](#input\_enable\_dynamodb\_delete\_protection) | Enable DynamoDB Delete Protection on all Tables | `bool` | `true` | no |
1620
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
21+
| <a name="input_force_destroy"></a> [force\_destroy](#input\_force\_destroy) | Flag to force deletion of S3 buckets | `bool` | `false` | no |
1722
| <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 |
1823
| <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 |
1924
| <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 |
@@ -32,8 +37,12 @@ No requirements.
3237
| Name | Source | Version |
3338
|------|--------|---------|
3439
| <a name="module_kms"></a> [kms](#module\_kms) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-kms.zip | n/a |
40+
| <a name="module_lambda_apim_key_generation"></a> [lambda\_apim\_key\_generation](#module\_lambda\_apim\_key\_generation) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-lambda.zip | n/a |
41+
| <a name="module_lambda_lambda_apim_refresh_token"></a> [lambda\_lambda\_apim\_refresh\_token](#module\_lambda\_lambda\_apim\_refresh\_token) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-lambda.zip | n/a |
3542
| <a name="module_mesh_poll"></a> [mesh\_poll](#module\_mesh\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-lambda.zip | n/a |
43+
| <a name="module_s3bucket_cf_logs"></a> [s3bucket\_cf\_logs](#module\_s3bucket\_cf\_logs) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
3644
| <a name="module_s3bucket_letters"></a> [s3bucket\_letters](#module\_s3bucket\_letters) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
45+
| <a name="module_s3bucket_static_assets"></a> [s3bucket\_static\_assets](#module\_s3bucket\_static\_assets) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
3746
| <a name="module_sqs_event_publisher_errors"></a> [sqs\_event\_publisher\_errors](#module\_sqs\_event\_publisher\_errors) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
3847
| <a name="module_sqs_ttl"></a> [sqs\_ttl](#module\_sqs\_ttl) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
3948
| <a name="module_sqs_ttl_handle_expiry_errors"></a> [sqs\_ttl\_handle\_expiry\_errors](#module\_sqs\_ttl\_handle\_expiry\_errors) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
resource "aws_acm_certificate" "static_assets_hosting" {
2+
provider = aws.us-east-1
3+
domain_name = local.root_domain_name
4+
validation_method = "DNS"
5+
6+
lifecycle {
7+
create_before_destroy = true
8+
}
9+
}
10+
11+
resource "aws_acm_certificate_validation" "static_assets_hosting" {
12+
provider = aws.us-east-1
13+
certificate_arn = aws_acm_certificate.static_assets_hosting.arn
14+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
resource "aws_cloudfront_distribution" "static_assets_hosting" {
2+
enabled = true
3+
is_ipv6_enabled = true
4+
comment = "Static asset hosting for Digital Letters"
5+
price_class = "PriceClass_100"
6+
7+
restrictions {
8+
geo_restriction {
9+
restriction_type = "whitelist"
10+
locations = ["GB"]
11+
}
12+
}
13+
14+
aliases = [local.root_domain_name]
15+
16+
viewer_certificate {
17+
cloudfront_default_certificate = false
18+
acm_certificate_arn = aws_acm_certificate.static_assets_hosting.arn
19+
minimum_protocol_version = "TLSv1.2_2021"
20+
ssl_support_method = "sni-only"
21+
}
22+
23+
logging_config {
24+
include_cookies = false
25+
bucket = module.s3bucket_cf_logs.bucket_regional_domain_name
26+
}
27+
28+
origin {
29+
domain_name = module.s3bucket_static_assets.bucket_regional_domain_name
30+
origin_id = "${local.csi}-origin-static-assets"
31+
s3_origin_config {
32+
origin_access_identity = aws_cloudfront_origin_access_identity.static_assets.cloudfront_access_identity_path
33+
}
34+
}
35+
36+
default_cache_behavior {
37+
allowed_methods = ["GET", "HEAD"]
38+
cached_methods = ["GET", "HEAD"]
39+
target_origin_id = "${local.csi}-origin-static-assets"
40+
41+
forwarded_values {
42+
query_string = false
43+
headers = ["Origin"]
44+
cookies {
45+
forward = "none"
46+
}
47+
}
48+
49+
viewer_protocol_policy = "redirect-to-https"
50+
min_ttl = 0
51+
default_ttl = 0
52+
max_ttl = 86400
53+
compress = true
54+
}
55+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
locals {
22
aws_lambda_functions_dir_path = "../../../../lambdas"
33
log_destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs"
4-
4+
apim_access_token_ssm_parameter_name = "/${var.component}/${var.environment}/apim/access_token"
5+
apim_api_key_ssm_parameter_name = "/${var.component}/${var.environment}/apim/api_key"
6+
apim_private_key_ssm_parameter_name = "/${var.component}/${var.environment}/apim/private_key"
7+
apim_keystore_s3_bucket = "nhs-${var.aws_account_id}-${var.region}-${var.environment}-${var.component}-static-assets"
8+
root_domain_name = "${var.environment}.${local.acct.route53_zone_names["digital-letters"]}"
9+
root_domain_id = local.acct.route53_zone_ids["digital-letters"]
510
ttl_shard_count = 3
611
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
module "lambda_apim_key_generation" {
2+
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-lambda.zip"
3+
4+
function_name = "apim-key-generation"
5+
description = "A function to generate APIM public and private keys"
6+
7+
aws_account_id = var.aws_account_id
8+
component = var.component
9+
environment = var.environment
10+
project = var.project
11+
region = var.region
12+
group = var.group
13+
14+
log_retention_in_days = var.log_retention_in_days
15+
kms_key_arn = module.kms.key_arn
16+
17+
iam_policy_document = {
18+
body = data.aws_iam_policy_document.lambda_apim_key_generation.json
19+
}
20+
21+
function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"]
22+
function_code_base_path = local.aws_lambda_functions_dir_path
23+
function_code_dir = "key-generation/dist"
24+
function_include_common = true
25+
function_module_name = "lambda"
26+
handler_function_name = "handler"
27+
runtime = "nodejs22.x"
28+
memory = 512
29+
timeout = 300
30+
log_level = var.log_level
31+
schedule = var.apim_keygen_schedule
32+
33+
force_lambda_code_deploy = var.force_lambda_code_deploy
34+
enable_lambda_insights = false
35+
36+
send_to_firehose = true
37+
log_destination_arn = local.log_destination_arn
38+
log_subscription_role_arn = local.acct.log_subscription_role_arn
39+
40+
lambda_env_vars = {
41+
SSM_PRIVATE_KEY_PARAMETER_NAME = local.apim_private_key_ssm_parameter_name
42+
KEYSTORE_S3_BUCKET = local.apim_keystore_s3_bucket
43+
ENVIRONMENT = var.environment
44+
}
45+
}
46+
47+
data "aws_iam_policy_document" "lambda_apim_key_generation" {
48+
statement {
49+
sid = "AllowS3List"
50+
effect = "Allow"
51+
52+
actions = [
53+
"s3:ListBucket",
54+
"s3:PutObject"
55+
]
56+
57+
resources = [
58+
"arn:aws:s3:::${local.apim_keystore_s3_bucket}/*"
59+
]
60+
}
61+
62+
statement {
63+
sid = "AllowSSMParam"
64+
effect = "Allow"
65+
66+
actions = [
67+
"ssm:DeleteParameter",
68+
"ssm:GetParameter",
69+
"ssm:GetParameters",
70+
"ssm:GetParametersByPath",
71+
"ssm:PutParameter",
72+
]
73+
74+
resources = [
75+
"arn:aws:ssm:${var.region}:${var.aws_account_id}:parameter/${var.component}/${var.environment}/apim/*"
76+
]
77+
}
78+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
module "lambda_lambda_apim_refresh_token" {
2+
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-lambda.zip"
3+
4+
function_name = "apim-refresh-token"
5+
description = "A function to generate APIM access tokens"
6+
7+
aws_account_id = var.aws_account_id
8+
component = var.component
9+
environment = var.environment
10+
project = var.project
11+
region = var.region
12+
group = var.group
13+
14+
log_retention_in_days = var.log_retention_in_days
15+
kms_key_arn = module.kms.key_arn
16+
17+
iam_policy_document = {
18+
body = data.aws_iam_policy_document.lambda_apim_refresh_token.json
19+
}
20+
21+
function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"]
22+
function_code_base_path = local.aws_lambda_functions_dir_path
23+
function_code_dir = "refresh-apim-access-token/dist"
24+
function_include_common = true
25+
handler_function_name = "handler"
26+
runtime = "nodejs22.x"
27+
memory = 128
28+
timeout = 5
29+
log_level = var.log_level
30+
schedule = var.apim_auth_token_schedule
31+
32+
force_lambda_code_deploy = var.force_lambda_code_deploy
33+
enable_lambda_insights = false
34+
35+
send_to_firehose = true
36+
log_destination_arn = local.log_destination_arn
37+
log_subscription_role_arn = local.acct.log_subscription_role_arn
38+
39+
lambda_env_vars = {
40+
NHS_AUTH_SERVER_TOKEN_ENDPOINT = var.apim_auth_token_url
41+
SSM_ACCESS_TOKEN_PARAMETER_NAME = local.apim_access_token_ssm_parameter_name
42+
SSM_API_KEY_PARAMETER_NAME = local.apim_api_key_ssm_parameter_name
43+
SSM_PRIVATE_KEY_PARAMETER_NAME = local.apim_private_key_ssm_parameter_name
44+
ENVIRONMENT = var.environment
45+
}
46+
}
47+
48+
data "aws_iam_policy_document" "lambda_apim_refresh_token" {
49+
statement {
50+
sid = "AllowSSMParam"
51+
effect = "Allow"
52+
53+
actions = [
54+
"ssm:DeleteParameter",
55+
"ssm:GetParameter",
56+
"ssm:GetParameters",
57+
"ssm:GetParametersByPath",
58+
"ssm:PutParameter",
59+
]
60+
61+
resources = [
62+
"arn:aws:ssm:${var.region}:${var.aws_account_id}:parameter/${var.component}/${var.environment}/apim/*"
63+
]
64+
}
65+
}

0 commit comments

Comments
 (0)