Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Migrate IAM AWS managed policies#13836

Merged
dfangl merged 5 commits into
iam/moto-migrationfrom
daniel/unc-273
Feb 25, 2026
Merged

Migrate IAM AWS managed policies#13836
dfangl merged 5 commits into
iam/moto-migrationfrom
daniel/unc-273

Conversation

@dfangl

@dfangl dfangl commented Feb 24, 2026

Copy link
Copy Markdown
Member

Motivation

With this PR, we are migrating AWS managed IAM policies.
This does not yet include an automatic github action to update those policies.

Changes

Static data, not persisted in the store

AWS managed policies are fixed and identical for every account. Persisting them in the store would waste space and add noise to state snapshots, and we would not easily be able to update it with new LocalStack versions. Instead:

  1. Policy data is stored in a static file (aws_managed_policies.json) copied from moto's dataset — a JSON file containing ~1,400 policies keyed by policy name.
  2. At module import time, provider.py parses the JSON once and builds a policy cache, a dict keyed by normalized ARN (arn:aws:iam::aws:policy/<Path><Name>).

Attachment counts are the only per-account state

The only account-specific data for AWS managed policies is how many principals have them attached. This is stored in IamStore.AWS_MANAGED_POLICIES — a CrossRegionAttribute dict mapping non-normalized ARN → AwsManagedPolicy(attachment_count). A key is only present when attachment_count > 0; it is removed when the count drops back to zero.

ARN normalization

AWS managed policy ARNs can use any partition (aws, aws-cn, aws-us-gov). The static index uses the aws partition. All lookups normalize the incoming ARN to arn:aws:iam::aws:policy/... before consulting the cache (but not the in-store attributes), so China and GovCloud work transparently.

Policy IDs are deterministic

Real AWS managed policy IDs (e.g. ANPAIWMBCKSKIEE64ZLYK) are not in moto's dataset. LocalStack generates a stable, deterministic ID for each policy: ANPA + the first 17 hex characters of SHA-256(policy_name). The value is consistent across restarts without needing to be persisted. In the future we can copy those IDs from AWS as well.

Files Changed

File Change
localstack/services/iam/aws_managed_policies.json Created — verbatim copy of moto's moto/iam/aws_managed_policies.py
localstack/services/iam/models.py Added AwsManagedPolicy dataclass; added AWS_MANAGED_POLICIES field to IamStore
localstack/services/iam/provider.py Static-data loading + ARN index; updated get_policy, get_policy_version, list_policies, attach_role_policy, detach_role_policy, attach_user_policy, detach_user_policy, _validate_permissions_boundary
tests/aws/services/iam/test_iam_managed_policies.py Removed pytestmark = pytest.mark.skip

Data Limitations

The static dataset is sourced from moto and reflects AWS policy versions at the time moto last updated its data. Policies may have been updated in real AWS since then (e.g. a policy at DefaultVersionId: "v8" locally may be at "v12" in real AWS). Only the latest version document is available; older historical versions cannot be retrieved.

Tests

All tests for managed policies are enabled and passing

Related

Closes UNC-273

@dfangl dfangl added semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases docs: skip Pull request does not require documentation changes notes: skip Pull request does not have to be mentioned in the release notes labels Feb 24, 2026
@dfangl dfangl force-pushed the daniel/unc-273 branch 2 times, most recently from d914d4a to d315aa5 Compare February 24, 2026 13:46
@github-actions

github-actions Bot commented Feb 24, 2026

Copy link
Copy Markdown

LocalStack Community integration with Pro

  2 files  ±    0    2 suites  ±0   2m 47s ⏱️ - 2h 8m 32s
519 tests  - 5 113  440 ✅  - 4 208  64 💤  - 368  15 ❌  - 517 
521 runs   - 5 113  440 ✅  - 4 208  66 💤  - 368  15 ❌  - 517 

For more details on these failures, see this check.

Results for commit 940032f. ± Comparison against base commit daa78fb.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Feb 24, 2026

Copy link
Copy Markdown

Test Results - Preflight, Unit

23 123 tests  +53   21 252 ✅ +73   6m 16s ⏱️ +17s
     1 suites ± 0    1 871 💤  - 20 
     1 files   ± 0        0 ❌ ± 0 

Results for commit 940032f. ± Comparison against base commit daa78fb.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Feb 24, 2026

Copy link
Copy Markdown

Test Results (amd64) - Acceptance

7 tests  ±0   5 ✅ ±0   3m 3s ⏱️ +2s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit 940032f. ± Comparison against base commit daa78fb.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Feb 24, 2026

Copy link
Copy Markdown

Test Results (amd64) - Integration, Bootstrap

  5 files  ±    0    5 suites  ±0   11m 33s ⏱️ - 2h 30m 11s
543 tests  - 5 494  460 ✅  - 4 970  64 💤  - 524  19 ❌ ±0 
549 runs   - 5 494  460 ✅  - 4 970  70 💤  - 524  19 ❌ ±0 

For more details on these failures, see this check.

Results for commit 940032f. ± Comparison against base commit daa78fb.

♻️ This comment has been updated with latest results.

@pinzon pinzon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this. 👍

Comment thread localstack-core/localstack/services/iam/provider.py
Comment on lines +824 to +832
def _generate_aws_managed_policy_id(self, name: str) -> str:
"""Generate a deterministic, stable PolicyId for an AWS managed policy.

The format mirrors real AWS IDs (``ANPA`` + 17 upper-hex chars). The value
is derived from a SHA-256 hash of the policy name so it is consistent across
restarts without needing to be persisted.
"""
hash_hex = hashlib.sha256(name.encode()).hexdigest()[:17].upper()
return f"ANPA{hash_hex}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: we could add this to the utils file.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with the other PR - let's do them all at once!

@dfangl dfangl merged commit 64364d0 into iam/moto-migration Feb 25, 2026
4 checks passed
@dfangl dfangl deleted the daniel/unc-273 branch February 25, 2026 09:25
dfangl added a commit that referenced this pull request Feb 26, 2026
dfangl added a commit that referenced this pull request Feb 26, 2026
dfangl added a commit that referenced this pull request Mar 4, 2026
dfangl added a commit that referenced this pull request Mar 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

docs: skip Pull request does not require documentation changes notes: skip Pull request does not have to be mentioned in the release notes semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants