120 lines
3.5 KiB
Terraform
120 lines
3.5 KiB
Terraform
terraform {
|
|
required_version = ">= 1.9, < 1.10"
|
|
required_providers {
|
|
aws = {
|
|
source = "hashicorp/aws"
|
|
version = "~> 5.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
variable "consumer_repo" {
|
|
description = "The consumer repository (org/repo) — for the nova:contract tag."
|
|
type = string
|
|
default = "acdl/consumer-a"
|
|
}
|
|
|
|
variable "owner_id" {
|
|
description = "The owning team (for the nova:owner ABAC tag)."
|
|
type = string
|
|
default = "team-a"
|
|
}
|
|
|
|
variable "account_id" {
|
|
description = "The consumer's AWS account ID (where the deploy role is created)."
|
|
type = string
|
|
default = "000000000000"
|
|
}
|
|
|
|
variable "region" {
|
|
description = "AWS region."
|
|
type = string
|
|
default = "us-east-1"
|
|
}
|
|
|
|
provider "aws" {
|
|
region = var.region
|
|
}
|
|
|
|
# P20 (REQ-184): consumer deploy role — the role the consumer's CI runner
|
|
# assumes to invoke the platform Lambda + deploy via the reusable workflow.
|
|
# The trust policy allows the consumer's CI runner (GitHub Actions /
|
|
# Gitea act_runner) to assume this role. In a real deployment, the trust
|
|
# policy is scoped to the consumer's OIDC provider; for offline-proven
|
|
# mode, a placeholder trust is used.
|
|
resource "aws_iam_role" "consumer_deploy" {
|
|
name = "nova-${replace(var.consumer_repo, "/", "-")}-deploy"
|
|
|
|
assume_role_policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Principal = {
|
|
# Placeholder: in a real deployment, this is the consumer's
|
|
# OIDC provider ARN. Offline-proven mode uses a wildcard.
|
|
Federated = "arn:aws:iam::${var.account_id}:oidc-provider/token.actions.githubusercontent.com"
|
|
}
|
|
Action = "sts:AssumeRoleWithWebIdentity"
|
|
Condition = {
|
|
StringEquals = {
|
|
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
|
|
}
|
|
StringLike = {
|
|
"token.actions.githubusercontent.com:sub" = "repo:${var.consumer_repo}:*"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
|
|
tags = {
|
|
"nova:owner" = var.owner_id
|
|
"nova:contract" = var.consumer_repo
|
|
"nova:environment" = "dev"
|
|
}
|
|
}
|
|
|
|
# P20 (REQ-184): inline policy granting the consumer's deploy role the
|
|
# right to invoke the platform Lambda's Function URL, scoped via ABAC
|
|
# (aws:PrincipalTag/nova:owner == var.owner_id). The platform Lambda's
|
|
# resource-based policy + the consumer_invoke_policy.json template
|
|
# enforce the ABAC scope at the Lambda side; this policy grants the
|
|
# invoke permission on the consumer side.
|
|
resource "aws_iam_role_policy" "consumer_invoke" {
|
|
name = "nova-consumer-invoke"
|
|
role = aws_iam_role.consumer_deploy.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"lambda:InvokeFunctionUrl",
|
|
]
|
|
Resource = [
|
|
# The platform Lambda ARN (cross-account). The account_id is
|
|
# the platform account, not the consumer account. For offline-
|
|
# proven mode, a placeholder ARN is used.
|
|
"arn:aws:lambda:${var.region}:000000000000:function:nova-contract-ingestor"
|
|
]
|
|
Condition = {
|
|
StringEquals = {
|
|
"aws:PrincipalTag/nova:owner" = var.owner_id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
output "consumer_deploy_role_arn" {
|
|
description = "The ARN of the consumer deploy role."
|
|
value = aws_iam_role.consumer_deploy.arn
|
|
}
|
|
|
|
output "consumer_deploy_role_name" {
|
|
description = "The name of the consumer deploy role."
|
|
value = aws_iam_role.consumer_deploy.name
|
|
} |