Skip to content

Commit

Permalink
Feature | add security scan
Browse files Browse the repository at this point in the history
  • Loading branch information
eze-godoy committed May 11, 2023
1 parent bd4c51f commit d084505
Show file tree
Hide file tree
Showing 11 changed files with 780 additions and 79 deletions.
16 changes: 16 additions & 0 deletions .checkov.yml
@@ -0,0 +1,16 @@
block-list-secret-scan: []
branch: master
directory:
- .
download-external-modules: true
evaluate-variables: true
external-modules-download-path: .external_modules
framework:
- terraform
mask: []
quiet: true
secrets-history-timeout: 12h
secrets-scan-file-type: []
skip-path:
- examples
summary-position: top
15 changes: 15 additions & 0 deletions .github/workflows/ci.yaml
@@ -0,0 +1,15 @@
on: [pull_request]

jobs:
checkov-job:
runs-on: ubuntu-latest
name: checkov-action
steps:
- name: Checkout repo
uses: actions/checkout@master

- name: Run Checkov action
id: checkov
uses: bridgecrewio/checkov-action@master
with:
config_file: .checkov.yml
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -16,6 +16,7 @@
!*.gitkeep
!*.editorconfig
!*.pre-commit-config.yaml
!.checkov.yml

# SSH keys #
############
Expand Down
128 changes: 117 additions & 11 deletions README.md

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions backend_config.tf
@@ -0,0 +1,27 @@
locals {
backend_config_template_file = coalesce(var.backend_config_template_file, "${path.module}/templates/backend.tf.tpl")
}

data "aws_region" "current" {
provider = aws.primary
}

resource "local_file" "backend_config" {
count = var.backend_config_filepath != "" ? 1 : 0
filename = "${var.backend_config_filepath}/${var.backend_config_filename}"
file_permission = "0644"

content = templatefile(local.backend_config_template_file, {
region = data.aws_region.current.name
bucket = aws_s3_bucket.default.id
encrypt = var.enable_server_side_encryption
profile = var.backend_config_profile
role_arn = var.backend_config_role_arn
state_file = var.backend_config_state_file

dynamodb_table = one(coalescelist(
aws_dynamodb_table.with_server_side_encryption.*.id,
aws_dynamodb_table.without_server_side_encryption.*.id,
))
})
}
82 changes: 82 additions & 0 deletions bucket_notification.tf
@@ -0,0 +1,82 @@
data "aws_iam_policy_document" "topic" {
count = var.notifications_sns ? 1 : 0
provider = aws.primary

statement {
effect = "Allow"

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

actions = ["SNS:Publish"]
resources = ["arn:aws:sns:*:*:${aws_s3_bucket.default.bucket}-topic"]

condition {
test = "ArnLike"
variable = "aws:SourceArn"
values = [aws_s3_bucket.default.arn]
}
}
}

resource "aws_sns_topic" "topic" {
count = var.notifications_sns ? 1 : 0
provider = aws.primary

name = "${aws_s3_bucket.default.bucket}-topic"
policy = data.aws_iam_policy_document.topic[0].json
kms_master_key_id = aws_kms_key.primary[0].arn
}

data "aws_iam_policy_document" "queue" {
count = var.notifications_sqs ? 1 : 0

statement {
effect = "Allow"

principals {
type = "*"
identifiers = ["*"]
}

actions = ["sqs:SendMessage"]
resources = ["arn:aws:sqs:*:*:${aws_s3_bucket.default.bucket}-queue"]

condition {
test = "ArnEquals"
variable = "aws:SourceArn"
values = [aws_s3_bucket.default.arn]
}
}
}

resource "aws_sqs_queue" "queue" {
count = var.notifications_sqs ? 1 : 0

name = "${aws_s3_bucket.default.bucket}-queue"
policy = data.aws_iam_policy_document.queue[0].json
}

resource "aws_s3_bucket_notification" "bucket_notification" {
count = (var.notifications_sns || var.notifications_sqs) ? 1 : 0

bucket = aws_s3_bucket.default.id

dynamic "topic" {
for_each = aws_sns_topic.topic
content {
topic_arn = topic.value.arn
events = var.notifications_events
}
}

dynamic "queue" {
for_each = aws_sqs_queue.queue
content {
queue_arn = queue.value.arn
events = var.notifications_events
}
}
}
198 changes: 159 additions & 39 deletions bucket_replication.tf
@@ -1,35 +1,122 @@
resource "aws_s3_bucket" "replication_bucket" {
count = var.bucket_replication_enabled ? 1 : 0

# checkov:skip=CKV2_AWS_62:False Positive. This bucket is the replication destination
# checkov:skip=CKV_AWS_144:False Positive. This bucket is the replication destination

provider = aws.secondary
bucket = format("%s-%s-%s-%s", var.namespace, var.stage, var.name, var.bucket_replication_name)

dynamic "logging" {
for_each = var.replica_logging == null ? [] : [1]
content {
target_bucket = var.replica_logging["bucket_name"]
target_prefix = var.replica_logging["prefix"]
}
}

tags = {
Terraform = "true"
Environment = var.stage
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "replication_bucket" {
resource "aws_s3_bucket_replication_configuration" "this" {
count = var.bucket_replication_enabled ? 1 : 0
bucket = aws_s3_bucket.replication_bucket[0].id

bucket = aws_s3_bucket.default.id
role = aws_iam_role.bucket_replication[0].arn

rule {
id = "standard_bucket_replication"
prefix = ""
status = "Enabled"

destination {
bucket = aws_s3_bucket.replication_bucket[0].arn
storage_class = "STANDARD"

dynamic "encryption_configuration" {
for_each = var.create_kms_key ? [1] : []
content {
replica_kms_key_id = aws_kms_replica_key.secondary[0].arn
}
}
}

dynamic "source_selection_criteria" {
for_each = var.create_kms_key ? [1] : []
content {
sse_kms_encrypted_objects {
status = "Enabled"
}
}
}
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "replication_bucket" {
count = var.bucket_replication_enabled ? 1 : 0
provider = aws.secondary
bucket = aws_s3_bucket.replication_bucket[0].id

rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
kms_master_key_id = var.create_kms_key ? aws_kms_key.primary[0].id : null
sse_algorithm = var.create_kms_key ? "aws:kms" : "AES256"
}
}
}

resource "aws_s3_bucket_versioning" "replication_bucket" {
count = var.bucket_replication_enabled ? 1 : 0
bucket = aws_s3_bucket.replication_bucket[0].id
count = var.bucket_replication_enabled ? 1 : 0
provider = aws.secondary
bucket = aws_s3_bucket.replication_bucket[0].id

versioning_configuration {
status = "Enabled"
}
}


resource "aws_s3_bucket_lifecycle_configuration" "replication_bucket" {
count = (var.bucket_replication_enabled && var.bucket_lifecycle_enabled) ? 1 : 0
provider = aws.secondary
depends_on = [aws_s3_bucket_versioning.replication_bucket]

bucket = aws_s3_bucket.replication_bucket[0].id

rule {
id = "noncurrent_expiration"

noncurrent_version_expiration {
noncurrent_days = var.bucket_lifecycle_expiration
}

noncurrent_version_transition {
noncurrent_days = var.bucket_lifecycle_transition_standard_ia
storage_class = "STANDARD_IA"
}

noncurrent_version_transition {
noncurrent_days = var.bucket_lifecycle_transition_glacier
storage_class = "GLACIER"
}

status = "Enabled"
}

rule {
id = "Abort incomplete multipart uploads"
abort_incomplete_multipart_upload {
days_after_initiation = 7
}

status = "Enabled"
}
}


resource "aws_s3_bucket_public_access_block" "replication_bucket" {
count = var.bucket_replication_enabled ? 1 : 0

Expand Down Expand Up @@ -64,46 +151,79 @@ resource "aws_iam_role" "bucket_replication" {
POLICY
}

resource "aws_iam_policy" "bucket_replication" {
data "aws_iam_policy_document" "bucket_replication" {
count = var.bucket_replication_enabled ? 1 : 0

provider = aws.primary
name = format("%s-%s-%s-%s", var.namespace, var.stage, var.name, var.bucket_replication_name_suffix)
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"${aws_s3_bucket.default.arn}"
statement {
sid = "1"
effect = "Allow"
resources = ["${aws_s3_bucket.default.arn}"]

actions = [
"s3:GetReplicationConfiguration",
"s3:ListBucket",
]
}

statement {
sid = "2"
effect = "Allow"
resources = ["${aws_s3_bucket.default.arn}/*"]

actions = [
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionForReplication"
]
}

dynamic "statement" {
for_each = var.create_kms_key == true ? [1] : []
content {
sid = "4"
effect = "Allow"
resources = [aws_kms_key.primary[0].arn, ]

actions = [
"kms:Decrypt",
"kms:GenerateDataKey"
]
},
{
"Action": [
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl"
],
"Effect": "Allow",
"Resource": [
"${aws_s3_bucket.default.arn}/*"
}
}

dynamic "statement" {
for_each = var.create_kms_key == true ? [1] : []
content {
sid = "5"
effect = "Allow"
resources = [aws_kms_replica_key.secondary[0].arn]

actions = [
"kms:GenerateDataKey",
"kms:Encrypt"
]
},
{
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete"
],
"Effect": "Allow",
"Resource": "${aws_s3_bucket.replication_bucket[0].arn}/*"
}
]
}

statement {
sid = "6"
effect = "Allow"
resources = ["${aws_s3_bucket.replication_bucket[0].arn}/*"]

actions = [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags"
]
}
}
POLICY

resource "aws_iam_policy" "bucket_replication" {
count = var.bucket_replication_enabled ? 1 : 0

provider = aws.primary
name = format("%s-%s-%s-%s", var.namespace, var.stage, var.name, var.bucket_replication_name_suffix)
policy = data.aws_iam_policy_document.bucket_replication[0].json

depends_on = [aws_s3_bucket.replication_bucket, aws_s3_bucket_public_access_block.default, time_sleep.wait_30_secs]
}
Expand Down

0 comments on commit d084505

Please sign in to comment.