Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Externalize logging bucket and KMS key #141

Merged
merged 11 commits into from
Apr 13, 2023
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
13 changes: 13 additions & 0 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,26 @@ kubectl get nodes

| Name | Type |
|------|------|
| [aws_kms_alias.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
| [aws_kms_key.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_s3_bucket.access_log_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
| [aws_s3_bucket_lifecycle_configuration.access_log_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource |
| [aws_s3_bucket_notification.access_log_bucket_notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_notification) | resource |
| [aws_s3_bucket_public_access_block.access_log_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
| [aws_s3_bucket_server_side_encryption_configuration.access_log_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
| [aws_s3_bucket_versioning.access_log_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource |
| [aws_sqs_queue.access_log_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource |
| [random_id.default](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [aws_ami.amazonlinux2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [aws_iam_policy_document.kms_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_access_log_expire_days"></a> [access\_log\_expire\_days](#input\_access\_log\_expire\_days) | Number of days to wait before deleting access logs | `number` | `30` | no |
| <a name="input_amazon_eks_aws_ebs_csi_driver_config"></a> [amazon\_eks\_aws\_ebs\_csi\_driver\_config](#input\_amazon\_eks\_aws\_ebs\_csi\_driver\_config) | configMap for AWS EBS CSI Driver add-on | `any` | `{}` | no |
| <a name="input_amazon_eks_coredns_config"></a> [amazon\_eks\_coredns\_config](#input\_amazon\_eks\_coredns\_config) | Configuration for Amazon CoreDNS EKS add-on | `any` | `{}` | no |
| <a name="input_amazon_eks_kube_proxy_config"></a> [amazon\_eks\_kube\_proxy\_config](#input\_amazon\_eks\_kube\_proxy\_config) | ConfigMap for Amazon EKS Kube-Proxy add-on | `any` | `{}` | no |
Expand All @@ -161,6 +172,7 @@ kubectl get nodes
| <a name="input_enable_eks_managed_nodegroups"></a> [enable\_eks\_managed\_nodegroups](#input\_enable\_eks\_managed\_nodegroups) | Enable managed node groups | `bool` | n/a | yes |
| <a name="input_enable_metrics_server"></a> [enable\_metrics\_server](#input\_enable\_metrics\_server) | Enable metrics server add-on | `bool` | `false` | no |
| <a name="input_enable_self_managed_nodegroups"></a> [enable\_self\_managed\_nodegroups](#input\_enable\_self\_managed\_nodegroups) | Enable self managed node groups | `bool` | n/a | yes |
| <a name="input_enable_sqs_events_on_access_log_access"></a> [enable\_sqs\_events\_on\_access\_log\_access](#input\_enable\_sqs\_events\_on\_access\_log\_access) | If true, generates an SQS event whenever on object is created in the Access Log bucket, which happens whenever a server access log is generated by any entity. This will potentially generate a lot of events, so use with caution. | `bool` | `false` | no |
| <a name="input_kc_db_allocated_storage"></a> [kc\_db\_allocated\_storage](#input\_kc\_db\_allocated\_storage) | The database allocated storage to use for Keycloak | `number` | n/a | yes |
| <a name="input_kc_db_engine_version"></a> [kc\_db\_engine\_version](#input\_kc\_db\_engine\_version) | The database engine to use for Keycloak | `string` | n/a | yes |
| <a name="input_kc_db_family"></a> [kc\_db\_family](#input\_kc\_db\_family) | The database family to use for Keycloak | `string` | n/a | yes |
Expand All @@ -169,6 +181,7 @@ kubectl get nodes
| <a name="input_kc_db_max_allocated_storage"></a> [kc\_db\_max\_allocated\_storage](#input\_kc\_db\_max\_allocated\_storage) | The database allocated storage to use for Keycloak | `number` | n/a | yes |
| <a name="input_keycloak_db_password"></a> [keycloak\_db\_password](#input\_keycloak\_db\_password) | The password to use for the Keycloak database | `string` | `"my-password"` | no |
| <a name="input_keycloak_enabled"></a> [keycloak\_enabled](#input\_keycloak\_enabled) | Whether to enable Keycloak | `bool` | `false` | no |
| <a name="input_kms_key_deletion_window"></a> [kms\_key\_deletion\_window](#input\_kms\_key\_deletion\_window) | Waiting period for scheduled KMS Key deletion. Can be 7-30 days. | `number` | `7` | no |
| <a name="input_manage_aws_auth_configmap"></a> [manage\_aws\_auth\_configmap](#input\_manage\_aws\_auth\_configmap) | Determines whether to manage the aws-auth configmap | `bool` | `false` | no |
| <a name="input_metrics_server_helm_config"></a> [metrics\_server\_helm\_config](#input\_metrics\_server\_helm\_config) | Metrics Server Helm Chart config | `any` | `{}` | no |
| <a name="input_name_prefix"></a> [name\_prefix](#input\_name\_prefix) | The prefix to use when naming all resources | `string` | `"ex-complete"` | no |
Expand Down
164 changes: 164 additions & 0 deletions examples/complete/access-logging.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# TODO: Evaluate whether this should all go into a new module

# Create a KMS key and corresponding alias. This KMS key will be used whenever encryption is needed in creating this infrastructure deployment
resource "aws_kms_key" "default" {
description = "SSM Key"
deletion_window_in_days = var.kms_key_deletion_window
enable_key_rotation = true
policy = data.aws_iam_policy_document.kms_access.json
tags = local.tags
multi_region = true
}

resource "aws_kms_alias" "default" {
name_prefix = local.kms_key_alias_name_prefix
target_key_id = aws_kms_key.default.key_id

}

# Create custom policy for KMS
data "aws_iam_policy_document" "kms_access" {
# checkov:skip=CKV_AWS_111: todo reduce perms on key
# checkov:skip=CKV_AWS_109: todo be more specific with resources
statement {
sid = "KMS Key Default"
principals {
type = "AWS"
identifiers = [
"arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:root"
]
}

actions = [
"kms:*",
]

resources = ["*"]
}
statement {
sid = "CloudWatchLogsEncryption"
principals {
type = "Service"
identifiers = ["logs.${var.region}.amazonaws.com"]
}
actions = [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*",
]

resources = ["*"]
}
statement {
sid = "Cloudtrail KMS permissions"
principals {
type = "Service"
identifiers = [
"cloudtrail.amazonaws.com"
]
}
actions = [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*",
]
resources = ["*"]
}

}

# Create S3 bucket for access logs with versioning, encryption, blocked public access enabled
resource "aws_s3_bucket" "access_log_bucket" {
# checkov:skip=CKV_AWS_144: Cross region replication is overkill
# checkov:skip=CKV_AWS_18: "Ensure the S3 bucket has access logging enabled" -- This is the access logging bucket. Logging to the logging bucket would cause an infinite loop.
bucket_prefix = local.access_logging_name_prefix
force_destroy = true
tags = local.tags

lifecycle {
precondition {
condition = length(local.access_logging_name_prefix) <= 37
error_message = "Bucket name prefixes may not be longer than 37 characters."
}
}
}

resource "aws_s3_bucket_versioning" "access_log_bucket" {
bucket = aws_s3_bucket.access_log_bucket.id

versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "access_log_bucket" {
bucket = aws_s3_bucket.access_log_bucket.id

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

resource "aws_s3_bucket_public_access_block" "access_log_bucket" {
bucket = aws_s3_bucket.access_log_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

resource "aws_s3_bucket_lifecycle_configuration" "access_log_bucket" {
bucket = aws_s3_bucket.access_log_bucket.id

rule {
id = "delete_after_X_days"
status = "Enabled"

expiration {
days = var.access_log_expire_days
}
}
}

resource "aws_sqs_queue" "access_log_queue" {
count = var.enable_sqs_events_on_access_log_access ? 1 : 0
name = local.access_log_sqs_queue_name
kms_master_key_id = aws_kms_key.default.arn
kms_data_key_reuse_period_seconds = 300
visibility_timeout_seconds = 300

policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSend",
"Effect": "Allow",
"Principal": "*",
"Action": "sqs:SendMessage",
"Resource": "arn:${data.aws_partition.current.partition}:sqs:*:*:${local.access_log_sqs_queue_name}",
"Condition": {
"ArnEquals": { "aws:SourceArn": "${aws_s3_bucket.access_log_bucket.arn}" }
}
}
]
}
POLICY
}

resource "aws_s3_bucket_notification" "access_log_bucket_notification" {
count = var.enable_sqs_events_on_access_log_access ? 1 : 0
bucket = aws_s3_bucket.access_log_bucket.id

queue {
queue_arn = aws_sqs_queue.access_log_queue[0].arn
events = ["s3:ObjectCreated:*"]
}
}
4 changes: 2 additions & 2 deletions examples/complete/bigbang-dependencies.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module "flux_sops" {
cluster_name = module.eks.cluster_name
vpc_id = module.vpc.vpc_id
policy_name_prefix = "${module.eks.cluster_name}-flux-sops"
kms_key_alias = "${module.eks.cluster_name}-flux-sops"
kms_key_arn = aws_kms_key.default.arn
kubernetes_service_account = "flux-system-sops-sa"
kubernetes_namespace = "flux-system"
irsa_sops_iam_role_name = "${module.eks.cluster_name}-flux-system-sa-role"
Expand All @@ -33,7 +33,7 @@ module "loki_s3_bucket" {
name_prefix = "${local.loki_name_prefix}-s3"
region = var.region
policy_name_prefix = "${local.loki_name_prefix}-s3-policy"
kms_key_alias = local.loki_name_prefix
kms_key_arn = aws_kms_key.default.arn
kubernetes_service_account = "logging-loki" #Must be logging-loki to match BigBang deployment
kubernetes_namespace = "logging"
irsa_iam_role_name = "${module.eks.cluster_name}-logging-loki-sa-role"
Expand Down
24 changes: 14 additions & 10 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ resource "random_id" "default" {
}

locals {
vpc_name = "${var.name_prefix}-${lower(random_id.default.hex)}"
cluster_name = "${var.name_prefix}-${lower(random_id.default.hex)}"
bastion_name = "${var.name_prefix}-bastion-${lower(random_id.default.hex)}"
loki_name_prefix = "${var.name_prefix}-loki-${lower(random_id.default.hex)}"
vpc_name = "${var.name_prefix}-${lower(random_id.default.hex)}"
cluster_name = "${var.name_prefix}-${lower(random_id.default.hex)}"
bastion_name = "${var.name_prefix}-bastion-${lower(random_id.default.hex)}"
loki_name_prefix = "${var.name_prefix}-loki-${lower(random_id.default.hex)}"
access_logging_name_prefix = "${var.name_prefix}-accesslog-${lower(random_id.default.hex)}"
kms_key_alias_name_prefix = "alias/${var.name_prefix}-${lower(random_id.default.hex)}"
access_log_sqs_queue_name = "${var.name_prefix}-accesslog-access-${lower(random_id.default.hex)}"

account = data.aws_caller_identity.current.account_id

tags = {
Blueprint = replace(basename(path.cwd), "_", "-") # tag names based on the directory name
GithubRepo = "github.com/aws-ia/terraform-aws-eks-blueprints"
GithubRepo = "github.com/defenseunicorns/iac"
}

eks_managed_node_groups = {
Expand Down Expand Up @@ -157,20 +160,21 @@ module "bastion" {
name = local.bastion_name
vpc_id = module.vpc.vpc_id
subnet_id = module.vpc.private_subnets[0]
aws_region = var.region
access_log_bucket_name_prefix = "${local.bastion_name}-accesslogs"
region = var.region
access_logs_bucket_name = aws_s3_bucket.access_log_bucket.id
session_log_bucket_name_prefix = "${local.bastion_name}-sessionlogs"
kms_key_arn = aws_kms_key.default.arn
ssh_user = var.bastion_ssh_user
ssh_password = var.bastion_ssh_password
assign_public_ip = false # var.assign_public_ip
assign_public_ip = false
enable_log_to_s3 = true
enable_log_to_cloudwatch = true
vpc_endpoints_enabled = true
tenancy = var.bastion_tenancy
zarf_version = var.zarf_version
tags = {
tags = merge(local.tags, {
Function = "bastion-ssm"
}
})
}

###########################################################
Expand Down
18 changes: 18 additions & 0 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ variable "default_tags" {
default = {}
}

variable "kms_key_deletion_window" {
description = "Waiting period for scheduled KMS Key deletion. Can be 7-30 days."
type = number
default = 7
}

variable "access_log_expire_days" {
description = "Number of days to wait before deleting access logs"
type = number
default = 30
}

variable "enable_sqs_events_on_access_log_access" {
description = "If true, generates an SQS event whenever on object is created in the Access Log bucket, which happens whenever a server access log is generated by any entity. This will potentially generate a lot of events, so use with caution."
type = bool
default = false
}

###########################################################
#################### VPC Config ###########################
variable "vpc_cidr" {
Expand Down
Loading