Skip to content

Commit

Permalink
terraform, aws: bucket_readonly_access added
Browse files Browse the repository at this point in the history
  • Loading branch information
consideRatio committed Apr 11, 2024
1 parent 38e597d commit d218030
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 59 deletions.
59 changes: 59 additions & 0 deletions terraform/aws/bucket-access.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
locals {
# Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/
hub_role_bucket = flatten([
for hub, hub_value in var.hub_cloud_permissions : [
for role, role_value in hub_value : flatten([
[
for bucket in role_value.bucket_admin_access : {
// id can be simplified, it was set to not change anything
id = role == "user-sa" ? "${hub}.${bucket}" : "${hub}.${role}.${bucket}.admin"
// role should match the id set in irsa.tf
role = role == "user-sa" ? hub : "${hub}-${role}"
bucket = bucket
actions = ["s3:*"]
}
],
[
for bucket in role_value.bucket_readonly_access : {
id = "${hub}.${role}.${bucket}.readonly"
// role should match the id set in irsa.tf
role = role == "user-sa" ? hub : "${hub}-${role}"
bucket = bucket
actions = [
"s3:ListBucket",
"s3:GetObject",
"s3:GetObjectVersion",
]
}
]
])
]
])
}

// FIXME: there can only be one declared per bucket, so if we have multiple
// roles that has permissions, we need to merge them
data "aws_iam_policy_document" "bucket_admin_access" {
for_each = { for index, hrb in local.hub_role_bucket : hrb.id => hrb }
statement {
effect = "Allow"
actions = each.value.actions
principals {
type = "AWS"
identifiers = [
aws_iam_role.irsa_role[each.value.role].arn
]
}
resources = [
# Grant access only to the bucket and its contents
aws_s3_bucket.user_buckets[each.value.bucket].arn,
"${aws_s3_bucket.user_buckets[each.value.bucket].arn}/*",
]
}
}

resource "aws_s3_bucket_policy" "user_bucket_access" {
for_each = { for index, hrb in local.hub_role_bucket : hrb.id => hrb }
bucket = aws_s3_bucket.user_buckets[each.value.bucket].id
policy = data.aws_iam_policy_document.bucket_admin_access[each.key].json
}
37 changes: 0 additions & 37 deletions terraform/aws/bucket-admin-access.tf

This file was deleted.

42 changes: 29 additions & 13 deletions terraform/aws/irsa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,25 @@ data "aws_partition" "current" {}



// TODO: update to loop over hub and role
locals {
hub_role = flatten([
for hub, hub_value in var.hub_cloud_permissions : [
for role, role_value in hub_value : {
// id is conservatively adjusted to not change any previous resource
// name set to the hub's name when only "user-sa" roles were around
id = role == "user-sa" ? hub : "${hub}-${role}"
hub = hub
role = role
data = role_value
}
]
])
}



data "aws_iam_policy_document" "irsa_role_assume" {
for_each = var.hub_cloud_permissions
for_each = { for index, hr in local.hub_role : hr.id => hr }
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
Expand All @@ -30,31 +46,31 @@ data "aws_iam_policy_document" "irsa_role_assume" {
test = "StringEquals"
variable = "${replace(data.aws_eks_cluster.cluster.identity[0].oidc[0].issuer, "https://", "")}:sub"
values = [
"system:serviceaccount:${each.key}:user-sa"
"system:serviceaccount:${each.value.hub}:${each.value.role}"
]
}
}
}

// TODO: update to loop over hub and role
resource "aws_iam_role" "irsa_role" {
for_each = var.hub_cloud_permissions
for_each = { for index, hr in local.hub_role : hr.id => hr }
name = "${var.cluster_name}-${each.key}"

assume_role_policy = data.aws_iam_policy_document.irsa_role_assume[each.key].json
}

// TODO: update to loop over hub and role


resource "aws_iam_policy" "extra_user_policy" {
for_each = { for hub_name, value in var.hub_cloud_permissions : hub_name => value if value.extra_iam_policy != "" }
name = "${var.cluster_name}-${each.key}-extra-user-policy"
for_each = { for index, hr in local.hub_role : hr.id => hr if hr.data.extra_iam_policy != "" }
name = "${var.cluster_name}-${each.key}-extra-user-policy"

description = "Extra permissions granted to users on hub ${each.key} on ${var.cluster_name}"
policy = each.value.extra_iam_policy
policy = each.value.data.extra_iam_policy
}

// TODO: update to loop over hub and role
resource "aws_iam_role_policy_attachment" "extra_user_policy" {
for_each = { for hub_name, value in var.hub_cloud_permissions : hub_name => value if value.extra_iam_policy != "" }
for_each = { for index, hr in local.hub_role : hr.id => hr if hr.data.extra_iam_policy != "" }
role = aws_iam_role.irsa_role[each.key].name
policy_arn = aws_iam_policy.extra_user_policy[each.key].arn
}
Expand All @@ -63,8 +79,8 @@ resource "aws_iam_role_policy_attachment" "extra_user_policy" {

output "kubernetes_sa_annotations" {
value = {
for k, v in var.hub_cloud_permissions :
k => "eks.amazonaws.com/role-arn: ${aws_iam_role.irsa_role[k].arn}"
for index, hr in local.hub_role :
hr.id => "eks.amazonaws.com/role-arn: ${aws_iam_role.irsa_role[hr.id].arn}"
}
description = <<-EOT
Annotations to apply to userServiceAccount in each hub to enable cloud permissions for them.
Expand Down
25 changes: 16 additions & 9 deletions terraform/aws/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,27 @@ variable "user_buckets" {
}

variable "hub_cloud_permissions" {
type = map(object({
bucket_admin_access : set(string),
extra_iam_policy : string
}))
type = map(
map(
object({
bucket_admin_access : optional(set(string), [])
bucket_readonly_access : optional(set(string), [])
extra_iam_policy : optional(string, "")
})
)
)
default = {}
description = <<-EOT
Map of cloud permissions given to a particular hub
Map of cloud permissions given to a particular hub (k8s namespace) and
its associated IAM Role's that are 1:1 with k8s ServiceAccounts.
Key is name of the hub namespace in the cluster, and values are particular
permissions users running on those hubs should have. Currently supported are:
Currently supported are:
1. bucket_admin_access: List of S3 storage buckets that users on this hub should have read
1. bucket_admin_access: List of S3 storage buckets that the associated aws-iam-role/k8s-service-account should have read
and write permissions for.
2. extra_iam_policy: An AWS IAM Policy document that grants additional rights to the users
2. bucket_readonly_access: List of S3 storage buckets that users on this hub should have read
permissions for.
3. extra_iam_policy: An AWS IAM Policy document that grants additional rights to the users
on this hub when talking to AWS services.
EOT
}
Expand Down

0 comments on commit d218030

Please sign in to comment.