Skip to content

Commit

Permalink
Infra refactor (#86)
Browse files Browse the repository at this point in the history
* Refactor terraform

Setting up IAM for GHA to function should be part of the bootstrap process
and needs to be executed by an admin

* Remove import

* Rename deploy to apply
  • Loading branch information
arianvp committed Feb 19, 2024
1 parent 861d241 commit 796a1d4
Show file tree
Hide file tree
Showing 17 changed files with 2,218 additions and 613 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
name: Deploy
name: Plan and Apply
permissions:
id-token: write
contents: read
on:
push:
paths:
- 'tf/**'
- '.github/workflows/deploy.yml'
branches:
- main
pull_request:
paths:
- 'tf/**'
- '.github/workflows/deploy.yml'
branches:
- main
jobs:
Expand Down Expand Up @@ -67,7 +61,7 @@ jobs:
- uses: DeterminateSystems/magic-nix-cache-action@eeabdb06718ac63a7021c6132129679a8e22d0c7 # v3
- uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/deploy
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/apply
aws-region: ${{ vars.AWS_REGION }}
- name: Download plan
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4
Expand Down
28 changes: 14 additions & 14 deletions tf/.terraform.lock.hcl

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

30 changes: 30 additions & 0 deletions tf/assume_administrator_access_policy_document/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.37.0"
}
}
}

data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "this" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "AWS"
identifiers = [data.aws_caller_identity.current.account_id]
}
condition {
test = "ArnLike"
variable = "aws:PrincipalArn"
values = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_AdministratorAccess_*"]
}
}
}

output "json" {
value = data.aws_iam_policy_document.this.json
}
41 changes: 41 additions & 0 deletions tf/assume_github_actions_policy_document/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.37.0"
}
}
}

variable "subject_filter" {
type = list(string)
}

data "aws_caller_identity" "current" {}

data "aws_iam_openid_connect_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
}

data "aws_iam_policy_document" "assume_upload_ami" {

statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]

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

condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = var.subject_filter
}
}
}

output "json" {
value = data.aws_iam_policy_document.assume_upload_ami.json
}
20 changes: 20 additions & 0 deletions tf/bootstrap/.terraform.lock.hcl

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

File renamed without changes.
174 changes: 174 additions & 0 deletions tf/bootstrap/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.37.0"
}
}
}

variable "repo" {
type = string
}

data "aws_caller_identity" "current" {
}

resource "aws_iam_openid_connect_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"]
}

resource "aws_s3_bucket" "state" {
bucket_prefix = "tf-state"
force_destroy = true
}

resource "aws_dynamodb_table" "lock" {
name = "tf-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}

module "assume_administrator_access" {
providers = { aws = aws }
source = "../assume_administrator_access_policy_document"
}

module "assume_gha_plan" {
providers = { aws = aws }
source = "../assume_github_actions_policy_document"
depends_on = [aws_iam_openid_connect_provider.github_actions]
subject_filter = [
"repo:${var.repo}:pull_request",
"repo:${var.repo}:ref:refs/heads/main",
"repo:${var.repo}:environment:images",
"repo:${var.repo}:environment:infra",
]
}

data "aws_iam_policy_document" "assume_plan" {
source_policy_documents = [
module.assume_administrator_access.json,
module.assume_gha_plan.json,
]
}

data "aws_iam_policy_document" "state" {
statement {
effect = "Allow"
actions = [
"dynamodb:DescribeTable",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem",
]
resources = [aws_dynamodb_table.lock.arn]
}
statement {
effect = "Allow"
actions = ["s3:ListBucket"]
resources = [aws_s3_bucket.state.arn]

}
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
]
resources = ["${aws_s3_bucket.state.arn}/*"]

}
}

data "aws_iam_policy_document" "write_state" {
statement {
effect = "Allow"
actions = [
"s3:PutObject",
"s3:DeleteObject",
]
resources = ["${aws_s3_bucket.state.arn}/*"]
}
}

resource "aws_iam_policy" "write_state" {
name = "write-state"
policy = data.aws_iam_policy_document.write_state.json
}

resource "aws_iam_policy" "state" {
name = "state"
policy = data.aws_iam_policy_document.state.json
}

module "assume_gha_state" {
providers = { aws = aws }
source = "../assume_github_actions_policy_document"
depends_on = [aws_iam_openid_connect_provider.github_actions]
subject_filter = [
"repo:${var.repo}:environment:infra",
"repo:${var.repo}:environment:images",
"repo:${var.repo}:ref:refs/heads/main",
"repo:${var.repo}:pull_request",
]
}

data "aws_iam_policy_document" "assume_state" {
source_policy_documents = [
module.assume_administrator_access.json,
module.assume_gha_state.json,
]
}


resource "aws_iam_role" "state" {
name = "state"
assume_role_policy = data.aws_iam_policy_document.assume_state.json
managed_policy_arns = [aws_iam_policy.state.arn]
}

resource "aws_iam_role" "plan" {
name = "plan"
assume_role_policy = data.aws_iam_policy_document.assume_plan.json
managed_policy_arns = [
"arn:aws:iam::aws:policy/ReadOnlyAccess",
aws_iam_policy.state.arn,
aws_iam_policy.write_state.arn,
]
}

output "plan_role_arn" {
value = aws_iam_role.plan.arn
}

module "assume_gha_apply" {
providers = { aws = aws }
source = "../assume_github_actions_policy_document"
depends_on = [aws_iam_openid_connect_provider.github_actions]
subject_filter = ["repo:${var.repo}:environment:infra"]
}

data "aws_iam_policy_document" "assume_apply" {
source_policy_documents = [
module.assume_administrator_access.json,
module.assume_gha_apply.json,
]
}

resource "aws_iam_role" "apply" {
name = "apply"
assume_role_policy = data.aws_iam_policy_document.assume_apply.json
managed_policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess"]
}

output "apply_role_arn" {
value = aws_iam_role.apply.arn
}
File renamed without changes.
Loading

0 comments on commit 796a1d4

Please sign in to comment.