From 3565f0d6dd855d20c6cbcb32a49dc89d7091f13b Mon Sep 17 00:00:00 2001 From: tylerthome Date: Wed, 15 May 2024 08:55:54 -0700 Subject: [PATCH] add gha oidc module and invoke for incubator; add tyler for huu --- terraform/aws-gha-oidc-providers.tf | 13 +++ terraform/aws-users.tf | 11 +++ .../modules/aws-gha-oidc-providers/main.tf | 80 +++++++++++++++++++ .../modules/aws-gha-oidc-providers/outputs.tf | 9 +++ .../aws-gha-oidc-providers/variables.tf | 56 +++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 terraform/aws-gha-oidc-providers.tf create mode 100644 terraform/modules/aws-gha-oidc-providers/main.tf create mode 100644 terraform/modules/aws-gha-oidc-providers/outputs.tf create mode 100644 terraform/modules/aws-gha-oidc-providers/variables.tf diff --git a/terraform/aws-gha-oidc-providers.tf b/terraform/aws-gha-oidc-providers.tf new file mode 100644 index 0000000..d8979c0 --- /dev/null +++ b/terraform/aws-gha-oidc-providers.tf @@ -0,0 +1,13 @@ +module "iam_oidc_gha_incubator" { + source = "./modules/aws-gha-oidc-providers" + + role_name = "gha-incubator" + use_wildcard = true + allow_pull_request = true + github_branch = "refs/heads/*" # allows any branch + github_repo = "hackforla/incubator" + + policy_arns = [ + "arn:aws:iam::aws:policy/AdministratorAccess" + ] +} diff --git a/terraform/aws-users.tf b/terraform/aws-users.tf index c48be78..d2ad550 100644 --- a/terraform/aws-users.tf +++ b/terraform/aws-users.tf @@ -9,6 +9,17 @@ module "iam_user_JimmyJuarez10" { user_groups = ["read-only-group"] } +module "iam_user_tylerthome" { + source = "./modules/aws-users" + + user_name = "tyler.thome" + user_tags = { + "Project" = "home-unite-us" + "Access Level" = "1" + } + user_groups = ["read-only-group"] +} + module "iam_user_brittanyms" { source = "./modules/aws-users" diff --git a/terraform/modules/aws-gha-oidc-providers/main.tf b/terraform/modules/aws-gha-oidc-providers/main.tf new file mode 100644 index 0000000..5cf6d1f --- /dev/null +++ b/terraform/modules/aws-gha-oidc-providers/main.tf @@ -0,0 +1,80 @@ +locals { + oidc_aws_audience = "sts.amazonaws.com" + oidc_github_idp = "token.actions.githubusercontent.com" + + # compose the OIDC subject using opinionated set of claims + # TODO: discuss alternative with maintainers + # see 'claims_supported' for all possibilities (some of which would require custom GHA): + # https://token.actions.githubusercontent.com/.well-known/openid-configuration + ordered_claim_names = [ + "repo", "environment", "ref" + ] + + # map user-supplied args to claim names, some of which may be empty + claims_with_values = zipmap(local.ordered_claim_names, [ + var.github_repo, var.github_environment, var.github_branch + ]) + + # construct 'sub' claim parts by selecting non-empty arg values, then combine + claims = [ + for claim in local.ordered_claim_names : format( + "%s:%s", + claim, + local.claims_with_values[claim] + ) if length(local.claims_with_values[claim]) > 0 + ] + + oidc_gha_sub = join(":", var.allow_pull_request ? concat( + local.claims, ["pull_request"] + ) : local.claims + ) + + /* + Alternative, which would place more responsibility on user to specify valid OIDC claims: + + `oidc_expected_claims = join(":", [for k,v in var.claim_patterns : "${k}:${v}"])` + */ + +} + +data "aws_caller_identity" "current" {} + +resource "aws_iam_openid_connect_provider" "github_actions" { + url = "https://${local.oidc_github_idp}" + + client_id_list = [ + local.oidc_aws_audience + ] + + thumbprint_list = ["1b511abead59c6ce207077c0bf0e0043b1382612"] +} + +resource "aws_iam_role" "github_actions_oidc" { + + name = var.role_name + managed_policy_arns = var.policy_arns + + assume_role_policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [{ + "Effect" : "Allow", + "Principal" : { + "Federated" : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.oidc_github_idp}" + }, + "Action" : "sts:AssumeRoleWithWebIdentity", + "Condition" : var.use_wildcard ? { + "StringLike" : { + "token.actions.githubusercontent.com:sub" : local.oidc_gha_sub + }, + "StringEquals" : { + "token.actions.githubusercontent.com:aud" : local.oidc_aws_audience, + } + } : { + "StringEquals" : { + "token.actions.githubusercontent.com:aud" : local.oidc_aws_audience, + "token.actions.githubusercontent.com:sub" : local.oidc_gha_sub + } + } + }] + }) +} \ No newline at end of file diff --git a/terraform/modules/aws-gha-oidc-providers/outputs.tf b/terraform/modules/aws-gha-oidc-providers/outputs.tf new file mode 100644 index 0000000..18a6e75 --- /dev/null +++ b/terraform/modules/aws-gha-oidc-providers/outputs.tf @@ -0,0 +1,9 @@ +output "role_arn" { + value = aws_iam_role.github_actions_oidc.arn + description = "The ARN of the IAM role for the federated identity" +} + +output "provider_arn" { + value = aws_iam_openid_connect_provider.github_actions.arn + description = "The ARN of the OIDC provider" +} diff --git a/terraform/modules/aws-gha-oidc-providers/variables.tf b/terraform/modules/aws-gha-oidc-providers/variables.tf new file mode 100644 index 0000000..1ccd94c --- /dev/null +++ b/terraform/modules/aws-gha-oidc-providers/variables.tf @@ -0,0 +1,56 @@ +variable "role_name" { + description = "The name of the IAM role" + type = string +} + +variable "github_repo" { + description = "The repository name (or name wildcard pattern if use_wildcard=true)" + type = string + + validation { + condition = can(regex("hackforla/.*", var.github_repo)) + error_message = "The github_repo argument must begin with 'hackforla/'" + } +} + +variable "github_branch" { + description = "The branch name (or name wildcard pattern if use_wildcard=true)" + type = string + + validation { + condition = can(regex("refs/(heads|tags)/.*", var.github_branch)) + error_message = "The github_branch argument must begin with 'refs/heads/' or 'refs/tags/" + } +} + +variable "github_environment" { + description = "The environment name (optional)" + type = string + default = "" +} + +variable "policy_arns" { + description = "The ARN of the policy to attach to the role" + type = list(string) +} + +variable "use_wildcard" { + description = "Specifies whether OIDC claim subject should use wildcard pattern" + type = bool +} + +variable "allow_pull_request" { + description = "Authorize the token for pull requests" + type = bool + default = false +} + +/* + Alternative, which would place more responsibility on user to specify valid OIDC claims: + + `variable "claim_patterns" { + description = "Specifies arbitrary " + type = map(string) + }` + */ +