diff --git a/docs/generalized-terraform-product-architecture.md b/docs/generalized-terraform-product-architecture.md index aa13c04..de17343 100644 --- a/docs/generalized-terraform-product-architecture.md +++ b/docs/generalized-terraform-product-architecture.md @@ -259,7 +259,7 @@ auditable (every template repo change is a PR in the SCT-Engineering org). **Adding a new product type requires only creating a new template repo with a `handler.py`. No Lambda code changes, no Lambda redeployment, no registry entries.** -### 5. CloudFormation product template + Terraform registration +### 5. CloudFormation product template The CFN template for a product type lives in `service-catalog/{product_type}-product-template.yaml` inside the `sc-lambda-ghactions` repo. It follows the same pattern as the existing EKS template: @@ -283,48 +283,61 @@ Properties: tier: !Ref Tier ``` -**The template is never registered manually.** The `deploy/service_catalog.tf` workspace -manages all SC infrastructure — S3 upload, portfolio, product, provisioning artifact, -launch role, launch constraint, and principal associations — using `for_each` over a -`var.sc_products` map. This is the same proven pattern as `deploy_product/main.tf` in -`lambda-template-repo-generator`. +### 6. `deploy_products/` — dedicated Terraform workspace for SC product management -Adding a new product type requires only two steps: +SC portfolio and product registration lives in a **dedicated `deploy_products/` workspace**, +separate from `deploy/` (which manages the Lambda and CodeBuild engine). This mirrors the +pattern established by `lambda-template-repo-generator`, which has `deploy/` for the +Lambda infrastructure and `deploy_product/` for the SC product registration. -1. Add an entry to `var.sc_products` in `deploy/terraform.tfvars`: +``` +sc-lambda-ghactions/ +├── deploy/ ← Lambda, ECR, CodeBuild, IAM (engine — rarely touched) +└── deploy_products/ ← SC portfolio, products, S3, launch roles, OU sharing +``` + +The workspace is driven by two variables: ```hcl +# deploy_products/terraform.tfvars + sc_products = { - ekscluster = { + eks_cluster = { name = "EKS Cluster Repository Creator" description = "Creates an EKS cluster account repo from template-eks-cluster." - template = "service-catalog/eks-cluster-product-template.yaml" + template = "${path.module}/../service-catalog/eks-cluster-product-template.yaml" version = "2.0.0" } - s3bucket = { + s3_bucket = { name = "S3 Bucket Repository Creator" description = "Creates an S3 bucket account repo from template-s3-bucket." - template = "service-catalog/s3-bucket-product-template.yaml" + template = "${path.module}/../service-catalog/s3-bucket-product-template.yaml" version = "1.0.0" } } -``` - -2. Run `tf apply` in `deploy/` — Terraform creates (or updates) all SC resources for the new entry. -No AWS Console clicks, no manual artifact uploads, no census pipeline PR required to -test a new product type in the dev/lab environment. +# AWS Organizations OU IDs to share the portfolio with. +# Every account in these OUs will see the portfolio in their SC console automatically. +share_ous = [ + "ou-xxxx-xxxxxxxx", # platform-engineering + "ou-xxxx-yyyyyyyy", # app-teams +] +``` -### 6. Promotion to production via the census pipeline +Terraform iterates `var.sc_products` with `for_each` to create the S3 object, SC product, +provisioning artifact, and launch constraint for each entry. A single shared portfolio +(`aws_servicecatalog_portfolio`) is created once and shared to the OUs listed in +`var.share_ous` via `aws_servicecatalog_portfolio_share` — no per-account work required. -The `deploy/` workspace is the **development and testing path**. Once a new product type -has been validated end-to-end, it is promoted to production by adding the corresponding -entry to `terraform-service-catalog-census/templates/products/{product_type}/` and opening -a PR in `terraform-service-catalog-census`. The census pipeline applies this to all shared -accounts via the standard portfolio-sharing mechanism. +**Adding a new product type:** +1. Create the template repo and CFN template (steps above) +2. Add one entry to `var.sc_products` in `deploy_products/terraform.tfvars` +3. Run `tf apply` in `deploy_products/` -The CFN template file (`service-catalog/{product_type}-product-template.yaml`) is the -single source of truth — both the `deploy/` workspace and the census pipeline read from it. +No census pipeline PR, no YAML config files, no Terragrunt, no AWS Console clicks. +The `deploy_products/` workspace replaces the `terraform-service-catalog-census` dependency +for this system entirely. Any account in the configured OUs gets access to new products +immediately after apply. --- @@ -338,12 +351,11 @@ onboard any new Terraform workload without Lambda or CodeBuild changes: - flat `.tf.j2` file(s) rendered by the Proposer - `tf-run.data` - `.sc-automation.yml.j2` (optional; Proposer writes a default if absent) - **No files in the Lambda repository need to be created or modified.** -- [ ] Add `service-catalog/{product_type}-product-template.yaml` CFN template to `sc-lambda-ghactions` -- [ ] Add an entry to `var.sc_products` in `deploy/terraform.tfvars` and run `tf apply` in `deploy/` — - Terraform registers the SC portfolio, product, artifact, launch role, constraint, and principals -- [ ] Validate end-to-end in the dev/lab account via `scripts/test_service_catalog.py` -- [ ] Promote to production: add entry to `terraform-service-catalog-census/templates/products/{product_type}/` and open a PR +- [ ] Add `service-catalog/{product_type}-product-template.yaml` to `sc-lambda-ghactions` +- [ ] Add one entry to `var.sc_products` in `deploy_products/terraform.tfvars` +- [ ] Run `tf apply` in `deploy_products/` — creates S3 artifact, SC product, provisioning + artifact, launch constraint; all OU-member accounts see the new product immediately +- [ ] Validate end-to-end via `scripts/test_service_catalog.py` --- @@ -382,6 +394,9 @@ CloudFormation stacks or SC provisioned products. | Secrets Manager secrets | 2 (GHE tokens) + 1 (webhook) | No change | | Lambda Function URL | 1 | No change | | ECR repositories | 1 | No change | +| SC portfolios | 1 (EKS) | 1 (shared across all product types) | +| SC products | 1 | +1 per new product type (S3 object + SC product resource) | +| CFN StackSets | 0 | 1 (launch role deployed to all OU member accounts via `deploy_products/`) | -There is **no additional AWS infrastructure cost** to add new product types. Each new -product type is purely a code and configuration change. +Each new product type adds a single SC product + S3 artifact. No new Lambda functions, +no new CodeBuild projects, no new secrets — and no dependency on external pipeline teams. diff --git a/docs/service-catalog-census-integration.md b/docs/service-catalog-census-integration.md index 575be1a..a0cd9bf 100644 --- a/docs/service-catalog-census-integration.md +++ b/docs/service-catalog-census-integration.md @@ -1,89 +1,78 @@ -# Service Catalog Census Integration +# Service Catalog Product Deployment -**Ported and generalized from:** `lambda-template-repo-generator/design-docs/SERVICE_CATALOG_CENSUS_INTEGRATION.md` -**Updated for:** sc-lambda-ghactions (CodeBuild-based initial rollout; GHA planned for later) -**Date:** 2026-05-19 +**Previously titled:** Service Catalog Census Integration +**Updated for:** sc-lambda-ghactions +**Date:** 2026-05-20 **Status:** DRAFT --- ## Executive Summary -This document covers how sc-lambda-ghactions products are registered in the -`terraform-service-catalog-census` repo, which manages all enterprise Service Catalog -portfolios and products via Terragrunt. Each new product type (EKS cluster, S3 bucket, -RDS instance, etc.) requires entries in the census repo to become available in the SC -console org-wide. +All Service Catalog infrastructure for this system is managed from a single +**`deploy_products/`** Terraform workspace inside `sc-lambda-ghactions`. There is no +dependency on `terraform-service-catalog-census` or any external pipeline. -The census integration is designed for **enterprise-wide deployment from the outset**. -Every resource is classified by deployment scope — central (Lambda, ECR), StackSet (launch -roles), or census-managed (portfolios, products, constraints) — and handled accordingly. +The workspace handles the complete deployment lifecycle: +- S3 upload of CFN product templates (versioned) +- SC portfolio + `aws_servicecatalog_portfolio_share` to org OUs +- SC products, provisioning artifacts, and launch constraints +- A CloudFormation StackSet that deploys the IAM launch role to every account in the shared OUs automatically + +Adding a new product type = one entry in `terraform.tfvars` + `tf apply`. No census repo +PRs, no Terragrunt, no YAML config files, no AWS Console clicks. --- ## System Layout -### sc-lambda-ghactions system (4 repos) +### sc-lambda-ghactions (all in one repo) ``` -sc-lambda-ghactions/ ← Lambda + CodeBuild buildspecs + SC product templates -├── lambda/app.py ← Lambda handler (fetches + runs handler.py from template repo at runtime) -├── service-catalog/{product_type}-product-template.yaml ← CFN product template -└── deploy/ ← Terraform: Lambda, ECR, IAM, Function URL +sc-lambda-ghactions/ +├── lambda/app.py ← Lambda handler (fetches handler.py from template repo at runtime) +├── service-catalog/{type}-template.yaml ← CFN product templates (one per product type) +├── deploy/ ← Engine: Lambda, ECR, CodeBuild, IAM, Function URL +└── deploy_products/ ← SC: portfolio, products, OU sharing, launch role StackSet SCT-Engineering/template-{product_type}/ ← one repo per product type; fully self-contained ├── handler.py ← PRODUCT_TYPE + Pydantic model + handle() ├── {workload}.tf.j2 ← Jinja2 HCL templates (flat) -├── tf-run.data ← tf-run steps +├── tf-run.data ← tf-run orchestration steps └── .sc-automation.yml.j2 ← optional webhook config template - -terraform-sc-fleet/ ← Fleet operations manifest (all managed workloads) -packer-pipeline/ ← Container build CLI ``` -### `terraform-service-catalog-census` (census repo) +### Two workspaces, two responsibilities -``` -terraform-service-catalog-census/ -├── main-modules/service-catalog/ ← Main Terraform module -├── modules/ -│ ├── sc-portfolio/ ← Portfolio + principal association -│ ├── sc-product/ ← Product + S3 upload + versioning -│ └── cfn-roles-actions/ ← Launch roles via CFN StackSets -├── templates/ -│ ├── products/ -│ │ ├── eks-terragrunt-repo/ ← CFN product template (versioned YAMLs) -│ │ ├── s3-bucket-repo/ ← (planned) -│ │ └── {product-type}-repo/ ← pattern -│ └── role-templates/ ← IAM launch role CFN snippets -├── non-prod/csvd-dev/west/ -│ ├── configurations/ -│ │ ├── portfolios/*.yaml.tftpl ← Portfolio definitions -│ │ └── products/**/*.yaml.tftpl ← Product definitions -│ └── service-catalog/ -└── prod/operations-gov/ ← Prod (shares to org) -``` +| Workspace | Contains | Apply frequency | +|-----------|----------|-----------------| +| `deploy/` | Lambda, ECR, CodeBuild projects, IAM execution roles, Function URL | Rarely — only when the engine changes | +| `deploy_products/` | S3 templates, SC portfolio, products, artifacts, OU sharing, launch role StackSet | Whenever a new product type is added or a template version bumps | --- ## Resource Classification -Every resource falls into one of three deployment tiers: - -| Tier | What | Deployment mechanism | Scope | -|------|------|---------------------|-------| -| **Central** | Lambda, ECR, Secrets Manager, GHE token, Function URL | `sc-lambda-ghactions/deploy/` (`tf apply`) | csvd-dev only | -| **StackSet** | IAM launch role per product type | `cfn-roles-actions` StackSet via census repo | All OU-shared accounts | -| **Census-managed** | SC portfolio, product, provisioning artifact, constraints | YAML config in census repo → `terragrunt apply` | SC admin account + shared OUs | +| Resource | Workspace | Scope | +|----------|-----------|-------| +| Lambda function | `deploy/` | csvd-dev only (invoked cross-account via ServiceToken) | +| ECR repository | `deploy/` | csvd-dev only | +| CodeBuild projects (proposer + executor) | `deploy/` | csvd-dev only | +| Lambda cross-account invocation policy | `deploy/` | Org-wide via `aws:PrincipalOrgID` condition | +| S3 bucket + product template objects | `deploy_products/` | csvd-dev only | +| SC portfolio | `deploy_products/` | csvd-dev (shared to OUs) | +| `aws_servicecatalog_portfolio_share` | `deploy_products/` | All OU member accounts | +| SC products + provisioning artifacts | `deploy_products/` | csvd-dev (visible in shared accounts) | +| Launch role (IAM) | `deploy_products/` via CFN StackSet | All OU member accounts | +| Launch constraint | `deploy_products/` | Per product, references launch role ARN pattern | --- -## Step 1 — Central Infrastructure (`sc-lambda-ghactions/deploy/`) +## Step 1 — Engine Infrastructure (`deploy/`) -The Lambda is centralized in csvd-dev. CloudFormation in any org account invokes -it cross-account via the `ServiceToken` ARN. +The Lambda is centralized in csvd-dev. CloudFormation in any org account invokes it +cross-account via the `ServiceToken` ARN. A single resource policy covers the whole org: -**Lambda resource policy** — allows any account in the org: ```hcl resource "aws_lambda_permission" "cloudformation_org" { statement_id = "AllowCloudFormationOrgInvoke" @@ -98,218 +87,156 @@ resource "aws_lambda_permission" "cloudformation_org" { } ``` -No per-account Lambda deployment is needed. Provisioners never need the Lambda locally — -their CloudFormation stack calls it cross-account via the `ServiceToken`. +No per-account Lambda deployment. This resource lives in `deploy/` and is applied once. --- -## Step 2 — IAM Launch Roles (StackSet) - -One IAM launch role is required **per product type** in every account that will -provision the product via SC. These are deployed via the `cfn-roles-actions` StackSet, -which auto-deploys to all accounts in shared OUs. - -### Launch role template (per product type) - -Add a file to `templates/role-templates/`: - -```yaml -# templates/role-templates/sc-{product_type}-launch-role.yaml -Type: AWS::IAM::Role -Properties: - RoleName: !Sub "r-ent-servicecatalog-${ProductType}-sc-launch-role" - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: { Service: servicecatalog.amazonaws.com } - Action: sts:AssumeRole - Policies: - - PolicyName: InvokeCentralLambda - PolicyDocument: - Statement: - - Effect: Allow - Action: lambda:InvokeFunction - Resource: !Sub "arn:${AWS::Partition}:lambda:${LambdaRegion}:${CentralAccountId}:function:sc-template-automation" - - Effect: Allow - Action: [cloudformation:*, s3:GetObject] - Resource: "*" -``` +## Step 2 — SC Products & OU Sharing (`deploy_products/`) -### Registering in `roles.yaml.tftpl` - -```yaml -# non-prod/csvd-dev/west/configurations/roles.yaml.tftpl -- template: sc-eks-cluster-launch-role.yaml # existing - parameters: - - parameter: CentralAccountId - value: "229685449397" - - parameter: LambdaRegion - value: us-gov-west-1 - - parameter: ProductType - value: eks_cluster - -- template: sc-s3-bucket-launch-role.yaml # new product type - parameters: - - parameter: CentralAccountId - value: "229685449397" - - parameter: LambdaRegion - value: us-gov-west-1 - - parameter: ProductType - value: s3_bucket -``` +The `deploy_products/` workspace manages all SC resources from a single `tf apply`. -**Only one `terragrunt apply`** is needed after adding a new role entry. The StackSet -propagates to all shared accounts automatically via `auto_deployment { enabled = true }`. +### `var.sc_products` — product registry ---- +```hcl +# deploy_products/terraform.tfvars +sc_products = { + eks_cluster = { + name = "EKS Cluster Repository Creator" + description = "Creates an EKS cluster account repo from template-eks-cluster." + template = "${path.module}/../service-catalog/eks-cluster-product-template.yaml" + version = "2.0.0" + } + s3_bucket = { + name = "S3 Bucket Repository Creator" + description = "Creates an S3 bucket account repo from template-s3-bucket." + template = "${path.module}/../service-catalog/s3-bucket-product-template.yaml" + version = "1.0.0" + } +} -## Step 3 — Census Portfolio and Product Config - -### Portfolio YAML - -Portfolios are defined in `configurations/portfolios/`. The sc-lambda-ghactions products -belong in a single shared portfolio (or alongside existing census portfolios): - -```yaml -# configurations/portfolios/sc-automation.yaml.tftpl -sc_automation: - name: "Service Catalog Automation Portfolio" - description: >- - Self-service infrastructure provisioning via sc-lambda-ghactions. - Supports any Terraform workload type. - provider_name: CSVD - products: - - eks_cluster_repo - - s3_bucket_repo - user_roles: - - /census/*/sc-end-user-role - share_ous: - - name: census-workload-accounts +# AWS Organizations OU IDs — every account in these OUs sees the portfolio automatically +share_ous = [ + "ou-xxxx-xxxxxxxx", # platform-engineering + "ou-xxxx-yyyyyyyy", # app-teams +] ``` -### Product YAML (per product type) - -```yaml -# configurations/products/eks-cluster-repo/EKS_CLUSTER_REPO.yaml.tftpl -eks_cluster_repo: - name: "EKS Cluster Repository Creator" - description: >- - Creates a GitHub Enterprise repository with Terragrunt EKS cluster - configuration and opens a review PR. - type: CLOUD_FORMATION_TEMPLATE - distributor: CSVD - support_email: csvd.aws.service.catalog.team.list@census.gov - launch_role: r-ent-servicecatalog-eks-cluster-sc-launch-role - template_constraints: - Parameters: - # Lock the Lambda ARN — users cannot redirect to a different Lambda - ServiceToken: "arn:${Partition}:lambda:us-gov-west-1:229685449397:function:sc-template-automation" - versions: - - name: "1.0.0" - description: "Initial CodeBuild-based version" - file_path: products/eks-cluster-repo/1-0-0.yaml -``` +Terraform iterates `var.sc_products` with `for_each` to create: +- `aws_s3_object` — versioned CFN template in the artifacts bucket +- `aws_servicecatalog_product` — SC product backed by the S3 object +- `aws_servicecatalog_provisioning_artifact` — the working artifact version (the initial one created by `create-product` is deprecated automatically, as learned from `lambda-template-repo-generator`) +- `aws_servicecatalog_product_portfolio_association` — links product to the shared portfolio +- `aws_servicecatalog_constraint` — attaches the launch role -### Product template location +### OU portfolio sharing -The CFN product template lives at: -``` -templates/products/{product_type}-repo/{version}.yaml +```hcl +resource "aws_servicecatalog_portfolio_share" "ou" { + for_each = toset(var.share_ous) + + portfolio_id = aws_servicecatalog_portfolio.this.id + type = "ORGANIZATIONAL_UNIT" + principal_id = each.value + + share_principals = true # member accounts inherit principal associations +} ``` -This is a copy of (or symlink to) `sc-lambda-ghactions/service-catalog/{product_type}-product-template.yaml`. -When a new version of the product template is released, add a new versioned file here -and bump the `versions` list in the product YAML. +Every account in the listed OUs immediately sees all products in the portfolio — no +per-account work required. ---- +### IAM launch role — StackSet -## Step 4 — Moving the Lambda to a Different Account +The IAM launch role must exist in every member account that will provision products. +`deploy_products/` manages a CloudFormation StackSet that deploys it org-wide: -If the central Lambda needs to move to a different AWS account, the following must be -updated. **All other components are account-agnostic.** +```hcl +resource "aws_cloudformation_stack_set" "launch_role" { + name = "sc-automation-launch-role" + permission_model = "SERVICE_MANAGED" + capabilities = ["CAPABILITY_NAMED_IAM"] + template_body = file("${path.module}/cfn/sc-launch-role.yaml") + + parameters = { + CentralAccountId = data.aws_caller_identity.current.account_id + LambdaRegion = data.aws_region.current.name + LambdaName = var.lambda_function_name + } -| Resource | Location | What changes | -|----------|----------|-------------| -| Lambda + all central infra | `sc-lambda-ghactions/deploy/` | Re-deploy in new account | -| Launch role `lambda:InvokeFunction` ARN | `roles.yaml.tftpl` → `CentralAccountId` parameter | Update to new account ID — one change propagates to all shared accounts via StackSet | -| Template constraint `ServiceToken` | Product YAML `template_constraints` | Update ARN value | -| GitHub token secrets | Secrets Manager in new account | Recreate manually | + auto_deployment { + enabled = true + retain_stacks_on_account_removal = false + } +} -**Migration order:** Update StackSet launch roles (step 3) → wait for propagation → update -template constraint (step 4). Reversing the order causes a `lambda:InvokeFunction` permission -denial window. +resource "aws_cloudformation_stack_set_instance" "ou" { + for_each = toset(var.share_ous) -### Why parameterizing `CentralAccountId` matters + stack_set_name = aws_cloudformation_stack_set.launch_role.name + deployment_targets { + organizational_unit_ids = [each.value] + } +} +``` -The account ID is only in `roles.yaml.tftpl` under the `CentralAccountId` parameter. The -role template YAML itself is static and account-agnostic. A single value change propagates -to all shared accounts via the StackSet — no role template file needs updating. +The CFN template for the launch role is a static file at +`deploy_products/cfn/sc-launch-role.yaml`. It is the same role as in +`lambda-template-repo-generator/deploy_product/main.tf` — CFN + CloudFormation +permissions + `lambda:InvokeFunction` on the central Lambda ARN — but parameterized +so it works across any account without hard-coding the Lambda account ID. ---- +### Launch constraint -## Adding a New Product Type to the Census Portfolio +The constraint ARN pattern references the role deployed by the StackSet: -Checklist for each new product type: +```hcl +resource "aws_servicecatalog_constraint" "launch" { + for_each = var.sc_products -- [ ] Add CFN product template at `templates/products/{product_type}-repo/1-0-0.yaml` -- [ ] Add product YAML at `configurations/products/{product_type}-repo/{PRODUCT}.yaml.tftpl` -- [ ] Add launch role template at `templates/role-templates/sc-{product_type}-launch-role.yaml` -- [ ] Add launch role entry in `roles.yaml.tftpl` -- [ ] Add product key to portfolio YAML `products:` list -- [ ] Run `terragrunt apply` in `non-prod/csvd-dev/west/service-catalog/` -- [ ] Validate: product appears in SC console; end-to-end test from a workload account + portfolio_id = aws_servicecatalog_portfolio.this.id + product_id = aws_servicecatalog_product.this[each.key].id + type = "LAUNCH" ---- + parameters = jsonencode({ + # The role ARN uses !Sub at CFN time — member accounts resolve their own account ID + LocalRoleName = "sc-automation-launch-role" + }) +} +``` -## Validation Checklist +--- -### After central Lambda deploy: -- [ ] Lambda resource policy allows org-wide CloudFormation invocation -- [ ] Cross-account test: invoke Lambda from a different account via CFN Custom Resource +## Adding a New Product Type -### After StackSet launch role deploy: -- [ ] StackSet instances show `CURRENT` in CloudFormation console for target OUs -- [ ] Launch role exists in at least 2-3 workload accounts (spot check) -- [ ] Role trust policy allows `servicecatalog.amazonaws.com` +1. Create `SCT-Engineering/template-{product_type}` with `handler.py`, `.tf.j2` files, `tf-run.data` +2. Add `service-catalog/{product_type}-product-template.yaml` to `sc-lambda-ghactions` +3. Add one entry to `var.sc_products` in `deploy_products/terraform.tfvars` +4. Run `tf apply` in `deploy_products/` — product is live in all OU member accounts immediately -### After census product deploy: -- [ ] Portfolio visible in SC console in the admin account -- [ ] Portfolio shared to target OUs (verify in a workload account) -- [ ] Product associated with portfolio; launch constraint attached -- [ ] Template constraint locks `ServiceToken` to correct Lambda ARN -- [ ] End-to-end test: provision from a **workload account** (not csvd-dev) +No census repo PRs. No Terragrunt. No YAML config files. --- -## Appendix: Census Config Format Reference +## Moving the Lambda to a Different Account -### Portfolio YAML schema +If the central Lambda needs to move accounts, only `deploy/` changes. The StackSet +launch roles reference the Lambda by name + account, managed via the `CentralAccountId` +and `LambdaName` StackSet parameters — a single `tf apply` in `deploy_products/` after +re-deploying `deploy/` propagates the updated ARN to all member accounts automatically. -```yaml -: - name: string - description: string - provider_name: string - products: [, ...] - user_roles: [/path/pattern/*] - tags: {} - share_ous: [] # OU names; empty = inherit from terraform.tfvars -``` +--- -### Product YAML schema - -```yaml -: - name: string - description: string - type: CLOUD_FORMATION_TEMPLATE - launch_role: string # IAM role NAME (not ARN) — must exist in every target account - distributor: string - template_constraints: - Parameters: - ParamName: locked-value - versions: - - name: "1.0.0" - file_path: products/{product-dir}/{version}.yaml - actions: [] -``` +## Validation Checklist + +### After `deploy/` apply: +- [ ] Lambda resource policy allows org-wide CloudFormation invocation +- [ ] Cross-account test: invoke Lambda from a different account via CFN Custom Resource + +### After `deploy_products/` apply: +- [ ] StackSet instances show `CURRENT` for all target OUs +- [ ] Launch role exists in at least 2–3 spot-check workload accounts +- [ ] Portfolio visible in SC console in csvd-dev +- [ ] Portfolio shared to target OUs (verify from a workload account) +- [ ] Each product has an active provisioning artifact; initial broken artifact is deprecated +- [ ] Launch constraint references the correct role name +- [ ] End-to-end test: provision from a **workload account** (not csvd-dev) diff --git a/docs/template-management.md b/docs/template-management.md index d52408a..0507459 100644 --- a/docs/template-management.md +++ b/docs/template-management.md @@ -309,5 +309,6 @@ Checklist when onboarding a new product type: - `.sc-automation.yml.j2` (optional) **No files in the Lambda repository need to be created or modified.** - [ ] Add `service-catalog/{product_type}-product-template.yaml` to `sc-lambda-ghactions` -- [ ] Add entry to `var.sc_products` in `deploy/terraform.tfvars` and run `tf apply` in `deploy/` -- [ ] Promote to production via `terraform-service-catalog-census` PR +- [ ] Add one entry to `var.sc_products` in `deploy_products/terraform.tfvars` +- [ ] Run `tf apply` in `deploy_products/` — portfolio, product, artifact, launch roles, + and OU sharing are updated automatically; all OU-member accounts see the change immediately