Saltar al contenido principal

BYOC deployment — AWS

Procedure for provisioning the platform into a customer's AWS account. Every apply runs through the existing controller gate (plan → OPA → plan-binding → four-eyes approval → apply); workspaces named customer-<slug>-<env> are matched by the authz matrix to the full prod tier (hard-mandatory policy, distinct approver, step-up MFA).

Feature flag: byoc_deployments_enabled (monolith) gates the deployment record + spec routes.

Prerequisites​

Customer side (send them this section):

  1. Create IAM role AlphaSwarmDeployRole in the target account with a trust policy allowing our ops account to assume it, conditioned on an ExternalId (we supply it; it is the customer id — cross-reference the pattern in multi-account-rollout).
  2. Attach the deployment permission set (VPC/EKS-or-ECS/RDS/S3/KMS/ECR as per the module README: terraform/modules/customer_account_aws/README.md).
  3. Tell us the 12-digit account id, target region, and the role ARN.

Our side:

  • Customer onboarded with an active enterprise contract (byoc_deployments: true resolved — see enterprise-customer-onboarding).
  • The external id stored in the secrets platform; note its vault path (never the raw value) — e.g. secret/customers/<slug>/external-id.
  • State backend exists in the ops account: S3 bucket alphaswarm-customer-tfstate (+ DynamoDB lock table alphaswarm-customer-tf-lock).
  • You hold manage:infrastructure + terraform:admin; a second approver is available for the apply.

Steps​

  1. Create the deployment record — customer detail page → BYOC deployments → New deployment: name, env suffix (prod, staging), AWS account id, region, deploy-role ARN. This derives the workspace name customer-<org-slug>-<suffix>; then PATCH the record's external_id_vault_path to the vault path from prerequisites.
  2. (First lease) issue the deployment's license lease with license_deployment_id matching the record — see license-issuance-and-revocation. The terraform module wires ALPHASWARM_LICENSE_* + license_enforcement_enabled=true into the workloads.
  3. Render the spec — Render spec on the deployment row. This snapshots a hash-locked TerraformStackSpec (registry rule 43) and upserts the terraform_workspaces row (slug = workspace name, state in the ops-account S3 backend). Status: draft → planning.
  4. Plan — Plan / apply → deep-links to the Terraform page; run the plan on the customer workspace. The OPA customer gate enforces: provider must assume_role into the declared account, only allowlisted providers, no unreviewed stateful deletes.
  5. Review + approve — the plan binding pins the exact tfplan; the second operator approves (four-eyes; step-up). Apply executes the bound plan only.
  6. Sync status — Sync on the deployment row folds the run outcome into the record (awaiting_approval → applying → active).

Post-action verification​

  • Deployment row active with the apply-run id linked.
  • Customer-side smoke: platform health endpoint answers; a gated route (e.g. terraform surface) returns 200 with an entitled lease and no X-AlphaSwarm-License-Status header (i.e. lease active, not grace).
  • The KB silo exists in the customer account (RDS/S3 encrypted with the per-tenant KMS key) — module outputs list the endpoints.
  • Terraform state landed at s3://alphaswarm-customer-tfstate/customers/<slug>/<env>.tfstate.

Escalation​

  • OPA deny on plan → read the finding; assume_role/provider findings mean the rendered spec or role setup is wrong — fix and re-render; never downgrade the workspace's policy tier.
  • Assumed role landed in account … precondition failure → the role ARN points at the wrong account; verify with the customer.
  • Apply half-failed → terraform state is authoritative; re-plan and re-apply through the same gate (see byoc-upgrade-and-rollback for rollback).