From 3225f90755c44e66c3f4a1be6ce07feb6c333f7d Mon Sep 17 00:00:00 2001 From: Thomas Sibley Date: Wed, 15 May 2024 11:44:33 -0700 Subject: [PATCH] wip! Roles for our pathogen-repo-build GitHub Actions workflow Static role permissions policies which are expected to be narrowed/scoped-down by an inline session policy set by the pathogen-repo-build workflow. Problems with this approach noted in review commentary: - - Resolves: Related-to: --- ...le-GitHubActionsRoleNextstrainBatchJobs.tf | 4 +- ...-role-GitHubActionsRoleNextstrainBuilds.tf | 100 ++++++++++++++++++ env/production/github-oidc.tf | 19 ++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 env/production/aws-iam-role-GitHubActionsRoleNextstrainBuilds.tf create mode 100644 env/production/github-oidc.tf diff --git a/env/production/aws-iam-role-GitHubActionsRoleNextstrainBatchJobs.tf b/env/production/aws-iam-role-GitHubActionsRoleNextstrainBatchJobs.tf index 124cb58..6d34a2c 100644 --- a/env/production/aws-iam-role-GitHubActionsRoleNextstrainBatchJobs.tf +++ b/env/production/aws-iam-role-GitHubActionsRoleNextstrainBatchJobs.tf @@ -5,7 +5,7 @@ import { resource "aws_iam_role" "GitHubActionsRoleNextstrainBatchJobs" { name = "GitHubActionsRoleNextstrainBatchJobs" - description = "Provides permissions to run jobs on AWS Batch via the Nextstrain CLI to select GitHub Actions OIDC workflows." + description = "Provides permissions to launch and monitor jobs on AWS Batch via the Nextstrain CLI to select GitHub Actions OIDC workflows." max_session_duration = 43200 # seconds (12 hours) @@ -21,7 +21,7 @@ resource "aws_iam_role" "GitHubActionsRoleNextstrainBatchJobs" { "Condition": { "StringLike": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", - "token.actions.githubusercontent.com:sub": "repo:nextstrain/.github:*" + "token.actions.githubusercontent.com:sub": "repo:nextstrain/*:*:job_workflow_ref:nextstrain/.github/.github/workflows/pathogen-repo-build.yaml@refs/heads/*", } }, } diff --git a/env/production/aws-iam-role-GitHubActionsRoleNextstrainBuilds.tf b/env/production/aws-iam-role-GitHubActionsRoleNextstrainBuilds.tf new file mode 100644 index 0000000..1ce11d5 --- /dev/null +++ b/env/production/aws-iam-role-GitHubActionsRoleNextstrainBuilds.tf @@ -0,0 +1,100 @@ +resource "aws_iam_role" "GitHubActionsRoleNextstrainBuilds" { + name = "GitHubActionsRoleNextstrainBuilds" + description = "Provides permissions for a Nextstrain build (i.e. in a pathogen repo) to upload datasets, workflow files, etc. for select GitHub Actions OIDC workflows." + + max_session_duration = 43200 # seconds (12 hours) + + assume_role_policy = jsonencode({ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": aws_iam_openid_connect_provider.github-actions.arn + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringLike": { + "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", + "token.actions.githubusercontent.com:sub": "repo:nextstrain/*:*:job_workflow_ref:nextstrain/.github/.github/workflows/pathogen-repo-build.yaml@refs/heads/*", + } + }, + } + ] + }) + + # This role provides a superset of the permissions expected to actually be + # required by any individual Nextstrain pathogen build. In practice, we + # further scope down permissions per-repo using an inline session policy + # declared in our centralized and trusted pathogen-repo-build workflow. The + # inline session policy is obviously less of a hard boundary, but it still + # provides guardrails against accidental operations. See also the discussion + # in . + # -trs, 15 May 2024 + managed_policy_arns = [ + # Builds inside the AWS Batch runtime need access to the jobs bucket. + aws_iam_policy.NextstrainJobsAccessToBucket.arn, + ] + + # All builds need a subset of this access for downloading starting data and + # publishing results. + inline_policy { + name = "S3Access" + policy = jsonencode({ + "Version": "2012-10-17", + "Statement": [ + # Technically we don't need to include the public buckets + # nextstrain-data and nextstrain-staging in this statement since they + # already allow a superset of this with their bucket policies, but it's + # good to be explicit about what permissions we require. + # -trs, 16 Feb 2024 + { + "Sid": "List", + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + "s3:ListBucketVersions", + "s3:GetBucketLocation", + "s3:GetBucketVersioning", + ], + "Resource": [ + "arn:aws:s3:::nextstrain-data", + "arn:aws:s3:::nextstrain-data-private", + "arn:aws:s3:::nextstrain-ncov-private", + "arn:aws:s3:::nextstrain-staging", + ], + }, + { + "Sid": "ReadWrite", + "Effect": "Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectTagging", + "s3:GetObjectVersion", + "s3:GetObjectVersionTagging", + "s3:PutObject", + "s3:PutObjectTagging", + "s3:DeleteObject", + # but NOT s3:DeleteObjectVersion so objects can't be completely wiped + ], + "Resource": [ + "arn:aws:s3:::nextstrain-data/*.json", + "arn:aws:s3:::nextstrain-data/files/workflows/*", + "arn:aws:s3:::nextstrain-data/files/datasets/*", + + "arn:aws:s3:::nextstrain-data-private/*.json", + "arn:aws:s3:::nextstrain-data-private/files/workflows/*", + "arn:aws:s3:::nextstrain-data-private/files/datasets/*", + + # This bucket is akin to nextstrain-data-private/files/{workflows,datasets}/ncov/. + "arn:aws:s3:::nextstrain-ncov-private/*", + + "arn:aws:s3:::nextstrain-staging/*.json", + "arn:aws:s3:::nextstrain-staging/files/workflows/*", + "arn:aws:s3:::nextstrain-staging/files/datasets/*", + ], + }, + ] + }) + } +} diff --git a/env/production/github-oidc.tf b/env/production/github-oidc.tf new file mode 100644 index 0000000..41a2e76 --- /dev/null +++ b/env/production/github-oidc.tf @@ -0,0 +1,19 @@ +data "github_repositories" "nextstrain" { + query = "org:nextstrain" +} + +resource "github_actions_repository_oidc_subject_claim_customization_template" "nextstrain" { + for_each = toset(data.github_repositories.nextstrain.names) + repository = each.key + + # + use_default = false + include_claim_keys = [ + # The GitHub default… + "repo", + "context", + + # …plus the //@ of the workflow obtaining the token, if any. + "job_workflow_ref", + ] +}