seahaven-ap/terraform/cognito.tf

199 lines
6.4 KiB
HCL

locals {
cognito_prefix_domain = "${local.project}-${var.environment}"
google_oidc = jsondecode(data.aws_secretsmanager_secret_version.google_oidc.secret_string)
google_oidc_client_id = local.google_oidc.client_id
google_oidc_client_secret = sensitive(local.google_oidc.client_secret)
app_origin = "https://${aws_cloudfront_distribution.web.domain_name}"
portal_callback_urls = [
"${local.app_origin}/api/auth/callback",
"http://127.0.0.1:8787/api/auth/callback",
]
portal_logout_urls = [
local.app_origin,
"http://127.0.0.1:3000/",
]
cognito_pool_id = aws_cognito_user_pool.portal.id
cognito_issuer = "https://cognito-idp.${var.aws_region}.amazonaws.com/${aws_cognito_user_pool.portal.id}"
cognito_client_id = aws_cognito_user_pool_client.portal.id
cognito_hosted_domain = "${aws_cognito_user_pool_domain.prefix.domain}.auth.${var.aws_region}.amazoncognito.com"
}
data "aws_secretsmanager_secret_version" "google_oidc" {
secret_id = aws_secretsmanager_secret.google_oidc.id
depends_on = [aws_secretsmanager_secret_version.google_oidc]
}
data "archive_file" "cognito_presignup" {
type = "zip"
source_file = "${path.module}/lambda/cognito-presignup/index.mjs"
output_path = "${path.module}/build/packages/cognito-presignup.zip"
}
resource "aws_s3_object" "cognito_presignup" {
bucket = aws_s3_bucket.artifacts.id
key = "functions/cognito-presignup.zip"
content_base64 = filebase64(data.archive_file.cognito_presignup.output_path)
source_hash = data.archive_file.cognito_presignup.output_base64sha256
}
resource "aws_cloudwatch_log_group" "cognito_presignup" {
name = "/aws/lambda/${local.project}-cognito-presignup"
retention_in_days = 14
}
data "aws_iam_policy_document" "lambda_assume" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "cognito_presignup" {
name = "${local.project}-cognito-presignup"
path = "/tf-managed/"
assume_role_policy = data.aws_iam_policy_document.lambda_assume.json
permissions_boundary = data.aws_iam_policy.ecs_task_boundary.arn
}
resource "aws_iam_role_policy_attachment" "cognito_presignup_basic" {
role = aws_iam_role.cognito_presignup.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "cognito_presignup" {
function_name = "${local.project}-cognito-presignup"
role = aws_iam_role.cognito_presignup.arn
handler = "index.handler"
runtime = "nodejs24.x"
architectures = ["arm64"]
memory_size = 128
timeout = 5
s3_bucket = aws_s3_bucket.artifacts.id
s3_key = aws_s3_object.cognito_presignup.key
source_code_hash = data.archive_file.cognito_presignup.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.cognito_presignup,
aws_iam_role_policy_attachment.cognito_presignup_basic,
]
}
resource "aws_cognito_user_pool" "portal" {
name = local.project
username_attributes = ["email"]
auto_verified_attributes = ["email"]
mfa_configuration = "OFF"
admin_create_user_config {
allow_admin_create_user_only = true
}
password_policy {
minimum_length = 32
require_lowercase = true
require_numbers = true
require_symbols = true
require_uppercase = true
temporary_password_validity_days = 1
}
account_recovery_setting {
recovery_mechanism {
name = "verified_email"
priority = 1
}
}
lambda_config {
pre_sign_up = aws_lambda_function.cognito_presignup.arn
}
tags = {
Project = local.project
}
}
resource "aws_lambda_permission" "cognito_presignup" {
statement_id = "AllowCognitoInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.cognito_presignup.function_name
principal = "cognito-idp.amazonaws.com"
source_arn = aws_cognito_user_pool.portal.arn
source_account = local.account_id
}
resource "aws_cognito_identity_provider" "google" {
user_pool_id = aws_cognito_user_pool.portal.id
provider_name = "Google"
provider_type = "Google"
lifecycle {
precondition {
condition = local.google_oidc_client_id != "replace-me" && local.google_oidc_client_secret != "replace-me"
error_message = "seahaven-ap/google-oidc still has the placeholder. Replace client_id and client_secret in Secrets Manager, then re-run the HCP apply."
}
}
provider_details = {
client_id = local.google_oidc_client_id
client_secret = local.google_oidc_client_secret
authorize_scopes = "openid email profile"
attributes_url = "https://people.googleapis.com/v1/people/me?personFields="
attributes_url_add_attributes = "true"
authorize_url = "https://accounts.google.com/o/oauth2/v2/auth"
oidc_issuer = "https://accounts.google.com"
token_url = "https://www.googleapis.com/oauth2/v4/token"
token_request_method = "POST"
}
attribute_mapping = {
email = "email"
name = "name"
username = "sub"
}
}
resource "aws_cognito_user_pool_client" "portal" {
name = local.project
user_pool_id = aws_cognito_user_pool.portal.id
generate_secret = false
allowed_oauth_flows_user_pool_client = true
allowed_oauth_flows = ["code"]
allowed_oauth_scopes = ["openid", "email", "profile"]
supported_identity_providers = ["COGNITO", "Google"]
explicit_auth_flows = ["ALLOW_REFRESH_TOKEN_AUTH", "ALLOW_USER_SRP_AUTH"]
enable_token_revocation = true
prevent_user_existence_errors = "ENABLED"
callback_urls = local.portal_callback_urls
logout_urls = local.portal_logout_urls
access_token_validity = 1
id_token_validity = 1
refresh_token_validity = 8
token_validity_units {
access_token = "hours"
id_token = "hours"
refresh_token = "hours"
}
depends_on = [aws_cognito_identity_provider.google]
}
resource "aws_cognito_user_pool_domain" "prefix" {
domain = local.cognito_prefix_domain
user_pool_id = aws_cognito_user_pool.portal.id
}