From 9b88190f81a6d1d3f72730d887b21ee915ad921a Mon Sep 17 00:00:00 2001 From: Colin Hutchinson Date: Tue, 12 Sep 2023 10:28:45 -0400 Subject: [PATCH] feat(spec-tests): introduce aws spec tests --- .github/workflows/spec-tests.yaml | 23 +++++++++++ infrastructure/README.md | 67 +++++++++++++++++++++++++++++++ infrastructure/backend.tf | 7 ++++ infrastructure/main.tf | 57 ++++++++++++++++++++++++++ infrastructure/providers.tf | 3 ++ infrastructure/variables.tf | 0 infrastructure/versions.tf | 13 ++++++ 7 files changed, 170 insertions(+) create mode 100644 .github/workflows/spec-tests.yaml create mode 100644 infrastructure/README.md create mode 100644 infrastructure/backend.tf create mode 100644 infrastructure/main.tf create mode 100644 infrastructure/providers.tf create mode 100644 infrastructure/variables.tf create mode 100644 infrastructure/versions.tf diff --git a/.github/workflows/spec-tests.yaml b/.github/workflows/spec-tests.yaml new file mode 100644 index 0000000..cdda1eb --- /dev/null +++ b/.github/workflows/spec-tests.yaml @@ -0,0 +1,23 @@ +name: Run AWS Spec tests + +on: + workflow_dispatch: + schedule: + - cron: "0 13 * * 1" # Every Monday + +permissions: + contents: write + id-token: write + packages: write + +jobs: + run-aws-test-kitchen: + uses: observeinc/aws-test-kitchen/.github/workflows/ci.yml@main + with: + test_type: terraform + code_sha: ${{ github.sha }} + secrets: + OBSERVE_CUSTOMER: ${{ secrets.OBSERVE_CUSTOMER }} + OBSERVE_TOKEN: ${{ secrets.OBSERVE_TOKEN }} + OBSERVE_DOMAIN: ${{ secrets.OBSERVE_DOMAIN }} + AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }} diff --git a/infrastructure/README.md b/infrastructure/README.md new file mode 100644 index 0000000..2794726 --- /dev/null +++ b/infrastructure/README.md @@ -0,0 +1,67 @@ +# CloudFormation AWS Collection Infrastructure + +This directory contains a Terraform module responsible for setting up the necessary infrastructure to allow GitHub Actions to release CloudFormation templates to an S3 bucket using OIDC for authentication. This ensures a seamless integration between the CI/CD pipeline and AWS services. + +## Usage + +Changes to this module are not automatically applied. After merging changes, you should manually apply them. + +### Requirements + +- **AWS Credentials**: Ensure that you have AWS credentials set up with permissions to create IAM roles, OIDC providers, and manage the specified S3 bucket. + +- **GitHub Access Token**: Set the `GITHUB_TOKEN` environment variable to a GitHub access token with at least the `repo` scope. This token should also have permission to set repository secrets. + +### Setup + +1. Initialize the Terraform directory: + + ```bash + terraform init + ``` + +2. Verify your AWS identity to ensure you're acting as the expected user or role: + + ```bash + aws sts get-caller-identity + ``` + + Check the output to ensure your ARN and account match your expectations. + +3. Plan your Terraform changes: + + ```bash + terraform plan -out=tfplan + ``` + + Review the plan to see what changes will be made. Make sure everything aligns with your intentions. + +4. Apply the Terraform changes: + + ```bash + terraform apply tfplan + ``` + + If everything looks correct, approve the changes to apply them. + +### Destroy + +To tear down the resources created by this module (use with caution): + +```bash +terraform destroy +``` + +## Contents + +### GitHub Actions Integration + +- Sets up an OIDC provider in AWS to allow GitHub Actions to authenticate. + +- Creates an IAM role with permissions that allow GitHub Actions to release CloudFormation templates to the specified S3 bucket. + +- Configures GitHub Actions variables in the repository with the ARN of the IAM role so that it can be used. + +### S3 Bucket Management + +- Grants necessary permissions to the IAM role to read from and write to the specified S3 bucket. diff --git a/infrastructure/backend.tf b/infrastructure/backend.tf new file mode 100644 index 0000000..58ea09c --- /dev/null +++ b/infrastructure/backend.tf @@ -0,0 +1,7 @@ +terraform { + backend "s3" { + bucket = "observe-github-tf-state" + region = "us-west-2" + key = "github.com/observeinc/terraform-aws-collection" + } +} diff --git a/infrastructure/main.tf b/infrastructure/main.tf new file mode 100644 index 0000000..64cf8bd --- /dev/null +++ b/infrastructure/main.tf @@ -0,0 +1,57 @@ +locals { + organization = "observeinc" + repository = "terraform-aws-collection" +} + +data "aws_iam_openid_connect_provider" "github_actions" { + url = "https://token.actions.githubusercontent.com" +} + +locals { + oidc_claim_prefix = trimprefix(data.aws_iam_openid_connect_provider.github_actions.url, "https://") +} + +data "aws_iam_policy_document" "github_actions_assume_role" { + statement { + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = [data.aws_iam_openid_connect_provider.github_actions.arn] + } + + condition { + test = "StringLike" + variable = "${local.oidc_claim_prefix}:sub" + values = ["repo:${local.organization}/${local.repository}:*"] + } + + condition { + test = "StringEquals" + variable = "${local.oidc_claim_prefix}:aud" + values = ["sts.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "github_actions_ci" { + name = "${local.repository}-gha-ci" + + assume_role_policy = data.aws_iam_policy_document.github_actions_assume_role.json + + tags = { + Principal = "GitHub Actions" + Repository = "${local.organization}/${local.repository}" + } +} + +resource "aws_iam_role_policy_attachment" "admin_policy_attachment" { + role = aws_iam_role.github_actions_ci.name + policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" +} + +resource "github_actions_secret" "aws_ci_role" { + repository = local.repository + secret_name = "AWS_ROLE_ARN" + plaintext_value = aws_iam_role.github_actions_ci.arn +} diff --git a/infrastructure/providers.tf b/infrastructure/providers.tf new file mode 100644 index 0000000..3d01354 --- /dev/null +++ b/infrastructure/providers.tf @@ -0,0 +1,3 @@ +provider "github" { + owner = local.organization +} diff --git a/infrastructure/variables.tf b/infrastructure/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/infrastructure/versions.tf b/infrastructure/versions.tf new file mode 100644 index 0000000..4e4e016 --- /dev/null +++ b/infrastructure/versions.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + github = { + source = "integrations/github" + version = "~> 5" + } + + aws = { + source = "hashicorp/aws" + version = "~> 5" + } + } +}