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

IAM: Migrate server and signing certificates#13840

Merged
dfangl merged 1 commit into
iam/moto-migrationfrom
daniel/unc-292
Feb 25, 2026
Merged

IAM: Migrate server and signing certificates#13840
dfangl merged 1 commit into
iam/moto-migrationfrom
daniel/unc-292

Conversation

@dfangl

@dfangl dfangl commented Feb 25, 2026

Copy link
Copy Markdown
Member

Motivation

Next, we are migrating the IAM server and signing certificates.

Changes

Server Certificates (8 operations)

Operation Description
UploadServerCertificate Creates a server certificate with path, chain, and tags. Parses X.509 to extract expiration date.
GetServerCertificate Retrieves certificate by name (returns body, chain, tags - never private key)
ListServerCertificates Lists certificates with path_prefix filter and pagination
DeleteServerCertificate Deletes certificate by name
UpdateServerCertificate Updates certificate path and/or name
TagServerCertificate Adds tags to certificate (case-insensitive merge)
UntagServerCertificate Removes tags from certificate
ListServerCertificateTags Lists certificate tags with pagination

Signing Certificates (4 operations)

Operation Description
UploadSigningCertificate Uploads X.509 certificate for user, validates format, enforces quota of 2 per user
ListSigningCertificates Lists certificates for user with pagination
UpdateSigningCertificate Updates certificate status (Active/Inactive)
DeleteSigningCertificate Deletes certificate by ID

Entity Storage

Server Certificates:

  • Created ServerCertificateEntity dataclass wrapping the API's ServerCertificateMetadata
  • Private key is stored but never returned in API responses (AWS behavior)
  • Stored in IamStore.SERVER_CERTIFICATES dict keyed by certificate name
  • Uses CrossRegionAttribute since IAM is a global service

Signing Certificates:

  • Uses the API's SigningCertificate TypedDict directly (no wrapper needed)
  • Stored in UserEntity.signing_certificates dict keyed by certificate ID
  • Maximum 2 certificates per user (enforced via LimitExceededException)

Tests

All 7 tests pass with snapshot parity:

  • test_server_certificate_lifecycle[None]
  • test_server_certificate_lifecycle[/]
  • test_server_certificate_lifecycle[/test-path/]
  • test_server_certificate_with_chain
  • test_server_certificate_errors
  • test_signing_certificate_lifecycle
  • test_signing_certificate_errors

Related

Closes UNC-292

@dfangl dfangl requested a review from pinzon as a code owner February 25, 2026 12:13
@dfangl dfangl added this to the 2026.03 milestone Feb 25, 2026
@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 25, 2026
@github-actions

Copy link
Copy Markdown

LocalStack Community integration with Pro

  2 files    2 suites   2m 48s ⏱️
520 tests 489 ✅ 25 💤 6 ❌
522 runs  489 ✅ 27 💤 6 ❌

For more details on these failures, see this check.

Results for commit dfd4cef.

@github-actions

Copy link
Copy Markdown

Test Results - Preflight, Unit

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

Results for commit dfd4cef. ± Comparison against base commit 4cc1683.

@github-actions

Copy link
Copy Markdown

Test Results (amd64) - Acceptance

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

Results for commit dfd4cef. ± Comparison against base commit 4cc1683.

@github-actions

Copy link
Copy Markdown

Test Results (amd64) - Integration, Bootstrap

  5 files  ±    0    5 suites  ±0   11m 18s ⏱️ - 2h 28m 52s
544 tests  - 5 495  510 ✅  - 4 969  25 💤  - 524  9 ❌  - 2 
550 runs   - 5 495  510 ✅  - 4 969  31 💤  - 524  9 ❌  - 2 

For more details on these failures, see this check.

Results for commit dfd4cef. ± Comparison against base commit 4cc1683.

@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.

Pretty good PR 👍

Comment on lines +3543 to +3553
def _generate_server_certificate_id(self, context: RequestContext) -> str:
"""Generate a server certificate ID with ASCA prefix."""
return generate_iam_identifier(context.account_id, prefix="ASCA", total_length=21)

def _build_server_certificate_arn(
self, context: RequestContext, path: str, cert_name: str
) -> str:
"""Build the ARN for a server certificate."""
return (
f"arn:{context.partition}:iam::{context.account_id}:server-certificate{path}{cert_name}"
)

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.

comment: these 2 methods could be placed in the "utils" file.

Comment on lines +3811 to +3814
def _generate_signing_certificate_id(self) -> str:
"""Generate a 24-character signing certificate ID (uppercase alphanumeric)."""
return "".join(random.choices(string.ascii_uppercase + string.digits, k=24))

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.

Same here.

@dfangl dfangl merged commit 7046745 into iam/moto-migration Feb 25, 2026
47 of 52 checks passed
@dfangl dfangl deleted the daniel/unc-292 branch February 25, 2026 14:53
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