<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Rotation</title><link>https://www.pulumi.com/blog/tag/rotation/</link><description>Pulumi blog posts: Rotation.</description><language>en-us</language><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><item><title>Introducing ESC Secret Rotation Webhooks</title><link>https://www.pulumi.com/blog/introducing-esc-secret-rotation-webhooks/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/introducing-esc-secret-rotation-webhooks/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/introducing-esc-secret-rotation-webhooks/index.png" /&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/docs/esc/"&gt;Pulumi ESC&lt;/a&gt; centralizes your secrets and configuration, and it can &lt;a href="https://www.pulumi.com/docs/esc/concepts/rotators/"&gt;automatically rotate secrets&lt;/a&gt; on a schedule so credentials never go stale. But a rotation is only useful if the systems that depend on it know it happened. ESC secret rotation webhooks close that gap by notifying you the moment a secret rotates.&lt;/p&gt;
&lt;h2 id="introducing-secret-rotation-webhooks"&gt;Introducing secret rotation webhooks&lt;/h2&gt;
&lt;p&gt;With &lt;a href="https://www.pulumi.com/docs/esc/concepts/webhooks/"&gt;ESC webhooks&lt;/a&gt;, you can react to rotations automatically. When ESC rotates an environment&amp;rsquo;s secrets, a webhook can be configured to trigger on either success or failure. Use it to notify your team in Slack, refresh services that hold the old credential, or catch a failed rotation before it causes an outage.&lt;/p&gt;
&lt;h2 id="how-to-configure"&gt;How to configure&lt;/h2&gt;
&lt;h3 id="pulumi-cloud-console"&gt;Pulumi Cloud Console&lt;/h3&gt;
&lt;p&gt;Using the Pulumi Cloud Console, you can now configure webhooks for &amp;ldquo;Environment rotation succeeded&amp;rdquo; and &amp;ldquo;Environment rotation failed&amp;rdquo; in your ESC Environment&amp;rsquo;s Settings page (under &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Notifications&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="./rotation-webhook-triggers.png" alt="ESC webhook trigger settings with &amp;ldquo;Environment rotation succeeded&amp;rdquo; and &amp;ldquo;Environment rotation failed&amp;rdquo; selected"&gt;&lt;/p&gt;
&lt;h3 id="pulumi-service-provider"&gt;Pulumi Service Provider&lt;/h3&gt;
&lt;p&gt;You can use the Pulumi Service Provider in your Pulumi program to configure webhooks. Here is an example in TypeScript:&lt;/p&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;const&lt;/span&gt; &lt;span class="nx"&gt;environmentWebhook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;env-webhook&amp;#34;&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="nx"&gt;active&lt;/span&gt;: &lt;span class="kt"&gt;true&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="nx"&gt;displayName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;env-webhook&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="nx"&gt;organizationName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-org&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="nx"&gt;projectName&lt;/span&gt;: &lt;span class="kt"&gt;environment.project&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="nx"&gt;environmentName&lt;/span&gt;: &lt;span class="kt"&gt;environment.name&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="nx"&gt;payloadUrl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://example.com&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="nx"&gt;filters&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;WebhookFilters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EnvironmentRotationSucceeded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WebhookFilters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EnvironmentRotationFailed&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;h3 id="pulumi-cli"&gt;Pulumi CLI&lt;/h3&gt;
&lt;p&gt;You can also use the Pulumi CLI to configure the webhook:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pulumi env webhook new my-org/project/env env-webhook \
--url https://example.com \
--event environment_rotation_succeeded \
--event environment_rotation_failed
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="get-started"&gt;Get started&lt;/h2&gt;
&lt;p&gt;Secret rotation webhooks are available now for all Pulumi ESC environments. See the &lt;a href="https://www.pulumi.com/docs/esc/concepts/webhooks/"&gt;webhooks documentation&lt;/a&gt; to get started, and share your feedback on our &lt;a href="https://github.com/pulumi/esc"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;</description><author>Sean Yeh</author><category>esc</category><category>rotation</category><category>secrets</category></item><item><title>Announcing Snowflake Dynamic and Rotated Credentials with Pulumi ESC</title><link>https://www.pulumi.com/blog/esc-snowflake-providers-launch/</link><pubDate>Thu, 01 May 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/esc-snowflake-providers-launch/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/esc-snowflake-providers-launch/index.png" /&gt;
&lt;p&gt;Snowflake is the data cloud powerhouse for countless businesses, critical for everything from customer dashboards to billing pipelines. The stakes are immense: this data must be strictly secured and always available. But managing this with static credentials or manual key rotation creates persistent security vulnerabilities and introduces operational instability, risking disruptions during clumsy updates. &lt;a href="https://www.pulumi.com/product/secrets-management/"&gt;Pulumi ESC&lt;/a&gt; eliminates this dilemma with two purpose-built Snowflake integrations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/esc/integrations/dynamic-login-credentials/snowflake-login/"&gt;&lt;code&gt;snowflake-login&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Provides dynamic, short-lived OIDC tokens for temporary authentication &lt;em&gt;to&lt;/em&gt; Snowflake.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/"&gt;&lt;code&gt;snowflake-user&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; Automates the rotation of RSA keypair secrets &lt;em&gt;for&lt;/em&gt; Snowflake users, essential for secure key-pair authentication.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pulumi ESC allows you to securely manage and consume these Snowflake credentials in your applications, development workflows through &lt;a href="https://www.pulumi.com/docs/esc/development/languages-sdks/"&gt;ESC SDK&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_env/"&gt;Pulumi CLI&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/esc/integrations/kubernetes/"&gt;Kubernetes integrations&lt;/a&gt;, and more!&lt;/p&gt;
&lt;h2 id="snowflake-login-dynamic-oidc-authentication-for-temporary-access"&gt;snowflake-login: Dynamic OIDC Authentication for Temporary Access&lt;/h2&gt;
&lt;p&gt;Use the &lt;code&gt;snowflake-login&lt;/code&gt; provider when you need temporary, just-in-time credentials to interact with Snowflake, such as from local development environments, CI/CD pipelines, or scripts. It leverages OIDC to mint short-lived access tokens, eliminating the need to store static tokens.&lt;/p&gt;
&lt;p&gt;This approach significantly reduces the attack surface by removing long-lived credentials required for &lt;em&gt;authentication&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Configure OIDC in Snowflake:&lt;/strong&gt; Create a Security Integration in Snowflake to trust the Pulumi OIDC provider (&lt;code&gt;https://api.pulumi.com/oidc&lt;/code&gt;), map the appropriate user claims and create a Snowflake user. Check out the &lt;a href="https://www.pulumi.com/docs/esc/integrations/dynamic-login-credentials/snowflake-login/#configuring-oidc-for-snowflake"&gt;docs&lt;/a&gt;] for more details&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure ESC Environment:&lt;/strong&gt; Define the &lt;code&gt;snowflake-login&lt;/code&gt; provider in your ESC environment, specifying the Snowflake account and the user configured for OIDC.&lt;/li&gt;
&lt;/ol&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="c"&gt;# my-org/logins/snowflake&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;values&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;snowflake&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;login&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::open::snowflake-login&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;oidc&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;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;myorganization-account&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;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ESC_LOGIN_USER&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;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ESC_ROLE &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Optional&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;p&gt;When this environment is opened, ESC securely handles the OIDC flow and makes the temporary token available under &lt;code&gt;snowflake.login.token&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="snowflake-user-automated-rotation-for-rsa-key-secrets"&gt;snowflake-user: Automated Rotation for RSA Key Secrets&lt;/h2&gt;
&lt;p&gt;For applications or services using Snowflake&amp;rsquo;s key-pair authentication, maintaining the security of those RSA keys is crucial. The &lt;code&gt;snowflake-user&lt;/code&gt; rotator automates the lifecycle management of these keys as &lt;strong&gt;rotated secrets&lt;/strong&gt; within ESC. This rotater uses the same two-secret rotation strategy we use in rest of ESC&amp;rsquo;s &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/"&gt;rotated secrets&lt;/a&gt; providers. This eliminates manual rotation toil and ensures keys are regularly refreshed according to policy, enhancing the security of the &lt;em&gt;user secret&lt;/em&gt; itself. Check out the rotated secrets &lt;a href="https://www.pulumi.com/blog/esc-rotated-secrets-launch/#introducing-esc-rotated-secrets"&gt;blog post&lt;/a&gt; to learn more about its benefits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prepare Snowflake:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Create the &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/#step-1-create-the-target-user"&gt;target user&lt;/a&gt; (e.g., &lt;code&gt;MY_APP_SNOWFLAKE_USER&lt;/code&gt;) whose keys need rotation.&lt;/li&gt;
&lt;li&gt;Set up a dedicated &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/#step-2-create-a-rotator-role"&gt;rotation role&lt;/a&gt; with &lt;code&gt;OWNERSHIP&lt;/code&gt; permission over the users you wish to rotate, so it can modify their keys.&lt;/li&gt;
&lt;li&gt;Create a &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/#step-3-create-a-rotation-service-user"&gt;service user&lt;/a&gt; using the rotation role, and &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/#step-4-set-up-oidc-for-the-rotation-service-user"&gt;setup OIDC&lt;/a&gt; to allow ESC to assume the role for rotation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rotation Environment:&lt;/strong&gt; Define the rotation, importing the managing credentials and specifying the target user.&lt;/li&gt;
&lt;/ul&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="c"&gt;# Environment: my-org/rotators/snowflake-app-key&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;values&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;rotatedKey&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::rotate::snowflake-user&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;inputs&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;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${environments.logins.snowflake.snowflake.login}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#reference credentials created using `snowflake-login`&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;targetUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ESC_ROTATION_DEMO_USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# User whose keys rotate&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;p&gt;After setup, use the triple-dot menu -&amp;gt; “Rotate Secrets” in the Pulumi Cloud UI and ensure rotation happens. Once you rotate a couple of time and ensured everything works well, navigate to the “Secret Rotation” tab for your Rotation environment in the Pulumi Cloud console and define the rotation schedule.&lt;/p&gt;
&lt;h2 id="when-to-use-dynamic-login-vs-rotated-secrets"&gt;When to Use Dynamic Login vs. Rotated Secrets&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;snowflake-login&lt;/code&gt; (Dynamic OIDC Login)&lt;/strong&gt;&lt;/th&gt;
&lt;th style="text-align: left"&gt;&lt;strong&gt;&lt;code&gt;snowflake-user&lt;/code&gt; (Rotated Secrets)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Credential Type&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Short-lived OIDC access token&lt;/td&gt;
&lt;td style="text-align: left"&gt;Long-lived RSA Private Key secret (managed by ESC) + Public Keys (in Snowflake)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Primary Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Temporary authentication &lt;em&gt;to&lt;/em&gt; Snowflake (CLI, scripts, dev, CI/CD).&lt;/td&gt;
&lt;td style="text-align: left"&gt;Key-pair authentication &lt;em&gt;for&lt;/em&gt; long-lived applications/services connecting to Snowflake.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Ideal Scenario&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Short-lived tasks; frequent, temporary access needs.&lt;/td&gt;
&lt;td style="text-align: left"&gt;Applications needing persistent connections; keys required at deploy time; apps sensitive to auth blips.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Lifecycle&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Generated on-demand, expires quickly (minutes/hours).&lt;/td&gt;
&lt;td style="text-align: left"&gt;Rotated automatically on a schedule (e.g., days/months).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Connection Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Requires re-authentication or new token fetch when token expires.&lt;/td&gt;
&lt;td style="text-align: left"&gt;Rotation is typically seamless; two-key strategy avoids connection drops if apps update keys promptly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Benefit Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Eliminates static &lt;em&gt;authentication&lt;/em&gt; tokens/credentials.&lt;/td&gt;
&lt;td style="text-align: left"&gt;Automates lifecycle management of user &lt;em&gt;key-pair secrets&lt;/em&gt;, ensures key freshness.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pulumi ESC&amp;rsquo;s new Snowflake integrations provide robust solutions for modern credential management challenges. Use &lt;code&gt;snowflake-login&lt;/code&gt; for secure, temporary OIDC-based access and &lt;code&gt;snowflake-user&lt;/code&gt; to automate the rotation of critical RSA key secrets. By adopting these capabilities, you can significantly enhance your Snowflake security posture, reduce operational overhead, and simplify compliance.&lt;/p&gt;
&lt;p&gt;Explore the detailed documentation for &lt;a href="https://www.pulumi.com/docs/esc/integrations/dynamic-login-credentials/snowflake-login/"&gt;&lt;code&gt;snowflake-login&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/snowflake-user/"&gt;&lt;code&gt;snowflake-user&lt;/code&gt;&lt;/a&gt;, and see how Pulumi ESC can centralize and secure your configuration and secrets across all your environments. Join the conversation in the &lt;a href="https://slack.pulumi.com/"&gt;Pulumi Community Slack&lt;/a&gt; or our &lt;a href="https://github.com/pulumi/esc"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;</description><author>Claire Gaestel</author><author>Arun Loganathan</author><category>esc</category><category>secrets</category><category>features</category><category>snowflake</category><category>rotation</category><category>dynamic-login</category><category>oidc</category><category>security</category><category>configuration-management</category></item><item><title>Introducing Automated Database Credential Rotation for PostgreSQL and MySQL in Pulumi ESC</title><link>https://www.pulumi.com/blog/esc-db-secrets-rotation-launch/</link><pubDate>Wed, 30 Apr 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/esc-db-secrets-rotation-launch/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/esc-db-secrets-rotation-launch/index.png" /&gt;
&lt;p&gt;Securing access to critical data stores is paramount in today&amp;rsquo;s cloud-native world. Yet, managing database credentials often involves static, long-lived passwords – a significant security blind spot. These static secrets, frequently embedded in application configurations or accessible to multiple team members, represent a prime target for attackers. Manually rotating these credentials is a cumbersome, error-prone task that’s often neglected, leaving databases vulnerable for extended periods. Building on our commitment to robust secrets management, we are excited to launch &lt;strong&gt;Automated Database Credential Rotation&lt;/strong&gt; for &lt;strong&gt;PostgreSQL and MySQL&lt;/strong&gt; in &lt;a href="https://www.pulumi.com/product/secrets-management/"&gt;Pulumi ESC!&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-persistent-challenge-of-static-database-secrets"&gt;The Persistent Challenge of Static Database Secrets&lt;/h2&gt;
&lt;p&gt;Relying on static database credentials introduces substantial risks, which automated rotation helps mitigate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security Vulnerabilities &amp;amp; Exposure:&lt;/strong&gt; Static credentials, if compromised through leaks, phishing, or unauthorized access, provide long-term access to attackers. Automated rotation significantly shrinks this window of opportunity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operational &amp;amp; Compliance Burdens:&lt;/strong&gt; Manually rotating database credentials is complex, error-prone, and requires careful coordination to avoid downtime. These manual rotations are hard to audit and demonstrate compliance with regulations like SOC 2, GDPR, or HIPAA (which often mandate rotation).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Complexity &amp;amp; The DIY Burden:&lt;/strong&gt; Databases in private networks (like AWS VPCs) require secure access for rotation. We provide an open-source &lt;strong&gt;Lambda connector&lt;/strong&gt; for AWS VPCs. While homegrown solutions can bridge the network gap, building and maintaining the &lt;em&gt;actual rotation logic&lt;/em&gt; (state, error handling, two-secret strategy) is complex. Crucially, DIY approaches typically lack integrated revision history, centralized auditing, and unified management provided by platforms like Pulumi ESC, increasing operational overhead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tooling, Ecosystem, and Cloud-Native Connectivity:&lt;/strong&gt; Despite cloud IAM authentication options, many standard tools (GUIs, BI, ETL), legacy apps, and even certain cloud-native configurations (multi-cloud, specific Kubernetes setups) still rely on username/password. Direct IAM integration isn&amp;rsquo;t always feasible or practical, making automated rotation of traditional credentials essential for broad compatibility and security.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pulumi ESC addresses these challenges by automating the secrets rotation process, including connectivity options for databases in private AWS networks using our Lambda connector, and allows you to consume them in your applications through ESC&amp;rsquo;s various developer-friendly methods including &lt;a href="https://www.pulumi.com/docs/esc/development/languages-sdks/"&gt;ESC SDK&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_env/"&gt;Pulumi CLI&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/esc/integrations/kubernetes/external-secrets-operator/"&gt;Kubernetes External Secrets Operator&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/esc/integrations/kubernetes/secret-store-csi-driver/"&gt;CSI Driver&lt;/a&gt;, etc.&lt;/p&gt;
&lt;h2 id="introducing-esc-rotated-secrets-for-databases"&gt;Introducing ESC Rotated Secrets for Databases&lt;/h2&gt;
&lt;p&gt;Pulumi ESC’s &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/"&gt;Rotated Secrets&lt;/a&gt; capability now extends to your critical databases, bringing automation and enhanced security to credential lifecycle management. We are adding support for the following databases and connectivity options:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;Database&lt;/th&gt;
&lt;th style="text-align: center"&gt;Publicly Accessible&lt;/th&gt;
&lt;th style="text-align: center"&gt;AWS VPCs&lt;/th&gt;
&lt;th style="text-align: center"&gt;Azure VNETs&lt;/th&gt;
&lt;th style="text-align: center"&gt;GCloud VPCs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/postgres/"&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ &lt;small&gt;(via Lambda)&lt;/small&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Planned &lt;small&gt;(&lt;a href="https://github.com/pulumi/esc/issues/521"&gt;upvote issue&lt;/a&gt;)&lt;/small&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Planned &lt;small&gt;(&lt;a href="https://github.com/pulumi/esc/issues/522"&gt;upvote issue&lt;/a&gt;)&lt;/small&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/mysql/"&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ &lt;small&gt;(via Lambda)&lt;/small&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Planned &lt;small&gt;(&lt;a href="https://github.com/pulumi/esc/issues/521"&gt;upvote issue&lt;/a&gt;)&lt;/small&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Planned &lt;small&gt;(&lt;a href="https://github.com/pulumi/esc/issues/522"&gt;upvote issue&lt;/a&gt;)&lt;/small&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Key benefits include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automated Rotation Schedules:&lt;/strong&gt; Effortlessly define rotation frequencies (daily, weekly, monthly) that align with your security policies, eliminating manual toil and ensuring consistency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On-Demand Rotation:&lt;/strong&gt; Instantly rotate credentials in response to security events, personnel changes, or policy updates with a single click or command.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless ESC Environment Integration:&lt;/strong&gt; Manage rotated database credentials alongside all your other application configurations within ESC Environments, leveraging composition and environment inheritance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Two-Secret Strategy:&lt;/strong&gt; ESC maintains both the current and previous valid credentials simultaneously. This prevents application downtime during rotation, as instances can gracefully transition to the new credential.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditing and Tracking:&lt;/strong&gt; Maintain a complete audit trail of credential rotations, including who initiated the rotation and when, simplifying compliance and governance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admin and Creator Control:&lt;/strong&gt; Securely configure rotation using privileged database &amp;ldquo;managing user&amp;rdquo; credentials stored within ESC, keeping them separate from the rotated credentials consumed by applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure Webhooks for Automation:&lt;/strong&gt; Trigger notifications, CI/CD pipelines (e.g., Pulumi Deployments to update application stacks), or custom workflows upon successful rotation, keeping dependent systems synchronized.&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;The following setup guide provides a detailed walkthrough for rotating &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/postgres/"&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt; credentials for an &lt;strong&gt;AWS RDS instance hosted within a private VPC&lt;/strong&gt;, which requires the AWS Lambda-based connector. For publicly accessible databases (PostgreSQL or MySQL), you can use the simpler &lt;strong&gt;Direct Connect&lt;/strong&gt; method documented on the respective integration pages. Please refer to the &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/mysql/"&gt;&lt;strong&gt;MySQL&lt;/strong&gt;&lt;/a&gt; documentation page for specific instructions on MySQL rotation (both Direct Connect and Lambda Connector).&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="how-to-set-up-and-use-rotation-for-aws-rds-postgresql-running-in-vpc"&gt;How to Set Up and Use Rotation for AWS RDS PostgreSQL running in VPC&lt;/h2&gt;
&lt;p&gt;Setting up rotation for AWS RDS or Aurora PostgreSQL databases running inside an AWS VPC involves &lt;a href="https://www.pulumi.com/docs/esc/environments/rotation/db-user-setup/"&gt;creating the required users&lt;/a&gt; within your database, deploying the AWS Lambda connector infrastructure via a Pulumi template, configuring ESC environments, and scheduling the rotation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Understanding the AWS Lambda Connector:&lt;/strong&gt; The open-source &lt;a href="https://github.com/pulumi/templates/tree/master/esc-connector-lambda-typescript"&gt;ESC Lambda connector&lt;/a&gt; acts as a secure proxy for database credential rotation within your VPC. It enables Pulumi ESC to safely rotate database credentials without needing direct network access from ESC to your database and without exposing your database to external networks. This connector is currently required to rotate credentials for PostgreSQL or MySQL databases hosted within an AWS VPC. Note: The AWS Lambda Connector is only available to Enterprise and Business Critical customers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Prepare Your PostgreSQL Database Users&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll need two &lt;em&gt;types&lt;/em&gt; of users configured, resulting in &lt;em&gt;three&lt;/em&gt; specific database user accounts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Managing User:&lt;/strong&gt; A privileged user that ESC will use (via the Lambda connector) to perform the password rotations. This user needs permissions to change the passwords of the application users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application User 1 and Application User 2:&lt;/strong&gt; The two application users whose passwords ESC will manage. ESC rotates between these two users, ensuring two users are always active as applications gradually phase out the &lt;code&gt;previous&lt;/code&gt; user credentials.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Connect to the database as a superuser and run the following SQL commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Create the application users whose passwords you want ESC to rotate automatically:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```sql
CREATE USER user1 WITH PASSWORD 'initial_password';
GRANT SELECT, INSERT, UPDATE ON yourDatabase TO user1;
CREATE USER user2 WITH PASSWORD 'initial_password';
GRANT SELECT, INSERT, UPDATE ON yourDatabase TO user2;
```
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the designated &amp;ldquo;managing user&amp;rdquo; account with privileges to modify passwords for the application users:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```sql
CREATE USER managing_user WITH PASSWORD 'manager_password';
ALTER USER managing_user WITH CREATEROLE;
GRANT user1 TO managing_user WITH ADMIN OPTION;
GRANT user2 TO managing_user WITH ADMIN OPTION;
```
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Bootstrap Rotation Infrastructure (Lambda Connector) and Create ESC Environments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To rotate credentials for PostgreSQL databases within AWS VPCs securely, you need to configure an &lt;a href="https://www.pulumi.com/docs/esc/environments/rotation/aws-lambda/"&gt;AWS Lambda function (the connector)&lt;/a&gt; within your VPC and create the corresponding ESC environments.&lt;/p&gt;
&lt;p&gt;If your PostgreSQL instance is running on AWS RDS, we recommend using our &lt;a href="https://github.com/pulumi/templates/tree/master/esc-connector-lambda-typescript"&gt;Pulumi Template&lt;/a&gt; to simplify the process of creating the Lambda function, associated AWS IAM Roles, Security Groups, and the basic ESC environment structure. You can start it from the &lt;a href="https://app.pulumi.com/new?template=https://github.com/pulumi/templates/esc-connector-lambda-typescript"&gt;Pulumi console&lt;/a&gt; or by running the following command in your terminal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;pulumi new esc-connector-lambda-typescript&lt;/code&gt; in your terminal.&lt;/li&gt;
&lt;li&gt;This command initializes a new Pulumi project designed to provision the necessary AWS Lambda connector resources and create the ESC environments.&lt;/li&gt;
&lt;li&gt;Follow the prompts. You will first provide a &lt;strong&gt;Pulumi project name&lt;/strong&gt; (e.g., &lt;code&gt;my-db-rotation-infra&lt;/code&gt;). Then, you will be prompted for configuration values like:
&lt;ul&gt;
&lt;li&gt;Your target AWS Region (&lt;code&gt;aws:region&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The RDS Database Identifier (&lt;code&gt;rdsDbIdentifier&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The specific &lt;strong&gt;name for the ESC rotation environment&lt;/strong&gt; (e.g., &lt;code&gt;postgresrotation/Rotator&lt;/code&gt;). This environment will contain the two application users&amp;rsquo; credentials and configuration for rotation.&lt;/li&gt;
&lt;li&gt;The specific &lt;strong&gt;name for the ESC managing credentials environment&lt;/strong&gt; (e.g., &lt;code&gt;postgresrotation/ManagingCreds&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;pulumi up&lt;/code&gt; to deploy the AWS resources and create the ESC environments using the names you provided.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Configure ESC Environments and Test&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Pulumi template creates two ESC environments with most of the configuration pre-filled. You need to update them with your specific PostgreSQL user credentials and database name.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Managing Credentials Environment (e.g., &lt;code&gt;postgresrotation/ManagingCreds&lt;/code&gt;):&lt;/strong&gt; Navigate to this environment in the Pulumi Cloud console. Update the managing user&amp;rsquo;s username and password. The &lt;code&gt;awsLogin&lt;/code&gt; section, which provides credentials for the Lambda connector to assume, should be pre-filled by the template.&lt;/p&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="c"&gt;# postgresrotation/ManagingCreds&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;values&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;managingUser&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;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;managing_user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Replace with your managing user&amp;#39;s name&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;password&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="c"&gt;# Securely replace the placeholder with your managing user&amp;#39;s password using fn::secret&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::secret&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;ciphertext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ZXNjeA...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Replace with your encrypted password&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;awsLogin&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::open::aws-login&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;oidc&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;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1h&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;roleArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;arn:aws:iam::616138583583:role/PulumiEscSecretRotatorLambda-InvocationRole-7e4646f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Example Role ARN populated by template&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;sessionName&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-esc-secret-rotator-${esc.context.environment}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Example Session Name populated by template&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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rotation Environment (e.g., &lt;code&gt;&amp;lt;project-name&amp;gt;/Rotator&lt;/code&gt;):&lt;/strong&gt; Navigate to this environment. Most fields related to the Lambda connector (Lambda ARN, host, port, references) are pre-filled by the template outputs. You &lt;em&gt;must&lt;/em&gt; update the database name and the application usernames mapping. Note the &lt;code&gt;connector.awsLambda&lt;/code&gt; block indicating the use of the Lambda connector.&lt;/p&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="c"&gt;# postgresrotation/Rotator&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;values&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;dbRotator&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::rotate::postgres&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;inputs&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;database&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="c"&gt;# Configure the AWS Lambda connector for private VPC access&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;connector&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;awsLambda&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;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${environments.postgresrotation.ManagingCreds.awsLogin}&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;lambdaArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;arn:aws:lambda:us-west-2:616138583583:function:PulumiEscSecretRotatorLambda-Function-d9932fe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Example Lambda ARN populated by template&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="c"&gt;# Database connection details (used by the Lambda connector)&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;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mydb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Replace with your DB name&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;tf-20250428212643894700000001.cluster-chuqccm8uxqx.us-west-2.rds.amazonaws.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Example Host populated by template&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;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5432&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Example Port populated by template&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;managingUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${environments.postgresrotation.ManagingCreds.managingUser}&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="c"&gt;# List of application users whose passwords will be rotated&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;rotateUsers&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;username1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;user1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Replace DB username if different from logical name&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;username2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;user2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Replace DB username if different from logical name&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&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="c"&gt;# state section is automatically managed by ESC after first rotation&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="c"&gt;# Do not provide state unless migrating existing, known credentials.&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="c"&gt;# state:&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="c"&gt;# current:&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="c"&gt;# password:&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="c"&gt;# fn::secret:&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="c"&gt;# ciphertext: ZXNjeAAAA...&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="c"&gt;# username: user1&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="c"&gt;# previous:&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="c"&gt;# password:&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="c"&gt;# fn::secret:&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="c"&gt;# ciphertext: ZXNje21AA...&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="c"&gt;# username: user2&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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test with Manual Rotation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the triple-dot menu -&amp;gt; &amp;ldquo;Rotate Secrets&amp;rdquo; in the Pulumi Cloud UI for the Rotator environment.&lt;/li&gt;
&lt;li&gt;Alternatively, use the Pulumi CLI: &lt;code&gt;pulumi env rotate &amp;lt;your-org&amp;gt;/&amp;lt;project-name&amp;gt;/Rotator&amp;gt;&lt;/code&gt; (e.g., &lt;code&gt;pulumi env rotate myorg/postgresrotation/Rotator&lt;/code&gt;). Remember to replace &lt;code&gt;&amp;lt;your-org&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;project-name&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Perform a rotation. If you &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; provide the &lt;code&gt;state&lt;/code&gt; block, this first rotation generates a new password for the user designated as &lt;code&gt;current&lt;/code&gt; (e.g., &lt;code&gt;user1&lt;/code&gt; associated with &lt;code&gt;username1&lt;/code&gt;) and updates it in the database via the Lambda connector. The &lt;code&gt;dbRotator&lt;/code&gt; value in ESC will now show this user/password under &lt;code&gt;current&lt;/code&gt;, and the &lt;code&gt;state&lt;/code&gt; block will be populated.&lt;/li&gt;
&lt;li&gt;Perform a &lt;em&gt;second&lt;/em&gt; rotation. Observe how the previous &lt;code&gt;current&lt;/code&gt; user (&lt;code&gt;user1&lt;/code&gt;/&lt;code&gt;username1&lt;/code&gt;) and its password become the &lt;code&gt;previous&lt;/code&gt; entry in the ESC value. The system now rotates the password for the &lt;em&gt;other&lt;/em&gt; user (&lt;code&gt;user2&lt;/code&gt;/&lt;code&gt;username2&lt;/code&gt;), makes it the new &lt;code&gt;current&lt;/code&gt;, and updates the database accordingly. Subsequent rotations cycle between &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;user2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check the Environment Revision History in the Pulumi Cloud console to track the changes to the &lt;code&gt;current&lt;/code&gt; and &lt;code&gt;previous&lt;/code&gt; state fields after each rotation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Schedule Automated Rotations&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Once you are satisfied that manual rotations via the Lambda connector are working correctly, navigate to the &amp;ldquo;Secret Rotation&amp;rdquo; tab for your Rotator environment (e.g., &lt;code&gt;postgresrotation/Rotator&lt;/code&gt;) in the Pulumi Cloud console.&lt;/li&gt;
&lt;li&gt;Define your desired automated rotation schedule (e.g., every 30 days). ESC will automatically trigger rotations according to this schedule, ensuring your credentials stay fresh without manual intervention.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whats-next"&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;This launch significantly enhances database security posture through automation for PostgreSQL and MySQL, but we&amp;rsquo;re just getting started. We plan to expand our rotated secrets capabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More Databases:&lt;/strong&gt; Support for &lt;a href="https://github.com/pulumi/esc/issues/525"&gt;MongoDB&lt;/a&gt;, &lt;a href="https://github.com/pulumi/esc/issues/526"&gt;Microsoft SQL Server&lt;/a&gt;, &lt;a href="https://github.com/pulumi/esc/issues/527"&gt;Oracle&lt;/a&gt;, and others.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Databases in Private Networks on Other Clouds:&lt;/strong&gt; Rotation solutions for databases hosted in private networks within &lt;a href="https://github.com/pulumi/esc/issues/521"&gt;Azure&lt;/a&gt;, &lt;a href="https://github.com/pulumi/esc/issues/522"&gt;Google Cloud&lt;/a&gt;, and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Have a specific database or integration in mind? Upvote existing issues or open a new request in our &lt;a href="https://github.com/pulumi/esc/issues"&gt;GitHub repository&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pulumi ESC&amp;rsquo;s Automated Database Credential Rotation drastically simplifies a critical security task. By automating the rotation of &lt;strong&gt;PostgreSQL&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt; credentials, ESC reduces operational overhead, minimizes the risk associated with static secrets, and helps you meet compliance requirements more easily. Whether your databases are publicly accessible (using Direct Connect) or in private AWS networks (using the Lambda connector), ESC provides a unified way to manage their lifecycle securely.&lt;/p&gt;
&lt;p&gt;We encourage you to explore the &lt;a href="https://www.pulumi.com/docs/esc/"&gt;Pulumi ESC documentation&lt;/a&gt; and try out rotated database secrets for &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/postgres/"&gt;PostgreSQL&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/esc/integrations/rotated-secrets/mysql/"&gt;MySQL&lt;/a&gt;. Your feedback is invaluable – please share your experiences and suggestions on our &lt;a href="https://github.com/pulumi/esc"&gt;GitHub repository&lt;/a&gt;. Secure your databases with automated rotation and build with confidence!&lt;/p&gt;</description><author>Sean Yeh</author><author>Iaroslav Titov</author><author>Arun Loganathan</author><category>esc</category><category>secrets</category><category>features</category><category>rotation</category><category>database</category><category>security</category></item></channel></rss>