Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions infra/modules/storage/access_control.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ data "aws_iam_policy_document" "storage_access" {
"arn:aws:s3:::${var.name}/*"
]
}

statement {
actions = ["kms:GenerateDataKey", "kms:Decrypt"]
effect = "Allow"
Expand Down
53 changes: 53 additions & 0 deletions infra/modules/storage/encryption.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,62 @@

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

data "aws_iam_policy_document" "kms_key_policy" {
# checkov:skip=CKV_AWS_109:Root account requires full KMS permissions to enable IAM-based access control
# checkov:skip=CKV_AWS_111:Root account requires full KMS permissions to enable IAM-based access control
# checkov:skip=CKV_AWS_356:In a key policy, the wildcard character in the Resource element represents the KMS key to which the key policy is attached.

# This gives the AWS account that owns the KMS key full access to the KMS key,
# deferring specific access rules to IAM roles.
#
# This is the default key policy for programmatically generated KMS keys in
# general, see: https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-root-enable-iam
statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["kms:*"]
resources = ["*"]
}

# Optional: Allow the given AWS service principals to use the key via S3, for situations
# where the service can't use more explicitly configured IAM roles
dynamic "statement" {
for_each = length(var.service_principals_with_access) > 0 ? [1] : []
content {
sid = "AllowViaS3Service"
effect = "Allow"
principals {
type = "Service"
identifiers = var.service_principals_with_access
}
actions = [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
]
resources = ["*"]
condition {
test = "StringEquals"
variable = "kms:ViaService"
values = ["s3.${data.aws_region.current.name}.amazonaws.com"]
}
}
}
}

resource "aws_kms_key" "storage" {
description = "KMS key for bucket ${var.name}"
# The waiting period, specified in number of days. After the waiting period ends, AWS KMS deletes the KMS key.
deletion_window_in_days = "10"
# Generates new cryptographic material every 365 days, this is used to encrypt your data. The KMS key retains the old material for decryption purposes.
enable_key_rotation = "true"

policy = data.aws_iam_policy_document.kms_key_policy.json
}

resource "aws_s3_bucket_server_side_encryption_configuration" "storage" {
Expand Down
14 changes: 14 additions & 0 deletions infra/modules/storage/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,17 @@ variable "name" {
type = string
description = "Name of the AWS S3 bucket. Needs to be globally unique across all regions."
}

variable "service_principals_with_access" {
description = <<-EOT
Storage access should generally be controlled via attaching the `access_policy_arn`
output to an IAM role, but there are some situations where that may not be possible.
Generally when an AWS service doesn't have a way to assume a particular IAM role for operations.

This list of AWS service principals (e.g., bedrock.amazonaws.com) will be used to configure
resources (e.g., the bucket's KMS key) such that the services will be able
to access the bucket's objects.
EOT
type = list(string)
default = []
}
Loading