Skip to content

updating terraform based deployment #1

Merged
merged 1 commit into from
Apr 15, 2025
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
19 changes: 19 additions & 0 deletions .github/workflows/gh-token.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: GitHub Token Refresh

on:
schedule:
- cron: '*/5 * * * *' # Runs every 5 minutes
workflow_dispatch: # Allows manual triggering

jobs:
refresh-token:
name: Refresh GitHub Token
uses: CSVD/centralized-actions/.github/workflows/upload-github-token.yml@main
with:
aws_region: 'us-east-1'
secret_name: '/dev/eks_automation_github_token' # This matches the SECRET_NAME in app.py
github_app_id: ${{ vars.GITHUB_APP_ID }}
github_installation_id: ${{ vars.GITHUB_INSTALLATION_ID }}
use_ecs_credentials: true
secrets:
github_app_private_key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,6 @@ cython_debug/
artifacts/

.aws-sam

terraform_data_dirs
terraform.tfstate.d
42 changes: 42 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.PHONY: init venv install-deps clean terraform-init terraform-plan terraform-apply package all

PYTHON=python3
PIP=pip3
TERRAFORM=terraform
VENV=.venv
VENV_BIN=$(VENV)/bin
VENV_PIP=$(VENV_BIN)/pip

# Set PIP_CONFIG_FILE to use custom pip.conf
export PIP_CONFIG_FILE=$(CURDIR)/scripts/pip.conf

all: venv install-deps package terraform-apply

venv:
test -d $(VENV) || $(PYTHON) -m venv $(VENV)
$(VENV_PIP) install --upgrade pip setuptools wheel

install-deps: venv
source $(VENV_BIN)/activate && $(VENV_PIP) install -r scripts/requirements.txt

clean:
rm -rf dist/
rm -f *.zip
rm -rf __pycache__/
rm -rf .terraform/
rm -rf $(VENV)

package: venv
source $(VENV_BIN)/activate && chmod +x scripts/package.sh && ./scripts/package.sh

terraform-init:
$(TERRAFORM) init

terraform-plan: terraform-init
$(TERRAFORM) plan

terraform-apply: terraform-init package
$(TERRAFORM) apply -auto-approve

terraform-destroy:
$(TERRAFORM) destroy -auto-approve
Empty file added backend.tf
Empty file.
227 changes: 227 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
provider "aws" {
default_tags = {
organization = "census:ocio:csvd"
finops_project_name = "csvd_platformbaseline"
finops_project_number = "fs0000000078"
finops_project_role = "csvd_platformbaseline_app"
}
}

locals {
common_tags = {
environment = var.environment
environment_abbr = var.environment_abbr
organization = var.organization
finops_project_name = var.finops_project_name
finops_project_number = var.finops_project_number
finops_project_role = var.finops_project_role
}
}

# API Gateway
resource "aws_api_gateway_rest_api" "eks_automation" {
name = "eks-automation-api"
tags = local.common_tags
}

resource "aws_api_gateway_resource" "eks_automation" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
parent_id = aws_api_gateway_rest_api.eks_automation.root_resource_id
path_part = "EKSAutomation"
}

resource "aws_api_gateway_method" "eks_automation" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = "POST"
authorization = "NONE"
api_key_required = true
}

resource "aws_api_gateway_integration" "lambda" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = aws_api_gateway_method.eks_automation.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.eks_automation.invoke_arn
}

resource "aws_api_gateway_deployment" "eks_automation" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
depends_on = [aws_api_gateway_integration.lambda]
}

resource "aws_api_gateway_stage" "prod" {
deployment_id = aws_api_gateway_deployment.eks_automation.id
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
stage_name = "Prod"
}

resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.eks_automation.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.eks_automation.execution_arn}/*/*"
}

resource "aws_api_gateway_method" "options" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = "OPTIONS"
authorization = "NONE"
}

resource "aws_api_gateway_integration" "options" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = aws_api_gateway_method.options.http_method
type = "MOCK"
request_templates = {
"application/json" = "{\"statusCode\": 200}"
}
}

resource "aws_api_gateway_method_response" "options" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = aws_api_gateway_method.options.http_method
status_code = "200"

response_parameters = {
"method.response.header.Access-Control-Allow-Headers" = true,
"method.response.header.Access-Control-Allow-Methods" = true,
"method.response.header.Access-Control-Allow-Origin" = true
}
}

resource "aws_api_gateway_integration_response" "options" {
rest_api_id = aws_api_gateway_rest_api.eks_automation.id
resource_id = aws_api_gateway_resource.eks_automation.id
http_method = aws_api_gateway_method.options.http_method
status_code = aws_api_gateway_method_response.options.status_code

response_parameters = {
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,Authorization'",
"method.response.header.Access-Control-Allow-Methods" = "'POST,OPTIONS'",
"method.response.header.Access-Control-Allow-Origin" = "'*'"
}
}

resource "aws_api_gateway_usage_plan" "eks_automation" {
name = "eks-automation-usage-plan"
description = "Usage plan for EKS Automation API"

api_stages {
api_id = aws_api_gateway_rest_api.eks_automation.id
stage = aws_api_gateway_stage.prod.stage_name
}

quota_settings {
limit = 5000
period = "MONTH"
}

throttle_settings {
burst_limit = 500
rate_limit = 100
}

tags = local.common_tags
}

resource "aws_api_gateway_api_key" "eks_automation" {
name = "eks-automation-api-key"
}

resource "aws_api_gateway_usage_plan_key" "eks_automation" {
key_id = aws_api_gateway_api_key.eks_automation.id
key_type = "API_KEY"
usage_plan_id = aws_api_gateway_usage_plan.eks_automation.id
}

# Lambda Layer
resource "aws_lambda_layer_version" "git" {
filename = "layer.zip" # Make sure to create this zip file with Git binaries
layer_name = "git-lambda-layer"
description = "Git Lambda Layer"
compatible_runtimes = ["python3.9", "python3.10", "python3.11"]
}

# Lambda Function
resource "aws_lambda_function" "eks_automation" {
filename = "eks_automation.zip" # Make sure to create this zip file
function_name = "eks-automation"
role = aws_iam_role.lambda_role.arn
handler = "app.lambda_handler"
runtime = "python3.11"
timeout = var.lambda_timeout

vpc_config {
subnet_ids = var.vpc_subnet_ids
security_group_ids = var.vpc_security_group_ids
}

layers = [aws_lambda_layer_version.git.arn]

environment {
variables = {
ENVIRONMENT = var.environment
}
}

tags = local.common_tags
}

# IAM Role for Lambda
resource "aws_iam_role" "lambda_role" {
name = "eks-automation-lambda-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})

tags = local.common_tags
}

# IAM Policies
resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
role = aws_iam_role.lambda_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}

resource "aws_iam_role_policy" "lambda_ssm_access" {
name = "eks-automation-ssm-access"
role = aws_iam_role.lambda_role.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "SSMDescribeParametersPolicy"
Effect = "Allow"
Action = ["ssm:DescribeParameters"]
Resource = "*"
},
{
Sid = "SSMGetParameterPolicy"
Effect = "Allow"
Action = [
"ssm:GetParameters",
"ssm:GetParameter"
]
Resource = "*"
}
]
})
}
10 changes: 10 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
output "api_endpoint" {
description = "API Gateway endpoint URL"
value = "${aws_api_gateway_stage.prod.invoke_url}${aws_api_gateway_resource.eks_automation.path}"
}

output "api_key" {
description = "API Key for accessing the endpoint"
value = aws_api_gateway_api_key.eks_automation.value
sensitive = true
}
9 changes: 0 additions & 9 deletions samconfig.toml

This file was deleted.

24 changes: 24 additions & 0 deletions scripts/package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

# Create temporary directories
mkdir -p dist/lambda
mkdir -p dist/layer

# Package Lambda function
cp -r eks_automation/* dist/lambda/
cd dist/lambda
zip -r ../eks_automation.zip .
cd ../..

# Package Lambda layer
mkdir -p dist/layer/python
pip install -r eks_automation/requirements.txt -t dist/layer/python
cd dist/layer
zip -r ../layer.zip .
cd ../..

# Move zip files to root
mv dist/*.zip .

# Cleanup
rm -rf dist
10 changes: 10 additions & 0 deletions scripts/pip.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[global]
cert = /etc/pki/ca-trust/source/anchors/katello-server-ca.pem
#proxy = http://proxy.tco.census.gov:3128
index = https://nexus.it.census.gov:8443/repository/DataScience-Group/pypi
index-url = https://nexus.it.census.gov:8443/repository/DataScience-Group/simple
trusted-host = nexus.it.census.gov
pypi.python.org
pypi.org
files.pythonhosted.org
proxy.tco.census.gov
5 changes: 5 additions & 0 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Jinja2>=3.1.0
PyGithub>=2.1.1
GitPython>=3.1.40
boto3>=1.34.0
botocore>=1.34.0
Loading