Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
8 changes: 5 additions & 3 deletions .github/workflows/manual-terraform-apply.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Manual Terraform Apply

on:
pull_request:
types: [ opened, synchronize, reopened ]
workflow_dispatch:
inputs:
environment:
Expand All @@ -10,13 +12,13 @@ on:
options: [dev, test, preprod]

jobs:
plan-stacks:
apply-stacks:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
permissions:
id-token: write
contents: read

timeout-minutes: 30
steps:
- name: "Setup Terraform"
uses: hashicorp/setup-terraform@v3
Expand Down Expand Up @@ -57,7 +59,7 @@ jobs:
- name: "Terraform Plan Stacks"
env:
ENVIRONMENT: ${{ inputs.environment }}
WORKSPACE: ${{ inputs.environment }}
WORKSPACE: "default"
TF_VAR_API_CA_CERT: ${{ secrets.API_CA_CERT }}
TF_VAR_API_CLIENT_CERT: ${{ secrets.API_CLIENT_CERT }}
TF_VAR_API_PRIVATE_KEY_CERT: ${{ secrets.API_PRIVATE_KEY_CERT }}
Expand Down
2 changes: 2 additions & 0 deletions infrastructure/modules/api_gateway/api_gateway.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ resource "aws_api_gateway_rest_api" "api_gateway" {
create_before_destroy = true
}

depends_on = [aws_kms_key_policy.api_gateway]

tags = {
Stack = var.stack_name
}
Expand Down
2 changes: 2 additions & 0 deletions infrastructure/modules/api_gateway/cloudwatch.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ resource "aws_cloudwatch_log_group" "api_gateway" {
lifecycle {
prevent_destroy = false
}

depends_on = [aws_kms_key_policy.api_gateway]
}
4 changes: 3 additions & 1 deletion infrastructure/modules/api_gateway/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ resource "aws_iam_role" "api_gateway" {

data "aws_iam_policy_document" "api_gateway_logging" {
#checkov:skip=CKV_AWS_356: Wildcard permissions needed for global log event reads
#checkov:skip=CKV_AWS_111: Ensure IAM policies does not allow write access without constraints
statement {
sid = "AllowCreateLogGroup"
effect = "Allow"
Expand Down Expand Up @@ -44,7 +45,8 @@ data "aws_iam_policy_document" "api_gateway_logging" {
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:GetLogEvents",
"logs:FilterLogEvents"
"logs:FilterLogEvents",
"logs:PutRetentionPolicy"
]
resources = ["*"]
}
Expand Down
16 changes: 12 additions & 4 deletions infrastructure/modules/api_gateway/kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,34 @@ data "aws_iam_policy_document" "api_gateway" {
sid = "Enable IAM User Permissions for ${var.api_gateway_name} API Gateway"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["kms:*"]
actions = ["kms:*"]
resources = [aws_kms_key.api_gateway.arn]
}
statement {
sid = "APIGatewayCloudwatchKMSAccess"
effect = "Allow"
principals {
type = "Service"
type = "Service"
identifiers = ["logs.${var.region}.amazonaws.com"]
}
actions = [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
"kms:Describe*",
"kms:CreateGrant"
]
resources = [aws_kms_key.api_gateway.arn]
condition {
test = "StringLike"
variable = "kms:EncryptionContext:aws:logs:arn"
values = [
"arn:aws:logs:${var.region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/*"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,10 @@ resource "aws_kinesis_firehose_delivery_stream" "eligibility_audit_firehose_deli
key_type = "CUSTOMER_MANAGED_CMK"
}

depends_on = [
aws_kms_key_policy.firehose_key_policy,
var.kinesis_cloud_watch_log_group_name
]

tags = var.tags
}
3 changes: 2 additions & 1 deletion infrastructure/modules/kinesis_firehose/kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ data "aws_iam_policy_document" "firehose_kms_key_policy" {
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
"kms:DescribeKey",
"kms:CreateGrant"
]
resources = [aws_kms_key.firehose_cmk.arn]
condition {
Expand Down
8 changes: 8 additions & 0 deletions infrastructure/modules/s3/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ output "storage_bucket_id" {
value = aws_s3_bucket.storage_bucket.id
}

output "storage_bucket_kms_key_id" {
value = aws_kms_key.storage_bucket_cmk.id
}

output "storage_bucket_kms_key_arn" {
value = aws_kms_key.storage_bucket_cmk.arn
}

output "storage_bucket_versioning_config" {
value = aws_s3_bucket_versioning.storage_bucket_versioning_config
}
38 changes: 21 additions & 17 deletions infrastructure/stacks/api-layer/iam_policies.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Read-only policy for DynamoDB
data "aws_iam_policy_document" "dynamodb_read_policy_doc" {
statement {
actions = ["dynamodb:GetItem", "dynamodb:Query", "dynamodb:Scan"]
actions = ["dynamodb:GetItem", "dynamodb:Query", "dynamodb:Scan"]
resources = [module.eligibility_status_table.arn]
}
}
Expand All @@ -16,14 +16,14 @@ resource "aws_iam_role_policy" "lambda_dynamodb_read_policy" {
# Write-only policy for DynamoDB
data "aws_iam_policy_document" "dynamodb_write_policy_doc" {
statement {
actions = ["dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem"]
actions = ["dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem"]
resources = [module.eligibility_status_table.arn]
}
}

# Attach dynamoDB write policy to external write role
resource "aws_iam_role_policy" "external_dynamodb_write_policy" {
count = length(aws_iam_role.write_access_role)
count = length(aws_iam_role.write_access_role)
name = "DynamoDBWriteAccess"
role = aws_iam_role.write_access_role[count.index].id
policy = data.aws_iam_policy_document.dynamodb_write_policy_doc.json
Expand All @@ -43,7 +43,7 @@ data "aws_iam_policy_document" "s3_rules_bucket_policy" {
]
condition {
test = "Bool"
values = ["true"]
values = ["true"]
variable = "aws:SecureTransport"
}
}
Expand Down Expand Up @@ -106,15 +106,15 @@ resource "aws_iam_role_policy_attachment" "lambda_logs_policy_attachment" {
# Policy doc for S3 Audit bucket
data "aws_iam_policy_document" "s3_audit_bucket_policy" {
statement {
sid = "AllowSSLRequestsOnly"
sid = "AllowSSLRequestsOnly"
actions = ["s3:*"]
resources = [
module.s3_audit_bucket.storage_bucket_arn,
"${module.s3_audit_bucket.storage_bucket_arn}/*",
]
condition {
test = "Bool"
values = ["true"]
values = ["true"]
variable = "aws:SecureTransport"
}
}
Expand All @@ -136,18 +136,18 @@ data "aws_iam_policy_document" "dynamodb_kms_key_policy" {
sid = "EnableIamUserPermissions"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["kms:*"]
actions = ["kms:*"]
resources = ["*"]
}

statement {
sid = "AllowLambdaDecrypt"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = [aws_iam_role.eligibility_lambda_role.arn]
}
actions = [
Expand All @@ -174,21 +174,21 @@ data "aws_iam_policy_document" "s3_rules_kms_key_policy" {
sid = "EnableIamUserPermissions"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["kms:*"]
actions = ["kms:*"]
resources = ["*"]
}

statement {
sid = "AllowLambdaDecrypt"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = [aws_iam_role.eligibility_lambda_role.arn]
}
actions = ["kms:Decrypt"]
actions = ["kms:Decrypt"]
resources = ["*"]
}
}
Expand All @@ -207,18 +207,18 @@ data "aws_iam_policy_document" "s3_audit_kms_key_policy" {
sid = "EnableIamUserPermissions"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["kms:*"]
actions = ["kms:*"]
resources = ["*"]
}

statement {
sid = "AllowLambdaFullWrite"
effect = "Allow"
principals {
type = "AWS"
type = "AWS"
identifiers = [aws_iam_role.eligibility_lambda_role.arn, aws_iam_role.eligibility_audit_firehose_role.arn]
}
actions = [
Expand All @@ -241,8 +241,12 @@ data "aws_iam_policy_document" "lambda_firehose_write_policy" {
sid = "AllowLambdaToPutToFirehose"
effect = "Allow"
actions = [
"firehose:StartDeliveryStreamEncryption",
"firehose:StopDeliveryStreamEncryption",
"firehose:PutRecord",
"firehose:PutRecordBatch"
"firehose:PutRecordBatch",
"firehose:DescribeDeliveryStream",
"firehose:ListDeliveryStreams"
]
resources = [
"arn:aws:firehose:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:deliverystream/${module.eligibility_audit_firehose_delivery_stream.firehose_stream_name}"
Expand Down
54 changes: 49 additions & 5 deletions infrastructure/stacks/api-layer/truststore_s3_bucket.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ data "aws_iam_policy_document" "truststore_api_gateway" {
effect = "Allow"

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

Expand All @@ -31,9 +31,53 @@ data "aws_iam_policy_document" "truststore_api_gateway" {
}

resource "aws_s3_object" "pem_file" {
bucket = module.s3_truststore_bucket.storage_bucket_name
key = "truststore.pem"
content = local.pem_file_content
bucket = module.s3_truststore_bucket.storage_bucket_name
key = "truststore.pem"
content = local.pem_file_content
acl = "private"
kms_key_id = module.s3_truststore_bucket.storage_bucket_kms_key_arn

acl = "private"
depends_on = [module.s3_truststore_bucket.storage_bucket_versioning_config]
}


resource "aws_kms_key_policy" "storage_bucket_cmk" {
key_id = module.s3_truststore_bucket.storage_bucket_kms_key_id
policy = data.aws_iam_policy_document.trust_store_kms_policy.json
}

data "aws_iam_policy_document" "trust_store_kms_policy" {
#checkov:skip=CKV_AWS_111: Root user needs full KMS key management
#checkov:skip=CKV_AWS_356: Root user needs full KMS key management
#checkov:skip=CKV_AWS_109: Root user needs full KMS key management
statement {
sid = "AllowRootAccountFullAccess"
effect = "Allow"

principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
]
}

actions = ["kms:*"]
resources = ["*"]
}

# 2. Allow API Gateway to decrypt truststore
statement {
sid = "APIGatewayS3TruststoreDecrypt"
effect = "Allow"
principals {
type = "Service"
identifiers = [
"apigateway.amazonaws.com",
"apigateway.${var.default_aws_region}.amazonaws.com"
]
}
actions = ["kms:Decrypt"]
resources = ["*"]
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,9 @@ resource "aws_iam_policy" "firehose_readonly" {
"firehose:PutRecordBatch",
"firehose:TagDeliveryStream",
"firehose:ListTagsForDeliveryStream",
"firehose:UntagDeliveryStream"
"firehose:UntagDeliveryStream",
"firehose:StartDeliveryStreamEncryption",
"firehose:StopDeliveryStreamEncryption"
]
Resource = "arn:aws:firehose:${var.default_aws_region}:${data.aws_caller_identity.current.account_id}:deliverystream/eligibility-signposting-api*"
}
Expand Down
Loading