<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Devon Grove</title><link>https://www.pulumi.com/blog/author/devon-grove/</link><description>Pulumi blog posts: Devon Grove.</description><language>en-us</language><pubDate>Mon, 27 Jul 2026 00:00:00 +0000</pubDate><item><title>Enforce Access Token Expiry Policies in Pulumi Cloud</title><link>https://www.pulumi.com/blog/access-token-expiry-policy/</link><pubDate>Mon, 27 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/access-token-expiry-policy/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/access-token-expiry-policy/index.png" /&gt;
&lt;p&gt;Pulumi Cloud organizations can now enforce a maximum expiry on the access tokens used against them. Organization admins can set a cap in days, and from that point on, personal, organization, and team tokens operating on resources in the org must carry an expiration within the cap for requests to succeed. Tokens that never expire, or that have too much lifetime remaining, get rejected with an error that tells the user exactly how to regain access.&lt;/p&gt;
&lt;h2 id="why-cap-token-lifetimes"&gt;Why cap token lifetimes&lt;/h2&gt;
&lt;p&gt;Many organizations already have a credential rotation policy that says tokens must expire, but until now, Pulumi Cloud could only &lt;em&gt;recommend&lt;/em&gt; an expiry at creation time. Nothing stopped a member from creating a never-expiring personal token, and nothing aged out the long-lived tokens created before your policy existed.&lt;/p&gt;
&lt;p&gt;That gap matters because a leaked token is only as dangerous as its remaining lifetime. A token that never expires is a standing liability.&lt;/p&gt;
&lt;p&gt;By adding support for access token expiry policies, Pulumi Cloud now closes the gap at the platform level. Once you&amp;rsquo;ve set the cap, Pulumi Cloud enforces it immediately for your organization, including for tokens that already exist.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;/h2&gt;
&lt;p&gt;In your organization&amp;rsquo;s settings, navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; &amp;gt; &lt;strong&gt;Other&lt;/strong&gt; and scroll to &lt;strong&gt;Access token expiry policy&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/access-token-expiry-policy/expiry-policy-card.png" alt="The access token expiry policy card in Pulumi Cloud organization settings, with a 14-day maximum entered and buttons to preview affected tokens and save the policy."&gt;&lt;/p&gt;
&lt;p&gt;You can also get there from the &lt;strong&gt;Access Tokens&lt;/strong&gt; tab, where a banner shows whether a policy is in effect — select &lt;strong&gt;Edit policy&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/access-token-expiry-policy/expiry-policy-banner.png" alt="The banner on the Access Tokens tab stating that the organization caps access token expiry at 14 days, with an Edit policy link."&gt;&lt;/p&gt;
&lt;p&gt;The policy is a single number: the maximum expiry, in days, for tokens used against your organization. Compliance is checked on every request, and a token complies when both of these are true:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It has an expiration date. Never-expiring tokens violate any policy.&lt;/li&gt;
&lt;li&gt;Its &lt;em&gt;remaining lifetime&lt;/em&gt; — the time between now and its expiration — is within the cap.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because compliance is based on remaining lifetime rather than the expiry chosen at creation, the policy is pragmatic about existing credentials: a token created a year ago with a two-year expiry becomes compliant once it has less than the cap remaining. You&amp;rsquo;re enforcing exposure going forward, not retroactively punishing old tokens that are already near the end of their life.&lt;/p&gt;
&lt;p&gt;Enforcement is tailored to each token type:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Organization and team tokens&lt;/strong&gt; can&amp;rsquo;t be created out of compliance: the creation dialog caps the expiry picker at your policy maximum, and the API rejects requests that exceed it. Existing machine tokens that violate the policy stop authenticating and need to be recreated with a compliant expiry.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal tokens&lt;/strong&gt; span all of a user&amp;rsquo;s organizations, so they can&amp;rsquo;t be blocked at creation. Instead, a non-compliant personal token is rejected when it&amp;rsquo;s used against your organization, and the member sees an error explaining the policy and how to fix it. The personal token creation dialog also warns members when a chosen expiry doesn&amp;rsquo;t meet a policy in one of their organizations, steering them toward a compliant choice up front.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web console sessions are unaffected&lt;/strong&gt;, as are the short-lived tokens issued through &lt;a href="https://www.pulumi.com/docs/administration/access-identity/oidc-issuers/"&gt;OIDC token exchange&lt;/a&gt; — those are already bounded by their issuer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a policy is active, the creation dialog does the steering for you — the expiry picker tops out at the policy maximum:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/access-token-expiry-policy/new-token-dialog-capped.png" alt="The New Access Token dialog with the expiration picker set to &amp;ldquo;14 Days (org policy max)&amp;rdquo; and helper text noting the 14-day policy maximum."&gt;&lt;/p&gt;
&lt;h2 id="rolling-it-out-without-breaking-ci"&gt;Rolling it out without breaking CI&lt;/h2&gt;
&lt;p&gt;The riskiest moment for any new enforcement policy is the moment you turn it on. Two things make that safe here.&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;Preview affected tokens&lt;/strong&gt; shows you the blast radius before you save: the organization and team tokens that would stop authenticating under the proposed cap, by name and creator. Recreate those credentials with compliant expiries first, then save the policy.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/access-token-expiry-policy/preview-affected-tokens.png" alt="The preview listing one machine token that would fail to authenticate under a 14-day policy, with a note that non-compliant personal tokens are rejected at request time."&gt;&lt;/p&gt;
&lt;p&gt;Second, rejections are designed to be self-explanatory. A blocked request fails with a &lt;code&gt;403 Forbidden&lt;/code&gt; that names your organization and its policy maximum, so a member whose personal token no longer complies knows immediately what happened and what to do: generate a new token that meets the policy. Policy changes are also recorded in your organization&amp;rsquo;s &lt;a href="https://www.pulumi.com/docs/administration/security-compliance/audit-logs/"&gt;audit logs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/access-token-expiry-policy/policy-rejection-cli.png" alt="A pulumi up run rejected with a 403 error stating that the acme-corp organization enforces a max access token expiry of 14 days that the current token does not meet."&gt;&lt;/p&gt;
&lt;p&gt;A reasonable rollout looks like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Decide on a cap that matches your rotation policy. 90 days is a common choice for CI credentials.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Preview affected tokens&lt;/strong&gt; and recreate any non-compliant machine tokens.&lt;/li&gt;
&lt;li&gt;Socialize the change in your organization: personal tokens without a compliant expiry will stop working against the organization.&lt;/li&gt;
&lt;li&gt;Save the policy. From here on, the platform enforces it for you.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;
&lt;p&gt;The access token expiry policy is available now in your organization&amp;rsquo;s access settings. For the full reference — compliance rules, per-token-type behavior, and exemptions — see the &lt;a href="https://www.pulumi.com/docs/administration/access-identity/access-tokens/#access-token-expiry-policy"&gt;access tokens documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have feedback, we&amp;rsquo;d love to hear it in the &lt;a href="https://slack.pulumi.com/"&gt;Pulumi Community Slack&lt;/a&gt; or on &lt;a href="https://github.com/pulumi/pulumi/issues"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Devon Grove</author><category>features</category><category>security</category></item><item><title>Sign in to Pulumi Cloud with Passkeys</title><link>https://www.pulumi.com/blog/passkey-support-in-pulumi-cloud/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/passkey-support-in-pulumi-cloud/</guid><description>
&lt;img src="https://www.pulumi.com/blog/passkey-support-in-pulumi-cloud/meta.png" /&gt;
&lt;p&gt;Pulumi Cloud now supports passkeys for users who sign in with email and password. Select a button, approve with Touch ID, Face ID, Windows Hello, or your hardware key, and you&amp;rsquo;re signed in.&lt;/p&gt;
&lt;p&gt;A passkey is a public-key credential stored on your device: your phone, your laptop, a hardware key (YubiKey, Google Titan, etc.), or your password manager can all function as the authenticator. When you sign in, your device authenticates you locally and signs a challenge from Pulumi Cloud with the private key.&lt;/p&gt;
&lt;p&gt;The private key stays on your device — Pulumi Cloud never sees or stores it. Passkeys are built on the &lt;a href="https://www.w3.org/TR/webauthn-3/"&gt;WebAuthn&lt;/a&gt; standard, so they&amp;rsquo;re already supported on every major browser and operating system.&lt;/p&gt;
&lt;h2 id="who-this-is-for"&gt;Who this is for&lt;/h2&gt;
&lt;p&gt;This release applies to users who sign in to Pulumi Cloud with an email address and password. If you sign in through an identity provider (IdP), such as GitHub OAuth, GitLab, Bitbucket, Google, or your organization&amp;rsquo;s SAML SSO, your existing flow is unchanged.&lt;/p&gt;
&lt;h2 id="why-passkeys"&gt;Why passkeys&lt;/h2&gt;
&lt;p&gt;Passwords have always been the weakest link in account security. Since they are shared secrets, they are vulnerable to phishing attacks, and every place you type one is a place that can be impersonated or a data store that can be leaked. Passkeys swap that out for a per-site key pair that lives on your device:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phishing-resistant by design.&lt;/strong&gt; A passkey is bound to the exact origin it was registered for. A look-alike domain can&amp;rsquo;t trigger your authenticator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Synced across your devices.&lt;/strong&gt; Apple iCloud Keychain, Google Password Manager, 1Password, Dashlane, Bitwarden: most credential managers now sync passkeys end-to-end-encrypted to every device you&amp;rsquo;ve signed in on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discoverable.&lt;/strong&gt; Pulumi Cloud doesn&amp;rsquo;t need to know which user you are before you authenticate. Just select &amp;ldquo;Sign in with a passkey&amp;rdquo; and your device offers the right credential.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nothing to remember.&lt;/strong&gt; A passkey lives on your device. There&amp;rsquo;s no string to memorize, and no sensitive credential stored by us.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="setting-up-a-passkey"&gt;Setting up a passkey&lt;/h2&gt;
&lt;p&gt;The next time you sign in with a password, Pulumi Cloud will ask if you&amp;rsquo;d like to configure a passkey. It&amp;rsquo;s a single-step prompt, so you can enroll once and take advantage of passkeys on every subsequent sign-in.&lt;/p&gt;
&lt;p&gt;If you dismiss the prompt and would like to add one later, or want to add multiple passkeys, navigate to &lt;strong&gt;Account Settings → Passkeys&lt;/strong&gt; under your user profile. Select &lt;strong&gt;Register a passkey&lt;/strong&gt;, complete the OS-level prompt (Touch ID, Face ID, Windows Hello, or your hardware key), and you&amp;rsquo;re done. Pulumi Cloud will pick a sensible default name like &lt;code&gt;&amp;quot;iCloud Keychain&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;Chrome on macOS&amp;quot;&lt;/code&gt; based on the authenticator, but you can rename it inline anytime under &lt;strong&gt;Account Settings → Passkeys&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/passkey-support-in-pulumi-cloud/account-settings-passkeys.png" alt="Pulumi Cloud Account Settings page showing the Passkeys section, with a &amp;ldquo;Register a passkey&amp;rdquo; button and an enrolled passkey named &amp;ldquo;Pulumipus&amp;rsquo;s iPhone&amp;rdquo;."&gt;&lt;/p&gt;
&lt;p&gt;You can register as many passkeys as you want. Typical setups are one per personal device, or one synced credential plus a hardware key as backup. Removing a passkey takes effect immediately; deleted credentials cannot be used to sign in.&lt;/p&gt;
&lt;h2 id="signing-in"&gt;Signing in&lt;/h2&gt;
&lt;p&gt;Depending on how you arrive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explicit sign-in.&lt;/strong&gt; On the sign-in page, select &lt;strong&gt;Sign in with a passkey&lt;/strong&gt;. Your browser opens the passkey picker, and you authenticate from there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autofill.&lt;/strong&gt; If your browser supports &lt;a href="https://web.dev/articles/passkey-form-autofill"&gt;conditional mediation&lt;/a&gt; (Chrome, Safari, Edge, recent Firefox), the email field on the sign-in page proactively offers your registered passkeys as autofill suggestions. Pick one and you&amp;rsquo;re signed in.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-about-my-existing-password-and-mfa"&gt;What about my existing password and MFA?&lt;/h2&gt;
&lt;p&gt;Your existing password still works. Passkeys are an additional sign-in option, not a replacement, and they don&amp;rsquo;t disable password sign-in on your account. If you lose access to every registered passkey, you can still sign in with your email and password as you always have, then register a new passkey from settings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Other 2FA still applies.&lt;/strong&gt; If you have TOTP-based MFA enabled on your Pulumi account, a passkey sign-in will still prompt for your second factor. WebAuthn doesn&amp;rsquo;t reliably tell us &lt;em&gt;how&lt;/em&gt; you unlocked the passkey on your device (biometric, PIN, or something weaker), so we can&amp;rsquo;t safely treat the passkey itself as proof of two factors. Your existing MFA configuration remains the boundary it always was.&lt;/p&gt;
&lt;h2 id="try-it-out"&gt;Try it out&lt;/h2&gt;
&lt;p&gt;Passkey support is generally available today for every Pulumi Cloud user who signs in with email and password, at no additional cost and with no configuration. Visit &lt;a href="https://app.pulumi.com/account/profile"&gt;your account settings&lt;/a&gt; to register your first passkey, and let us know what you think on &lt;a href="https://slack.pulumi.com/"&gt;our community Slack&lt;/a&gt; or &lt;a href="https://github.com/pulumi/pulumi/issues"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description><author>Devon Grove</author><category>features</category><category>security</category><category>product-launches</category></item><item><title>Pulumi Cloud REST API Docs, Now Generated from OpenAPI</title><link>https://www.pulumi.com/blog/rest-api-docs-from-openapi/</link><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/rest-api-docs-from-openapi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/rest-api-docs-from-openapi/index.png" /&gt;
&lt;p&gt;The &lt;a href="https://www.pulumi.com/docs/reference/cloud-rest-api/"&gt;Pulumi Cloud REST API reference&lt;/a&gt; is now generated directly from the live &lt;a href="https://api.pulumi.com/api/openapi/pulumi-spec.json"&gt;OpenAPI spec&lt;/a&gt; at build time. Every endpoint, parameter, request body, and response schema you see on the page comes from the same spec the API itself publishes. The docs now stay in sync with the API automatically!&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;Why this matters&lt;/h2&gt;
&lt;p&gt;The previous REST API reference was a set of handwritten pages. That meant every new endpoint, renamed parameter, or revised response shape needed a matching docs PR, and in practice the pages drifted. Small inconsistencies added up: missing parameters, outdated request shapes, schemas that no longer matched what the API returned. We wanted a durable fix that keeps the docs in sync as the API grows.&lt;/p&gt;
&lt;p&gt;Generating the reference from the OpenAPI spec closes that gap. When the API ships a change, the docs pick it up automatically the next time our docs are built.&lt;/p&gt;
&lt;h2 id="whats-new"&gt;What&amp;rsquo;s new&lt;/h2&gt;
&lt;p&gt;The reference at &lt;code&gt;/docs/reference/cloud-rest-api/&lt;/code&gt; now includes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find what you need faster
&lt;ul&gt;
&lt;li&gt;Endpoints are grouped by product area — Stacks, Deployments, Environments, Organizations, Registry, Insights, AI, Workflows, and more — so you can jump straight to the part of the API you&amp;rsquo;re working with.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Complete request and response details
&lt;ul&gt;
&lt;li&gt;Every endpoint documents its parameters, request body, and the exact shape of what it returns, so you know what to send and what to expect back without guessing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;One-click navigation between related types
&lt;ul&gt;
&lt;li&gt;When a response references another object, the type name is a link. Click through to drill into its full definition if desired instead of scrolling a lengthy API reference page.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="what-this-unlocks-for-agents"&gt;What this unlocks for agents&lt;/h2&gt;
&lt;p&gt;Keeping the reference in sync with the spec isn&amp;rsquo;t just a human convenience. It changes what&amp;rsquo;s reliable for AI agents that read the docs and call the API on your behalf. An agent reading a handwritten reference might see a parameter that was renamed six months ago, or miss a field the API now returns, and the call fails silently or in ways that are hard to debug. When the reference is generated from the spec, the agent is working from what the API actually accepts today.&lt;/p&gt;
&lt;p&gt;Say you&amp;rsquo;re onboarding a new team and need to stand up their access in Pulumi Cloud. Point an agent at the REST API reference and ask it to create an &lt;code&gt;sre-oncall&lt;/code&gt; team, add four members, and grant admin on three stacks. The agent walks the teams, memberships, and stack-permissions endpoints, builds the right sequence of calls, and executes.&lt;/p&gt;
&lt;p&gt;The same pattern holds for bulk audits and cleanup. Ask an agent to find every stack in your org with no recent updates and tag them &lt;code&gt;stale&lt;/code&gt;, and it can paginate correctly because the response schema matches reality. While workflows like these were technically possible before, they&amp;rsquo;re much more reliable now.&lt;/p&gt;
&lt;h2 id="same-url-existing-links-keep-working"&gt;Same URL, existing links keep working&lt;/h2&gt;
&lt;p&gt;The generated docs live at the same URL as the previous reference: &lt;code&gt;/docs/reference/cloud-rest-api/&lt;/code&gt;. Bookmarks, blog links, and inbound search traffic still land on the right page. Redirects are in place for any API reference docs page that has been tweaked, renamed, or moved.&lt;/p&gt;
&lt;h2 id="try-it-out"&gt;Try it out&lt;/h2&gt;
&lt;p&gt;Start at the new &lt;a href="https://www.pulumi.com/docs/reference/cloud-rest-api/"&gt;REST API reference&lt;/a&gt; and browse by category. Each page links through to the request and response object schemas it uses.&lt;/p&gt;
&lt;p&gt;If you spot anything that looks wrong, the most likely culprit is the OpenAPI spec itself — file an issue in &lt;a href="https://github.com/pulumi/docs"&gt;pulumi/docs&lt;/a&gt; and we&amp;rsquo;ll trace it back to the source. For tag intros and structural improvements, PRs to &lt;a href="https://github.com/pulumi/docs"&gt;pulumi/docs&lt;/a&gt; are welcome. Questions and feedback are always welcome in the &lt;a href="https://slack.pulumi.com"&gt;Pulumi Community Slack&lt;/a&gt;.&lt;/p&gt;
&lt;a
href="https://www.pulumi.com/docs/reference/cloud-rest-api/"
class="btn btn-primary"
&gt;
Explore the REST API
&lt;/a&gt;</description><author>Devon Grove</author><category>pulumi-cloud</category><category>features</category><category>api</category></item><item><title>Pulumi IAM Expands: Manage Access at Scale with Tags, Roles, and Teams</title><link>https://www.pulumi.com/blog/expanding-pulumi-iam-custom-permissions/</link><pubDate>Thu, 19 Mar 2026 10:30:00 -0700</pubDate><guid>https://www.pulumi.com/blog/expanding-pulumi-iam-custom-permissions/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/expanding-pulumi-iam-custom-permissions/index.png" /&gt;
&lt;p&gt;Since the launch of &lt;a href="https://www.pulumi.com/blog/pulumi-cloud-iam-launch/"&gt;Pulumi IAM&lt;/a&gt; with &lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/roles/"&gt;custom roles&lt;/a&gt; and scoped &lt;a href="https://www.pulumi.com/docs/administration/access-identity/access-tokens/"&gt;access tokens&lt;/a&gt;, organizations have been using fine-grained permissions to secure their automation and CI/CD pipelines. As teams scale to hundreds or thousands of stacks, environments, and accounts, the next challenge is applying those permissions efficiently.&lt;/p&gt;
&lt;p&gt;Today, we&amp;rsquo;re introducing three new capabilities to help you manage permissions more dynamically at scale: &lt;strong&gt;tag-based access control&lt;/strong&gt;, &lt;strong&gt;team role assignments&lt;/strong&gt;, and &lt;strong&gt;user role assignments&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="why-tag-based-access-control"&gt;Why tag-based access control?&lt;/h2&gt;
&lt;p&gt;With custom roles, you can define granular permissions using &lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/scopes"&gt;fine-grained scopes&lt;/a&gt;. However, applying those roles still requires selecting individual stacks, environments, or accounts one by one. For organizations managing a large number of Pulumi entities, this means either granting overly broad access or spending significant time on manual configuration. Tag-based access control solves this problem.&lt;/p&gt;
&lt;h2 id="whats-new"&gt;What&amp;rsquo;s new?&lt;/h2&gt;
&lt;h3 id="tag-based-access-control"&gt;Tag-based access control&lt;/h3&gt;
&lt;p&gt;You can now create rules within a custom role that dynamically grant permissions based on entity tags. This works across IaC stacks, ESC environments, and Insights accounts. For example, when a new stack is created and tagged &lt;code&gt;env:prod&lt;/code&gt;, anyone with a role containing a matching tag-based rule automatically gets the right permissions. No manual assignment required.&lt;/p&gt;
&lt;p&gt;A single role can include multiple tag-based rules, and they are evaluated with &lt;strong&gt;OR&lt;/strong&gt; logic. If an entity matches any of the rules, the permissions are granted. Within a single rule, you can combine multiple key-value conditions with implicit &lt;strong&gt;AND&lt;/strong&gt; logic for precise targeting. For example, a rule with conditions &lt;code&gt;env:prod&lt;/code&gt; and &lt;code&gt;team:payments&lt;/code&gt; ensures access is granted only to production resources owned by the payments team.&lt;/p&gt;
&lt;h3 id="team-role-assignments"&gt;Team role assignments&lt;/h3&gt;
&lt;p&gt;Custom roles can now be assigned directly to &lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/teams"&gt;teams&lt;/a&gt; within your Pulumi organization. When an engineer joins a team, whether manually or via &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/scim/"&gt;SCIM provisioning&lt;/a&gt;, they automatically inherit the permissions defined in the team&amp;rsquo;s assigned roles.&lt;/p&gt;
&lt;p&gt;Teams support both &lt;strong&gt;inline permissions&lt;/strong&gt; (ad-hoc access to specific stacks, environments, or accounts) and &lt;strong&gt;role-based permissions&lt;/strong&gt; simultaneously. You can assign &lt;strong&gt;multiple roles&lt;/strong&gt; to a single team, giving you full flexibility to compose access from reusable building blocks while retaining the ability to grant one-off access where needed. If you have existing workflows built around ad-hoc assignments to teams, those continue to work exactly as before. You can adopt roles incrementally or mix both approaches on the same team.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Team admins (or users with the &lt;code&gt;team:update&lt;/code&gt; scope) can continue to manage their team&amp;rsquo;s inline permissions as they do today. However, assigning organization-level custom roles to a team requires additional permissions: &lt;code&gt;role:read&lt;/code&gt; and &lt;code&gt;role:update&lt;/code&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="user-role-assignments"&gt;User role assignments&lt;/h3&gt;
&lt;p&gt;Custom roles can also be assigned directly to individual organization members. This is useful for users whose responsibilities span multiple teams or require permissions beyond the existing org-level &lt;code&gt;Admin&lt;/code&gt;, &lt;code&gt;Member&lt;/code&gt;, and &lt;code&gt;Billing Manager&lt;/code&gt; &lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/roles"&gt;roles&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="how-permissions-work-together"&gt;How permissions work together&lt;/h3&gt;
&lt;p&gt;Permissions in Pulumi IAM are &lt;strong&gt;additive&lt;/strong&gt;. A user receives the union of all permissions granted to them, including permissions from roles assigned directly to them as a user and permissions from roles assigned to any team they belong to. A user on both the &amp;ldquo;SRE&amp;rdquo; and &amp;ldquo;Security&amp;rdquo; teams inherits permissions from both team roles, plus any role assigned to them individually.&lt;/p&gt;
&lt;h2 id="how-to-get-started"&gt;How to get started&lt;/h2&gt;
&lt;p&gt;Configuring tag-based access control and role assignments is done through the Pulumi Cloud console and REST API.&lt;/p&gt;
&lt;h3 id="1-create-a-custom-role-with-tag-based-rules"&gt;1. Create a custom role with tag-based rules&lt;/h3&gt;
&lt;p&gt;In Pulumi Cloud, navigate to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; &amp;gt; &lt;strong&gt;Roles&lt;/strong&gt; and create a new custom role. In the role configuration, add tag-based rules that define which entities the role should apply to.&lt;/p&gt;
&lt;p&gt;For example, to create a role that grants write access to all production stacks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create custom role&lt;/strong&gt; and give it a descriptive name (e.g., &amp;ldquo;Production Deployer&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Add a permission set (e.g., Stack Write) to the role&lt;/li&gt;
&lt;li&gt;Under entity selection, choose &lt;strong&gt;Tag-based rule&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Set the condition: tag key &lt;code&gt;env&lt;/code&gt; equals &lt;code&gt;prod&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the role&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="2-assign-the-role-to-a-team"&gt;2. Assign the role to a team&lt;/h3&gt;
&lt;p&gt;Go to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; &amp;gt; &lt;strong&gt;Teams&lt;/strong&gt;, select a team, and assign your custom role. All team members immediately inherit the defined permissions.&lt;/p&gt;
&lt;h3 id="3-assign-a-role-to-an-individual-user"&gt;3. Assign a role to an individual user&lt;/h3&gt;
&lt;p&gt;For users with unique access requirements, go to &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; &amp;gt; &lt;strong&gt;Members&lt;/strong&gt;, select a user, and assign a custom role directly.&lt;/p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Custom roles with tag-based access control"
controls
autoplay muted playsinline
loop &gt;
&lt;source src="abac-demo.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;h2 id="enforce-tagging-standards-with-pulumi-policy"&gt;Enforce tagging standards with Pulumi Policy&lt;/h2&gt;
&lt;p&gt;Tag-based access control relies on consistent tagging. If a stack is missing a tag or has an incorrect value, permissions won&amp;rsquo;t be applied as expected. &lt;a href="https://www.pulumi.com/docs/insights/policy/"&gt;Pulumi Policy&lt;/a&gt; closes this gap by letting you enforce tagging standards as a &lt;a href="https://www.pulumi.com/docs/insights/policy/policy-groups/"&gt;preventative policy group&lt;/a&gt;, so any &lt;code&gt;pulumi up&lt;/code&gt; on a stack with missing or invalid tags is blocked before deployment. This ensures your tag-based RBAC rules always grant the correct permissions. Policy enforces the standard, RBAC enforces the access.&lt;/p&gt;
&lt;p&gt;To learn how to write policies that validate stack tags, see &lt;a href="https://www.pulumi.com/docs/insights/policy/policy-packs/authoring/#using-stack-tags-in-policies"&gt;Using stack tags in policies&lt;/a&gt;.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Pulumi Policy currently supports tag enforcement for IaC stacks. For ESC environments and Insights accounts, tags are managed through the Pulumi Cloud console or REST API.&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="availability"&gt;Availability&lt;/h2&gt;
&lt;p&gt;Tag-based access control, team role assignments, and user role assignments are available today for customers on the &lt;strong&gt;Pulumi Enterprise&lt;/strong&gt; and &lt;strong&gt;Pulumi Business Critical&lt;/strong&gt; plans. Check out our &lt;a href="https://www.pulumi.com/pricing/"&gt;pricing page&lt;/a&gt; for more details on editions and what&amp;rsquo;s included.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With custom roles providing fine-grained permissions, tag-based rules enabling dynamic access policies, and the ability to assign roles directly to teams and users, Pulumi IAM now provides everything you need to implement automated, least-privilege access control at scale. We&amp;rsquo;re excited to see how you leverage these new capabilities to secure and streamline your cloud operations.&lt;/p&gt;
&lt;p&gt;Explore the &lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac"&gt;IAM documentation&lt;/a&gt; to get started, and share your feedback in our &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="learn-more"&gt;Learn more&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac"&gt;RBAC overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/roles"&gt;Roles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/permission-sets"&gt;Permission sets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/teams"&gt;Teams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/administration/access-identity/rbac/scopes"&gt;Scopes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-cloud-iam-launch/"&gt;Pulumi IAM launch blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-cloud-iam-self-hosted/"&gt;Pulumi IAM for self-hosted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Devon Grove</author><author>Davide Massarenti</author><author>Casey Huang</author><author>Arun Loganathan</author><category>iam</category><category>rbac</category><category>security</category><category>features</category><category>pulumi-cloud</category></item><item><title>Announcing OpenAPI support for the Pulumi Cloud REST API</title><link>https://www.pulumi.com/blog/announcing-openapi-support-pulumi-cloud/</link><pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/announcing-openapi-support-pulumi-cloud/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/announcing-openapi-support-pulumi-cloud/index.png" /&gt;
&lt;p&gt;We&amp;rsquo;re thrilled to announce that the Pulumi Cloud REST API is now described by an OpenAPI 3.0 specification, and we&amp;rsquo;re just getting started.&lt;/p&gt;
&lt;p&gt;This is a feature that has been a long time coming. We have heard your requests for OpenAPI support &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues/100"&gt;loud and clear&lt;/a&gt;, and we&amp;rsquo;re excited to share that not only do we have a published specification for consumption, but our API code is now built from this specification as well. Moving forward, this single source of truth unlocks better tooling, tighter integration, and a more predictable API experience for everyone.&lt;/p&gt;
&lt;p&gt;You can fetch the spec directly from the API at runtime or use it for client generation, validation, and documentation, all from one machine-readable contract.&lt;/p&gt;
&lt;h2 id="a-single-contract-for-the-pulumi-cloud-rest-api"&gt;A single contract for the Pulumi Cloud REST API&lt;/h2&gt;
&lt;p&gt;The Pulumi Cloud API powers the Pulumi CLI, the Pulumi Console, and third-party integrations. Until now, there was no single, published machine-readable description of that API. We&amp;rsquo;ve changed that. The API is now defined and served as a standard OpenAPI 3.0.3 document.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Runtime discovery&lt;/strong&gt;: You can retrieve the spec from the API itself, so your tooling always sees the same surface the service implements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client generation&lt;/strong&gt;: Use your favorite OpenAPI tooling (e.g. OpenAPI Generator, Swagger Codegen) to generate API clients in the language of your choice.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validation and testing&lt;/strong&gt;: Validate requests and responses, or build mocks and tests, from the same spec the service uses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: The spec is the source of truth, not a separate, hand-maintained API doc that can drift from reality. Load the spec into Swagger UI, Redoc, or another viewer to browse the Pulumi Cloud API interactively.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-get-the-spec"&gt;How to get the spec&lt;/h2&gt;
&lt;p&gt;Send a GET request to:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;https://api.pulumi.com/api/openapi/pulumi-spec.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;No authentication is required. The response is the OpenAPI 3.0 document for the Pulumi Cloud API, describing the supported, documented API surface.&lt;/p&gt;
&lt;h2 id="source-of-truth-and-stability"&gt;Source of truth and stability&lt;/h2&gt;
&lt;p&gt;We do not hand-write the OpenAPI spec. We generate it from the same API definition that drives our backend and console code. When we add or change API routes or models, we regenerate the spec so the published document stays in sync with what the service actually implements. That gives you a clear, stable contract for the Pulumi Cloud API.&lt;/p&gt;
&lt;h2 id="what-we-are-building-next"&gt;What we are building next&lt;/h2&gt;
&lt;p&gt;We are using this spec as the foundation for our own tooling, and have plans to continue leveraging the spec in our toolchain long-term.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLI&lt;/strong&gt;: We plan to drive the Pulumi CLI’s API client from the OpenAPI spec so that CLI and API stay in lockstep.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulumi Service Provider&lt;/strong&gt;: We are also building towards day 1 updates to the &lt;a href="https://www.pulumi.com/registry/packages/pulumiservice/"&gt;Pulumi Service Provider&lt;/a&gt; so that new and changed API resources are generated from the spec and ship in sync with the service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docs Enhancements&lt;/strong&gt;: Although you can load the spec using Swagger UI for your own browsing, we are intent on shipping enhancements to our &lt;a href="https://www.pulumi.com/docs/reference/cloud-rest-api/"&gt;public REST API docs&lt;/a&gt; that will keep them up-to-date according to the OpenAPI spec.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As we ship those updates, you will get a single source of truth from API to CLI to provider.&lt;/p&gt;
&lt;p&gt;If you have questions or feedback about the OpenAPI spec or the Pulumi Cloud API, reach out in our &lt;a href="https://slack.pulumi.com/"&gt;Community Slack&lt;/a&gt; or open an issue in the &lt;a href="https://github.com/pulumi/pulumi"&gt;Pulumi repository&lt;/a&gt;. We&amp;rsquo;re excited to see what you build with it.&lt;/p&gt;</description><author>Davide Massarenti</author><author>Claire Gaestel</author><author>Devon Grove</author><author>Arun Loganathan</author><author>Zac Cook</author><category>features</category><category>pulumi-cloud</category><category>api</category></item><item><title>Pulumi IAM Now Available for Self-Hosted Pulumi Cloud</title><link>https://www.pulumi.com/blog/pulumi-cloud-iam-self-hosted/</link><pubDate>Wed, 14 Jan 2026 11:18:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-cloud-iam-self-hosted/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-cloud-iam-self-hosted/index.png" /&gt;
&lt;p&gt;We&amp;rsquo;re excited to announce that &lt;strong&gt;Pulumi Identity and Access Management (IAM)&lt;/strong&gt; is now available for self-hosted instances of Pulumi Cloud. This foundational security capability brings the same &lt;a href="https://www.pulumi.com/blog/pulumi-cloud-iam-launch/"&gt;enterprise-grade access management&lt;/a&gt; we launched for Pulumi Cloud SaaS to organizations running Pulumi on their own infrastructure.&lt;/p&gt;
&lt;h2 id="enterprise-security-for-self-hosted-deployments"&gt;Enterprise Security for Self-Hosted Deployments&lt;/h2&gt;
&lt;p&gt;Self-hosted Pulumi Cloud customers can now leverage the full power of &lt;strong&gt;Custom Roles&lt;/strong&gt; and &lt;strong&gt;Granular Access Tokens&lt;/strong&gt; to implement Zero Trust security principles and least privilege access controls within their own environments. This means you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Define Custom Permissions&lt;/strong&gt; with fine-grained scopes (e.g., &lt;code&gt;stack:delete&lt;/code&gt;, &lt;code&gt;environment:read&lt;/code&gt;) tailored to your organization&amp;rsquo;s security requirements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create Custom Roles&lt;/strong&gt; by combining these permissions with specific Pulumi entities (Stacks, Environments, etc.).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate Scoped Organization Access Tokens&lt;/strong&gt; that are precisely limited to the permissions defined in their associated roles, dramatically reducing the blast radius if credentials are compromised.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="secure-automation-for-on-premises-infrastructure"&gt;Secure Automation for On-Premises Infrastructure&lt;/h2&gt;
&lt;p&gt;This release is powerful for self-hosted Pulumi Cloud deployments where security and compliance requirements are often even more stringent. You can now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Implement Least Privilege CI/CD:&lt;/strong&gt; Scope pipeline tokens to only the actions and resources they absolutely need, ensuring your automation follows the same security standards as your infrastructure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhance Compliance Posture:&lt;/strong&gt; Demonstrate precise, auditable control over programmatic access to auditors and security teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduce Operational Risk:&lt;/strong&gt; Limit the potential impact of compromised tokens by restricting them to specific roles and permissions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="getting-started"&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Self-hosted customers can access IAM features through the same intuitive interface available in Pulumi Cloud SaaS. Navigate to &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Roles&lt;/strong&gt; to begin creating Custom Permissions and Custom Roles, then generate scoped Organization Access Tokens from &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Access Management&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Access Tokens&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For detailed information about Pulumi IAM capabilities, including step-by-step guides and best practices, see our &lt;a href="https://www.pulumi.com/blog/pulumi-cloud-iam-launch/"&gt;comprehensive announcement blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="learn-more"&gt;Learn More&lt;/h2&gt;
&lt;p&gt;Explore the IAM &amp;amp; RBAC documentation to get started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/roles"&gt;Roles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/permissions"&gt;Permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/scopes"&gt;Scopes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;rsquo;re committed to bringing enterprise-grade security features to all Pulumi deployments, whether in the cloud or on-premises. If you have questions or feedback, please reach out through your account representative or our &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;</description><author>Davide Massarenti</author><author>Devon Grove</author><author>Casey Huang</author><author>Arun Loganathan</author><category>iam</category><category>rbac</category><category>security</category><category>features</category><category>pulumi-cloud</category><category>access-tokens</category><category>self-hosted</category></item><item><title>Announcing Pulumi Identity and Access Management (IAM)</title><link>https://www.pulumi.com/blog/pulumi-cloud-iam-launch/</link><pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-cloud-iam-launch/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-cloud-iam-launch/index.png" /&gt;
&lt;p&gt;Cloud development is accelerating at an unprecedented pace, fueled by AI and the relentless drive for innovation. But this incredible speed demands unwavering trust in your security posture. How do you empower teams to deploy rapidly and frequently without opening doors to risk or violating compliance mandates? Today, we&amp;rsquo;re thrilled to answer that critical challenge by introducing &lt;strong&gt;Pulumi Identity and Access Management&lt;/strong&gt; (IAM) – a foundational new capability designed to embed robust, granular security directly into your cloud development lifecycle, enabling you to innovate both quickly and safely with Pulumi. Pulumi IAM provides the unified framework for fine-grained authorization needed to confidently manage modern cloud infrastructure and applications across the entire Pulumi Cloud platform.&lt;/p&gt;
&lt;h2 id="our-vision-for-pulumi-iam"&gt;Our Vision for Pulumi IAM&lt;/h2&gt;
&lt;p&gt;Pulumi IAM is a foundational investment, delivering enterprise-grade access management through a phased approach. Today&amp;rsquo;s release marks the beginning, with much more planned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phase 1: Granular Access Tokens &amp;amp; Custom Roles (Available Today)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define custom, reusable &lt;strong&gt;Permissions&lt;/strong&gt; with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/scopes"&gt;fine-grained scopes&lt;/a&gt; (e.g., &lt;code&gt;stack:delete&lt;/code&gt; only).&lt;/li&gt;
&lt;li&gt;Create &lt;strong&gt;Custom Roles&lt;/strong&gt; by combining Permissions with specific Pulumi Entities (Stacks, Environments, etc.).&lt;/li&gt;
&lt;li&gt;Generate &lt;strong&gt;Organization Access Tokens&lt;/strong&gt; scoped precisely to these Custom Roles, perfect for secure automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phase 2: User &amp;amp; Team Role Assignment (Coming Soon)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Leverage &lt;strong&gt;OIDC configuration&lt;/strong&gt; to dynamically assume Custom Roles for secure, tokenless authentication from CI/CD systems like GitHub Actions, GitLab, and more.&lt;/li&gt;
&lt;li&gt;Assign these powerful Custom Roles directly to &lt;strong&gt;individual users and teams&lt;/strong&gt; within your Pulumi organization.&lt;/li&gt;
&lt;li&gt;Implement a complete overhaul of user and team access management, moving beyond the basic &lt;code&gt;Admin&lt;/code&gt;/&lt;code&gt;Member&lt;/code&gt; distinctions, and enabling reusability of custom building blocks permissions and roles that work for your organization&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Phase 3: Advanced Authorization &amp;amp; Scalability (Future Release)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce &lt;strong&gt;Attribute-Based Access Control (ABAC)&lt;/strong&gt;, allowing policies based on tags or other attributes of Pulumi Entities (e.g., &amp;ldquo;grant &amp;lsquo;dev-role&amp;rsquo; access to all stacks tagged &amp;rsquo;env:dev&amp;rsquo;&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;Enable the creation of &lt;strong&gt;Custom RBAC Policies&lt;/strong&gt; with conditional logic for highly specific access scenarios and reuse them&lt;/li&gt;
&lt;li&gt;Provide mechanisms to manage permissions across hundreds or thousands of Pulumi Entities efficiently.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="a-foundation-for-zero-trust--unified-security"&gt;A Foundation for Zero Trust &amp;amp; Unified Security&lt;/h2&gt;
&lt;p&gt;Pulumi IAM isn&amp;rsquo;t just another feature; it&amp;rsquo;s a foundational pillar underpinning security across the entire Pulumi Cloud ecosystem, enabling organizations to implement &lt;strong&gt;Zero Trust&lt;/strong&gt; principles for their infrastructure management. Modern security models assume breaches will happen and demand rigorous verification for every access request. Static, organization-wide roles no longer suffice where separation of duties, least privilege, and compliance are paramount.&lt;/p&gt;
&lt;p&gt;Pulumi IAM addresses these challenges by providing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Least Privilege Enforcement:&lt;/strong&gt; Define precisely &lt;em&gt;who&lt;/em&gt; can do &lt;em&gt;what&lt;/em&gt; on &lt;em&gt;which&lt;/em&gt; specific resources, minimizing the potential impact if credentials or accounts are compromised. This is core to Zero Trust – grant only the minimum necessary access, verified at the point of action.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Granular Control Across Pulumi:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure as Code (IaC):&lt;/strong&gt; Apply fine-grained controls over Pulumi Stacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrets Management:&lt;/strong&gt; Define specific access levels for Pulumi ESC Environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insights:&lt;/strong&gt; Manage permissions for Pulumi Insights account settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure Automation:&lt;/strong&gt; Provide secure, least-privilege tokens and OIDC integration for CI/CD pipelines and automation, drastically reducing the risk associated with over-privileged service accounts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unified, Scalable Governance:&lt;/strong&gt; Establish a consistent authorization model that simplifies administration and scales from small teams to complex enterprise environments, ensuring security doesn&amp;rsquo;t hinder velocity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="launching-today-granular-access-tokens-via-custom-roles"&gt;Launching Today: Granular Access Tokens via Custom Roles&lt;/h2&gt;
&lt;p&gt;This vision begins today with the initial phase of Pulumi IAM, enabling you to define &lt;strong&gt;Custom Roles&lt;/strong&gt; built from &lt;strong&gt;fine-grained Permissions&lt;/strong&gt; and apply them specifically to &lt;strong&gt;Organization Access Tokens&lt;/strong&gt;. This initial step provides immediate, significant security benefits, particularly for automation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;True Least Privilege for CI/CD:&lt;/strong&gt; Scope pipeline tokens to &lt;em&gt;only&lt;/em&gt; the actions (e.g., &lt;code&gt;pulumi up&lt;/code&gt;) and Entities (e.g., &lt;code&gt;stack: myapp-prod&lt;/code&gt;) they absolutely need.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced Blast Radius:&lt;/strong&gt; If a scoped token is compromised, the potential damage is limited strictly to the permissions defined in its associated role.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Compliance:&lt;/strong&gt; Demonstrate precise control over programmatic access to auditors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-to-get-started-with-granular-access-tokens"&gt;How to Get Started with Granular Access Tokens&lt;/h2&gt;
&lt;p&gt;Configuring and using Custom Roles for scoped tokens is done via the Pulumi Cloud console:&lt;/p&gt;
&lt;h3 id="1-define-a-custom-permission-optional"&gt;1. Define a Custom Permission (Optional)&lt;/h3&gt;
&lt;p&gt;Create reusable sets of fine-grained scopes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As an admin, navigate to Organization Settings -&amp;gt; Roles -&amp;gt; Permissions&lt;/li&gt;
&lt;li&gt;Follow instructions for &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/permissions#creating-custom-permissions"&gt;creating a custom permission&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-create-a-custom-role"&gt;2. Create a Custom Role&lt;/h3&gt;
&lt;p&gt;Combine permissions with specific resources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As an admin, navigate to Organization Settings -&amp;gt; Roles&lt;/li&gt;
&lt;li&gt;Follow instructions for &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/roles#creating-custom-roles"&gt;creating a custom role&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-generate-a-scoped-organization-access-token"&gt;3. Generate a Scoped Organization Access Token&lt;/h3&gt;
&lt;p&gt;Generate an organization access token with narrowed scope.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As an admin, navigate to Organization Settings -&amp;gt; Access Tokens -&amp;gt; Organization Access Tokens.*&lt;/li&gt;
&lt;li&gt;Click &amp;ldquo;Create token&amp;rdquo;. Provide a description. &lt;strong&gt;Select your Custom Role&lt;/strong&gt; from the &amp;ldquo;Role&amp;rdquo; dropdown. Generate the token.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="new-scenarios-unlocked-today"&gt;New Scenarios Unlocked Today&lt;/h2&gt;
&lt;p&gt;This release immediately enables more secure and compliant workflows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secure Multi-Environment CI/CD:&lt;/strong&gt; A single pipeline can use different tokens based on the target environment (dev, staging, prod), each assuming a role with appropriately restricted permissions (e.g., read-only for prod dependencies, write for the target stack).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restricted Operational Scripts:&lt;/strong&gt; An automation script designed only to read audit logs can use a token tied to a role granting &lt;em&gt;only&lt;/em&gt; &lt;code&gt;audit_log:read&lt;/code&gt; permission, preventing accidental or malicious modifications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Safer ChatOps &amp;amp; Tooling:&lt;/strong&gt; Integrations like ChatOps bots can operate with tokens scoped down to only necessary actions (e.g., triggering a &lt;code&gt;pulumi preview&lt;/code&gt; on specific stacks).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;strong&gt;Available Today:&lt;/strong&gt; Custom Permissions, Custom Roles, and the ability to scope Organization Access Tokens using these roles, is &lt;strong&gt;available now&lt;/strong&gt; for customers on the &lt;strong&gt;Pulumi Enterprise&lt;/strong&gt; and &lt;strong&gt;Pulumi Business Critical&lt;/strong&gt; tiers. Explore these features in your Pulumi Cloud organization settings!&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="conclusion-building-a-more-secure-future"&gt;Conclusion: Building a More Secure Future&lt;/h2&gt;
&lt;p&gt;Pulumi Identity and Access Management (IAM) represents a fundamental advancement in securing cloud development lifecycles managed by Pulumi, providing the controls needed to confidently embrace speed and scale. Today’s launch of Granular Access Tokens via Custom Roles provides immediate security improvements for automation and programmatic access, laying the vital groundwork for our comprehensive IAM vision rooted in Zero Trust principles.&lt;/p&gt;
&lt;p&gt;This empowers platform and security teams with the fine-grained control needed to implement least privilege, enhance compliance, and scale Pulumi usage securely without sacrificing velocity.&lt;/p&gt;
&lt;p&gt;We encourage our Enterprise and Business Critical customers to explore Custom Roles and Granular Access Tokens today. Dive into the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac"&gt;documentation&lt;/a&gt; and start building roles tailored to your security requirements. We welcome your feedback and feature requests in our &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues"&gt;GitHub repository&lt;/a&gt;. Join us as we build a more secure foundation for cloud engineering!&lt;/p&gt;
&lt;h2 id="learn-more"&gt;Learn More&lt;/h2&gt;
&lt;p&gt;Learn more about Pulumi Cloud&amp;rsquo;s new IAM &amp;amp; RBAC features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/roles"&gt;Roles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/permissions"&gt;Permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/rbac/scopes"&gt;Scopes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Germán Lena</author><author>Devon Grove</author><author>Arun Loganathan</author><category>iam</category><category>rbac</category><category>security</category><category>features</category><category>pulumi-cloud</category><category>access-tokens</category><category>oidc</category></item><item><title>Admin Organization Access Tokens in Pulumi Cloud</title><link>https://www.pulumi.com/blog/org-admin-tokens/</link><pubDate>Mon, 28 Aug 2023 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/org-admin-tokens/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/org-admin-tokens/index.png" /&gt;
&lt;p&gt;Last year &lt;a href="https://www.pulumi.com/blog/organization-access-tokens"&gt;we launched Organization Access Tokens for Pulumi Cloud&lt;/a&gt;, service tokens not tied to individual users, ideal for garnering programmatic access for continuous integration and continuous delivery (CI/CD) tools and other automated processes. After launching this feature we saw record level adoption, with a majority of customers who could use it creating Organization Access Tokens within a matter of weeks.&lt;/p&gt;
&lt;p&gt;Organization Access Tokens have member level permissions, meaning they can be used to perform actions that a member has permissions to perform. We heard from multiple customers that being able to provision access tokens with admin level permissions would light up several programmatic use cases. Today we are launching an Admin permission scope for Organization Access Tokens: increased privileges for when you need them.&lt;/p&gt;
&lt;h3 id="see-it-in-action"&gt;See it in action!&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/uploads/admintoken.gif" alt="Gif of creating an Admin token"&gt;&lt;/p&gt;
&lt;h3 id="increased-privileges"&gt;Increased Privileges&lt;/h3&gt;
&lt;div class="note note-warning"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-warning-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Admin Organization Access Tokens have elevated permissions, please use them with caution.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Admin Organization Access Tokens can perform many actions that a regular Organization Access Token can not. Here are some of the actions you can now perform with a token that were previously not possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transferring stacks&lt;/li&gt;
&lt;li&gt;Adding and removing users in your organization&lt;/li&gt;
&lt;li&gt;Update team membership roles&lt;/li&gt;
&lt;li&gt;Add and remove stacks from Teams&lt;/li&gt;
&lt;li&gt;Add and remove Team Access Tokens&lt;/li&gt;
&lt;li&gt;Get audit log events&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a full list of all actions that can be performed by each access token type please refer to the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/"&gt;Access Token documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="wrapping-up"&gt;Wrapping up&lt;/h3&gt;
&lt;p&gt;Organization Access Tokens are available to Enterprise and Business Critical customers, as well as on our 14-day trial. You can &lt;a href="https://app.pulumi.com/site/trial"&gt;start a trial&lt;/a&gt; or &lt;a href="https://www.pulumi.com/contact?form=sales"&gt;Contact Us&lt;/a&gt; about the Pulumi Service Enterprise Edition and Business Critical Edition to take it for a spin!&lt;/p&gt;
&lt;p&gt;As always, submit any feedback on the feature in the &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues/new/choose"&gt;Pulumi Cloud Requests&lt;/a&gt; repository.&lt;/p&gt;</description><author>Meagan Cojocar</author><author>Devon Grove</author><category>features</category></item><item><title>Announcing Team Access Tokens for the Pulumi Service</title><link>https://www.pulumi.com/blog/team-access-tokens/</link><pubDate>Tue, 16 Aug 2022 14:00:00 -0700</pubDate><guid>https://www.pulumi.com/blog/team-access-tokens/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/team-access-tokens/index.png" /&gt;
&lt;p&gt;A few months ago we launched &lt;a href="https://www.pulumi.com/blog/organization-access-tokens/"&gt;Organization Access Tokens&lt;/a&gt; for the &lt;a href="https://www.pulumi.com/product/pulumi-service/"&gt;Pulumi Service&lt;/a&gt; and saw overwhelmingly fast adoption from our customer base. Based on this customer demand, and existing customer feedback, we prioritized improvements in the scoping of access tokens. Today, we are launching Team Access Tokens, which allow Organization and Team Admins to create access tokens scoped to a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/"&gt;Pulumi Team&lt;/a&gt;. Pulumi Service customers on the Enterprise and Business Critical editions can use Pulumi Teams to set role-based access controls (RBAC) for stacks by enabling Organization administrators to assign a set of stack permissions to a group of users.&lt;/p&gt;
&lt;p&gt;Since Pulumi Teams are only available on these editions, Team Access Tokens are also only available to customers on the Enterprise and Business Critical editions of the Pulumi Service. See the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/team-access-tokens/"&gt;Team Access Tokens&lt;/a&gt; documentation for more information on how to use the feature.&lt;/p&gt;
&lt;h2 id="see-it-in-action"&gt;See it in action!&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/uploads/team_tokens.gif" alt="Team Access Tokens in the Pulumi Service"&gt;&lt;/p&gt;
&lt;h2 id="hear-from-our-customers"&gt;Hear from our customers&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Snowflake&lt;/a&gt;, a Pulumi customer, delivers the Data Cloud, a global network where thousands of organizations mobilize data with near-unlimited scale, concurrency, and performance. “Scoping down access tokens will help our Platform team manage Pulumi stacks at scale across multiple departments within Snowflake. When Organization Access Tokens came out we were quick to adopt them internally and intend to adopt Team Access Tokens now as well. Using Pulumi Teams and Team Access Tokens enables us to follow the principle of least privilege.” said Jonas-Taha El Sesiy, Senior Software Engineer at Snowflake.&lt;/p&gt;
&lt;h2 id="feature-overview"&gt;Feature overview&lt;/h2&gt;
&lt;p&gt;This feature is particularly useful for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Scoping programmatic access for continuous integration and continuous delivery (CI/CD) tools and other automated processes to the Pulumi Team instead of the entire Organization&lt;/li&gt;
&lt;li&gt;Enterprise customers using SSO/SAML/SCIM, as it enables them to set fine-grained stack permissions to the Pulumi Teams provisioned through their identity provider&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Team Access Tokens scope token access down to the stacks a Pulumi Team has access to. Customers can use Team Access Tokens when they need more fine grained access than a Personal Access Token. Personal Access Tokens have full permissions the user has across Organizations, Teams and Stacks. Team Access Tokens have less privilege than Organization Access Tokens, which have access across the Pulumi Organization and across multiple Teams.&lt;/p&gt;
&lt;p&gt;With the launch of Team Access Tokens, Pulumi users can now create the following access token types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Personal Access Tokens&lt;/strong&gt;: access tokens tied to a user’s access&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organization Access Tokens&lt;/strong&gt;: access tokens tied to a Pulumi organization’s access&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Team Access Tokens&lt;/strong&gt;: access tokens scoped to a Pulumi Team’s access&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature is available to all Enterprise and Business Critical customers today, as well as those on our 14-day trial. You can &lt;a href="https://app.pulumi.com/site/trial"&gt;start a trial&lt;/a&gt; or &lt;a href="https://www.pulumi.com/contact"&gt;Contact Us&lt;/a&gt; about the Pulumi Enterprise Edition and Business Critical Edition to take it for a spin!&lt;/p&gt;</description><author>Devon Grove</author><author>Meagan Cojocar</author><category>features</category><category>pulumi-cloud</category></item><item><title>Stack READMEs in the Pulumi Service</title><link>https://www.pulumi.com/blog/stack-readme/</link><pubDate>Thu, 19 May 2022 09:35:01 -0700</pubDate><guid>https://www.pulumi.com/blog/stack-readme/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/stack-readme/index.png" /&gt;
&lt;p&gt;Starting today, users can create &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/projects-and-stacks/#stack-readme"&gt;Stack READMEs&lt;/a&gt; in the &lt;a href="https://app.pulumi.com/signin"&gt;Pulumi Service&lt;/a&gt; that dynamically update based on &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/stack-outputs"&gt;Stack Outputs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Each Pulumi Stack you deploy manages a key set of cloud infrastructure for your organization. The Pulumi Console includes a variety of features for exposing key information about your stack for other users within your organization - configuration, outputs, resources under management, links to cloud providers, and a graph of all resources. However, it&amp;rsquo;s often useful to allow the author of a Pulumi Stack to describe in their own words the key elements of a stack, so future viewers can quickly understand the components and cloud resources that are managed.&lt;/p&gt;
&lt;p&gt;A README is a text file that introduces and explains a project. A Pulumi Service Stack README can contain documentation and common links for the Stack. The key difference between a source control README, such as a GitHub README, and a Pulumi Service Stack README, is that it is dynamically populated with details from your stack outputs. It does this by interpolating output variables on the stack (&lt;code&gt;${outputs.instances[0].ARN}&lt;/code&gt;) so that each stack can construct links to dashboards, shell commands, and other pieces of documentation. All of this content stays up to date as you stand up new stacks, rename resources, and refactor your infrastructure.&lt;/p&gt;
&lt;p&gt;There are a lot of operational activities that happen around &lt;a href="https://www.pulumi.com/docs/concepts/stack"&gt;Pulumi Stacks&lt;/a&gt;, but critical information is spread across many tools. We have heard from our users that it can be time consuming switching from different tools and web apps to manage their deployments- from their cloud Console, to the Pulumi Service User Interface (UI), to the CLI, and so on. By collecting resource outputs in the Pulumi Service UI, we are reducing this friction and keeping relevant Stack information in one place so that is kept up to date automatically.&lt;/p&gt;
&lt;p&gt;README templates can reference Stack outputs and resource properties, for example &lt;code&gt;${outputs.vpc.ARN}&lt;/code&gt;. To walk you through a tangible example, a user can deploy an RDS instance and then use a variable in their README template to link to their CloudWatch dashboard to keep an eye on operational metrics. This CloudWatch dashboard link will dynamically update when deployments happen. You can use the same README template across dev, testing and production and have the correct dashboard links for each Stack. Learn more in the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/projects-and-stacks/#stack-readme"&gt;Stack READMEs documentation page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new experience lives in the Stack page, which can be navigated to through Projects and clicking on the specific Stack you want to view the README for. Let&amp;rsquo;s take a look at this new feature!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/uploads/stack-readme.gif" alt="Stack READMEs in the Pulumi Console"&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Pulumi.README.md&lt;/code&gt; file we added to the Stack &amp;lsquo;Production&amp;rsquo; above is a template README for our Pulumi Service. In it we have links to our AWS authentication tool, our CloudWatch metrics, to our production deployment documentation, and so on. The common places that we navigate to and from when managing this Stack. Here is some of the Markdown for this README:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Pulumi Service README
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[&lt;span class="nt"&gt;Sign in to AWS to view stack resources!&lt;/span&gt;](&lt;span class="na"&gt;https://top-secret-url.com&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;​
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## On Call Operations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;​
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### Monitor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;​
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**Cloudwatch Metrics**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Monitor holistic metrics tracking overall service health
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[&lt;span class="nt"&gt;Link&lt;/span&gt;](&lt;span class="na"&gt;https://us-west-2.console.aws.amazon.com/cloudwatch/home?region=us-west-2#dashboards:name=${outputs.dashboardName}&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**RDS Performance Metrics**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Monitor RDS performance (wait times, top queries)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[&lt;span class="nt"&gt;Link&lt;/span&gt;](&lt;span class="na"&gt;https://us-west-2.console.aws.amazon.com/rds/home?region=us-west-2#performance-insights-v20206:/resourceId/${outputs.databaseClusterId}/resourceName/${outputs.rdsClusterWriterInstance}&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gs"&gt;**Cloudwatch Logs**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Search across service logs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[&lt;span class="nt"&gt;Link&lt;/span&gt;](&lt;span class="na"&gt;https://us-west-2.console.aws.amazon.com/cloudwatch/home?region=us-west-2#logStream:group=${outputs.cloudwatchLogGroup}&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="how-to-add-a-stack-readme-to-your-stack"&gt;How to add a Stack README to your Stack&lt;/h2&gt;
&lt;p&gt;In order to add a README to your Pulumi Stack, you will need to do the following:&lt;/p&gt;
&lt;h3 id="step-1"&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Export a &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/stack-outputs"&gt;Stack output&lt;/a&gt; named &lt;code&gt;readme&lt;/code&gt; that contains your templated Stack README markdown, commonly by reading a file, i.e. &lt;code&gt;Pulumi.README.md&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;
&lt;pulumi-chooser type="language" options="typescript,python,go,csharp,java,yaml" mode=""&gt;&lt;/pulumi-chooser&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="typescript" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fizz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;buzz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// add readme to stack outputs. must be named &amp;#34;readme&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;readme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./Pulumi.README.md&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="python" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;strVar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;arrVar&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fizz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;buzz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# open template readme and read contents into stack output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./Pulumi.README.md&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;readme&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="go" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strVar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arrVar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fizz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;buzz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;readmeBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ioutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;./Pulumi.README.md&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;failed to read readme: %w&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strVar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strVar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;arrVar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToStringArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrVar&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;readme&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;readmeBytes&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="csharp" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StrVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArrVar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;fizz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;buzz&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Readme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;./Pulumi.README.md&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Output]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;StrVar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Output]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ArrVar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Output]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Readme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="java" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;stackreadme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;java.nio.file.Files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;java.nio.file.Paths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.Pulumi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.pulumi.core.Output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strVar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arrVar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fizz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;buzz&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;./Pulumi.README.md&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strVar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strVar&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;arrVar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrVar&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;readme&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pulumi-choosable type="language" values="yaml" mode=""&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;stack-readme-yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;A minimal Pulumi YAML program demonstrating stack readme feature&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Fn::ReadFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./Pulumi.README.md&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strVar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;foo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;arrVar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;fizz&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;buzz&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;readme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${readme}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pulumi-choosable&gt;
&lt;/div&gt;
&lt;h3 id="step-2"&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Create a README template for the Stack. In this example, we will create a &lt;code&gt;Pulumi.README.md&lt;/code&gt; file that looks as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# Stack README
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Full markdown support! Substitute stack outputs dynamically so that links can depend on your infrastructure! Link to dashboards, logs, metrics, and more.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;1.&lt;/span&gt; Reference a string stack output: ${outputs.strVar}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;2.&lt;/span&gt; Reference an array stack output: ${outputs.arrVar[1]}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="step-3"&gt;Step 3&lt;/h3&gt;
&lt;p&gt;Run &lt;code&gt;pulumi up&lt;/code&gt; on that Stack&lt;/p&gt;
&lt;h3 id="step-4"&gt;Step 4&lt;/h3&gt;
&lt;p&gt;Open the Pulumi Service UI, navigate to Projects and then the Stack you have updated. Once on the Stack page you will see the README tab with your README file.&lt;/p&gt;
&lt;p&gt;Ta da! 🎉&lt;/p&gt;
&lt;p&gt;We now have a README on the Stack.&lt;/p&gt;
&lt;p&gt;Refer to the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/projects-and-stacks/#stack-readme"&gt;Stack README documentation page&lt;/a&gt; for more details on how to use this feature. As always, please feel free to submit feature requests and bug reports to the &lt;a href="https://github.com/pulumi/pulumi-cloud-requests"&gt;Pulumi Service GitHub Repo&lt;/a&gt;. We love hearing feedback from users about ways we can improve your productivity when using Pulumi. We look forward to seeing how you make Stack READMEs fit your needs!&lt;/p&gt;</description><author>Evan Boyle</author><author>Devon Grove</author><author>Myles Haynes</author><author>Casey Huang</author><author>Meagan Cojocar</author><category>features</category></item><item><title>Launching Organization Access Tokens for the Pulumi Service</title><link>https://www.pulumi.com/blog/organization-access-tokens/</link><pubDate>Thu, 28 Apr 2022 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/organization-access-tokens/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/organization-access-tokens/index.png" /&gt;
&lt;p&gt;As enterprise adoption of the Pulumi Service has grown 350% over the last year, we&amp;rsquo;ve seen a strong customer demand for tools to manage automated Pulumi use cases such as CI/CD and Automation API at scale. Today we are launching Organization Access Tokens to empower our largest customers to manage automated workloads in a secure and collaborative manner.&lt;/p&gt;
&lt;p&gt;Enterprise and Business Critical customers of the Pulumi Service can now create Access Tokens tied to their Pulumi Organization. In addition to creating and managing Access Tokens tied to a user’s access (Personal Access Tokens), customers can utilize Organization Access Tokens, tokens which are not tied to a specific user. This feature is particularly useful for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enterprise customers using SSO/SAML/SCIM, as it enables them to create Pulumi Service tokens not tied to identities within their identity provider (IdP)&lt;/li&gt;
&lt;li&gt;Garnering programmatic access for continuous integration and continuous delivery (CI/CD) tools and other automated processes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We&amp;rsquo;re excited to deliver one of the most &lt;a href="https://github.com/pulumi/pulumi-cloud-requests/issues/16"&gt;requested features from the community&lt;/a&gt; and a top ask from some of the largest customers using the Pulumi Service. The need to use Personal Access Tokens to manage automation and organization-specific resources can lead to some friction. When a user is deprovisioned or otherwise leaves the organization, their tokens in use no longer grant access and pipelines can become broken. Additionally, since Personal Access Tokens grant access to all resources and organizations they have access to, using personal tokens in organization automation pipelines leads to the pipeline having more privileged access than is necessary. We want to enable our customers to use the principle of least privilege. At launch, Organization Access Tokens will have write permissions to stacks in an Organization. We plan to continue to expand options for scoping this access based on feedback from our customers.&lt;/p&gt;
&lt;p&gt;See below what the experience looks like in the Pulumi Service:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/uploads/content/blog/organization-access-tokens/nav-org-tokens.gif" alt="Gif of tokens navigation"&gt;&lt;/p&gt;
&lt;p&gt;Users can now create an Organization Access Token in the Pulumi Service, give it a unique human-readable name (i.e. jenkins-ci-dev) and then use it to gain access to their Pulumi Service Organization. Only Organization Admins can create and manage Organization Access Tokens. As a security consideration for our customers, Organization Access Tokens cannot create other Organization Access Tokens. When a token is created they are provided a one-time token value. These tokens can only be deleted as an explicit action, either by clicking a button in the console or calling an API to delete the token. Creating or deleting an Organization Access Token will be logged as an event in the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/"&gt;Audit Logs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To determine which actions have been taken by which Organization Access Tokens, and to give greater clarity into specifically which tokens are conducting what operations, we have expanded Audit Log events to include information about the Organization Access Token that took the action. As an organization can have multiple Organization Access Tokens, this is a necessary step to ensure that accurate auditing can be done in the event that a token is compromised or is being used maliciously.&lt;/p&gt;
&lt;p&gt;See below how Organization Access Tokens appears in Audit Logs:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/uploads/content/blog/organization-access-tokens/audit-logs-org-tokens.gif" alt="Gif of tokens in Audit Logs"&gt;&lt;/p&gt;
&lt;p&gt;Learn more about using this feature in our &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/organization-access-tokens/"&gt;Access Token documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s explore how one of our customers is adopting Organization Access Tokens in the Pulumi Service. &lt;a href="https://faunadb.org/"&gt;Fauna&lt;/a&gt;, a Pulumi customer, is a distributed document relational database, delivered as a Cloud API. A native serverless architecture means no operations are required. Developers choose Fauna to build new applications faster and confidently scale existing ones across regions and the globe.&lt;/p&gt;
&lt;p&gt;Previously, Fauna created a user on the Pulumi Service under a shared email account and generated a Personal Access Token for that account to manage their organization wide access. This worked well as it meant the access token was not tied to a specific user. However, when they migrated to using the Pulumi Service single sign-on (SSO) for their Organization, this approach no longer worked since all Pulumi users were now attached to their SSO provider. “This will immediately solve the issues we have. This is an improvement over the process we’re using today,” said Ben Cohen, Software Engineer at Fauna.&lt;/p&gt;
&lt;p&gt;This feature is available to all Enterprise and Business Critical customers today, as well as on our 14-day trial. You can &lt;a href="https://app.pulumi.com/site/trial"&gt;start a trial&lt;/a&gt; or &lt;a href="https://www.pulumi.com/contact?form=sales"&gt;Contact Us&lt;/a&gt; about the Pulumi Service Enterprise Edition and Business Critical Edition to take it for a spin!&lt;/p&gt;</description><author>Devon Grove</author><category>features</category><category>pulumi-enterprise</category></item></channel></rss>