Skip to content

Organizations: account vending + SCP attachment for local Terraform apply (store + list, not enforce) #989

Description

@b-rajesh

AWS Service name

Organizations

Operations needed

Account lifecycle — for aws_organizations_account:

  • CreateAccount (return CreateAccountStatus; immediate SUCCEEDED is fine for an emulator, or IN_PROGRESS→poll to mirror AWS)
  • DescribeCreateAccountStatus
  • MoveAccount (root → target OU)
  • ListParents — needed for the round-trip: the provider refreshes parent_id via ListParents, so without it the resource shows perpetual drift after a move (DescribeAccount doesn't return the parent, same as real AWS)

SCP control-plane — store + list, not enforce — for aws_organizations_policy + _policy_attachment:

  • CreatePolicy / UpdatePolicy / DeletePolicy / DescribePolicy / ListPolicies (SERVICE_CONTROL_POLICY)
  • TagResource / UntagResource / ListTagsForResourceaws_organizations_policy Read calls ListTagsForResource, so once CreatePolicy lands, omitting these moves the hard-stop to the post-create read-back (a Create without its paired Read op fails apply).
  • AttachPolicy / DetachPolicy
  • ListPoliciesForTarget / ListTargetsForPolicy
  • EnablePolicyType / DisablePolicyType
  • seed AWS-managed FullAWSAccess attached to root/OUs (real-AWS default, so attach/detach diffs match)

_Out of scope:_ request-time SCP enforcement (per-request deny). This proves the SCP is authored + attached, not that a disallowed call is blocked.

Use case

Validate an AWS Organizations IaC flow locally (Terraform/OpenTofu apply, not just plan): vend a sub-account → place it under an OU → author an SCP → attach it to the OU. Today both aws_organizations_account and aws_organizations_policy(_attachment) fail at apply against MiniStack because these mutation ops are missing, so the flow is plan-only.

MiniStack already maintains the OU tree with parent/child semantics (CreateOrganizationalUnit, ListAccountsForParent filters by parent), so most of this builds on existing machinery. It's pure in-memory control-plane CRUD — the whole flow completes locally (applylist-accounts-for-parent / list-policies-for-target → assert), with no real infra and nothing to maintain over time (CRUD on user-created resources, not a mirror of AWS data). It mirrors the recently-merged AssociateIamInstanceProfile round-trip (#968) and completes a surface you already ship.

Why-. A landing-zone codebase authors region-pin / data-residency guardrails as Service Control Policies and attaches them to OUs — aws_organizations_policy (SERVICE_CONTROL_POLICY) + aws_organizations_policy_attachment. The value in an emulator: the SCP authoring + attachment flow applys and round-trips locally — author → attach to an OU → read back via aws organizations list-policies-for-target to assert the guardrail is wired — so IaC changes to the org's policy layer are testable without a real organization. Pure in-memory control-plane CRUD on user-created resources (no AWS data to mirror, nothing to maintain), building on the OU tree MiniStack already keeps.

Before opening a PR — is this in scope? One PR, or split account-lifecycle from SCP? And any preference on CreateAccount being immediate-SUCCEEDED vs IN_PROGRESS→poll?

Would you like to contribute this?

  • Yes, I'd like to implement this service and open a PR
  • I can help review/test an implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions