Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: centralize iam role setup for github actions #4

Merged
merged 1 commit into from
Oct 30, 2024
Merged
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ The project is split into four main Terraform configurations:
Monitoring infrastructure. **This applies to both dev and prod environments**. You can switch
between workspaces (as mentioned earlier) to deploy infrastructure in either the dev or prod
account.
- [21-continuous-delivery][cd]: This configuration contains the definition of the IAM roles that
allow access to GitHub Action for specific repositories and operations. **This applies to both
dev and prod environments**. You can switch between workspaces (as mentioned earlier) to deploy
infrastructure in either the dev or prod account.

### System Flow Overview

Expand Down Expand Up @@ -170,3 +174,4 @@ This project is licensed under the [MIT License](LICENSE).
[route-53]: /pillarbox-monitoring-terraform/10-pillarbox-monitoring-route-53
[ecr]: /pillarbox-monitoring-terraform/11-pillarbox-monitoring-ecr
[app]: /pillarbox-monitoring-terraform/20-pillarbox-monitoring-app
[cd]: /pillarbox-monitoring-terraform/21-continuous-delivery
88 changes: 0 additions & 88 deletions pillarbox-monitoring-terraform/11-pillarbox-monitoring-ecr/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -77,94 +77,6 @@ resource "aws_ecr_lifecycle_policy" "ecr_lifecycles" {
EOF
}

# -----------------------------------
# IAM Configuration for GitHub Actions
# -----------------------------------

## Set Up OIDC Provider

resource "aws_iam_openid_connect_provider" "github_actions" {
# Create an IAM OIDC provider for GitHub Actions
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = var.github_thumbprint_list
}

## Define IAM Policy Documents

### Assume Role Policy Document

data "aws_iam_policy_document" "gha_assume_policy" {
# Generate policy documents for assuming IAM roles via OIDC
for_each = var.ecr_repositories

statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github_actions.arn]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:${each.value}:*"]
}
}
}

### Permissions Policy Document

data "aws_iam_policy_document" "gha_policy" {
# Define permissions for GitHub Actions to interact with ECR
for_each = var.ecr_repositories

# Allow Docker login to ECR
statement {
sid = "AllowDockerLogin"
effect = "Allow"
actions = ["ecr:GetAuthorizationToken"]
resources = ["*"]
}

# Allow pushing and pulling images to/from ECR
statement {
sid = "AllowPushPull"
effect = "Allow"
actions = [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage"
]
resources = [aws_ecr_repository.repositories[each.key].arn]
}
}

## Create IAM Roles for GitHub Actions

resource "aws_iam_role" "gha_role" {
# Create IAM roles for each ECR repository for GitHub Actions
for_each = var.ecr_repositories

name = "gh-actions-role-${each.key}"
assume_role_policy = data.aws_iam_policy_document.gha_assume_policy[each.key].json

# Attach inline policy for ECR permissions
inline_policy {
name = "GithubActionECRBuilds"
policy = data.aws_iam_policy_document.gha_policy[each.key].json
}
}

# -----------------------------------
# Cross-Account ECR Access Configuration
# -----------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
# See https://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/
variable "github_thumbprint_list" {
type = list(string)
description = "Github Thumbprint list"
default = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
"1c58a3a8518e8759bf075b76b750d4f2df264fcd"
]
}

variable "ecr_repositories" {
description = "Map of ECR repository names to their associated GitHub repository"
type = map(string)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions pillarbox-monitoring-terraform/21-continuous-delivery/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
locals {
ecs_cluster_name = "${var.application_name}-cluster"
is_prod = terraform.workspace == "prod"

default_tags = {
"srg-managed-by" = "terraform"
"srg-application" = var.application_name
"srg-owner" = "[email protected]"
"srg-businessowner" = "pillarbox"
"srg-environment" = terraform.workspace
}
}
158 changes: 158 additions & 0 deletions pillarbox-monitoring-terraform/21-continuous-delivery/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# -----------------------------------
# Terraform Configuration
# -----------------------------------

terraform {
# Backend configuration for storing the Terraform state in S3 with DynamoDB table for state locking
backend "s3" {
encrypt = true
bucket = "pillarbox-monitoring-tfstate"
key = "terraform/21-continuous-delivery/terraform.tfstate"
dynamodb_table = "pillarbox-monitoring-terraform-statelock"
profile = "prod"
}

# Specify required providers and their versions
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>5.4.0"
}
}
}

# -----------------------------------
# AWS Provider Setup
# -----------------------------------

provider "aws" {
# Apply default tags to all AWS resources
default_tags {
tags = local.default_tags
}
}

# -----------------------------------
# AWS Data Sources
# -----------------------------------

# Get current AWS region
data "aws_region" "current" {}

# Get current AWS identity
data "aws_caller_identity" "current" {}

# -----------------------------------
# IAM Configuration for GitHub Actions
# -----------------------------------

## Set Up OIDC Provider

resource "aws_iam_openid_connect_provider" "github_actions" {
# Create an IAM OIDC provider for GitHub Actions
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = var.github_thumbprint_list
}

## Define IAM Policy Documents

### Assume Role Policy Document

data "aws_iam_policy_document" "gha_assume_policy" {
# Generate policy documents for assuming IAM roles via OIDC
for_each = var.service_mappings

statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github_actions.arn]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:${each.value.github_repo_name}:*"]
}
}
}

### Permissions Policy Document

data "aws_iam_policy_document" "gha_policy" {
# Define permissions for GitHub Actions to interact with ECR and ECS
for_each = var.service_mappings

# Allow Docker login to ECR
dynamic "statement" {
for_each = local.is_prod ? [1] : []

content {
sid = "AllowDockerLogin"
effect = "Allow"
actions = ["ecr:GetAuthorizationToken"]
resources = ["*"]
}
}

# Allow pushing and pulling images to/from ECR
dynamic "statement" {
for_each = local.is_prod ? [1] : []

content {
sid = "AllowPushPull"
effect = "Allow"
actions = [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage"
]
resources = [
"arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/${each.value.ecr_image_name}"
]

}
}

# Allow updating ECS services
statement {
sid = "AllowUpdateService"
effect = "Allow"
actions = [
"ecs:UpdateService",
"ecs:DescribeServices"
]
resources = [
"arn:aws:ecs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:cluster/${local.ecs_cluster_name}",
"arn:aws:ecs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:service/${local.ecs_cluster_name}/${each.key}"
]
}
}

## Create IAM Roles for GitHub Actions

resource "aws_iam_role" "gha_role" {
# Create IAM roles for each service
for_each = var.service_mappings

name = "gh-actions-role-${each.key}"
assume_role_policy = data.aws_iam_policy_document.gha_assume_policy[each.key].json

# Attach inline policy for ECR and ECS permissions
inline_policy {
name = "GithubActionPermissions"
policy = data.aws_iam_policy_document.gha_policy[each.key].json
}
}


34 changes: 34 additions & 0 deletions pillarbox-monitoring-terraform/21-continuous-delivery/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
variable "application_name" {
description = "The name of the application"
type = string
default = "pillarbox-monitoring"
}

# See https://github.blog/changelog/2023-06-27-github-actions-update-on-oidc-integration-with-aws/
variable "github_thumbprint_list" {
type = list(string)
description = "Github Thumbprint list"
default = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
"1c58a3a8518e8759bf075b76b750d4f2df264fcd"
]
}

variable "service_mappings" {
description = "Service mapping to Github repository and ECR image name"
type = map(object({
github_repo_name = string
ecr_image_name = string
}))

default = {
"dispatch-service" = {
github_repo_name = "SRGSSR/pillarbox-event-dispatcher"
ecr_image_name = "pillarbox-event-dispatcher"
}
"data-transfer-service" = {
github_repo_name = "SRGSSR/pillarbox-monitoring-transfer"
ecr_image_name = "pillarbox-monitoring-transfer"
}
}
}