From e6fdaf0a60aa0ca672de6a53860f6927a7da127a Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Wed, 10 Apr 2024 22:27:17 +0200 Subject: [PATCH 01/18] terraform, aws: prepare to support user-sa and admin-sa roles --- terraform/aws/bucket-admin-access.tf | 37 ++++++++++++++++++++++++++ terraform/aws/buckets.tf | 39 ---------------------------- terraform/aws/irsa.tf | 32 ++++++++++++++++------- 3 files changed, 60 insertions(+), 48 deletions(-) create mode 100644 terraform/aws/bucket-admin-access.tf diff --git a/terraform/aws/bucket-admin-access.tf b/terraform/aws/bucket-admin-access.tf new file mode 100644 index 0000000000..5abec706c1 --- /dev/null +++ b/terraform/aws/bucket-admin-access.tf @@ -0,0 +1,37 @@ +locals { + # Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/ + bucket_permissions = distinct(flatten([ + for hub_name, permissions in var.hub_cloud_permissions : [ + for bucket_name in permissions.bucket_admin_access : { + hub_name = hub_name + bucket_name = bucket_name + } + ] + ])) +} + +// TODO: update to loop over hub, role +data "aws_iam_policy_document" "bucket_admin_access" { + for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } + statement { + effect = "Allow" + actions = ["s3:*"] + principals { + type = "AWS" + identifiers = [ + aws_iam_role.irsa_role[each.value.hub_name].arn + ] + } + resources = [ + # Grant access only to the bucket and its contents + aws_s3_bucket.user_buckets[each.value.bucket_name].arn, + "${aws_s3_bucket.user_buckets[each.value.bucket_name].arn}/*" + ] + } +} + +resource "aws_s3_bucket_policy" "user_bucket_access" { + for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } + bucket = aws_s3_bucket.user_buckets[each.value.bucket_name].id + policy = data.aws_iam_policy_document.bucket_admin_access[each.key].json +} diff --git a/terraform/aws/buckets.tf b/terraform/aws/buckets.tf index 2b1c7244d5..6d17c45229 100644 --- a/terraform/aws/buckets.tf +++ b/terraform/aws/buckets.tf @@ -1,7 +1,6 @@ resource "aws_s3_bucket" "user_buckets" { for_each = var.user_buckets bucket = lower("${var.cluster_name}-${each.key}") - } resource "aws_s3_bucket_lifecycle_configuration" "user_bucket_expiry" { @@ -36,44 +35,6 @@ resource "aws_s3_bucket_lifecycle_configuration" "user_bucket_expiry" { } } -locals { - # Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/ - bucket_permissions = distinct(flatten([ - for hub_name, permissions in var.hub_cloud_permissions : [ - for bucket_name in permissions.bucket_admin_access : { - hub_name = hub_name - bucket_name = bucket_name - } - ] - ])) -} - -data "aws_iam_policy_document" "bucket_access" { - for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } - statement { - effect = "Allow" - actions = ["s3:*"] - principals { - type = "AWS" - identifiers = [ - aws_iam_role.irsa_role[each.value.hub_name].arn - ] - } - resources = [ - # Grant access only to the bucket and its contents - aws_s3_bucket.user_buckets[each.value.bucket_name].arn, - "${aws_s3_bucket.user_buckets[each.value.bucket_name].arn}/*" - ] - } -} - -resource "aws_s3_bucket_policy" "user_bucket_access" { - - for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } - bucket = aws_s3_bucket.user_buckets[each.value.bucket_name].id - policy = data.aws_iam_policy_document.bucket_access[each.key].json -} - output "buckets" { value = { for b, _ in var.user_buckets : b => aws_s3_bucket.user_buckets[b].id } description = <<-EOT diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index c79f09b17d..e142c37291 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -1,20 +1,22 @@ -data "aws_caller_identity" "current" {} +/* + This file provides resources _per hub and role_. Each role is tied to a + specific k8s ServiceAccount allowed to assume the role. + + - Role - for use by k8s ServiceAccount (user-sa, admin-sa) + - Policy - if extra_iam_policy is declared + - RolePolicyAttachment - if extra_iam_policy is declared +*/ +data "aws_caller_identity" "current" {} data "aws_partition" "current" {} -resource "aws_iam_role" "irsa_role" { - for_each = var.hub_cloud_permissions - 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 data "aws_iam_policy_document" "irsa_role_assume" { for_each = var.hub_cloud_permissions statement { - - effect = "Allow" - + effect = "Allow" actions = ["sts:AssumeRoleWithWebIdentity"] principals { @@ -34,6 +36,15 @@ data "aws_iam_policy_document" "irsa_role_assume" { } } +// TODO: update to loop over hub and role +resource "aws_iam_role" "irsa_role" { + for_each = var.hub_cloud_permissions + 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" @@ -41,12 +52,15 @@ resource "aws_iam_policy" "extra_user_policy" { policy = each.value.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 != "" } role = aws_iam_role.irsa_role[each.key].name policy_arn = aws_iam_policy.extra_user_policy[each.key].arn } + + output "kubernetes_sa_annotations" { value = { for k, v in var.hub_cloud_permissions : From 8fd5d3d5bd3d2f0435ac76c82c3737e7b23fc770 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Thu, 11 Apr 2024 00:20:04 +0200 Subject: [PATCH 02/18] terraform, aws: migrate hub_cloud_permissions to declare role explicitly --- terraform/aws/projects/2i2c-aws-us.tfvars | 42 +-- terraform/aws/projects/bican.tfvars | 14 +- .../projects/catalystproject-africa.tfvars | 14 +- terraform/aws/projects/dandi.tfvars | 15 +- terraform/aws/projects/earthscope.tfvars | 14 +- terraform/aws/projects/gridsst.tfvars | 14 +- terraform/aws/projects/jupyter-health.tfvars | 14 +- .../projects/jupyter-meets-the-earth.tfvars | 20 +- terraform/aws/projects/kitware.tfvars | 23 +- terraform/aws/projects/linc.tfvars | 12 +- terraform/aws/projects/nasa-cryo.tfvars | 132 +++++----- terraform/aws/projects/nasa-esdis.tfvars | 124 ++++----- terraform/aws/projects/nasa-ghg.tfvars | 200 ++++++++------- terraform/aws/projects/nasa-veda.tfvars | 240 +++++++++--------- terraform/aws/projects/openscapes.tfvars | 24 +- terraform/aws/projects/smithsonian.tfvars | 12 +- terraform/aws/projects/template.tfvars | 6 +- terraform/aws/projects/ubc-eoas.tfvars | 14 +- terraform/aws/projects/victor.tfvars | 14 +- 19 files changed, 511 insertions(+), 437 deletions(-) diff --git a/terraform/aws/projects/2i2c-aws-us.tfvars b/terraform/aws/projects/2i2c-aws-us.tfvars index a9a3a0cf3d..d360c4a278 100644 --- a/terraform/aws/projects/2i2c-aws-us.tfvars +++ b/terraform/aws/projects/2i2c-aws-us.tfvars @@ -31,30 +31,42 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "dask-staging" : { - bucket_admin_access : ["scratch-dask-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-dask-staging"], + extra_iam_policy : "", + }, }, "showcase" : { - bucket_admin_access : [ - "scratch-researchdelight", - "persistent-showcase" - ], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : [ + "scratch-researchdelight", + "persistent-showcase", + ], + extra_iam_policy : "", + }, }, "ncar-cisl" : { - bucket_admin_access : ["scratch-ncar-cisl"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-ncar-cisl"], + extra_iam_policy : "", + }, }, "go-bgc" : { - bucket_admin_access : ["scratch-go-bgc"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-go-bgc"], + extra_iam_policy : "", + }, }, "itcoocean" : { - bucket_admin_access : ["scratch-itcoocean"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-itcoocean"], + extra_iam_policy : "", + }, }, } diff --git a/terraform/aws/projects/bican.tfvars b/terraform/aws/projects/bican.tfvars index 0b0c92785b..b4ec1f3a4e 100644 --- a/terraform/aws/projects/bican.tfvars +++ b/terraform/aws/projects/bican.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/catalystproject-africa.tfvars b/terraform/aws/projects/catalystproject-africa.tfvars index 728f18a381..7dd5753aeb 100644 --- a/terraform/aws/projects/catalystproject-africa.tfvars +++ b/terraform/aws/projects/catalystproject-africa.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/dandi.tfvars b/terraform/aws/projects/dandi.tfvars index a66677c70b..e33f0bd3a0 100644 --- a/terraform/aws/projects/dandi.tfvars +++ b/terraform/aws/projects/dandi.tfvars @@ -13,13 +13,18 @@ user_buckets = { }, } + hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/earthscope.tfvars b/terraform/aws/projects/earthscope.tfvars index 688977269b..ef80ccc156 100644 --- a/terraform/aws/projects/earthscope.tfvars +++ b/terraform/aws/projects/earthscope.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/gridsst.tfvars b/terraform/aws/projects/gridsst.tfvars index 74680c5fcd..b995159683 100644 --- a/terraform/aws/projects/gridsst.tfvars +++ b/terraform/aws/projects/gridsst.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/jupyter-health.tfvars b/terraform/aws/projects/jupyter-health.tfvars index b0a8c30d2f..a273ce3b98 100644 --- a/terraform/aws/projects/jupyter-health.tfvars +++ b/terraform/aws/projects/jupyter-health.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/jupyter-meets-the-earth.tfvars b/terraform/aws/projects/jupyter-meets-the-earth.tfvars index 73a5a38797..4781c8f7e3 100644 --- a/terraform/aws/projects/jupyter-meets-the-earth.tfvars +++ b/terraform/aws/projects/jupyter-meets-the-earth.tfvars @@ -16,10 +16,11 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - # FIXME: Previously, users were granted full S3 permissions. - # Keep it the same for now - extra_iam_policy : <<-EOT + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + # FIXME: Previously, users were granted full S3 permissions. + # Keep it the same for now + extra_iam_policy : <<-EOT { "Version": "2012-10-17", "Statement": [ @@ -31,12 +32,14 @@ hub_cloud_permissions = { ] } EOT + }, }, "prod" : { - bucket_admin_access : ["scratch"], - # FIXME: Previously, users were granted full S3 permissions. - # Keep it the same for now - extra_iam_policy : <<-EOT + "user-sa" : { + bucket_admin_access : ["scratch"], + # FIXME: Previously, users were granted full S3 permissions. + # Keep it the same for now + extra_iam_policy : <<-EOT { "Version": "2012-10-17", "Statement": [ @@ -48,5 +51,6 @@ EOT ] } EOT + }, }, } diff --git a/terraform/aws/projects/kitware.tfvars b/terraform/aws/projects/kitware.tfvars index 128ba71b22..54cc305028 100644 --- a/terraform/aws/projects/kitware.tfvars +++ b/terraform/aws/projects/kitware.tfvars @@ -1,18 +1,9 @@ -/* - Some of the assumptions this template makes about the cluster: - - location of the nodes of the kubernetes cluster will be a - - no default scratch buckets support -*/ - region = "us-west-2" cluster_name = "kitware" cluster_nodes_location = "us-west-2a" -# Tip: uncomment and fill the missing info in the lines below if you want -# to setup scratch buckets for the hubs on this cluster. -# user_buckets = { "scratch-staging" : { "delete_after" : 7 @@ -24,11 +15,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/linc.tfvars b/terraform/aws/projects/linc.tfvars index d3d934c5fb..0bd1caaa37 100644 --- a/terraform/aws/projects/linc.tfvars +++ b/terraform/aws/projects/linc.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, } diff --git a/terraform/aws/projects/nasa-cryo.tfvars b/terraform/aws/projects/nasa-cryo.tfvars index 72197c009d..1cbe601377 100644 --- a/terraform/aws/projects/nasa-cryo.tfvars +++ b/terraform/aws/projects/nasa-cryo.tfvars @@ -22,71 +22,75 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging", "persistent-staging"], - # Provides readonly requestor-pays access to usgs-landsat bucket - # FIXME: We should find a way to allow access to *all* requester pays - # buckets, without having to explicitly list them. However, we don't want - # to give access to all *internal* s3 buckets willy-nilly - this can be - # a massive security hole, especially if terraform state is also here. - # As a temporary measure, we allow-list buckets here. - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:*" - ], - "Resource": [ - "arn:aws:s3:::usgs-landsat" - ] - }, - { - "Effect": "Allow", - "Action": [ - "s3:*" - ], - "Resource": [ - "arn:aws:s3:::usgs-landsat/*" - ] - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch-staging", "persistent-staging"], + # Provides readonly requestor-pays access to usgs-landsat bucket + # FIXME: We should find a way to allow access to *all* requester pays + # buckets, without having to explicitly list them. However, we don't want + # to give access to all *internal* s3 buckets willy-nilly - this can be + # a massive security hole, especially if terraform state is also here. + # As a temporary measure, we allow-list buckets here. + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::usgs-landsat" + ] + }, + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::usgs-landsat/*" + ] + } + ] + } + EOT + }, }, "prod" : { - bucket_admin_access : ["scratch", "persistent"], - # Provides readonly requestor-pays access to usgs-landsat bucket - # FIXME: We should find a way to allow access to *all* requester pays - # buckets, without having to explicitly list them. However, we don't want - # to give access to all *internal* s3 buckets willy-nilly - this can be - # a massive security hole, especially if terraform state is also here. - # As a temporary measure, we allow-list buckets here. - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:*" - ], - "Resource": [ - "arn:aws:s3:::usgs-landsat" - ] - }, - { - "Effect": "Allow", - "Action": [ - "s3:*" - ], - "Resource": [ - "arn:aws:s3:::usgs-landsat/*" - ] - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch", "persistent"], + # Provides readonly requestor-pays access to usgs-landsat bucket + # FIXME: We should find a way to allow access to *all* requester pays + # buckets, without having to explicitly list them. However, we don't want + # to give access to all *internal* s3 buckets willy-nilly - this can be + # a massive security hole, especially if terraform state is also here. + # As a temporary measure, we allow-list buckets here. + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::usgs-landsat" + ] + }, + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::usgs-landsat/*" + ] + } + ] + } + EOT + }, }, } diff --git a/terraform/aws/projects/nasa-esdis.tfvars b/terraform/aws/projects/nasa-esdis.tfvars index 9beb0b55cb..dcfcf24d0c 100644 --- a/terraform/aws/projects/nasa-esdis.tfvars +++ b/terraform/aws/projects/nasa-esdis.tfvars @@ -16,67 +16,71 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::grss-veda-data-store", - "arn:aws:s3:::grss-veda-data-store/*", - "arn:aws:s3:::sentinel-cogs", - "arn:aws:s3:::sentinel-cogs/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::grss-veda-data-store", + "arn:aws:s3:::grss-veda-data-store/*", + "arn:aws:s3:::sentinel-cogs", + "arn:aws:s3:::sentinel-cogs/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] + } + EOT + }, }, } diff --git a/terraform/aws/projects/nasa-ghg.tfvars b/terraform/aws/projects/nasa-ghg.tfvars index 831205b98e..bdb5418caf 100644 --- a/terraform/aws/projects/nasa-ghg.tfvars +++ b/terraform/aws/projects/nasa-ghg.tfvars @@ -16,105 +16,109 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::ghgc-data-staging", - "arn:aws:s3:::ghgc-data-staging/*", - "arn:aws:s3:::ghgc-data-store-dev", - "arn:aws:s3:::ghgc-data-store-dev/*", - "arn:aws:s3:::ghgc-data-store", - "arn:aws:s3:::ghgc-data-store/*", - "arn:aws:s3:::ghgc-data-store-staging", - "arn:aws:s3:::ghgc-data-store-staging/*", - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::ghgc-data-staging", + "arn:aws:s3:::ghgc-data-staging/*", + "arn:aws:s3:::ghgc-data-store-dev", + "arn:aws:s3:::ghgc-data-store-dev/*", + "arn:aws:s3:::ghgc-data-store", + "arn:aws:s3:::ghgc-data-store/*", + "arn:aws:s3:::ghgc-data-store-staging", + "arn:aws:s3:::ghgc-data-store-staging/*", + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] + } + EOT + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::ghgc-data-staging", - "arn:aws:s3:::ghgc-data-staging/*", - "arn:aws:s3:::ghgc-data-store-dev", - "arn:aws:s3:::ghgc-data-store-dev/*", - "arn:aws:s3:::ghgc-data-store", - "arn:aws:s3:::ghgc-data-store/*", - "arn:aws:s3:::ghgc-data-store-staging", - "arn:aws:s3:::ghgc-data-store-staging/*", - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::ghgc-data-staging", + "arn:aws:s3:::ghgc-data-staging/*", + "arn:aws:s3:::ghgc-data-store-dev", + "arn:aws:s3:::ghgc-data-store-dev/*", + "arn:aws:s3:::ghgc-data-store", + "arn:aws:s3:::ghgc-data-store/*", + "arn:aws:s3:::ghgc-data-store-staging", + "arn:aws:s3:::ghgc-data-store-staging/*", + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] + } + EOT + }, }, } diff --git a/terraform/aws/projects/nasa-veda.tfvars b/terraform/aws/projects/nasa-veda.tfvars index fae2cfff2f..a414b0f1d2 100644 --- a/terraform/aws/projects/nasa-veda.tfvars +++ b/terraform/aws/projects/nasa-veda.tfvars @@ -16,125 +16,129 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::sdap-dev-zarr", - "arn:aws:s3:::sdap-dev-zarr/*", - "arn:aws:s3:::usgs-landsat", - "arn:aws:s3:::usgs-landsat/*", - "arn:aws:s3:::sentinel-cogs", - "arn:aws:s3:::sentinel-cogs/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::sdap-dev-zarr", + "arn:aws:s3:::sdap-dev-zarr/*", + "arn:aws:s3:::usgs-landsat", + "arn:aws:s3:::usgs-landsat/*", + "arn:aws:s3:::sentinel-cogs", + "arn:aws:s3:::sentinel-cogs/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] + } + EOT + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : <<-EOT - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::sdap-dev-zarr", - "arn:aws:s3:::sdap-dev-zarr/*", - "arn:aws:s3:::usgs-landsat", - "arn:aws:s3:::usgs-landsat/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } - ] - } - EOT + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : <<-EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::sdap-dev-zarr", + "arn:aws:s3:::sdap-dev-zarr/*", + "arn:aws:s3:::usgs-landsat", + "arn:aws:s3:::usgs-landsat/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] + } + EOT + }, }, } diff --git a/terraform/aws/projects/openscapes.tfvars b/terraform/aws/projects/openscapes.tfvars index e1f9b5dc44..a24be639c8 100644 --- a/terraform/aws/projects/openscapes.tfvars +++ b/terraform/aws/projects/openscapes.tfvars @@ -25,17 +25,21 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : [ - "scratch-staging", - "persistent-staging" - ], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : [ + "scratch-staging", + "persistent-staging", + ], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : [ - "scratch", - "persistent" - ], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : [ + "scratch", + "persistent", + ], + extra_iam_policy : "", + } }, } diff --git a/terraform/aws/projects/smithsonian.tfvars b/terraform/aws/projects/smithsonian.tfvars index 1ec655e8e7..8bbf537938 100644 --- a/terraform/aws/projects/smithsonian.tfvars +++ b/terraform/aws/projects/smithsonian.tfvars @@ -13,11 +13,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, } diff --git a/terraform/aws/projects/template.tfvars b/terraform/aws/projects/template.tfvars index cc953250a0..64a41ea476 100644 --- a/terraform/aws/projects/template.tfvars +++ b/terraform/aws/projects/template.tfvars @@ -25,8 +25,10 @@ cluster_nodes_location = "{{ cluster_region }}a" # #hub_cloud_permissions = { # "{{ hub_name }}" : { -# bucket_admin_access : ["scratch-{{ hub_name }}"], -# extra_iam_policy : "" +# "user-sa" : { +# bucket_admin_access : ["scratch-{{ hub_name }}"], +# extra_iam_policy : "", +# }, # }, # # Tip: add more namespaces below, if this cluster will be multi-tenant #} diff --git a/terraform/aws/projects/ubc-eoas.tfvars b/terraform/aws/projects/ubc-eoas.tfvars index f38abdf057..ecb02e5a43 100644 --- a/terraform/aws/projects/ubc-eoas.tfvars +++ b/terraform/aws/projects/ubc-eoas.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} diff --git a/terraform/aws/projects/victor.tfvars b/terraform/aws/projects/victor.tfvars index f6237fe892..1c22c00cca 100644 --- a/terraform/aws/projects/victor.tfvars +++ b/terraform/aws/projects/victor.tfvars @@ -16,11 +16,15 @@ user_buckets = { hub_cloud_permissions = { "staging" : { - bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch-staging"], + extra_iam_policy : "", + }, }, "prod" : { - bucket_admin_access : ["scratch"], - extra_iam_policy : "" + "user-sa" : { + bucket_admin_access : ["scratch"], + extra_iam_policy : "", + }, }, -} \ No newline at end of file +} From 5bf16f152ce4416505da5a67c6bab5c7c2961e22 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Thu, 11 Apr 2024 01:53:01 +0200 Subject: [PATCH 03/18] terraform, aws: bucket_readonly_access added --- terraform/aws/bucket-access.tf | 59 ++++++++++++++++++++++++++++ terraform/aws/bucket-admin-access.tf | 37 ----------------- terraform/aws/irsa.tf | 42 ++++++++++++++------ terraform/aws/variables.tf | 25 +++++++----- 4 files changed, 104 insertions(+), 59 deletions(-) create mode 100644 terraform/aws/bucket-access.tf delete mode 100644 terraform/aws/bucket-admin-access.tf diff --git a/terraform/aws/bucket-access.tf b/terraform/aws/bucket-access.tf new file mode 100644 index 0000000000..5d2c5e5d16 --- /dev/null +++ b/terraform/aws/bucket-access.tf @@ -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 +} diff --git a/terraform/aws/bucket-admin-access.tf b/terraform/aws/bucket-admin-access.tf deleted file mode 100644 index 5abec706c1..0000000000 --- a/terraform/aws/bucket-admin-access.tf +++ /dev/null @@ -1,37 +0,0 @@ -locals { - # Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/ - bucket_permissions = distinct(flatten([ - for hub_name, permissions in var.hub_cloud_permissions : [ - for bucket_name in permissions.bucket_admin_access : { - hub_name = hub_name - bucket_name = bucket_name - } - ] - ])) -} - -// TODO: update to loop over hub, role -data "aws_iam_policy_document" "bucket_admin_access" { - for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } - statement { - effect = "Allow" - actions = ["s3:*"] - principals { - type = "AWS" - identifiers = [ - aws_iam_role.irsa_role[each.value.hub_name].arn - ] - } - resources = [ - # Grant access only to the bucket and its contents - aws_s3_bucket.user_buckets[each.value.bucket_name].arn, - "${aws_s3_bucket.user_buckets[each.value.bucket_name].arn}/*" - ] - } -} - -resource "aws_s3_bucket_policy" "user_bucket_access" { - for_each = { for bp in local.bucket_permissions : "${bp.hub_name}.${bp.bucket_name}" => bp } - bucket = aws_s3_bucket.user_buckets[each.value.bucket_name].id - policy = data.aws_iam_policy_document.bucket_admin_access[each.key].json -} diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index e142c37291..f37a0a12af 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -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"] @@ -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 } @@ -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. diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index 332a78ab5a..0e9c65a86b 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -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 } From fbd853a36e4c8776b0e4c9cbe3f5db3e3ccefab7 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Thu, 11 Apr 2024 03:35:00 +0200 Subject: [PATCH 04/18] terraform, aws: fix implementation no longer hardcoding `user-sa` role --- terraform/aws/bucket-access.tf | 142 ++++++++++++++++++++++++++------- 1 file changed, 114 insertions(+), 28 deletions(-) diff --git a/terraform/aws/bucket-access.tf b/terraform/aws/bucket-access.tf index 5d2c5e5d16..a9b17b8791 100644 --- a/terraform/aws/bucket-access.tf +++ b/terraform/aws/bucket-access.tf @@ -1,59 +1,145 @@ +/* + Creates one aws_s3_bucket_policy per bucket - there can't be more than one as + they otherwise replace each other when applied. + + The bucket policies grant bucket specific permissions to specific IAM Roles + based on them having `bucket_admin_access` or `bucket_readonly_access` + referencing the bucket via `var.hub_cloud_permissions`. +*/ + locals { - # Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/ - hub_role_bucket = flatten([ + /* + The bucket_role_actions local variable defined below is a list of objects + generated from `var.hub_cloud_permissions` roles and their respective + bucket_admin_access and bucket_readonly_access lists. + + If for example `var.hub_cloud_permissions` is: + + hub_cloud_permissions: + staging: + user-sa: + bucket_admin_access: [scratch-staging] + sciencecore: + user-sa: + bucket_admin_access: [scratch-sciencecore] + bucket_readonly_access: [persistent-sciencecore] + admin-sa: + bucket_admin_access: [scratch-sciencecore, persistent-sciencecore] + + Then, the `local.bucket_role_actions` will look like below, with one list + item for each element in all `bucket_admin/readonly_access` lists: + + bucket_role_actions: + - bucket: scratch-staging + role: staging + actions: ["s3:*"] + - bucket: scratch-sciencecore + role: sciencecore + actions: ["s3:*"] + - bucket: scratch-sciencecore + role: sciencecore-admin-sa + actions: ["s3:*"] + - bucket: persistent-sciencecore + role: sciencecore + actions: ["s3:ListBucket", "s3:GetObject", "s3:GetObjectVersion"] + - bucket: persistent-sciencecore + role: sciencecore + actions: ["s3:*"] + */ + bucket_role_actions = 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" + bucket = bucket // 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 + // role should match the id set in irsa.tf + role = role == "user-sa" ? hub : "${hub}-${role}" 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 +locals { + /* + The `local.bucket_role_actions_lists` variable defined below is reprocessing + `local.bucket_role_actions` to a dictionary with one key per bucket with + associated permissions. + + bucket_role_actions_lists: + scratch-staging: + - bucket: scratch-staging + role: staging + actions: ["s3:*"] + scratch-sciencecore: + - bucket: scratch-sciencecore + role: sciencecore + actions: ["s3:*"] + - bucket: scratch-sciencecore + role: sciencecore-admin-sa + actions: ["s3:*"] + persistent-sciencecore: + - bucket: persistent-sciencecore + role: sciencecore + actions: ["s3:ListBucket", "s3:GetObject", "s3:GetObjectVersion"] + - bucket: persistent-sciencecore + role: sciencecore + actions: ["s3:*"] + */ + bucket_role_actions_lists = { + for bucket, _ in var.user_buckets : + bucket => [for bra in local.bucket_role_actions : bra if bra.bucket == bucket] + // Filter out user_buckets not mentioned in hub_cloud_permissions + if length([for bra in local.bucket_role_actions : bra if bra.bucket == bucket]) != 0 + } +} + + + +data "aws_iam_policy_document" "bucket_policy" { + for_each = local.bucket_role_actions_lists + + // Only one policy document can be declared per bucket, so we provide multiple + // "statement" in this policy. + dynamic "statement" { + for_each = { for index, bra in each.value : "${bra.bucket}.${bra.role}" => bra } + + content { + effect = "Allow" + actions = statement.value.actions + principals { + type = "AWS" + identifiers = [ + aws_iam_role.irsa_role[statement.value.role].arn + ] + } + resources = [ + # Grant access only to the bucket and its contents + aws_s3_bucket.user_buckets[statement.value.bucket].arn, + "${aws_s3_bucket.user_buckets[statement.value.bucket].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}/*", - ] } } +// There can only be one of these per bucket, if more are defined they will end +// up replacing each other without terraform indicating there is trouble. 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 + for_each = local.bucket_role_actions_lists + bucket = aws_s3_bucket.user_buckets[each.key].id + policy = data.aws_iam_policy_document.bucket_policy[each.key].json } From a108ceeec5a785df7fe642832c0060e4da97603b Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 19 Apr 2024 15:51:20 +0200 Subject: [PATCH 05/18] terraform, aws: refactor iam policy indentation --- .../projects/jupyter-meets-the-earth.tfvars | 44 ++-- terraform/aws/projects/nasa-cryo.tfvars | 4 +- terraform/aws/projects/nasa-esdis.tfvars | 106 ++++----- terraform/aws/projects/nasa-ghg.tfvars | 176 +++++++------- terraform/aws/projects/nasa-veda.tfvars | 216 +++++++++--------- 5 files changed, 273 insertions(+), 273 deletions(-) diff --git a/terraform/aws/projects/jupyter-meets-the-earth.tfvars b/terraform/aws/projects/jupyter-meets-the-earth.tfvars index 4781c8f7e3..09b553e953 100644 --- a/terraform/aws/projects/jupyter-meets-the-earth.tfvars +++ b/terraform/aws/projects/jupyter-meets-the-earth.tfvars @@ -21,17 +21,17 @@ hub_cloud_permissions = { # FIXME: Previously, users were granted full S3 permissions. # Keep it the same for now extra_iam_policy : <<-EOT -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": ["s3:*"], - "Resource": ["arn:aws:s3:::*"] - } - ] -} -EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["s3:*"], + "Resource": ["arn:aws:s3:::*"] + } + ] + } + EOT }, }, "prod" : { @@ -40,17 +40,17 @@ EOT # FIXME: Previously, users were granted full S3 permissions. # Keep it the same for now extra_iam_policy : <<-EOT -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": ["s3:*"], - "Resource": ["arn:aws:s3:::*"] - } - ] -} -EOT + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["s3:*"], + "Resource": ["arn:aws:s3:::*"] + } + ] + } + EOT }, }, } diff --git a/terraform/aws/projects/nasa-cryo.tfvars b/terraform/aws/projects/nasa-cryo.tfvars index 1cbe601377..c58e9cbde6 100644 --- a/terraform/aws/projects/nasa-cryo.tfvars +++ b/terraform/aws/projects/nasa-cryo.tfvars @@ -54,7 +54,7 @@ hub_cloud_permissions = { } ] } - EOT + EOT }, }, "prod" : { @@ -90,7 +90,7 @@ hub_cloud_permissions = { } ] } - EOT + EOT }, }, } diff --git a/terraform/aws/projects/nasa-esdis.tfvars b/terraform/aws/projects/nasa-esdis.tfvars index dcfcf24d0c..803c412fa2 100644 --- a/terraform/aws/projects/nasa-esdis.tfvars +++ b/terraform/aws/projects/nasa-esdis.tfvars @@ -25,62 +25,62 @@ hub_cloud_permissions = { "user-sa" : { bucket_admin_access : ["scratch"], extra_iam_policy : <<-EOT - { + { "Version": "2012-10-17", "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::grss-veda-data-store", - "arn:aws:s3:::grss-veda-data-store/*", - "arn:aws:s3:::sentinel-cogs", - "arn:aws:s3:::sentinel-cogs/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::grss-veda-data-store", + "arn:aws:s3:::grss-veda-data-store/*", + "arn:aws:s3:::sentinel-cogs", + "arn:aws:s3:::sentinel-cogs/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } ] - } - EOT + } + EOT }, }, } diff --git a/terraform/aws/projects/nasa-ghg.tfvars b/terraform/aws/projects/nasa-ghg.tfvars index bdb5418caf..91482a309b 100644 --- a/terraform/aws/projects/nasa-ghg.tfvars +++ b/terraform/aws/projects/nasa-ghg.tfvars @@ -19,106 +19,106 @@ hub_cloud_permissions = { "user-sa" : { bucket_admin_access : ["scratch-staging"], extra_iam_policy : <<-EOT - { + { "Version": "2012-10-17", "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::ghgc-data-staging", - "arn:aws:s3:::ghgc-data-staging/*", - "arn:aws:s3:::ghgc-data-store-dev", - "arn:aws:s3:::ghgc-data-store-dev/*", - "arn:aws:s3:::ghgc-data-store", - "arn:aws:s3:::ghgc-data-store/*", - "arn:aws:s3:::ghgc-data-store-staging", - "arn:aws:s3:::ghgc-data-store-staging/*", - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::ghgc-data-staging", + "arn:aws:s3:::ghgc-data-staging/*", + "arn:aws:s3:::ghgc-data-store-dev", + "arn:aws:s3:::ghgc-data-store-dev/*", + "arn:aws:s3:::ghgc-data-store", + "arn:aws:s3:::ghgc-data-store/*", + "arn:aws:s3:::ghgc-data-store-staging", + "arn:aws:s3:::ghgc-data-store-staging/*", + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } ] - } - EOT + } + EOT }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], extra_iam_policy : <<-EOT - { + { "Version": "2012-10-17", "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::ghgc-data-staging", - "arn:aws:s3:::ghgc-data-staging/*", - "arn:aws:s3:::ghgc-data-store-dev", - "arn:aws:s3:::ghgc-data-store-dev/*", - "arn:aws:s3:::ghgc-data-store", - "arn:aws:s3:::ghgc-data-store/*", - "arn:aws:s3:::ghgc-data-store-staging", - "arn:aws:s3:::ghgc-data-store-staging/*", - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::ghgc-data-staging", + "arn:aws:s3:::ghgc-data-staging/*", + "arn:aws:s3:::ghgc-data-store-dev", + "arn:aws:s3:::ghgc-data-store-dev/*", + "arn:aws:s3:::ghgc-data-store", + "arn:aws:s3:::ghgc-data-store/*", + "arn:aws:s3:::ghgc-data-store-staging", + "arn:aws:s3:::ghgc-data-store-staging/*", + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } ] - } - EOT + } + EOT }, }, } diff --git a/terraform/aws/projects/nasa-veda.tfvars b/terraform/aws/projects/nasa-veda.tfvars index a414b0f1d2..6192ede19a 100644 --- a/terraform/aws/projects/nasa-veda.tfvars +++ b/terraform/aws/projects/nasa-veda.tfvars @@ -19,126 +19,126 @@ hub_cloud_permissions = { "user-sa" : { bucket_admin_access : ["scratch-staging"], extra_iam_policy : <<-EOT - { + { "Version": "2012-10-17", "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::sdap-dev-zarr", - "arn:aws:s3:::sdap-dev-zarr/*", - "arn:aws:s3:::usgs-landsat", - "arn:aws:s3:::usgs-landsat/*", - "arn:aws:s3:::sentinel-cogs", - "arn:aws:s3:::sentinel-cogs/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::sdap-dev-zarr", + "arn:aws:s3:::sdap-dev-zarr/*", + "arn:aws:s3:::usgs-landsat", + "arn:aws:s3:::usgs-landsat/*", + "arn:aws:s3:::sentinel-cogs", + "arn:aws:s3:::sentinel-cogs/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } ] - } - EOT + } + EOT }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], extra_iam_policy : <<-EOT - { + { "Version": "2012-10-17", "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:GetObject", - "s3:ListBucketMultipartUploads", - "s3:AbortMultipartUpload", - "s3:ListBucketVersions", - "s3:CreateBucket", - "s3:ListBucket", - "s3:DeleteObject", - "s3:GetBucketLocation", - "s3:ListMultipartUploadParts" - ], - "Resource": [ - "arn:aws:s3:::veda-data-store-staging", - "arn:aws:s3:::veda-data-store-staging/*", - "arn:aws:s3:::veda-nex-gddp-cmip6-public", - "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", - "arn:aws:s3:::cmip6-staging", - "arn:aws:s3:::cmip6-staging/*", - "arn:aws:s3:::lp-prod-protected", - "arn:aws:s3:::lp-prod-protected/*", - "arn:aws:s3:::gesdisc-cumulus-prod-protected", - "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", - "arn:aws:s3:::nsidc-cumulus-prod-protected", - "arn:aws:s3:::nsidc-cumulus-prod-protected/*", - "arn:aws:s3:::ornl-cumulus-prod-protected", - "arn:aws:s3:::ornl-cumulus-prod-protected/*", - "arn:aws:s3:::pangeo-forge-veda-output", - "arn:aws:s3:::pangeo-forge-veda-output/*", - "arn:aws:s3:::podaac-ops-cumulus-public", - "arn:aws:s3:::podaac-ops-cumulus-public/*", - "arn:aws:s3:::podaac-ops-cumulus-protected", - "arn:aws:s3:::podaac-ops-cumulus-protected/*", - "arn:aws:s3:::maap-ops-workspace", - "arn:aws:s3:::maap-ops-workspace/*", - "arn:aws:s3:::nasa-maap-data-store", - "arn:aws:s3:::nasa-maap-data-store/*", - "arn:aws:s3:::sdap-dev-zarr", - "arn:aws:s3:::sdap-dev-zarr/*", - "arn:aws:s3:::usgs-landsat", - "arn:aws:s3:::usgs-landsat/*" - ] - }, - { - "Effect": "Allow", - "Action": "s3:ListAllMyBuckets", - "Resource": "*" - } + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:AbortMultipartUpload", + "s3:ListBucketVersions", + "s3:CreateBucket", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketLocation", + "s3:ListMultipartUploadParts" + ], + "Resource": [ + "arn:aws:s3:::veda-data-store-staging", + "arn:aws:s3:::veda-data-store-staging/*", + "arn:aws:s3:::veda-nex-gddp-cmip6-public", + "arn:aws:s3:::veda-nex-gddp-cmip6-public/*", + "arn:aws:s3:::cmip6-staging", + "arn:aws:s3:::cmip6-staging/*", + "arn:aws:s3:::lp-prod-protected", + "arn:aws:s3:::lp-prod-protected/*", + "arn:aws:s3:::gesdisc-cumulus-prod-protected", + "arn:aws:s3:::gesdisc-cumulus-prod-protected/*", + "arn:aws:s3:::nsidc-cumulus-prod-protected", + "arn:aws:s3:::nsidc-cumulus-prod-protected/*", + "arn:aws:s3:::ornl-cumulus-prod-protected", + "arn:aws:s3:::ornl-cumulus-prod-protected/*", + "arn:aws:s3:::pangeo-forge-veda-output", + "arn:aws:s3:::pangeo-forge-veda-output/*", + "arn:aws:s3:::podaac-ops-cumulus-public", + "arn:aws:s3:::podaac-ops-cumulus-public/*", + "arn:aws:s3:::podaac-ops-cumulus-protected", + "arn:aws:s3:::podaac-ops-cumulus-protected/*", + "arn:aws:s3:::maap-ops-workspace", + "arn:aws:s3:::maap-ops-workspace/*", + "arn:aws:s3:::nasa-maap-data-store", + "arn:aws:s3:::nasa-maap-data-store/*", + "arn:aws:s3:::sdap-dev-zarr", + "arn:aws:s3:::sdap-dev-zarr/*", + "arn:aws:s3:::usgs-landsat", + "arn:aws:s3:::usgs-landsat/*" + ] + }, + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } ] - } - EOT + } + EOT }, }, } From 58a3bf5477f85bdea3f5164e85713ef313520f8d Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 19 Apr 2024 15:51:46 +0200 Subject: [PATCH 06/18] deployer: cleanup docstring typo --- deployer/commands/generate/billing/importers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deployer/commands/generate/billing/importers.py b/deployer/commands/generate/billing/importers.py index deb0ce61f5..f1f5add55d 100644 --- a/deployer/commands/generate/billing/importers.py +++ b/deployer/commands/generate/billing/importers.py @@ -16,7 +16,6 @@ def build_gcp_query(cluster: dict, service_id=None): Returns: string: query string - """ """ """ bq = cluster["gcp"]["billing"]["bigquery"] From d70397f076d0c8c9b64ab831df0cf6533e25700e Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Fri, 19 Apr 2024 15:52:11 +0200 Subject: [PATCH 07/18] docs helper-programs: add comment about hub_cloud_permissions structure --- docs/helper-programs/generate-hub-features-table.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/helper-programs/generate-hub-features-table.py b/docs/helper-programs/generate-hub-features-table.py index 8e7e1e1e5c..e7b4f275e5 100644 --- a/docs/helper-programs/generate-hub-features-table.py +++ b/docs/helper-programs/generate-hub-features-table.py @@ -155,6 +155,11 @@ def parse_terraform_value_files_for_features(terraform_config): hub_cloud_permissions = terraform_config.get("hub_cloud_permissions", None) if hub_cloud_permissions: for hub_slug, permissions in hub_cloud_permissions.items(): + # The permission object doesn't have the same structure in AWS + # as for GCP currently, and requestor_pays is only available for + # GCP currently. The logic below works, but needs an update if + # GCP aligns with the same structure as AWS, or if + # requestor_pays config is added for AWS. features[hub_slug] = { "user_buckets": True, "requestor_pays": permissions.get("requestor_pays", False), From df594cb23466443fee9fb02f7f0e2f5e083ddc85 Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Fri, 19 Apr 2024 17:22:07 -0700 Subject: [PATCH 08/18] Expand docstring for `hub_cloud_permissions` --- terraform/aws/variables.tf | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index 0e9c65a86b..c85e007701 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -55,17 +55,27 @@ variable "hub_cloud_permissions" { ) default = {} description = <<-EOT - Map of cloud permissions given to a particular hub (k8s namespace) and - its associated IAM Role's that are 1:1 with k8s ServiceAccounts. - - Currently supported are: - - 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. 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. + Cloud permissions attached to Kubernetes Service Accounts in a particular + hub in this cluster. + + The key is a Kubernetes namespace, which by convention in 2i2c clusters + is also the name of the hub. + + The value is itself a map, as each hub can have multiple Kubernetes Service + Accounts attached to it, for different kinds of users. The key is the name + of the Kubernetes Service Account. By convention, the currently supported keys + are are `user-sa` (for non-admin users on the hub) and `admin-sa` (for admin + users on the hub). The value can be one of: + + 1. bucket_admin_access: List of S3 storage buckets to grant full read & write + permissions to. + 2. bucket_readonly_access: List of S3 storage buckets to grant full read + permissions to. + 3. extra_iam_policy: An AWS IAM Policy document that grants additional rights + to this Kubernetes Service Account. + + Note that these are independent of each other - so if you want both admins + and non-admins to have a set of permissions, you may need to repeat them. EOT } From d16fdb83f2903e870382c100984d3ee15f2b59d8 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 10:03:00 +0200 Subject: [PATCH 09/18] docs: minor clarification regarding k8s namespace and hub --- terraform/aws/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index c85e007701..01e0668753 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -56,7 +56,7 @@ variable "hub_cloud_permissions" { default = {} description = <<-EOT Cloud permissions attached to Kubernetes Service Accounts in a particular - hub in this cluster. + k8s namespace (hub) in this cluster. The key is a Kubernetes namespace, which by convention in 2i2c clusters is also the name of the hub. From 50cd6ad0644f04857bf677f47e660c2872103eeb Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 12:53:38 +0200 Subject: [PATCH 10/18] Add clarity to where constraints are, basehub as compared to terraform --- terraform/aws/variables.tf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/terraform/aws/variables.tf b/terraform/aws/variables.tf index 01e0668753..f7272c32f9 100644 --- a/terraform/aws/variables.tf +++ b/terraform/aws/variables.tf @@ -63,9 +63,10 @@ variable "hub_cloud_permissions" { The value is itself a map, as each hub can have multiple Kubernetes Service Accounts attached to it, for different kinds of users. The key is the name - of the Kubernetes Service Account. By convention, the currently supported keys - are are `user-sa` (for non-admin users on the hub) and `admin-sa` (for admin - users on the hub). The value can be one of: + of the Kubernetes Service Account. By convention, basehub currently only + supports creation of Kubernetes Service Accounts `user-sa` (for non-admin + users on the hub) and `admin-sa` (for admin users on the hub). The value + can be one of: 1. bucket_admin_access: List of S3 storage buckets to grant full read & write permissions to. From aea9ba999b00b142c7a59d78daa111df8cf83577 Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Fri, 19 Apr 2024 17:38:41 -0700 Subject: [PATCH 11/18] Reword why user-sa is special cased in role name --- terraform/aws/irsa.tf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index f37a0a12af..8befb0e8ef 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -16,8 +16,10 @@ 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 + // Most hubs only use `user-sa`, so we use just the hub name for the IAM + // role for user-sa. `user-sa` was also the only service account supported + // for a long time, so this special casing reduces the amount of work + // we needed to do to introduce other service accounts. id = role == "user-sa" ? hub : "${hub}-${role}" hub = hub role = role From 8fb8a29433d5b1ac0cb2e0d1b0088cbf5f87d2f9 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 13:44:54 +0200 Subject: [PATCH 12/18] terraform, aws: rename local variable, hub_role to hub_to_role_mapping --- terraform/aws/irsa.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index 8befb0e8ef..31c8619410 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -13,7 +13,7 @@ data "aws_partition" "current" {} locals { - hub_role = flatten([ + hub_to_role_mapping = flatten([ for hub, hub_value in var.hub_cloud_permissions : [ for role, role_value in hub_value : { // Most hubs only use `user-sa`, so we use just the hub name for the IAM @@ -32,7 +32,7 @@ locals { data "aws_iam_policy_document" "irsa_role_assume" { - for_each = { for index, hr in local.hub_role : hr.id => hr } + for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr } statement { effect = "Allow" actions = ["sts:AssumeRoleWithWebIdentity"] @@ -55,7 +55,7 @@ data "aws_iam_policy_document" "irsa_role_assume" { } resource "aws_iam_role" "irsa_role" { - for_each = { for index, hr in local.hub_role : hr.id => hr } + for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr } name = "${var.cluster_name}-${each.key}" assume_role_policy = data.aws_iam_policy_document.irsa_role_assume[each.key].json @@ -64,7 +64,7 @@ resource "aws_iam_role" "irsa_role" { resource "aws_iam_policy" "extra_user_policy" { - for_each = { for index, hr in local.hub_role : hr.id => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : 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}" @@ -72,7 +72,7 @@ resource "aws_iam_policy" "extra_user_policy" { } resource "aws_iam_role_policy_attachment" "extra_user_policy" { - for_each = { for index, hr in local.hub_role : hr.id => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : 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 } @@ -81,7 +81,7 @@ resource "aws_iam_role_policy_attachment" "extra_user_policy" { output "kubernetes_sa_annotations" { value = { - for index, hr in local.hub_role : + for index, hr in local.hub_to_role_mapping : hr.id => "eks.amazonaws.com/role-arn: ${aws_iam_role.irsa_role[hr.id].arn}" } description = <<-EOT From d72f591e548ccba9117ce2318fb323949145585b Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 13:46:27 +0200 Subject: [PATCH 13/18] terraform, aws: rename local variable, id -> iam_role_name --- terraform/aws/irsa.tf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index 31c8619410..4f8c170844 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -20,10 +20,10 @@ locals { // role for user-sa. `user-sa` was also the only service account supported // for a long time, so this special casing reduces the amount of work // we needed to do to introduce other service accounts. - id = role == "user-sa" ? hub : "${hub}-${role}" - hub = hub - role = role - data = role_value + iam_role_name = role == "user-sa" ? hub : "${hub}-${role}" + hub = hub + role = role + data = role_value } ] ]) @@ -32,7 +32,7 @@ locals { data "aws_iam_policy_document" "irsa_role_assume" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr } statement { effect = "Allow" actions = ["sts:AssumeRoleWithWebIdentity"] @@ -55,7 +55,7 @@ data "aws_iam_policy_document" "irsa_role_assume" { } resource "aws_iam_role" "irsa_role" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr } name = "${var.cluster_name}-${each.key}" assume_role_policy = data.aws_iam_policy_document.irsa_role_assume[each.key].json @@ -64,7 +64,7 @@ resource "aws_iam_role" "irsa_role" { resource "aws_iam_policy" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => 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}" @@ -72,7 +72,7 @@ resource "aws_iam_policy" "extra_user_policy" { } resource "aws_iam_role_policy_attachment" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.id => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => 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 } @@ -82,7 +82,7 @@ resource "aws_iam_role_policy_attachment" "extra_user_policy" { output "kubernetes_sa_annotations" { value = { for index, hr in local.hub_to_role_mapping : - hr.id => "eks.amazonaws.com/role-arn: ${aws_iam_role.irsa_role[hr.id].arn}" + hr.iam_role_name => "eks.amazonaws.com/role-arn: ${aws_iam_role.irsa_role[hr.iam_role_name].arn}" } description = <<-EOT Annotations to apply to userServiceAccount in each hub to enable cloud permissions for them. From 5429fd8e4a58dcc120236f4eb5d7757cbd3f7a43 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 13:53:10 +0200 Subject: [PATCH 14/18] terraform, aws: rename local variable, role/data -> ksa_name/ksa_value --- terraform/aws/irsa.tf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index 4f8c170844..7887ae2c53 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -15,15 +15,15 @@ data "aws_partition" "current" {} locals { hub_to_role_mapping = flatten([ for hub, hub_value in var.hub_cloud_permissions : [ - for role, role_value in hub_value : { + for ksa_name, ksa_value in hub_value : { // Most hubs only use `user-sa`, so we use just the hub name for the IAM // role for user-sa. `user-sa` was also the only service account supported // for a long time, so this special casing reduces the amount of work // we needed to do to introduce other service accounts. - iam_role_name = role == "user-sa" ? hub : "${hub}-${role}" + iam_role_name = ksa_name == "user-sa" ? hub : "${hub}-${ksa_name}" hub = hub - role = role - data = role_value + ksa_name = ksa_name + ksa_value = ksa_value } ] ]) @@ -48,7 +48,7 @@ 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.value.hub}:${each.value.role}" + "system:serviceaccount:${each.value.hub}:${each.value.ksa_name}" ] } } @@ -64,15 +64,15 @@ resource "aws_iam_role" "irsa_role" { resource "aws_iam_policy" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.ksa_value.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.data.extra_iam_policy + policy = each.value.ksa_value.extra_iam_policy } resource "aws_iam_role_policy_attachment" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.data.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.ksa_value.extra_iam_policy != "" } role = aws_iam_role.irsa_role[each.key].name policy_arn = aws_iam_policy.extra_user_policy[each.key].arn } From add4e85c1b310266f39d2e40d8cba414ee6de876 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 14:08:48 +0200 Subject: [PATCH 15/18] terraform, aws: rely on default value for extra_iam_policy --- terraform/aws/projects/2i2c-aws-us.tfvars | 6 ------ terraform/aws/projects/bican.tfvars | 2 -- terraform/aws/projects/catalystproject-africa.tfvars | 2 -- terraform/aws/projects/dandi.tfvars | 2 -- terraform/aws/projects/earthscope.tfvars | 2 -- terraform/aws/projects/gridsst.tfvars | 2 -- terraform/aws/projects/jupyter-health.tfvars | 2 -- terraform/aws/projects/kitware.tfvars | 2 -- terraform/aws/projects/linc.tfvars | 2 -- terraform/aws/projects/nasa-esdis.tfvars | 1 - terraform/aws/projects/openscapes.tfvars | 2 -- terraform/aws/projects/smithsonian.tfvars | 2 -- terraform/aws/projects/template.tfvars | 1 - terraform/aws/projects/ubc-eoas.tfvars | 2 -- terraform/aws/projects/victor.tfvars | 2 -- 15 files changed, 32 deletions(-) diff --git a/terraform/aws/projects/2i2c-aws-us.tfvars b/terraform/aws/projects/2i2c-aws-us.tfvars index d360c4a278..38c20188d6 100644 --- a/terraform/aws/projects/2i2c-aws-us.tfvars +++ b/terraform/aws/projects/2i2c-aws-us.tfvars @@ -33,13 +33,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "dask-staging" : { "user-sa" : { bucket_admin_access : ["scratch-dask-staging"], - extra_iam_policy : "", }, }, "showcase" : { @@ -48,25 +46,21 @@ hub_cloud_permissions = { "scratch-researchdelight", "persistent-showcase", ], - extra_iam_policy : "", }, }, "ncar-cisl" : { "user-sa" : { bucket_admin_access : ["scratch-ncar-cisl"], - extra_iam_policy : "", }, }, "go-bgc" : { "user-sa" : { bucket_admin_access : ["scratch-go-bgc"], - extra_iam_policy : "", }, }, "itcoocean" : { "user-sa" : { bucket_admin_access : ["scratch-itcoocean"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/bican.tfvars b/terraform/aws/projects/bican.tfvars index b4ec1f3a4e..5411d6f659 100644 --- a/terraform/aws/projects/bican.tfvars +++ b/terraform/aws/projects/bican.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/catalystproject-africa.tfvars b/terraform/aws/projects/catalystproject-africa.tfvars index 7dd5753aeb..daf6ec5bd2 100644 --- a/terraform/aws/projects/catalystproject-africa.tfvars +++ b/terraform/aws/projects/catalystproject-africa.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/dandi.tfvars b/terraform/aws/projects/dandi.tfvars index e33f0bd3a0..eb70b296b5 100644 --- a/terraform/aws/projects/dandi.tfvars +++ b/terraform/aws/projects/dandi.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/earthscope.tfvars b/terraform/aws/projects/earthscope.tfvars index ef80ccc156..0fecda7e47 100644 --- a/terraform/aws/projects/earthscope.tfvars +++ b/terraform/aws/projects/earthscope.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/gridsst.tfvars b/terraform/aws/projects/gridsst.tfvars index b995159683..7def9eecb5 100644 --- a/terraform/aws/projects/gridsst.tfvars +++ b/terraform/aws/projects/gridsst.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/jupyter-health.tfvars b/terraform/aws/projects/jupyter-health.tfvars index a273ce3b98..5af56b293f 100644 --- a/terraform/aws/projects/jupyter-health.tfvars +++ b/terraform/aws/projects/jupyter-health.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/kitware.tfvars b/terraform/aws/projects/kitware.tfvars index 54cc305028..4636b90ae6 100644 --- a/terraform/aws/projects/kitware.tfvars +++ b/terraform/aws/projects/kitware.tfvars @@ -17,13 +17,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/linc.tfvars b/terraform/aws/projects/linc.tfvars index 0bd1caaa37..8b40a75889 100644 --- a/terraform/aws/projects/linc.tfvars +++ b/terraform/aws/projects/linc.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/nasa-esdis.tfvars b/terraform/aws/projects/nasa-esdis.tfvars index 803c412fa2..b371a6bdc6 100644 --- a/terraform/aws/projects/nasa-esdis.tfvars +++ b/terraform/aws/projects/nasa-esdis.tfvars @@ -18,7 +18,6 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { diff --git a/terraform/aws/projects/openscapes.tfvars b/terraform/aws/projects/openscapes.tfvars index a24be639c8..1bd7851e47 100644 --- a/terraform/aws/projects/openscapes.tfvars +++ b/terraform/aws/projects/openscapes.tfvars @@ -30,7 +30,6 @@ hub_cloud_permissions = { "scratch-staging", "persistent-staging", ], - extra_iam_policy : "", }, }, "prod" : { @@ -39,7 +38,6 @@ hub_cloud_permissions = { "scratch", "persistent", ], - extra_iam_policy : "", } }, } diff --git a/terraform/aws/projects/smithsonian.tfvars b/terraform/aws/projects/smithsonian.tfvars index 8bbf537938..28edc972f6 100644 --- a/terraform/aws/projects/smithsonian.tfvars +++ b/terraform/aws/projects/smithsonian.tfvars @@ -15,13 +15,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/template.tfvars b/terraform/aws/projects/template.tfvars index 64a41ea476..afd0412f0c 100644 --- a/terraform/aws/projects/template.tfvars +++ b/terraform/aws/projects/template.tfvars @@ -27,7 +27,6 @@ cluster_nodes_location = "{{ cluster_region }}a" # "{{ hub_name }}" : { # "user-sa" : { # bucket_admin_access : ["scratch-{{ hub_name }}"], -# extra_iam_policy : "", # }, # }, # # Tip: add more namespaces below, if this cluster will be multi-tenant diff --git a/terraform/aws/projects/ubc-eoas.tfvars b/terraform/aws/projects/ubc-eoas.tfvars index ecb02e5a43..98686f1f7f 100644 --- a/terraform/aws/projects/ubc-eoas.tfvars +++ b/terraform/aws/projects/ubc-eoas.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } diff --git a/terraform/aws/projects/victor.tfvars b/terraform/aws/projects/victor.tfvars index 1c22c00cca..7e61ad64a4 100644 --- a/terraform/aws/projects/victor.tfvars +++ b/terraform/aws/projects/victor.tfvars @@ -18,13 +18,11 @@ hub_cloud_permissions = { "staging" : { "user-sa" : { bucket_admin_access : ["scratch-staging"], - extra_iam_policy : "", }, }, "prod" : { "user-sa" : { bucket_admin_access : ["scratch"], - extra_iam_policy : "", }, }, } From 5e6f22ac2f33c34453a683dfbb46ca55bebff29d Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 14:11:04 +0200 Subject: [PATCH 16/18] terraform, aws: rename local variable, ksa_value -> cloud_permissions --- terraform/aws/irsa.tf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index 7887ae2c53..2707acf646 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -15,15 +15,15 @@ data "aws_partition" "current" {} locals { hub_to_role_mapping = flatten([ for hub, hub_value in var.hub_cloud_permissions : [ - for ksa_name, ksa_value in hub_value : { + for ksa_name, cloud_permissions in hub_value : { // Most hubs only use `user-sa`, so we use just the hub name for the IAM // role for user-sa. `user-sa` was also the only service account supported // for a long time, so this special casing reduces the amount of work // we needed to do to introduce other service accounts. - iam_role_name = ksa_name == "user-sa" ? hub : "${hub}-${ksa_name}" - hub = hub - ksa_name = ksa_name - ksa_value = ksa_value + iam_role_name = ksa_name == "user-sa" ? hub : "${hub}-${ksa_name}" + hub = hub + ksa_name = ksa_name + cloud_permissions = cloud_permissions } ] ]) @@ -64,15 +64,15 @@ resource "aws_iam_role" "irsa_role" { resource "aws_iam_policy" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.ksa_value.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.cloud_permissions.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.ksa_value.extra_iam_policy + policy = each.value.cloud_permissions.extra_iam_policy } resource "aws_iam_role_policy_attachment" "extra_user_policy" { - for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.ksa_value.extra_iam_policy != "" } + for_each = { for index, hr in local.hub_to_role_mapping : hr.iam_role_name => hr if hr.cloud_permissions.extra_iam_policy != "" } role = aws_iam_role.irsa_role[each.key].name policy_arn = aws_iam_policy.extra_user_policy[each.key].arn } From a3352c74494ed367efe1d1515ff1a91eaeb0c430 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 14:12:25 +0200 Subject: [PATCH 17/18] terraform, aws: add back reference to flatten trick --- terraform/aws/irsa.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/terraform/aws/irsa.tf b/terraform/aws/irsa.tf index 2707acf646..672e2180d4 100644 --- a/terraform/aws/irsa.tf +++ b/terraform/aws/irsa.tf @@ -13,6 +13,7 @@ data "aws_partition" "current" {} locals { + # Nested for loop, thanks to https://www.daveperrett.com/articles/2021/08/19/nested-for-each-with-terraform/ hub_to_role_mapping = flatten([ for hub, hub_value in var.hub_cloud_permissions : [ for ksa_name, cloud_permissions in hub_value : { From 0b401689f30e2743299779b458d29ace3669fe1e Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Sat, 20 Apr 2024 14:17:37 +0200 Subject: [PATCH 18/18] terraform, aws: add inline comment to clarify example value of local var --- terraform/aws/bucket-access.tf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/terraform/aws/bucket-access.tf b/terraform/aws/bucket-access.tf index a9b17b8791..85d914619e 100644 --- a/terraform/aws/bucket-access.tf +++ b/terraform/aws/bucket-access.tf @@ -80,6 +80,11 @@ locals { `local.bucket_role_actions` to a dictionary with one key per bucket with associated permissions. + Below is an example value `local.bucket_role_actions_lists` could take. This + example value is aligned with the example value for + `var.hub_cloud_permissions` and `local.bucket_role_actions` in the code + block above. + bucket_role_actions_lists: scratch-staging: - bucket: scratch-staging