Skip to content

Commit

Permalink
Migrate Terraform to use Github App (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
gomez385 committed Oct 2, 2024
1 parent 12e3f21 commit 8e678b0
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 17 deletions.
15 changes: 10 additions & 5 deletions .github/workflows/terraform_plan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
runs-on: [ "229685449397" ]

env:
# GITHUB_APP_ID: ${{ vars.GH_APP_ID }}
# GITHUB_APP_INSTALLATION_ID: ${{ vars.GH_APP_INSTALLATION_ID }}
# GITHUB_APP_PEM_FILE: ${{ secrets.GH_APP_PEM_FILE }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
# GITHUB_APP_ID: ${{ vars.GH_APP_ID }}
GITHUB_APP_INSTALLATION_ID: ${{ vars.GH_APP_INSTALLATION_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.GH_APP_PEM_FILE }}
# GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_OWNER: CSVD
GITHUB_BASE_URL: https://github.e.it.census.gov/
TF_WORKSPACE: ${{ vars.terraform_workspace }}
Expand Down Expand Up @@ -48,7 +48,12 @@ jobs:
echo AWS_SECRET_ACCESS_KEY=`jq -r '.SecretAccessKey' aws_credentials.json` >> $GITHUB_ENV
aws configure set aws_session_token `jq -r '.Token' aws_credentials.json`
echo AWS_SESSION_TOKEN=`jq -r '.Token' aws_credentials.json` >> $GITHUB_ENV
- name: Setup GITHUB Credentials
id: github_credentials
run: |
echo GITHUB_TOKEN=$(python encode_jwt.py "$GITHUB_APP_PEM_FILE" "$GITHUB_APP_INSTALLATION_ID" "$GITHUB_BASE_URL") >> $GITHUB_ENV
- name: Terraform Init
id: init
run: /opt/tfenv/bin/terraform init -upgrade
Expand Down
2 changes: 0 additions & 2 deletions data.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
data "aws_region" "current" {}

data "github_organization_teams" "teams" {}
80 changes: 80 additions & 0 deletions encode_jwt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
## Run this script set the private key as github_app_private_key and installation_id as the installation id of the app

#export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt
#export github_app_private_key="-----BEGIN"
#export github_app_installation_id=11
#export github_app_url=https://github.e.it.census.gov
#export GITHUB_TOKEN=$(python encode_jwt.py "$github_app_private_key" "$github_app_installation_id" "$github_app_url")

import time
import json
import base64
import argparse
import requests
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_private_key
import sys

# Set up argument parser
parser = argparse.ArgumentParser(description='Encode JWT with RS256 and get GitHub Enterprise installation access token')
parser.add_argument('private_key', type=str, help='PEM formatted private key string')
parser.add_argument('installation_id', type=str, help='GitHub App Installation ID')
parser.add_argument('enterprise_url', type=str, help='GitHub Enterprise API URL (e.g., https://github.e.it.census.gov)')
args = parser.parse_args()

# Load the PEM private key
private_key = load_pem_private_key(args.private_key.encode(), password=None)

# JWT Header
header = {
"alg": "RS256",
"typ": "JWT"
}

# JWT Payload
payload = {
"iat": int(time.time()),
"exp": int(time.time()) + (10 * 60),
"iss": "6" # Replace with your actual GitHub App ID
}

# Encode Header and Payload as Base64
header_encoded = base64.urlsafe_b64encode(json.dumps(header).encode()).decode().rstrip("=")
payload_encoded = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")

# Create the message (header + payload)
message = f"{header_encoded}.{payload_encoded}".encode()

# Sign the message using RS256
signature = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA256()
)

# Encode the signature in Base64
signature_encoded = base64.urlsafe_b64encode(signature).decode().rstrip("=")

# Construct the full JWT
jwt_token = f"{header_encoded}.{payload_encoded}.{signature_encoded}"

# Prepare the request to get the installation access token
headers = {
"Authorization": f"Bearer {jwt_token}",
"Accept": "application/vnd.github+json"
}

# Make the request to the GitHub Enterprise API to get the installation access token
url = f"{args.enterprise_url}api/v3/app/installations/{args.installation_id}/access_tokens"
response = requests.post(url, headers=headers)

# Check if the request was successful
if response.status_code == 201:
installation_access_token = response.json().get('token')
print(installation_access_token) # Output the token only
else:
# Raise an error with a message
sys.stderr.write(f"Error: Failed to get installation access token. Status code: {response.status_code}\n")
sys.stderr.write(f"{response.text}\n")
sys.exit(1) # Exit with an error code
6 changes: 3 additions & 3 deletions image-pipeline.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module "asset_releases" {
github_repo_description = "Terraform Workspace for publishing image-pipeline-assets"
repo_org = "CSVD"
name = "image-pipeline-asset-releases"
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
github_repo_topics = [
"terraform"
]
Expand All @@ -68,7 +68,7 @@ module "aws_image_pipeline" {
github_repo_description = "Terraform Workspace for creating and managing AWS Image Pipelines"
repo_org = "CSVD"
name = "aws-image-pipeline"
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
github_repo_topics = [
"terraform"
]
Expand Down Expand Up @@ -112,7 +112,7 @@ module "terraform_aws_image_pipeline" {
github_repo_description = "Terraform Module that creates codepipeline and codebuild jobs and other resources for building and deploying images"
repo_org = "CSVD"
name = "terraform-aws-image-pipeline"
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
github_repo_topics = [
"terraform"
]
Expand Down
8 changes: 4 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module "elastic_beanstalk" {
enforce_prs = false
collaborators = local.collaborators
pull_request_bypassers = local.pull_request_bypassers
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
}


Expand Down Expand Up @@ -273,7 +273,7 @@ module "setup_terraform" {
create_codeowners = false
enforce_prs = false
collaborators = local.collaborators
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
}

module "setup_node" {
Expand All @@ -289,7 +289,7 @@ module "setup_node" {
create_codeowners = false
enforce_prs = false
collaborators = local.collaborators
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
}

# ghe-runner
Expand All @@ -306,7 +306,7 @@ module "ghe_runners" {
create_codeowners = false
enforce_prs = false
collaborators = local.collaborators
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
}

module "vpc_services" {
Expand Down
2 changes: 1 addition & 1 deletion morpheus.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module "morpheus_repos" {
source = "HappyPathway/repo/github"
#github_codeowners_team = "CSVD"
github_repo_description = "Repo for morpheus cloud"
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
repo_org = "CSVD"
name = each.value
github_repo_topics = [
Expand Down
18 changes: 18 additions & 0 deletions repolist.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module "repo_list" {
source = "HappyPathway/repo/github"
for_each = tomap({ for repo in var.repolist : repo.name => repo })
#github_codeowners_team = "CSVD"
github_repo_description = each.value.description
repo_org = each.value.repo_org
name = each.value.name
github_repo_topics = [
"terraform"
]
is_template = each.value.is_template
force_name = true
create_codeowners = false
enforce_prs = each.value.enforce_prs
collaborators = local.collaborators
pull_request_bypassers = local.pull_request_bypassers
github_org_teams = local.github_organization_teams
}
2 changes: 1 addition & 1 deletion sandbox.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module "sandbox" {
create_codeowners = false
enforce_prs = false
collaborators = { "arnol377" : "admin" }
github_org_teams = local.github_organization_teams
github_org_teams = local.github_organization_teams
managed_extra_files = [
{
path = ".github/workflows/terraform-plan.yaml"
Expand Down
Empty file removed varfiles/default
Empty file.
14 changes: 14 additions & 0 deletions varfiles/default.tfvars
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
image_pipeline_workflows = {
"image-pipeline-goss-testing" = "./workflows/goss-testing.yaml"
}

repolist = [
{
description = "Managing AWS CSVD Secrets"
repo_org = "CSVD"
name = "aws-secrets"
},
{
description = "Tools for managing Terraform"
repo_org = "CSVD"
name = "tf-tools"
}
]

12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
variable "image_pipeline_workflows" {
type = map(string)
}

variable "repolist" {
type = list(object({
description = string
repo_org = string
name = string
is_template = optional(bool, false)
create_codeowners = optional(bool, false)
enforce_prs = optional(bool, false)
}))
default = []
}
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
random = {
source = "integrations/github"
version = ">= 6.2.2"
version = ">= 6.3.0"
}
aws = {
source = "hashicorp/aws"
Expand Down

0 comments on commit 8e678b0

Please sign in to comment.