Skip to content

content(what-is): rewrite the iam list-users with dynamic credentials guide#19273

Draft
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-iam-list-users-rewrite
Draft

content(what-is): rewrite the iam list-users with dynamic credentials guide#19273
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-iam-list-users-rewrite

Conversation

@alexleventer
Copy link
Copy Markdown
Contributor

Summary

Rewrites content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md for SEO and AEO. The page now opens with a quotable, prereqs-aware framing, calls out the elevated sensitivity of IAM reads, walks through a tight numbered setup, and resolves doubts in a focused FAQ. Pulumi ESC + OIDC is the throughline.

What changed

  • Quotable opening stating exactly what the guide does and why dynamic credentials beat static keys, with a note that IAM is sensitive and the role should be tightly scoped.
  • "In this article" bullets for scannability.
  • Why dynamic credentials beat static AWS keys section — five concrete reasons, emphasized for IAM's identity-surface exposure.
  • "Least privilege matters more for IAM" standalone section — no iam:*, separate environment, MFA-conditioned trust where applicable, CloudTrail alerting.
  • Prerequisites section — Pulumi Cloud, ESC CLI, AWS IAM role with OIDC trust, iam:ListUsers.
  • Numbered setup steps with the aws-login ESC YAML and a sanity-check aws configure list.
  • The aws iam list-users invocation with flag-by-flag explanation, including the global-service note (no --region) and partition caveats.
  • Verification via aws sts get-caller-identity showing the assumed-role principal.
  • Common-errors tableAccessDenied (trust and identity policy), InvalidClientTokenId, ExpiredToken, Unable to locate credentials.
  • FAQ — CI auditing use case, minimum IAM (and that ListUsers requires Resource: "*"), multi-account, MFA on the trust policy with OIDC sub claim guidance, aws-vault comparison, session duration.
  • Cross-links to /product/esc/, the AWS OIDC guide, sibling sts / s3 / ec2 describe pages, and resolve-* error pages.
  • Stronger meta_desc that leads with the value prop.

Test plan

  • make serve; visit /what-is/run-aws-iam-list-users-with-dynamic-credentials/ and confirm the headings, code blocks, table, and cross-links render
  • Spot-check cross-links (/product/esc/, /docs/esc/guides/configuring-oidc/aws/, sibling run-aws-* pages, resolve-* pages)
  • CI lint + pinned review

🤖 Generated with Claude Code

… guide

Rewrite for SEO and AEO: quotable opening, semantic chunking,
numbered setup steps, common-errors table, FAQ targeting
doubt-removers, and cross-links to Pulumi ESC and related guides.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:docs PR touches technical docs review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-05-20T16:52:26Z

Tip

Summary: This PR rewrites the existing aws iam list-users with dynamic credentials guide under content/what-is/, restructuring it into a step-by-step ESC + OIDC workflow aligned with the other run-aws-*-with-dynamic-credentials siblings (e.g. run-aws-sts-get-caller-identity-with-dynamic-credentials, run-aws-s3-ls-with-dynamic-credentials). Reader-blocking wrongness would be a factually incorrect security claim or an unrunnable workflow — e.g. a wrong OIDC subject claim format that breaks the trust-policy condition, a misstated session-duration default, or an absolute claim about "no keys ever issued" that the YAML on the same page contradicts. Investigative passes that ran: claim extraction (37 claims, 4 specialists), external claim verification, frontmatter sweep, temporal-trigger sweep, code-examples checks (3 specialists), and Vale style linting.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts HIGH 3 real factual errors flagged; 1 verifier finding (L42 link path) triaged as spurious — see 📋.
code correctness HIGH
Investigation log
  • Cross-sibling reads: spot-checked 1 of 9 siblings (run-aws-sts-get-caller-identity-with-dynamic-credentials.md) to confirm the /docs/install/esc/ link is an established sibling-wide convention (it is — all siblings use it, and the alias resolves)
  • External claim verification: 23 of 37 claims verified (3 unverifiable, 4 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 29 Pass 1, 0 Pass 2, 8 Pass 3 (verified 3, contradicted 0, unverifiable 5).
  • Cited-claim spot-checks: not run (no cited claims)
  • Frontmatter sweep: ran on body + meta_desc
  • Temporal-trigger sweep: ran (recency words present in diff; spot-check in-review)
  • Code execution: not run (no static/programs/ change)
  • Code-examples checks: ran (3 specialists: structural, existence, body-code-coverage); 0 findings
  • Editorial-balance pass: not run (not under content/blog/)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
3 10 0 0

🔍 Verification trail

37 claims extracted · 23 verified · 3 unverifiable · 4 contradicted
  • L3 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Pulumi ESC brokers short-lived, OIDC-scoped AWS credentials so that 'aws iam list-users' can be run without static IAM keys." → ✅ verified (evidence: The file's meta_desc (L3) reads: "Run 'aws iam list-users' with short-lived, OIDC-scoped credentials brokered by Pulumi ESC. No static IAM keys, least-privilege role, fully auditable." The body further confirms: "The fn::open::aws-login…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L10 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Dynamic credentials for 'aws iam list-users' are issued by AWS STS at the moment the command runs, scoped to a single role, and time-bound to the role's sessio…" → ✅ verified (framing: strengthened — claim omits the CloudTrail visibility clause from the source sentence; the source's broader form proves the claim as a subset; evidence: The file at L10 states verbatim: "Dynamic credentials are issued by AWS STS at the moment the command runs, scoped to that single role, time-bound to the role's session duration, and visible end-to-end in CloudTrail." The claim matches thi…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L10 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Every 'ListUsers' CloudTrail event carries the assumed-role principal and a session name the user controls when using Pulumi ESC dynamic credentials." → ➖ not-a-claim (evidence: The statement at L10 ("Every ListUsers event carries the assumed-role principal and a session name you control") is a description of the PR author's own documented workflow/pipeline behavior within the file being introduced — it describe…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L10 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Dynamic credentials for 'aws iam list-users' via Pulumi ESC are issued by AWS STS at the moment the command runs, scoped to a single role, and time-bound to th…" → ✅ verified (evidence: The file's introductory paragraph (line 10) states verbatim: "Dynamic credentials are issued by AWS STS at the moment the command runs, scoped to that single role, time-bound to the role's session duration, and visible end-to-end in CloudT…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L14 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "- Why dynamic credentials beat static AWS keys for sensitive IAM reads" → ✅ verified (framing: strengthened — claim narrows the general AWS recommendation (dynamic > static for all AWS API calls) to the specific case of sensitive IAM reads; source's broa…; evidence: AWS official docs state: "Temporary security credentials are more secure because they are not stored with the user but are generated dynamically and provided to the user when requested." AWS strongly recommends temporary/dynamic credential…; source: https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds-programmatic-access.html)
  • L22 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "## Why dynamic credentials beat static AWS keys" → ➖ not-a-claim (evidence: The text "## Why dynamic credentials beat static AWS keys" is a markdown section heading in the PR author's own document. It is an editorial framing choice/title, not a falsifiable factual assertion about a third-party system or source.; source: content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md L22)
  • L24 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "- No aws_access_key_id on disk. Nothing to leak from ~/.aws/credentials, a developer laptop, a CI runner cache, or a screenshot in Slack. Especially im…" → ➖ not-a-claim (evidence: The line is the PR author's own editorial description of a security benefit of using Pulumi ESC dynamic credentials — it is a faithful description of the author's own pipeline design, not a third-party-attributed assertion. Pulumi docs con…; source: https://www.pulumi.com/what-is/run-aws-iam-list-users-with-dynamic-credentials/)
  • L26 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "AWS STS sessions obtained via Pulumi ESC expire based on the 'duration' configured, with a default of 1 hour." → ❌ contradicted (framing: shifted — claim states "default 1 hour" but the source says "Defaults to 2 hours"; the 1-hour figure refers to AWS's own MaxDuration default, not the Pulumi ES…; evidence: The official aws-login ESC provider docs state: "The duration of the role session. Defaults to 2 hours. Unless explicitly specified, AWS sets MaxDuration to 1 hour by default." The claim says the default is 1 hour, but the Pulumi ESC provi…; source: repo:content/docs/esc/integrations/dynamic-login-credentials/aws-login.md)
  • L41 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "- A Pulumi Cloud account and an organization you can create environments in." → ➖ not-a-claim (evidence: The text is a prerequisite bullet point in the PR author's own documentation, linking to the Pulumi Cloud sign-in page (https://app.pulumi.com/signin). The URL is a well-known, stable Pulumi product login page and the statement is a standa…; source: content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md L41)
  • L42 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The ESC CLI installation documentation is located at /docs/install/esc/." → ❌ contradicted (evidence: The pulumi/docs repo has no content/docs/install/esc/ path — the /docs/install/ directory contains only _index.md and versions.md. ESC CLI documentation exists under content/docs/esc/cli/, not at /docs/install/esc/.; source: gh api repos/pulumi/docs/contents/content/docs/install — returns only _index.md and versions.md, no esc subdirectory; gh api repos/pulumi/docs/contents/content/docs/install/esc returns HTTP 404)
  • L44-45 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The minimum IAM permission required for the role used with 'aws iam list-users' is 'iam:ListUsers'." → ✅ verified (evidence: The file itself at L44 states: "An IAM role with iam:ListUsers (the minimum), and a trust policy that allows Pulumi's OIDC issuer to assume it." The AWS IAM action iam:ListUsers directly maps to the ListUsers API call used by `aws ia…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L51 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Follow the configuring OIDC between Pulumi and AWS guide to create an IAM role whose trust policy accepts Pulumi's OI…" → ✅ verified (evidence: The file at /docs/esc/guides/configuring-oidc/aws/ exists and covers configuring OIDC between Pulumi and AWS, including creating an IAM role with a trust policy that accepts Pulumi's OIDC issuer. It explicitly states: "Before you log out…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L78 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The 'fn::open::aws-login' provider performs the 'AssumeRoleWithWebIdentity' call against AWS STS at runtime." → ✅ verified (evidence: The file at L78 states verbatim: "The fn::open::aws-login provider performs the AssumeRoleWithWebIdentity call against AWS STS at runtime." The same file's error table also references sts:AssumeRoleWithWebIdentity, corroborating that…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L78 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The 'environmentVariables' block in a Pulumi ESC environment exposes resulting short-lived credentials to any process 'esc run' invokes." → ✅ verified (evidence: The file at the claimed line contains the exact statement: "The environmentVariables block exposes the resulting short-lived credentials to any process esc run invokes." This accurately describes ESC's behavior where `environmentVariab…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L103 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "IAM is a global service in the standard AWS partition ('aws'), and the AWS CLI targets 'us-east-1' by default when no region is specified." → ✅ verified (evidence: The file at the relevant line states: "No --region is required: IAM is a global service in the standard partition (aws), and the CLI targets us-east-1 by default. In the aws-us-gov or aws-cn partitions, set AWS_REGION according…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L103 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "In the 'aws-us-gov' or 'aws-cn' partitions, 'AWS_REGION' must be set explicitly when running 'aws iam list-users'." → ✅ verified (framing: strengthened — the source says "set AWS_REGION accordingly"; the claim renders this as "must be set explicitly", which is a narrower/stronger restatement of…; evidence: The file at line ~103 states: "No --region is required: IAM is a global service in the standard partition (aws), and the CLI targets us-east-1 by default. In the aws-us-gov or aws-cn partitions, set AWS_REGION accordingly." Thi…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L113 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "'Arn': 'arn:aws:iam::123456789012:user/alice'," → ➖ not-a-claim (evidence: The text "Arn": "arn:aws:iam::123456789012:user/alice" is a placeholder/example value in a documentation code snippet. The account ID 123456789012 and username alice are canonical AWS documentation placeholders, not factual assertion…; source: AWS documentation convention for placeholder account IDs and usernames in example ARNs)
  • L114 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "'CreateDate': '2025-08-14T17:42:11+00:00'" → ➖ not-a-claim (evidence: This is a sample/example timestamp embedded in a JSON output snippet illustrating what aws iam list-users returns. It is fabricated example data authored by the PR author to demonstrate CLI output format, not a factual assertion about a…; source: content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md L114 (PR author's own illustrative example data))
  • L120 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "For large accounts, 'aws iam list-users' can be paginated with '--max-items 50' and '--starting-token' from the previous response." → ✅ verified (evidence: The file at line ~120 states: "For large accounts, paginate with --max-items 50 and feed --starting-token from the previous response." This matches the claim exactly and is consistent with standard AWS CLI pagination behavior for `aws…; source: content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L131 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "'Arn': 'arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc-iam-read/pulumi-environments-session'" → ➖ not-a-claim (evidence: The ARN arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc-iam-read/pulumi-environments-session appears in a JSON code block showing example output of aws sts get-caller-identity, using the standard AWS documentation placeholder ac…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L135 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The CloudTrail 'ListUsers' event will show 'userIdentity.type = AssumedRole' and the session name when dynamic credentials are used via Pulumi ESC." → ✅ verified (evidence: The file at the relevant section states: "The matching CloudTrail ListUsers event will show userIdentity.type = AssumedRole and the same session name." This is in the context of using Pulumi ESC dynamic credentials via esc run, confi…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L141 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "| AccessDenied: not authorized to perform: sts:AssumeRoleWithWebIdentity | IAM role trust policy does not allow Pulumi's OIDC issuer or your org's audience |…" → ✅ verified (evidence: The file content/docs/esc/guides/configuring-oidc/aws.md exists and is a complete guide titled "Configuring OpenID Connect for AWS", covering trust policy setup, IAM role configuration, and sts:AssumeRoleWithWebIdentity — exactly the c…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L143 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "| InvalidClientTokenId | The ESC env didn't inject credentials; you're hitting AWS with stale or empty keys | Confirm the environmentVariables block and th…" → ✅ verified (evidence: The file content/what-is/resolve-list-buckets-invalid-client-token-id.md exists in the repo and covers exactly the topic referenced — resolving InvalidClientTokenId errors when calling AWS operations (specifically ListBuckets) by using…; source: repo:content/what-is/resolve-list-buckets-invalid-client-token-id.md)
  • L144-145 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "'esc run' mints a fresh STS session each invocation, so re-running the command resolves an 'ExpiredToken' error." → ✅ verified (evidence: The source page /what-is/resolve-list-buckets-expired-token/ confirms that esc run dynamically generates credentials each invocation via OIDC: "you no longer have to worry about credential errors like 'ExpiredToken' as the service will…; source: content/what-is/resolve-list-buckets-expired-token.md)
  • L151 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support the 'esc run' pattern for CI use." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L155 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The 'iam:ListUsers' action does not support resource-level constraints and returns all users, so the policy resource must be '*'." → ✅ verified (framing: strengthened — claim narrows the general "no resource type → must use " rule to the specific iam:ListUsers action; source's broader form proves the claim as…; evidence: The AWS Service Authorization Reference for IAM confirms that iam:ListUsers has no resource type in the Resource types column, meaning "you must specify all resources ('') to which the policy applies." Official AWS example policies cons…; source: https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsidentityandaccessmanagementiam.html)
  • L159 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Using one ESC environment per account, each pointing at a read-only IAM role, is described as the recommended pattern for centralized IAM auditing across multi…" → 🤷 unverifiable (evidence: The cited source page (/docs/esc/environments/imports/) covers explicit and implicit environment imports for composing configurations, but contains no mention of "one ESC environment per account," "read-only IAM role," "recommended patte…; source: repo:content/docs/esc/environments/imports.md)
  • L163 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The OIDC 'sub' claim used by Pulumi ESC is formatted as 'pulumi:deploy:org::env:'." → ❌ contradicted (framing: shifted — claim uses 'pulumi:deploy:org::env:' but the source specifies 'pulumi:environments:org::env:'; the segment 'deploy' vs 'environme…; evidence: The official Pulumi ESC OIDC AWS guide states: "By default, the subject claim has the following format: pulumi:environments:org:<organization name>:env:<project name>/<environment name>" — the prefix is pulumi:environments:org:, not `p…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L171 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "'aws-vault' stores long-lived keys in the OS keychain and brokers temporary sessions locally, whereas Pulumi ESC removes the long-lived key entirely via OIDC-b…" → ✅ verified (framing: strengthened — the claim accurately narrows the source's description to "OS keychain" (the README lists macOS Keychain, Windows Credential Manager, Secret Serv…; evidence: The aws-vault README states: "AWS Vault stores IAM credentials in your operating system's secure keystore and then generates temporary credentials from those to expose to your shell and applications." This confirms the claim that aws-vault…; source: gh api repos/99designs/aws-vault/readme (base64-decoded README.md))
  • L171 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Pulumi ESC provides centralized environments, secret aggregation from other providers, and audit logs across the team — capabilities not offered by 'aws-vault'." → ✅ verified (framing: strengthened — the claim correctly identifies specific ESC capabilities (centralized environments, secret aggregation, audit logs) as a narrower subset of ESC'…; evidence: (escalated from pass1) Pulumi ESC is confirmed to offer centralized environments, secret aggregation from multiple providers (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, 1Password, etc.), and full audit logging. aws-vault is a…; source: WebSearch ran query "Pulumi ESC centralized environments secret aggregation audit logs features"; https://github.com/pulumi/esc and https://www.pulumi.com/product/secrets-management/)
  • L171 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no key is ever issued to a developer or runner." → ❌ contradicted (framing: narrowed — claim broadens "no long-lived key" to "no key is ever issued"; the source's environmentVariables block explicitly shows AWS_ACCESS_KEY_ID/SECRET_A…; evidence: The file itself shows that esc run injects AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN as environment variables — i.e., STS does issue short-lived keys to the runner. The source says "No aws_access_key_id on…; source: repo:content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md)
  • L175 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "For sensitive IAM reads, the guide recommends preferring the default 1-hour session window and having callers re-assume rather than extending the duration." → 🤷 unverifiable (evidence: AWS STS documentation confirms the default AssumeRole session duration is 3600 seconds (1 hour), but no AWS STS documentation recommends "preferring the default 1-hour session window and having callers re-assume rather than extending the d…; source: https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html; intuition: The claim attributes a specific security recommendation ("prefer 1-hour window, re-assume rather than extend") to AWS S… (WebSearch dispatched but verification did not converge within the turn budget))
  • L179-180 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "- Configuring OIDC between Pulumi and AWS" → ✅ verified (framing: strengthened — the link text "Configuring OIDC between Pulumi and AWS" is a slight paraphrase of the actual page title "Configuring OpenID Connect for AWS", bu…; evidence: The file content/docs/esc/guides/configuring-oidc/aws.md exists at the path /docs/esc/guides/configuring-oidc/aws/ and covers configuring OIDC between Pulumi and AWS (h1: "Configuring OpenID Connect for AWS"). The URL resolves correctl…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L181 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The 'esc run' command reference is located at /docs/esc/cli/commands/esc_run/." → ✅ verified (evidence: The file content/docs/esc/cli/commands/esc_run.md exists in the repo with title "esc run | CLI commands", confirming the esc run command reference is located at /docs/esc/cli/commands/esc_run/.; source: repo:content/docs/esc/cli/commands/esc_run.md)
  • L183-185 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The page '/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials/' exists as a related dynamic-credentials guide." → 🤝 matches (evidence: The file content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md exists in the repo and is a complete guide titled "Run 'aws sts get-caller-identity' using Dynamic Credentials", confirming the cross-referenced page ex…; source: repo:content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md)
  • L183-185 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "- Run aws sts get-caller-identity with dynamic credentials" → ✅ verified (evidence: The file content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md exists in the repo with the title "Run 'aws sts get-caller-identity' using Dynamic Credentials", confirming the linked page at `/what-is/run-aws-sts-get…; source: repo:content/what-is/run-aws-sts-get-caller-identity-with-dynamic-credentials.md)
  • L186 in content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md "The error resolution page '/what-is/resolve-list-buckets-invalid-client-token-id/' exists." → ✅ verified (evidence: The file content/what-is/resolve-list-buckets-invalid-client-token-id.md exists in the repository with a valid title and content about resolving the InvalidClientTokenId error when calling ListBuckets.; source: repo:content/what-is/resolve-list-buckets-invalid-client-token-id.md)

🚨 Outstanding in this PR

These must be resolved or refuted before merging.

  • [L26] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"Time-bound by STS. Sessions expire on the duration you configure (default 1 hour)." — The Pulumi ESC aws-login provider's duration field defaults to 2 hours, not 1 hour. Per content/docs/esc/integrations/dynamic-login-credentials/aws-login.md L53: "The duration of the role session. Defaults to 2 hours. Unless explicitly specified, AWS sets MaxDuration to 1 hour by default." The 1-hour figure is AWS's IAM-role MaxSessionDuration default — a separate ceiling that clamps duration when not raised. The example YAML in this PR explicitly sets duration: 1h (L69), which is a choice, not the default.

    - **Time-bound by STS.** Sessions expire on the `duration` you configure (the `aws-login` provider's default is 2 hours, clamped by the IAM role's `MaxSessionDuration` — which AWS sets to 1 hour by default unless raised). An exfiltrated session token is useless once that window closes.
    
  • [L163] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"The OIDC sub claim is pulumi:deploy:org:<org>:env:<env> and can be matched with StringEquals." — Wrong prefix. The default ESC OIDC subject is pulumi:environments: (not pulumi:deploy:), and the env segment includes the project. Per content/docs/esc/guides/configuring-oidc/aws.md L138: "pulumi:environments:org:<organization name>:env:<project name>/<environment name>". A trust-policy condition built against pulumi:deploy:… will never match and the role assumption will fail — this is a load-bearing factual error for any reader copying the format into a trust policy.

    Yes. Add a `Condition` block to the trust policy that requires `aws:MultiFactorAuthPresent` (for IAM-user-based assumption) or use OIDC subject conditions to restrict which Pulumi org or environment can assume the role. The default ESC OIDC `sub` claim is `pulumi:environments:org:<org>:env:<project>/<env>` and can be matched with `StringEquals`.
    
  • [L171] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no key is ever issued to a developer or runner." — Self-contradicting on the same page: the environmentVariables block in this PR's own example (L73–75) shows AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN being injected into the runner. STS does issue short-lived keys; what ESC eliminates is long-lived keys. The previous bullet at L24 ("No aws_access_key_id on disk") gets the framing right; this sentence overstates it. Tighten the wording so an attentive reader doesn't catch the contradiction with the YAML above.

    `aws-vault` stores long-lived keys in your OS keychain and brokers temporary sessions locally. Pulumi ESC removes the long-lived key entirely: the trust is OIDC-based and lives in IAM, so no long-lived key ever lands on a developer machine or CI runner — only the short-lived STS session credentials that `esc run` injects for the duration of the command. ESC also gives you centralized environments, secret aggregation from other providers, and audit logs across the team.
    

⚠️ Low-confidence

Review each and resolve as appropriate — these don't block the PR.

  • [L151] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support this pattern." — verifier didn't converge. Pulumi does ship a GitHub Action (pulumi/esc-action), and esc run works in any CI that lets you set PULUMI_ACCESS_TOKEN and run a shell command, so the claim is plausibly true — but the named first-party integrations for GitLab CI and CircleCI aren't documented in this repo under content/docs/esc/integrations/. Author question: can you link the specific GitLab CI and CircleCI integration docs you have in mind, or soften this to "works in any CI runner that can set PULUMI_ACCESS_TOKEN, including GitHub Actions, GitLab CI, and CircleCI"?

  • [L159] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"Yes, and it's the recommended pattern for centralized IAM auditing. Create one ESC environment per account…" — the environment imports docs describe the import mechanic but don't endorse "one env per account" as a named "recommended pattern." The linked page supports the how (compose a base env with per-account overrides) but not the recommendation. Not a blocker since the link still teaches the relevant capability — but the implied "Pulumi recommends" framing is the author's editorial call, not a documented stance. Author question: OK to soften from "it's the recommended pattern" to "a clean pattern is…" / "we recommend…", or do you have a Pulumi doc page that explicitly recommends this topology?

  • [L175] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"Up to the role's MaxSessionDuration (default 1 hour, configurable up to 12 hours for non-chained roles). For sensitive IAM reads, prefer the default 1-hour window and have callers re-assume rather than extending the duration." — the 1h/12h MaxSessionDuration facts are well-documented AWS behavior; the "prefer 1-hour, re-assume rather than extend" line is the author's own recommendation, not an attribution to AWS — so it reads fine as editorial advice. Related: re-check the bullet against the L26 fix above — once L26 stops claiming a "1 hour default," make sure this section still reads coherently (right now the page implies the default is 1 hour in two places, both wrong for the aws-login provider).

Style findings

Found by pattern-based linting; Findings may be false positives.

  • line 32: [style] wordiness — 'enumerate' is too wordy.
  • line 143: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 144: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 145: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 149: [style] first person — Avoid first-person pronouns such as ' I '.
  • line 161: [style] first person — Avoid first-person pronouns such as ' I '.
  • line 165: [style] first person — Avoid first-person pronouns such as ' I '.

📋 Triaged verifier findings

I double-checked these and realized they weren't real findings — click to expand
  • [L42] content/what-is/run-aws-iam-list-users-with-dynamic-credentials.md"The Pulumi CLI and the ESC CLI installed and authenticated"Spurious: the verifier checked for a content/docs/install/esc/ source file and found none, but /docs/install/esc/ is a valid published URL — it's declared as an alias on content/docs/esc/cli/download-install/_index.md (aliases: [/docs/install/esc/, /docs/esc/install, /docs/esc/download-install/]). All sibling run-aws-*-with-dynamic-credentials pages use the same alias, so this is a long-standing site-wide convention, not a broken link.

💡 Pre-existing issues in touched files (optional)

No pre-existing issues in touched files.

✅ Resolved since last review

No items resolved since the last review.

📜 Review history

  • 2026-05-20T16:52:26Z — 3 real factual errors flagged (aws-login duration default, OIDC sub claim prefix, "no key is ever issued" overclaim); 1 verifier finding triaged as spurious (/docs/install/esc/ is a valid alias) (4cff849)

Need a re-review? Want to dispute a finding? Mention @claude and include #update-review.
(For ad-hoc questions or fixes, just @claude — no hashtag.)

@github-actions github-actions Bot added review:outstanding-issues Claude review completed; outstanding has author-actionable findings and removed review:in-progress Claude review is currently running labels May 20, 2026
@pulumi-bot
Copy link
Copy Markdown
Collaborator

@alexleventer alexleventer marked this pull request as draft May 20, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:docs PR touches technical docs review:outstanding-issues Claude review completed; outstanding has author-actionable findings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants