Skip to content

content(what-is): rewrite the ec2 start-instances with dynamic credentials guide#19261

Draft
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-ec2-start-rewrite
Draft

content(what-is): rewrite the ec2 start-instances with dynamic credentials guide#19261
alexleventer wants to merge 1 commit into
masterfrom
aleventer/run-ec2-start-rewrite

Conversation

@alexleventer
Copy link
Copy Markdown
Contributor

Summary

Rewrites content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md for SEO and AEO. The page now opens with a quotable, prereqs-aware framing, 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, plus the prereqs.
  • "In this article" bullets for scannability.
  • Why dynamic credentials beat static AWS keys section — five concrete reasons, including tag-scoped least privilege for state-changing actions.
  • Prerequisites section — Pulumi Cloud, ESC CLI, AWS IAM role with OIDC trust, ec2:StartInstances + ec2:DescribeInstances.
  • Numbered setup steps with the aws-login ESC YAML and a sanity-check aws configure list.
  • The aws ec2 start-instances invocation with a flag-by-flag explanation plus a wait instance-running follow-up.
  • Verification via aws sts get-caller-identity showing the assumed-role principal.
  • Common-errors tableAccessDenied, UnauthorizedOperation, InvalidInstanceID.NotFound, InvalidClientTokenId, ExpiredToken, Unable to locate credentials.
  • FAQ — CI/cron use, minimum IAM with a tag-scoped policy example, multi-account, multi-region, aws-vault comparison, session duration.
  • Cross-links to /product/esc/, the AWS OIDC guide, sibling stop/describe pages, sts, and resolve-* error pages.
  • Stronger meta_desc that leads with the value prop.

Test plan

  • make serve; visit /what-is/run-aws-ec2-start-instances-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

…tials 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:49:18Z

Tip

Summary: This PR is a top-to-bottom rewrite of the /what-is/run-aws-ec2-start-instances-with-dynamic-credentials/ page — replacing the earlier marketing-style intro with a runnable, step-by-step ESC + OIDC walkthrough that parallels the existing sibling guides for stop-instances, describe-instances, and sts get-caller-identity. The kind of wrongness that would block a reader: an invocation, an IAM permission rationale, or a security claim that doesn't match how ESC + STS actually behave, so the reader copies it and either gets a confusing error or assumes a stronger guarantee than ESC actually provides. Investigative passes that ran: claim extraction + verification (39 candidates, 27 verified, 3 unverifiable, 3 contradicted), frontmatter sweep, code-example structural pass, link-target spot-checks, and a small in-review sibling consistency check against the other three EC2/STS dynamic-credentials guides.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM Two real fact issues to fix (L158 reasoning for DescribeInstances; L183 "no key ever issued" overstates what ESC does); three other claims couldn't be fully cited but read as plausible.
code correctness HIGH
Investigation log
  • Cross-sibling reads: 3 of 3 EC2/STS dynamic-credentials siblings spot-checked in-review (stop-instances, describe-instances, sts-get-caller-identity) — those use the older marketing-style template; this PR is the first of the series to follow the new step-by-step format, so no template-drift to flag
  • External claim verification: 27 of 39 claims verified (3 unverifiable, 3 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 26 Pass 1, 0 Pass 2, 13 Pass 3 (verified 10, contradicted 1, unverifiable 2).
  • 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
2 6 0 0

🔍 Verification trail

39 claims extracted · 27 verified · 3 unverifiable · 3 contradicted
  • L3 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Pulumi ESC brokers short-lived, OIDC-scoped credentials for aws ec2 start-instances with no static keys required." → ✅ verified (evidence: The file's meta_desc at L3 reads: "Start EC2 instances with 'aws ec2 start-instances' using short-lived, OIDC-scoped credentials brokered by Pulumi ESC. No static keys, fully auditable." The body further confirms: "The `fn::open::aws-login…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L10 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Using Pulumi ESC dynamic credentials for aws ec2 start-instances requires the Pulumi CLI, the esc CLI, a Pulumi Cloud account, and an AWS IAM role configur…" → ✅ verified (evidence: Line 10 of the file states: "You'll need the Pulumi CLI, the esc CLI, a Pulumi Cloud account, and an AWS IAM role configured to trust Pulumi as an OIDC provider." This exactly matches the claim's listed prerequisite…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L14 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "- Why dynamic credentials beat static AWS keys for state-changing EC2 calls" → ✅ verified (framing: strengthened — claim narrows the general "temporary over long-term credentials" best practice to the specific context of state-changing EC2 calls; source's bro…; evidence: AWS Well-Architected Security Pillar states: "it's best to use temporary credentials instead of long-term credentials to reduce or eliminate risks, such as credentials being inadvertently disclosed, shared, or stolen." Multiple AWS sources…; source: https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/sec_identities_unique.html)
  • L22 in content/what-is/run-aws-ec2-start-instances-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 a rhetorical/editorial framing choice by the author, not a falsifiable factual assertion about a third-party sy…; source: content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md, L22)
  • L24 in content/what-is/run-aws-ec2-start-instances-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." → ➖ not-a-claim (evidence: The line is a bullet-point in the PR author's own explanatory prose describing the security benefit of their dynamic-credentials design — specifically that no static aws_access_key_id is written to disk. This is a faithful description of t…; source: WebSearch ran query "AWS dynamic credentials no aws_access_key_id on disk ~/.aws/credentials security")
  • L26 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "AWS STS sessions expire based on the duration configured, with a default of 1 hour." → ✅ verified (framing: strengthened — claim says "AWS STS sessions" broadly; the 1-hour default applies specifically to AssumeRole-based sessions (the standard dynamic credentials pa…; evidence: AWS STS AssumeRole sessions default to 1 hour, confirmed by official AWS docs: "By default, the temporary security credentials created by AssumeRoleWithSAML last for one hour." The AssumeRole API reference also states the default is 1 hour…; source: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithSAML.html; https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html)
  • L27 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Every StartInstances CloudTrail event carries the assumed-role principal and a session name." → ✅ verified (framing: strengthened — claim narrows the general CloudTrail behavior (all events made with assumed-role credentials carry the principal and session name) to the specif…; evidence: AWS CloudTrail docs confirm that for requests made with temporary security credentials (assumed roles), the userIdentity element includes the assumed-role principal and the session name. Per the CloudTrail userIdentity reference: "For re…; source: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
  • L32 in content/what-is/run-aws-ec2-start-instances-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 linking to the Pulumi Cloud sign-in page (https://app.pulumi.com/signin). It is a navigational/reference link, not a falsifiable factual assertion about Pulumi's capabilities or behavior.; source: content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md L32)
  • L33 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "- The Pulumi CLI and the ESC CLI installed and authenticated (esc login)." → ❌ contradicted (framing: shifted — the link /docs/install/esc/ points to a non-existent path; the correct ESC CLI install/reference path is /docs/esc/cli/; evidence: The /docs/install/ directory in pulumi/docs contains only _index.md and versions.md — there is no esc page or subdirectory at that path. The ESC CLI documentation lives under /docs/esc/cli/, not /docs/install/esc/.; source: gh api repos/pulumi/docs/contents/content/docs/install)
  • L35 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "An IAM role used with Pulumi ESC for aws ec2 start-instances requires ec2:StartInstances and ec2:DescribeInstances permissions." → ➖ not-a-claim (evidence: The claim is the PR author's own design recommendation in their new content file: "An IAM role with ec2:StartInstances and ec2:DescribeInstances" is stated as a prerequisite the author is prescribing for the workflow they are documenti…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L36 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The AWS CLI v2 is required as a prerequisite for this workflow." → ✅ verified (evidence: The Prerequisites section of the file explicitly lists "The AWS CLI v2 installed." as one of the required prerequisites for the esc run workflow described in the article.; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L43 in content/what-is/run-aws-ec2-start-instances-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 content/docs/esc/guides/configuring-oidc/aws.md exists and covers exactly what the claim describes: creating an IAM role whose trust policy accepts Pulumi's OIDC issuer. The guide states "Before you log out of the AWS console…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L70 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The fn::open::aws-login provider performs the AssumeRoleWithWebIdentity call against AWS STS at runtime." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L70 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The environmentVariables block in a Pulumi ESC environment exposes the resulting short-lived credentials to any process esc run invokes." → ✅ verified (evidence: The file at L70 contains the exact sentence: "The environmentVariables block exposes the resulting short-lived credentials to any process esc run invokes." This is consistent with Pulumi ESC's documented behavior where `environmentVari…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L97 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "esc run <env> -- opens the named ESC environment, assumes the IAM role, and injects the short-lived credentials as environment variables for the command that…" → ➖ not-a-claim (evidence: The line at L97 is the PR author's own description of esc run behavior within the document they are writing — it is a faithful description of the author's own pipeline/design, not a third-party-attributed assertion. The surrounding file…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L98 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The --instance-ids flag for aws ec2 start-instances accepts a space-separated list of instance IDs." → ✅ verified (evidence: The file at line ~98 explicitly states "--instance-ids is the space-separated list of instance IDs to start," and the code example above it demonstrates this with --instance-ids i-0123456789abcdef0 i-0fedcba9876543210 — two IDs separat…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L99 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "EC2 start-instances is region-scoped, so instance IDs must live in the region you query." → ✅ verified (evidence: AWS EC2 instance types docs state: "The ID of an instance is tied to the Region for the instance, and can only be used in this Region." The EC2 resources page also confirms "Amazon EC2 resources are specific to the AWS Region or zone in wh…; source: https://docs.aws.amazon.com/ec2/latest/instancetypes/ec2-instance-regions.html)
  • L108-109 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "A successful aws ec2 start-instances response returns a StartingInstances array with CurrentState code 0 and name 'pending', and PreviousState code 80…" → ✅ verified (evidence: The official AWS EC2 API reference and CLI docs show the exact response: "CurrentState": { "Code": 0, "Name": "pending" }, "PreviousState": { "Code": 80, "Name": "stopped" } inside a StartingInstances array.; source: https://docs.aws.amazon.com/cli/latest/reference/ec2/start-instances.html)
  • L133 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "'Arn': 'arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc/pulumi-environments-session'" → ➖ not-a-claim (evidence: The ARN arn:aws:sts::123456789012:assumed-role/pulumi-esc-oidc/pulumi-environments-session appears in a sample sts get-caller-identity output block using the well-known AWS placeholder account ID 123456789012. It is illustrative exam…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L137 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The assumed-role ARN and the pulumi-environments-session suffix in sts get-caller-identity output confirm you're using a role session, not an IAM user." → ✅ verified (evidence: The file contains the exact sentence at the described location: "The assumed-role ARN and the pulumi-environments-session suffix confirm you're using a role session, not an IAM user." This follows a sts get-caller-identity output sho…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L137 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The matching CloudTrail StartInstances event will show userIdentity.type = AssumedRole and the same session name as the assumed-role session." → ✅ verified (framing: strengthened — claim narrows the general AssumedRole behavior to the specific StartInstances event; source's broader form (any API call made with AssumedRole c…; evidence: AWS CloudTrail docs confirm: "AssumedRole – The request was made with temporary security credentials that were obtained with a role by making a call to the AWS Security Token Service (AWS STS) AssumeRole API." The principalId field "incl…; source: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html)
  • L143 in content/what-is/run-aws-ec2-start-instances-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 on configuring OIDC for AWS with Pulumi ESC, covering trust policy setup including sts:AssumeRoleWithWebIdentity and the Pulumi OIDC issuer (`api.p…; source: repo:content/docs/esc/guides/configuring-oidc/aws.md)
  • L146 in content/what-is/run-aws-ec2-start-instances-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 (like ListBuckets) by using Pulumi E…; source: repo:content/what-is/resolve-list-buckets-invalid-client-token-id.md)
  • L147-148 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "esc run mints a fresh session each invocation, resolving ExpiredToken errors by re-running the command." → ✅ verified (framing: strengthened — claim narrows the source's "dynamically generate and refresh" to "mints a fresh session each invocation"; source's broader form proves the claim…; evidence: The referenced source page confirms that esc run with dynamic OIDC credentials resolves ExpiredToken errors: "you no longer have to worry about credential errors like 'ExpiredToken' as the service will dynamically generate and refresh…; source: content/what-is/resolve-list-buckets-expired-token.md)
  • L154 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Using esc run in CI to start EC2 instances requires setting PULUMI_ACCESS_TOKEN on the runner; the runner needs no long-lived AWS credentials." → ✅ verified (framing: strengthened — the document broadly states no long-lived AWS credentials are needed in any context (including CI); the claim narrows this to the CI runner spec…; evidence: The document's entire premise is that esc run eliminates long-lived AWS credentials by using OIDC-brokered dynamic credentials: "No aws_access_key_id on disk. Nothing to leak from ~/.aws/credentials, a developer laptop, a CI runner c…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L154 in content/what-is/run-aws-ec2-start-instances-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)
  • L158 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The minimum IAM permissions required for the role are ec2:StartInstances for the start action and ec2:DescribeInstances so the CLI can resolve and validate…" → ❌ contradicted (framing: shifted — the source pairs ec2:StartInstances + ec2:DescribeInstances in IAM policies, but the claimed reason ("CLI can resolve and validate the IDs passed") i…; evidence: AWS official IAM policy examples pair ec2:StartInstances with ec2:DescribeInstances, but no AWS documentation states that ec2:DescribeInstances is required "so the CLI can resolve and validate the IDs passed." The AWS CLI `start-inst…; source: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_ec2_tag-owner.html; https://docs.aws.amazon.com/cli/latest/reference/ec2/start-instances.html)
  • L164 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "'Resource': 'arn:aws:ec2:::instance/*'," → ✅ verified (evidence: AWS documentation and official sources confirm the EC2 instance ARN format is arn:aws:ec2:region:account:instance/*. Using wildcards for region and account is valid in IAM policy Resource elements; as the AWS Security Blog states, "You s…; source: https://aws.amazon.com/blogs/security/demystifying-ec2-resource-level-permissions/)
  • L171 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Pulumi ESC environment imports can be used to compose a base environment with account-specific overrides for multi-account AWS setups." → ✅ verified (framing: strengthened — claim narrows the general "compose environments" capability to the specific multi-account AWS override use case; the source's broader form prove…; evidence: The imports page states: "Pulumi ESC allows you to compose environments by importing configuration and secrets from other environments. This reduces duplication, ensures consistency, and enables you to organize configuration hierarchically…; source: content/docs/esc/environments/imports.md)
  • L175 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "aws ec2 start-instances is a single-region call and cannot start instances in multiple regions in one command." → ✅ verified (framing: strengthened — the docs don't explicitly state "cannot start instances in multiple regions in one command," but the command's single-region design (one --regi…; evidence: The official AWS CLI docs for start-instancesshow the command accepts a single--regionflag and only--instance-ids` as its primary parameter — there is no mechanism to target multiple regions in one invocation. The command signatur…; source: https://docs.aws.amazon.com/cli/latest/reference/ec2/start-instances.html)
  • L175 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "The IAM role is assumed once per esc run invocation." → ✅ verified (evidence: The file itself states in the ExpiredToken error row: "esc run mints a fresh session each invocation", and earlier describes that fn::open::aws-login "performs the AssumeRoleWithWebIdentity call against AWS STS at runtime" — confirmi…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L183 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "aws-vault stores long-lived keys in the OS keychain and brokers temporary sessions locally." → ✅ verified (framing: strengthened — claim narrows 'generates temporary credentials from those to expose to your shell and applications' to 'brokers temporary sessions locally'; sou…; evidence: The official 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 both storing lo…; source: https://github.com/99designs/aws-vault)
  • L183 in content/what-is/run-aws-ec2-start-instances-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: shifted — the source says "no static/long-lived keys" but the claim asserts "no key is ever issued to a developer or runner," which contradicts the document's…; evidence: The file itself shows that Pulumi ESC DOES issue credentials to the runner — the environmentVariables block exposes AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN (short-lived STS tokens) to the invoked process. Th…; source: repo:content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md)
  • L183 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "Pulumi ESC provides centralized environments, secret aggregation from other providers, and audit logs across the team, as differentiators from aws-vault." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L187 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "AWS STS sessions can last up to the role's MaxSessionDuration, which defaults to 1 hour and is configurable up to 12 hours for non-chained roles." → ✅ verified (evidence: AWS IAM docs confirm: "If you do not specify a value, the default maximum of 1 hour is applied" and "This setting can have a value from 1 hour to 12 hours." The AWS STS AssumeRole API reference also states "Role chaining limits your AWS CL…; source: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-settings.html)
  • L191-192 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "- Configuring OIDC between Pulumi and AWS" → ✅ verified (evidence: The file content/docs/esc/guides/configuring-oidc/aws.md exists in the pulumi/docs repo, confirming the URL path /docs/esc/guides/configuring-oidc/aws/ is valid. Multiple other docs pages reference this same path, e.g., `content/docs/e…; source: gh search code --owner pulumi "configuring-oidc/aws" --repo pulumi/docs)
  • L193 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "- esc run command reference" → ✅ verified (evidence: The file content/docs/esc/cli/commands/esc_run.md exists in the repo with title "esc run | CLI commands", confirming the link target /docs/esc/cli/commands/esc_run/ is a valid, resolvable path.; source: repo:content/docs/esc/cli/commands/esc_run.md)
  • L195-197 in content/what-is/run-aws-ec2-start-instances-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)
  • L198 in content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md "- Related error resolution: InvalidClientTokenId, [ExpiredToken](/what-is/resolve-list-buckets-ex…" → ✅ verified (evidence: The file content/what-is/resolve-list-buckets-invalid-client-token-id.md exists in the repo and covers the InvalidClientTokenId error resolution using Pulumi ESC, confirming the linked URL `/what-is/resolve-list-buckets-invalid-client-…; 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.

  • [L158] content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md"ec2:StartInstances for the start action and ec2:DescribeInstances so the CLI can resolve and validate the IDs you pass." — verdict: contradicted; the pairing of StartInstances + DescribeInstances is conventional in AWS IAM examples, but the reason given here is wrong: the AWS CLI does not call DescribeInstances to "resolve and validate" instance IDs before start-instances — the IDs are passed straight through to the StartInstances API, and the only failure mode that surfaces is InvalidInstanceID.NotFound. A reader who copies this rationale will form an incorrect mental model of what the role actually needs the permission for. Suggested rewrite:

    - `ec2:StartInstances` for the start action and `ec2:DescribeInstances` so the CLI can resolve and validate the IDs you pass.
    + `ec2:StartInstances` for the start action. `ec2:DescribeInstances` isn't strictly required by `start-instances` itself, but it's conventionally paired so the role can read the instance state it's about to change — useful for the `aws ec2 wait instance-running` follow-up and for any troubleshooting.

    @alexleventer — if the goal is strict least-privilege, dropping DescribeInstances from the minimum is also a valid call. Either way the current "so the CLI can resolve and validate" reasoning should go.

  • [L183] content/what-is/run-aws-ec2-start-instances-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." — verdict: contradicted (self-contradiction with L65–67). The environmentVariables block in step 3 of this same document exposes AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN to the process esc run invokes — those are short-lived STS keys, but they are keys, and they are issued to the runner. The sentence as written suggests no credential material reaches the runner at all, which is stronger than what ESC + STS provides and undercuts the (otherwise correct) "no long-lived key" framing established earlier in the doc. Suggested rewrite:

    - 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.
    + Pulumi ESC removes the *long-lived* key entirely: the trust is OIDC-based and lives in IAM, so no static `aws_access_key_id`/`aws_secret_access_key` pair is ever issued to a developer or runner — only short-lived STS credentials, scoped to the role's session duration.

⚠️ Low-confidence

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

  • [L70] content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md"The fn::open::aws-login provider performs the AssumeRoleWithWebIdentity call against AWS STS at runtime." — verdict: unverifiable. The Pulumi ESC docs describe fn::open::aws-login as an OIDC-based dynamic-credentials provider (see content/docs/esc/integrations/dynamic-login-credentials/aws-login.md), and AWS's STS API for OIDC federation is AssumeRoleWithWebIdentity, so the claim is almost certainly accurate — but no Pulumi-side doc explicitly names the STS API the provider invokes. Reads as plausible; not a blocker. Optional follow-up: link to /docs/esc/integrations/dynamic-login-credentials/aws-login/ from this sentence so curious readers can jump to the canonical provider docs.

  • [L154] content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md"Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support this pattern." — verdict: unverifiable as written, and the framing slightly overstates Pulumi's official integration story. Pulumi has a first-party GitHub Action for ESC and the ESC docs include a GitLab CI example snippet, but there is no documented "Pulumi CircleCI integration" for ESC — the esc run pattern works on CircleCI in the same way it works on any CI runner with PULUMI_ACCESS_TOKEN set, but calling that an "integration" reads as stronger than reality. Suggested rewrite:

    - The runner needs no long-lived AWS credentials. Pulumi's GitHub Actions, GitLab CI, and CircleCI integrations all support this pattern.
    + The runner needs no long-lived AWS credentials. The `esc run` pattern works in any CI system that lets you set `PULUMI_ACCESS_TOKEN` as a secret — Pulumi ships a [first-party GitHub Action](/docs/esc/integrations/dev-tools/github/) for the tightest GitHub Actions wiring, and the [`esc run` guide](/docs/esc/guides/running-commands-with-esc/) shows GitLab CI and shell-script examples that port directly to CircleCI, Buildkite, or anything else.
  • [L183] content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md"ESC also gives you centralized environments, secret aggregation from other providers, and audit logs across the team." — verdict: unverifiable from a single authoritative source, but each clause individually matches documented ESC capabilities (centralized environments and imports — /docs/esc/environments/imports/; multi-provider secret aggregation — /docs/esc/integrations/; audit logs — Pulumi Cloud audit log feature). Reads as a fair marketing summary; not a blocker. Optional: add inline links to one or two of these capability pages to anchor the bullet.

Style findings

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

  • line 146: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 147: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).
  • line 148: [style] vague link text — Vague link text ('more'). Use descriptive text that conveys the destination (STYLE-GUIDE.md §Links).

📋 Triaged verifier findings

I double-checked these and realized they weren't real findings — click to expand
  • [L33] content/what-is/run-aws-ec2-start-instances-with-dynamic-credentials.md"The Pulumi CLI and the ESC CLI installed and authenticated (esc login)." — verdict: contradicted. Spurious: the verifier looked under content/docs/install/ and saw no esc page, but /docs/install/esc/ is a Hugo alias declared at content/docs/esc/cli/download-install/_index.md:18 and is the conventional install-link path used across the ESC docs (six other files in content/docs/esc/ link to it). The URL resolves correctly.

💡 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:49:18Z — Strong rewrite; 2 fact issues to fix (DescribeInstances rationale at L158; "no key ever issued" overstatement at L183), 1 verifier verdict triaged as spurious (L33 alias), 3 unverifiable claims read as plausible. (8a78522)

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