Skip to content

Commit

Permalink
chore: end-of-session commit (3 files changed)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Arnold committed Jun 4, 2026
1 parent 9f88515 commit 4e84069
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
61 changes: 61 additions & 0 deletions deploy/stacksets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ---------------------------------------------------------------------------
# CloudFormation StackSet: sc-automation-codebuild-role
#
# Deploys an IAM cross-account role to every account in the target OU so the
# tf-run-executor CodeBuild project in csvd-dev can assume it to run Terraform
# in each target account.
#
# PREREQUISITE: SERVICE_MANAGED StackSets can only be managed from the AWS
# Organizations management account OR a delegated CloudFormation StackSets
# administrator account. If csvd-dev (229685449397) is not one of those, apply
# this module with credentials for the management/delegated-admin account by
# either:
# - setting AWS_PROFILE to a management-account profile, or
# - adding `assume_role { role_arn = "..." }` to the provider in provider.tf.
#
# Auto-deployment is enabled: accounts joining the OU automatically receive the
# role. Accounts removed from the OU lose the role (retain = false).
# ---------------------------------------------------------------------------

resource "aws_cloudformation_stack_set" "sc_automation_role" {
name = "sc-automation-codebuild-role"
description = "Deploys sc-automation-codebuild-role IAM role to all accounts in the target OU"

permission_model = "SERVICE_MANAGED"

auto_deployment {
enabled = true
retain_stacks_on_account_removal = false
}

capabilities = ["CAPABILITY_NAMED_IAM"]

# Template is rendered inline from the file so no S3 dependency is required.
template_body = file("${path.module}/../service-catalog/stackset-sc-automation-codebuild-role.yaml")

parameters = {
CodeBuildAccountId = var.codebuild_account_id
}

tags = {
Project = "sc-automation"
ManagedBy = "terraform"
}
}

resource "aws_cloudformation_stack_set_instance" "sc_automation_role" {
stack_set_name = aws_cloudformation_stack_set.sc_automation_role.name
region = data.aws_region.current.name

# Target the entire OU; CloudFormation resolves account membership dynamically.
deployment_targets {
organizational_unit_ids = [var.stackset_target_ou_id]
}

# Allow up to 5 concurrent stack instance deployments; tolerate no failures
# so a bad account never silently goes un-deployed.
operation_preferences {
failure_tolerance_count = 0
max_concurrent_count = 5
}
}
12 changes: 12 additions & 0 deletions deploy/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,15 @@ variable "principal_arns" {
type = list(string)
default = []
}

variable "stackset_target_ou_id" {
description = "AWS Organizations OU ID to target with the sc-automation-codebuild-role StackSet (e.g. \"ou-xxxx-xxxxxxxx\")"
type = string
# e.g. "ou-xxxx-xxxxxxxx"
}

variable "codebuild_account_id" {
description = "AWS account ID of the csvd-dev account where tf-run-executor-codebuild runs; used as the trust principal in the cross-account role"
type = string
default = "229685449397"
}
61 changes: 61 additions & 0 deletions service-catalog/stackset-sc-automation-codebuild-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
AWSTemplateFormatVersion: "2010-09-09"
Description: >
Deploys sc-automation-codebuild-role in each target account via a SERVICE_MANAGED
CloudFormation StackSet. Every account in the target OU receives the role
automatically. New accounts joining the OU get the role on vending (auto_deployment
enabled). See ADR-004 in sc-lambda-ghactions for the full design rationale.
Parameters:
CodeBuildAccountId:
Type: String
Default: "229685449397"
Description: >
AWS account ID of the csvd-dev account where the tf-run-executor CodeBuild
project runs. The IAM role tf-run-executor-codebuild in this account is
granted sts:AssumeRole on this target-account role.
AllowedPattern: "[0-9]{12}"
ConstraintDescription: Must be a 12-digit AWS account ID.

Resources:
SCAutomationCodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: sc-automation-codebuild-role
Description: >
Cross-account role assumed by the tf-run-executor CodeBuild service role in
csvd-dev to run Terraform in this account. Deployed and managed via
CloudFormation StackSet (sc-lambda-ghactions).
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowSCAutomationCodeBuild
Effect: Allow
Principal:
AWS: !Sub "arn:${AWS::Partition}:iam::${CodeBuildAccountId}:role/tf-run-executor-codebuild"
Action: sts:AssumeRole
Condition:
StringEquals:
# ExternalId = the target account's own ID, preventing confused-deputy
# attacks across accounts in the same org. The executor build passes
# the target account ID as ExternalId at assume-role time.
sts:ExternalId: !Ref AWS::AccountId
ManagedPolicyArns:
# Initial baseline: AdministratorAccess.
# Future hardening: replace with a least-privilege customer-managed policy
# once the full set of IAM actions required by each product workspace is
# known. Track in a follow-up ADR.
- !Sub "arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess"
Tags:
- Key: Project
Value: sc-automation
- Key: ManagedBy
Value: cloudformation-stackset
- Key: CreatedBy
Value: sc-lambda-ghactions

Outputs:
RoleArn:
Description: ARN of the sc-automation-codebuild-role IAM role
Value: !GetAtt SCAutomationCodeBuildRole.Arn
Export:
Name: sc-automation-codebuild-role-arn

0 comments on commit 4e84069

Please sign in to comment.