Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
15588b9
temporarily disable condition for apply step
kunduso May 28, 2025
139a209
added conditional logic to sequence resource provisioning steps
kunduso May 28, 2025
2fc759b
format
kunduso May 28, 2025
e346d2a
converted to read zip file from local workspace
kunduso May 28, 2025
9a74aa7
documentation
kunduso May 28, 2025
1a1ce07
added s3 resources for code signing
kunduso May 28, 2025
74d26f8
converted lambda to consume zip file from an s3 bucket
kunduso May 28, 2025
ebe54a8
corrected signer parameters
kunduso May 28, 2025
328d289
more fixes
kunduso May 28, 2025
fb4275e
updated resource dependency
kunduso May 28, 2025
40f15b8
signer profile names cannot be reused
kunduso May 28, 2025
4333916
updated with version id information
kunduso May 28, 2025
8462365
reading signed file into variable
kunduso May 28, 2025
be17cd0
added permissions to lambda
kunduso May 28, 2025
f3ae2ba
adding signer orchestration
kunduso May 28, 2025
a570657
removed blank
kunduso May 28, 2025
15fe914
converted to version arn from arn
kunduso May 28, 2025
427650d
added condition back
kunduso May 29, 2025
b7c05af
removed redudant permission policy
kunduso May 29, 2025
33008ec
added encryption for storage
kunduso May 29, 2025
bec6699
updated filename
kunduso May 29, 2025
f233095
set dependency to manage deployment sequence
kunduso May 29, 2025
bab1928
s3 configuration to store lambda code to enable code signing
kunduso May 29, 2025
a61fed9
fix format
kunduso May 29, 2025
83b68a3
fix for CKV_AWS_300
kunduso May 29, 2025
4a695e9
checkov finding suppress messages
kunduso May 29, 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
2 changes: 1 addition & 1 deletion cloudwatch.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ resource "aws_cloudwatch_log_group" "lambda_log" {
name = "${var.log_group_prefix}${var.name}"
retention_in_days = 365
kms_key_id = aws_kms_key.encryption.arn
depends_on = [aws_kms_key.encryption]
}
#
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_stream
resource "aws_cloudwatch_log_stream" "log_stream" {
name = "${var.name}-lambda-log-stream"
Expand Down
1 change: 1 addition & 0 deletions data.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity
data "aws_caller_identity" "current" {}
locals {
principal_root_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
Expand Down
11 changes: 11 additions & 0 deletions iam_role.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ resource "aws_iam_policy" "lambda_policy" {
"kms:Decrypt"
]
Resource = [aws_kms_key.encryption.arn]
},
# Add S3 permissions for accessing signed code
{
Effect = "Allow",
Action = [
"s3:GetObject",
"s3:GetObjectVersion"
],
Resource = [
"${aws_s3_bucket.lambda_source.arn}/*"
]
}
]
})
Expand Down
65 changes: 65 additions & 0 deletions kms_storage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key
resource "aws_kms_key" "encrypt_storage" {
enable_key_rotation = true
description = "Key to encrypt S3 bucket in ${var.name}."
deletion_window_in_days = 7
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias
resource "aws_kms_alias" "encrypt_storage" {
name = "alias/${var.name}-encrypt-storage"
target_key_id = aws_kms_key.encrypt_storage.key_id
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document
data "aws_iam_policy_document" "encrypt_storage_policy" {
statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Description: The KMS key policy grants broad permissions to the root user, which may pose security risks. Consider limiting the permissions granted to the root user in the KMS key policy. Use the principle of least privilege.

Severity: High

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix addresses the security concern by limiting the permissions granted to the root user in the KMS key policy. Instead of granting broad permissions to the root user, the fix assumes an AdminRole and grants it a more restricted set of permissions. The actions list has been reduced to include only the essential KMS operations. This change implements the principle of least privilege, reducing potential security risks.

Suggested change
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
effect = "Allow"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/AdminRole"] # Assuming an AdminRole exists
}
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
resources = [aws_kms_key.encrypt_storage.arn]
}

}
actions = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Description: The KMS key policy includes a long list of actions, which could be simplified for better readability and maintainability. Consider grouping similar actions or using wildcards where appropriate to reduce the length of the action list.

Severity: Low

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix simplifies the long list of KMS actions in the first statement by using a wildcard "kms:*" instead of listing all individual actions. This improves readability and maintainability of the policy document while still granting full KMS permissions to the root user. The second statement for S3 permissions remains unchanged as it requires specific actions.

Suggested change
actions = [
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = [
"kms:*"
]
resources = [aws_kms_key.encrypt_storage.arn]
}

"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:Create*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion",
"kms:TagResource",
"kms:UntagResource"
]
resources = [aws_kms_key.encrypt_storage.arn]
}
statement {
sid = "Allow S3 to use the key"
effect = "Allow"
principals {
type = "Service"
identifiers = ["s3.amazonaws.com"]
}
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:CreateGrant"
]
resources = [aws_kms_key.encrypt_storage.arn]
}
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key_policy
resource "aws_kms_key_policy" "encrypt_storage" {
key_id = aws_kms_key.encrypt_storage.id
policy = data.aws_iam_policy_document.encrypt_storage_policy.json
}
14 changes: 13 additions & 1 deletion lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ data "archive_file" "python_file" {
source_dir = "${path.module}/lambda_function/"
output_path = "${path.module}/lambda_function/lambda_function.zip"
}
# #https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object
#Upload Lambda code to source S3 bucket
resource "aws_s3_object" "lambda_zip" {
bucket = aws_s3_bucket.lambda_source.bucket
key = "lambda_function.zip"
source = data.archive_file.python_file.output_path
etag = filemd5(data.archive_file.python_file.output_path)
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function
resource "aws_lambda_function" "lambda_run" {
filename = "${path.module}/lambda_function/lambda_function.zip"
s3_bucket = aws_signer_signing_job.build_signing_job.signed_object[0].s3[0].bucket
s3_key = aws_signer_signing_job.build_signing_job.signed_object[0].s3[0].key
#filename = data.archive_file.python_file.output_path
source_code_hash = data.archive_file.python_file.output_base64sha256
function_name = var.name
role = aws_iam_role.lambda_role.arn
Expand Down Expand Up @@ -36,6 +46,8 @@ resource "aws_lambda_function" "lambda_run" {
code_signing_config_arn = aws_lambda_code_signing_config.configuration.arn
reserved_concurrent_executions = 5
#checkov:skip=CKV_AWS_50: Not applicable in this use case: X-Ray tracing is enabled for Lambda
# Ensure the code signing config is created before the Lambda function
depends_on = [aws_lambda_code_signing_config.configuration, aws_signer_signing_job.build_signing_job, aws_iam_role_policy_attachment.lambda_policy_attachement]
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule
resource "aws_cloudwatch_event_rule" "lambda_trigger" {
Expand Down
35 changes: 33 additions & 2 deletions lambda_signer.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
# Generate a random string to use as a suffix
#https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/signer_signing_profile
resource "aws_signer_signing_profile" "lambda_signing_profile" {
platform_id = "AWSLambda-SHA384-ECDSA"
name = "${replace(var.name, "-", "_")}_lambda_signing_profile"
name = "${replace(var.name, "-", "_")}_lambda_signing_profile_${random_string.suffix.result}"
signature_validity_period {
value = 135
type = "MONTHS"
}
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_code_signing_config
resource "aws_lambda_code_signing_config" "configuration" {
allowed_publishers {
signing_profile_version_arns = [aws_signer_signing_profile.lambda_signing_profile.arn]
signing_profile_version_arns = [aws_signer_signing_profile.lambda_signing_profile.version_arn]
}

policies {
untrusted_artifact_on_deployment = "Enforce"
}
description = "Code signing configuration for ${var.name} Lambda function."
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/signer_signing_job
resource "aws_signer_signing_job" "build_signing_job" {
profile_name = aws_signer_signing_profile.lambda_signing_profile.name

source {
s3 {
bucket = aws_s3_bucket.lambda_source.bucket
key = aws_s3_object.lambda_zip.key
version = aws_s3_object.lambda_zip.version_id
}
}

destination {
s3 {
bucket = aws_s3_bucket.lambda_source.bucket
prefix = "signed/"
}
}
}
62 changes: 62 additions & 0 deletions storage.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket
# Create S3 bucket for Lambda source code
resource "aws_s3_bucket" "lambda_source" {
bucket = "${var.name}-lambda-source-${data.aws_caller_identity.current.account_id}"
force_destroy = true
#checkov:skip=CKV_AWS_18: AWS Access logging not enabled on S3 buckets
#checkov:skip=CKV_AWS_144: Region replication not enabled on S3 bucket
#checkov:skip=CKV2_AWS_62: Ensure S3 buckets should have event notifications enabled
# These security controls are suppressed as this bucket is only used temporarily for Lambda code signing
# and is not intended for long-term storage or public access. The bucket has other security measures
# like encryption and public access blocking enabled.
}
Comment on lines +3 to +12

Check warning

Code scanning / checkov

Ensure S3 buckets should have event notifications enabled Warning

Ensure S3 buckets should have event notifications enabled
Comment on lines +3 to +12

Check warning

Code scanning / checkov

Ensure the S3 bucket has access logging enabled Warning

Ensure the S3 bucket has access logging enabled
Comment on lines +3 to +12

Check warning

Code scanning / checkov

Ensure that S3 bucket has cross-region replication enabled Warning

Ensure that S3 bucket has cross-region replication enabled
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning
# Enable versioning on the source S3 bucket (required for signing)
resource "aws_s3_bucket_versioning" "lambda_source" {
bucket = aws_s3_bucket.lambda_source.id
versioning_configuration {
status = "Enabled"
}
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block
resource "aws_s3_bucket_public_access_block" "lambda_source" {
bucket = aws_s3_bucket.lambda_source.id
block_public_acls = true
block_public_policy = true
restrict_public_buckets = true
ignore_public_acls = true
}
#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration
resource "aws_s3_bucket_server_side_encryption_configuration" "lambda_source" {
bucket = aws_s3_bucket.lambda_source.id

rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.encrypt_storage.arn
sse_algorithm = "aws:kms"
}
}
}

#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration
resource "aws_s3_bucket_lifecycle_configuration" "lambda_source" {
bucket = aws_s3_bucket.lambda_source.id

rule {
id = "abort-multipart-uploads"
status = "Enabled"

abort_incomplete_multipart_upload {
days_after_initiation = 3
}
}
rule {
id = "cleanup-old-versions"
status = "Enabled"

noncurrent_version_expiration {
noncurrent_days = 90
}
}

}
Loading