Skip to content

Commit

Permalink
Add s3 bucket for eks shell session dumps (#360)
Browse files Browse the repository at this point in the history
* added s3 bucket for shell session dump + cors and iam role to allow controlplane to putobjects

* break out into module

* fix policy

* add getobject to policy

* update to handle dependency issue between creating bucket and using it within control plane

* add bucket and cors policy, wire up permissions for access handler and control plane

* remove extra bucket

* added s3 bucket domain name to web to allow content policy

* update with leading https

* add trailing slash

* added changeset

---------

Co-authored-by: JoshuaWilkes <[email protected]>
  • Loading branch information
meyerjrr and JoshuaWilkes authored Nov 1, 2024
1 parent 193bb6b commit 7eb80b9
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/twelve-eagles-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@common-fate/terraform-aws-common-fate-deployment": minor
---

adds s3 bucket and networking for EKS shell session logs
65 changes: 44 additions & 21 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ module "control_plane" {
managed_deployment = var.managed_deployment
compare_entitlements_enabled = var.compare_entitlements_enabled
iam_role_permission_boundary = var.iam_role_permission_boundary
shell_session_logs_bucket_arn = module.shell_session_logs_bucket.arn
shell_session_logs_bucket_name = module.shell_session_logs_bucket.id

}

module "report_bucket" {
Expand All @@ -260,29 +263,46 @@ module "authz_eval_bucket" {
component = "evals"
}

module "shell_session_logs_bucket" {
source = "./modules/s3bucket"
bucket_prefix = "${var.namespace}-${var.stage}-shell-session-logs"
aws_account_id = data.aws_caller_identity.current.account_id
region = var.aws_region
namespace = var.namespace
stage = var.stage
component = "shell-session-logs"
cors_rules = [{
allowed_methods = ["GET", "PUT", "POST"]
allowed_origins = [var.app_url]
allowed_headers = ["Authorization", "Content-Type"]
expose_headers = ["ETag"]
max_age_seconds = 3000
}]
}

module "web" {
source = "./modules/web"
namespace = var.namespace
stage = var.stage
aws_region = var.aws_region
aws_account_id = data.aws_caller_identity.current.account_id
release_tag = var.release_tag
subnet_ids = local.private_subnet_ids
vpc_id = local.vpc_id
auth_authority_url = module.cognito.auth_authority_url
auth_cli_client_id = module.cognito.cli_client_id
auth_url = module.cognito.auth_url
auth_web_client_id = module.cognito.web_client_id
ecs_cluster_id = local.ecs_cluster_id
alb_listener_arn = module.alb.listener_arn
app_url = var.app_url
auth_issuer = module.cognito.auth_issuer
alb_security_group_id = module.alb.alb_security_group_id
web_image_repository = var.web_image_repository
centralised_support = var.centralised_support
web_target_group_arns = var.web_target_group_arns
iam_role_permission_boundary = var.iam_role_permission_boundary
source = "./modules/web"
namespace = var.namespace
stage = var.stage
aws_region = var.aws_region
aws_account_id = data.aws_caller_identity.current.account_id
release_tag = var.release_tag
subnet_ids = local.private_subnet_ids
vpc_id = local.vpc_id
auth_authority_url = module.cognito.auth_authority_url
auth_cli_client_id = module.cognito.cli_client_id
auth_url = module.cognito.auth_url
auth_web_client_id = module.cognito.web_client_id
ecs_cluster_id = local.ecs_cluster_id
alb_listener_arn = module.alb.listener_arn
app_url = var.app_url
auth_issuer = module.cognito.auth_issuer
alb_security_group_id = module.alb.alb_security_group_id
web_image_repository = var.web_image_repository
centralised_support = var.centralised_support
web_target_group_arns = var.web_target_group_arns
iam_role_permission_boundary = var.iam_role_permission_boundary
shell_session_logs_bucket_domain_name = module.shell_session_logs_bucket.bucket_regional_domain_name
}


Expand Down Expand Up @@ -329,6 +349,8 @@ module "access_handler" {
access_target_group_arns = var.access_target_group_arns
builtin_provisioner_url = module.provisioner.provisioner_url
iam_role_permission_boundary = var.iam_role_permission_boundary
shell_session_logs_bucket_arn = module.shell_session_logs_bucket.arn
shell_session_logs_bucket_name = module.shell_session_logs_bucket.id
}


Expand Down Expand Up @@ -370,3 +392,4 @@ module "authz-legacy" {
namespace = var.namespace
stage = var.stage
}

36 changes: 36 additions & 0 deletions modules/access/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,34 @@ resource "aws_iam_role_policy_attachment" "eval_bucket_attach" {
role = aws_iam_role.access_handler_ecs_task_role.name
policy_arn = aws_iam_policy.authz_eval_bucket.arn
}
resource "aws_iam_policy" "shell_logs_s3_write_access" {
name = "${var.namespace}-${var.stage}-access-handler-shell-logs-bucket"
description = "Allows access handler to read objects from the shell session s3 bucket"

policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
"Sid" : "ListObjectsInBucket",
"Effect" : "Allow",
"Action" : ["s3:ListBucket"],
"Resource" : [var.shell_session_logs_bucket_arn]
},
{
"Sid" : "AllObjectActions",
"Effect" : "Allow",
"Action" : ["s3:GetObject"],
"Resource" : ["${var.shell_session_logs_bucket_arn}/*"]
}
]
})
}


resource "aws_iam_role_policy_attachment" "control_plane_shell_session_logs_bucket_attach" {
role = aws_iam_role.access_handler_ecs_task_role.name
policy_arn = aws_iam_policy.shell_logs_s3_write_access.arn
}

resource "aws_ecs_task_definition" "access_handler_task" {
family = "${var.namespace}-${var.stage}-access-handler"
Expand Down Expand Up @@ -312,6 +340,14 @@ resource "aws_ecs_task_definition" "access_handler_task" {
name = "CF_BUILTIN_WEBHOOK_PROVISIONER_URL",
value = var.builtin_provisioner_url
},
{
name = "CF_SHELL_SESSION_SINK_AWS_S3_BUCKET",
value = var.shell_session_logs_bucket_name
},
{
name = "CF_SHELL_SESSION_SINK_TYPE",
value = "aws"
}
],
secrets = [
{
Expand Down
9 changes: 9 additions & 0 deletions modules/access/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,12 @@ variable "iam_role_permission_boundary" {
nullable = true
default = null
}
variable "shell_session_logs_bucket_name" {
type = string
description = "Name of shell session logs bucket"
}

variable "shell_session_logs_bucket_arn" {
type = string
description = "ARN of shell session logs bucket"
}
36 changes: 34 additions & 2 deletions modules/controlplane/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,34 @@ resource "aws_iam_role_policy_attachment" "control_plane_authz_eval_bucket_attac
policy_arn = aws_iam_policy.authz_eval_bucket.arn
}

resource "aws_iam_policy" "shell_logs_s3_write_access" {
name = "${var.namespace}-${var.stage}-control-plane-shell-logs-bucket"
description = "Allows control plane to read and write objects into the shell session s3 bucket"

policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
"Sid" : "ListObjectsInBucket",
"Effect" : "Allow",
"Action" : ["s3:ListBucket"],
"Resource" : [var.shell_session_logs_bucket_arn]
},
{
"Sid" : "AllObjectActions",
"Effect" : "Allow",
"Action" : ["s3:PutObject", "s3:GetObject"],
"Resource" : ["${var.shell_session_logs_bucket_arn}/*"]
}
]
})
}


resource "aws_iam_role_policy_attachment" "control_plane_shell_session_logs_bucket_attach" {
role = aws_iam_role.control_plane_ecs_task_role.name
policy_arn = aws_iam_policy.shell_logs_s3_write_access.arn
}


resource "aws_iam_policy" "eventbus_put_events" {
Expand Down Expand Up @@ -691,8 +719,12 @@ locals {
value = var.managed_deployment ? "true" : "false"
},
{
name = "CF_COMPARE_ENTITLEMENTS_ENABLED",
value = var.compare_entitlements_enabled ? "true" : "false"
name = "CF_SHELL_SESSION_SINK_AWS_S3_BUCKET",
value = var.shell_session_logs_bucket_name
},
{
name = "CF_SHELL_SESSION_SINK_TYPE",
value = "aws"
}
]

Expand Down
7 changes: 6 additions & 1 deletion modules/controlplane/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ output "worker_security_group_id" {

output "control_plane_tg_arn_suffix" {
description = "The arn suffix of the control plane target group"
value = aws_lb_target_group.control_plane_tg.arn_suffix
value = aws_lb_target_group.control_plane_tg.arn_suffix
}

output "task_role_name" {
description = "The Name of the IAM role assumed by the task"
value = aws_iam_role.control_plane_ecs_task_role.name
}
9 changes: 9 additions & 0 deletions modules/controlplane/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,12 @@ variable "iam_role_permission_boundary" {
nullable = true
default = null
}
variable "shell_session_logs_bucket_name" {
type = string
description = "Name of shell session logs bucket"
}

variable "shell_session_logs_bucket_arn" {
type = string
description = "ARN of shell session logs bucket"
}
17 changes: 17 additions & 0 deletions modules/s3bucket/s3_bucket_cors_configuration.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "aws_s3_bucket_cors_configuration" "main" {
count = var.cors_rules != null ? 1 : 0
bucket = aws_s3_bucket.main.id


dynamic "cors_rule" {
for_each = var.cors_rules
content {
allowed_headers = lookup(cors_rule.value, "allowed_headers", null)
allowed_methods = cors_rule.value.allowed_methods
allowed_origins = cors_rule.value.allowed_origins
expose_headers = lookup(cors_rule.value, "expose_headers", null)
max_age_seconds = lookup(cors_rule.value, "max_age_seconds", null)
id = lookup(cors_rule.value, "id", null)
}
}
}
15 changes: 15 additions & 0 deletions modules/s3bucket/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,18 @@ variable "object_ownership" {
description = "Ownership of objects written to the bucket"
default = "BucketOwnerEnforced"
}


variable "cors_rules" {
type = list(object({
id = optional(string)
allowed_headers = optional(list(string))
allowed_methods = list(string)
allowed_origins = list(string)
expose_headers = optional(list(string))
max_age_seconds = optional(number)
}))

description = "list of cors_rules rules of the bucket"
default = null
}
5 changes: 5 additions & 0 deletions modules/web/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ resource "aws_ecs_task_definition" "web_task" {
name = "CF_HIERARCHY_UI",
value = "true"
},
{
name = "CF_SESSION_LOGS_S3_URL",
value = "https://${var.shell_session_logs_bucket_domain_name}/"
},

]

logConfiguration = {
Expand Down
5 changes: 5 additions & 0 deletions modules/web/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,8 @@ variable "iam_role_permission_boundary" {
nullable = true
default = null
}

variable "shell_session_logs_bucket_domain_name" {
type = string
description = "Domain name of shell session logs bucket"
}
2 changes: 2 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -503,3 +503,5 @@ variable "iam_role_permission_boundary" {
nullable = true
default = null
}


0 comments on commit 7eb80b9

Please sign in to comment.