Create and manage individual AWS Organizations member accounts. This is a low-level building block - most users should use the Organization XRD with inline accounts instead.
Use Organization XRD (recommended):
- Creating accounts as part of your org hierarchy
- Want accounts placed in specific OUs automatically
- Managing multiple accounts together
Use Account XRD directly:
- Creating accounts outside the Organization XRD
- Advanced scenarios requiring per-account control
- Programmatic account vending (account factory)
When you create an account via AWS Organizations:
- AWS creates the account with the specified email
- AWS automatically creates
OrganizationAccountAccessRolein the new account - This role trusts the management account, enabling cross-account access
- You can assume this role to manage resources in the new account
apiVersion: aws.hops.ops.com.ai/v1alpha1
kind: Account
metadata:
name: team-platform-dev
namespace: default
spec:
email: platform-dev@acme.example.com # Must be unique across all AWS
parentId: ou-abc1-workloads # OU ID or root ID (r-xxxx)
providerConfigRef:
name: management # Management account ProviderConfig
kind: ProviderConfig
managementPolicies: ["*"]
tags:
team: platform
environment: devAlready have an account? Import it with externalName:
apiVersion: aws.hops.ops.com.ai/v1alpha1
kind: Account
metadata:
name: legacy-prod
namespace: default
spec:
externalName: "123456789012" # Existing account ID
email: legacy-prod@acme.example.com
parentId: ou-abc1-prod
providerConfigRef:
name: management
kind: ProviderConfig
# Don't delete if removed from Crossplane
managementPolicies: ["Create", "Observe", "Update", "LateInitialize"]SCPs restrict what actions accounts can perform - use them for guardrails:
apiVersion: aws.hops.ops.com.ai/v1alpha1
kind: Account
metadata:
name: team-sandbox
namespace: default
spec:
email: sandbox@acme.example.com
parentId: ou-abc1-sandbox
providerConfigRef:
name: management
kind: ProviderConfig
# Attach SCPs for guardrails
policyAttachments:
- arn:aws:organizations::111111111111:policy/o-abc123/service_control_policy/p-deny-root
- arn:aws:organizations::111111111111:policy/o-abc123/service_control_policy/p-region-restrict
tags:
environment: sandbox
cost-center: engineeringThe Account exposes the information needed for cross-account access:
status:
accountId: "123456789012"
organizationAccountAccessRoleArn: arn:aws:iam::123456789012:role/OrganizationAccountAccessRole
ready: trueCreate a ProviderConfig that assumes the OrganizationAccountAccessRole:
apiVersion: aws.m.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: team-platform-dev
spec:
assumeRoleChain:
- roleARN: arn:aws:iam::123456789012:role/OrganizationAccountAccessRole
credentials:
source: PodIdentity # Or Secret, IRSAThen reference it in resources:
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
providerConfigRef:
name: team-platform-dev # Creates bucket in the team's account
forProvider:
region: us-east-1For programmatic account creation, you can template Account resources:
# Create accounts from a list
{{ range $team := .teams }}
---
apiVersion: aws.hops.ops.com.ai/v1alpha1
kind: Account
metadata:
name: {{ $team.name }}-{{ $team.environment }}
namespace: default
spec:
email: {{ $team.name }}-{{ $team.environment }}@acme.example.com
parentId: {{ if eq $team.environment "prod" }}ou-abc1-prod{{ else }}ou-abc1-nonprod{{ end }}
providerConfigRef:
name: management
kind: ProviderConfig
tags:
team: {{ $team.name }}
environment: {{ $team.environment }}
{{ end }}- Use Organization XRD for most cases - It handles OU placement and keeps your hierarchy visible
- Always set tags - Include team, environment, and cost-center for billing
- Use unique emails - AWS requires globally unique emails; use
+addressing if needed (aws+prod@acme.com) - Don't delete production accounts - Use
managementPolicieswithout Delete to orphan on removal - Account deletion takes 90 days - AWS Organizations account closure is not immediate
make render # Render example
make test # Run tests
make validate # Validate compositionsApache-2.0