Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions aws/iam/github_oidc_role/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_iam_openid_connect_provider.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource |
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.permissions_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_policy_document.oidc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.permissions_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_github_branch"></a> [github\_branch](#input\_github\_branch) | GitHub branch name, the permissions will be limited to this branch | `string` | `"main"` | no |
| <a name="input_github_environment"></a> [github\_environment](#input\_github\_environment) | GitHub environment name, the permissions will be limited to this environment | `string` | n/a | yes |
| <a name="input_github_organization"></a> [github\_organization](#input\_github\_organization) | GitHub organization name | `string` | n/a | yes |
| <a name="input_github_repo"></a> [github\_repo](#input\_github\_repo) | GitHub repository name that the workflow will be runned | `string` | n/a | yes |
| <a name="input_iam_policy_statements"></a> [iam\_policy\_statements](#input\_iam\_policy\_statements) | A list of iam policy statement objects | <pre>list(object({<br/> sid = optional(string)<br/> effect = optional(string, "Allow")<br/> actions = list(string)<br/> not_actions = optional(list(string))<br/> resources = optional(list(string))<br/> not_resources = optional(list(string))<br/> condition = optional(list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> })))<br/> }))</pre> | `[]` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags, all of the tags are applied to all of the AWS resources | `map(string)` | `{}` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | Amazon Resource Name (ARN) specifying the role. |
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Name of the role. |
| <a name="output_role_unique_id"></a> [role\_unique\_id](#output\_role\_unique\_id) | Stable and unique string identifying the role. |
26 changes: 26 additions & 0 deletions aws/iam/github_oidc_role/examples/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

provider "aws" {
region = "us-east-1"
}

module "github_oidc_role" {
source = "../"

github_organization = "ufabc-next"
github_repo = "ufabc-next-app"
github_environment = "dev"

iam_policy_statements = [
{
sid = "S3List",
effect = "Allow",
actions = ["s3:ListAllMyBuckets"],
resources = ["*"]
}
]

tags = {
"ManagedBy" = "Terraform",
"Owner" = "Example"
}
}
28 changes: 28 additions & 0 deletions aws/iam/github_oidc_role/examples/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

include "root" {
path = find_in_parent_folders("root.hcl")
}

terraform {
source = "../../"
}

inputs = {
github_organization = "ufabc-next"
github_repo = "ufabc-next-app"
github_environment = "dev"

iam_policy_statements = [
{
sid = "S3List",
effect = "Allow",
actions = ["s3:ListAllMyBuckets"],
resources = ["*"]
}
]

tags = {
"ManagedBy" = "Terragrunt",
"Owner" = "Example"
}
}
72 changes: 72 additions & 0 deletions aws/iam/github_oidc_role/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
resource "aws_iam_openid_connect_provider" "this" {
url = "https://token.actions.githubusercontent.com"

client_id_list = [
"sts.amazonaws.com",
]

tags = var.tags
}

data "aws_iam_policy_document" "oidc" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]

principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.this.arn]
}

condition {
test = "StringEquals"
values = ["sts.amazonaws.com"]
variable = "token.actions.githubusercontent.com:aud"
}

condition {
test = "StringLike"
values = ["repo:${var.github_organization}/${var.github_repo}:environment:${var.github_environment}"]
variable = "token.actions.githubusercontent.com:sub"
}
}
}


resource "aws_iam_role" "this" {
name = "GitActionsOIDCRole-${var.github_environment}"
assume_role_policy = data.aws_iam_policy_document.oidc.json

tags = var.tags
}


data "aws_iam_policy_document" "permissions_policy" {
dynamic "statement" {
for_each = var.iam_policy_statements

content {
sid = statement.value.sid
effect = statement.value.effect
actions = statement.value.actions
not_actions = lookup(statement.value, "not_actions", null)
resources = lookup(statement.value, "resources", null)
not_resources = lookup(statement.value, "not_resources", null)

dynamic "condition" {
for_each = statement.value.condition != null ? statement.value.condition : []
content {
test = condition.value.test
variable = condition.value.variable
values = condition.value.values
}
}
}
}
}

resource "aws_iam_role_policy" "permissions_policy" {
name = "GithubOIDCPolicy"
role = aws_iam_role.this.name

policy = data.aws_iam_policy_document.permissions_policy.json
}
15 changes: 15 additions & 0 deletions aws/iam/github_oidc_role/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

output "role_arn" {
description = "Amazon Resource Name (ARN) specifying the role."
value = aws_iam_role.this.arn
}

output "role_name" {
description = "Name of the role."
value = aws_iam_role.this.name
}

output "role_unique_id" {
description = "Stable and unique string identifying the role."
value = aws_iam_role.this.unique_id
}
72 changes: 72 additions & 0 deletions aws/iam/github_oidc_role/tests/test.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

provider "aws" {
region = "us-east-1"
}

mock_provider "aws" {}

override_data {
target = data.aws_iam_policy_document.oidc
values = {
json = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRoleWithWebIdentity\",\"Effect\":\"Allow\",\"Principal\":{\"Federated\":\"arn:aws:iam::000000000000:oidc-provider/token.actions.githubusercontent.com\"},\"Condition\":{\"StringEquals\":{\"token.actions.githubusercontent.com:aud\":\"sts.amazonaws.com\"},\"StringLike\":{\"token.actions.githubusercontent.com:sub\":\"repo:ufabc-next/ufabc-next-app:environment:dev\"}}}]}"
}
}

override_data {
target = data.aws_iam_policy_document.permissions_policy
values = {
json = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"S3List\",\"Effect\":\"Allow\",\"Action\":[\"s3:ListAllMyBuckets\"],\"Resource\":[\"*\"]}]}"
}
}

variables {
github_organization = "ufabc-next"
github_repo = "ufabc-next-app"
github_environment = "dev"
iam_policy_statements = [
{
sid = "S3List",
effect = "Allow",
actions = ["s3:ListAllMyBuckets"],
resources = ["*"]
}
]
tags = {
"ManagedBy" = "Terraform",
"Owner" = "Test"
}
}

run "github_oidc_role" {
command = apply

assert {
condition = aws_iam_role.this.name == "GitActionsOIDCRole-dev"
error_message = "Role name is incorrect"
}

assert {
condition = jsondecode(aws_iam_role.this.assume_role_policy).Statement[0].Principal.Federated == "arn:aws:iam::000000000000:oidc-provider/token.actions.githubusercontent.com"
error_message = "Assume role policy principal is incorrect"
}

assert {
condition = jsondecode(aws_iam_role.this.assume_role_policy).Statement[0].Condition.StringLike["token.actions.githubusercontent.com:sub"] == "repo:ufabc-next/ufabc-next-app:environment:dev"
error_message = "Assume role policy condition is incorrect"
}

assert {
condition = jsondecode(aws_iam_role_policy.permissions_policy.policy).Statement[0].Action[0] == "s3:ListAllMyBuckets"
error_message = "IAM policy statement is incorrect"
}

assert {
condition = output.role_name == "GitActionsOIDCRole-dev"
error_message = "Output role_name is incorrect"
}

assert {
condition = output.role_arn == aws_iam_role.this.arn
error_message = "Output role_arn is incorrect"
}
}
42 changes: 42 additions & 0 deletions aws/iam/github_oidc_role/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
variable "github_environment" {
type = string
description = "GitHub environment name, the permissions will be limited to this environment"
}

variable "github_repo" {
type = string
description = "GitHub repository name that the workflow will be runned"
}


variable "github_organization" {
type = string
description = "GitHub organization name"
}



variable "iam_policy_statements" {
description = "A list of iam policy statement objects"
type = list(object({
sid = optional(string)
effect = optional(string, "Allow")
actions = list(string)
not_actions = optional(list(string))
resources = optional(list(string))
not_resources = optional(list(string))
condition = optional(list(object({
test = string
variable = string
values = list(string)
})))
}))

default = []
}

variable "tags" {
type = map(string)
description = "Tags, all of the tags are applied to all of the AWS resources"
default = {}
}
10 changes: 10 additions & 0 deletions aws/iam/github_oidc_role/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}

required_version = ">= 1.0.0"
}