Skip to content
Draft
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
15 changes: 13 additions & 2 deletions infrastructure/aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

| Name | Version |
|------|---------|
| <a name="provider_archive"></a> [archive](#provider\_archive) | n/a |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 6.14.1 |
| <a name="provider_infisical"></a> [infisical](#provider\_infisical) | n/a |

Expand All @@ -25,7 +26,18 @@ No modules.
| [aws_cognito_user_pool.branch_user_pool](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/cognito_user_pool) | resource |
| [aws_cognito_user_pool_client.branch_client](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/cognito_user_pool_client) | resource |
| [aws_db_instance.branch_rds](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/db_instance) | resource |
| [aws_iam_role.lambda_role](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.lambda_basic](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/iam_role_policy_attachment) | resource |
| [aws_lambda_function.functions](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/lambda_function) | resource |
| [aws_s3_bucket.lambda_deployments](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket) | resource |
| [aws_s3_bucket.reports_bucket](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket) | resource |
| [aws_s3_bucket_policy.reports_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket_policy) | resource |
| [aws_s3_bucket_public_access_block.reports_bucket_public_access](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket_public_access_block) | resource |
| [aws_s3_bucket_server_side_encryption_configuration.lambda_deployments](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket_server_side_encryption_configuration) | resource |
| [aws_s3_bucket_versioning.lambda_deployments](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_bucket_versioning) | resource |
| [aws_s3_object.lambda_placeholder](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/resources/s3_object) | resource |
| [archive_file.lambda_placeholder](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/6.14.1/docs/data-sources/caller_identity) | data source |
| [infisical_secrets.rds_folder](https://registry.terraform.io/providers/infisical/infisical/latest/docs/data-sources/secrets) | data source |

## Inputs
Expand All @@ -40,9 +52,8 @@ No modules.

| Name | Description |
|------|-------------|
| <a name="output_cognito_client_id"></a> [cognito\_client\_id](#output\_cognito\_client\_id) | Cognito User Pool Client ID |
| <a name="output_cognito_region"></a> [cognito\_region](#output\_cognito\_region) | AWS Region for Cognito |
| <a name="output_cognito_user_pool_arn"></a> [cognito\_user\_pool\_arn](#output\_cognito\_user\_pool\_arn) | Cognito User Pool ARN |
| <a name="output_cognito_user_pool_endpoint"></a> [cognito\_user\_pool\_endpoint](#output\_cognito\_user\_pool\_endpoint) | Cognito User Pool Endpoint |
| <a name="output_cognito_user_pool_id"></a> [cognito\_user\_pool\_id](#output\_cognito\_user\_pool\_id) | Cognito User Pool ID |
| <a name="output_reports_bucket_name"></a> [reports\_bucket\_name](#output\_reports\_bucket\_name) | Name of the S3 bucket for generated reports |
<!-- END_TF_DOCS -->
107 changes: 107 additions & 0 deletions infrastructure/aws/lambda.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# IAM role for Lambda functions
resource "aws_iam_role" "lambda_role" {
name = "branch-lambda-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
}]
})
}

# Attach basic execution policy for CloudWatch Logs
resource "aws_iam_role_policy_attachment" "lambda_basic" {
role = "aws_iam_role.lambda_role.name"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm this should be quoted? i think this might error on apply

policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also just wanting to confirm this is correct arn for the aws managed role

}

# Get AWS account ID for unique bucket naming
data "aws_caller_identity" "current" {}

resource "aws_s3_bucket" "lambda_deployments" {
bucket = "branch-lambda-deployments-${data.aws_caller_identity.current.account_id}"
}

resource "aws_s3_bucket_versioning" "lambda_deployments" {
bucket = aws_s3_bucket.lambda_deployments.id

versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "lambda_deployments" {
bucket = aws_s3_bucket.lambda_deployments.id

rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

# Define all Lambda functions in one place
locals {
lambda_functions = toset([
"projects",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think auth is missing here? also what do you think of generating this list dynamically from the list of folders in lambdas? open to either design just curious

"reports",
"users",
"donors",
"expenditures"
])
}

# Minimal placeholder that will be replaced by GitHub Actions on first deployment
data "archive_file" "lambda_placeholder" {
type = "zip"
output_path = "$${path.module}/lambda-placeholder.zip"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the double "$" here? is this escaping the first "$"? please confirm

source {
content = "exports.handler = async () => ({ statusCode: 200, body: JSON.stringify({ message: 'Placeholder - will be replaced by CI/CD' }) });"
filename = "handler.js"
}
}

# This allows Terraform to create the Lambda functions initially
resource "aws_s3_object" "lambda_placeholder" {
for_each = local.lambda_functions

bucket = aws_s3_bucket.lambda_deployments.id
key = "${each.key}/initial.zip"
source = data.archive_file.lambda_placeholder.output_path

content_type = "application/zip"
}

# Create all Lambda functions with a single resource block
resource "aws_lambda_function" "functions" {
for_each = local.lambda_functions

function_name = "branch-${each.key}"
runtime = "nodejs20.x"
handler = "handler.handler"
timeout = 30
memory_size = 256
role = aws_iam_role.lambda_role.arn

# Use S3 for deployment (initial placeholder, replaced by GitHub Actions)
s3_bucket = aws_s3_bucket.lambda_deployments.id
s3_key = aws_s3_object.lambda_placeholder[each.key].key

# Prevent Terraform from reverting code deployments made by GitHub Actions
lifecycle {
ignore_changes = [s3_key]
}

environment {
variables = {
NODE_ENV = "production"
DB_HOST = aws_db_instance.branch_rds.address
DB_USER = data.infisical_secrets.rds_folder.secrets["username"].value
DB_PASSWORD = data.infisical_secrets.rds_folder.secrets["password"].value
DB_PORT = try(data.infisical_secrets.rds_folder.secrets["db_port"].value, "5432")
DB_NAME = try(data.infisical_secrets.rds_folder.secrets["db_name"].value, aws_db_instance.branch_rds.db_name)
}
}
}
Loading