<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: maxxdev</title>
    <description>The latest articles on DEV Community by maxxdev (@maxxdev).</description>
    <link>https://dev.to/maxxdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F603656%2F622906e9-d97a-4649-a1ea-cdfe688acb7f.png</url>
      <title>DEV Community: maxxdev</title>
      <link>https://dev.to/maxxdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxxdev"/>
    <language>en</language>
    <item>
      <title>Stop Hardcoding Secrets in Azure DevOps Pipelines</title>
      <dc:creator>maxxdev</dc:creator>
      <pubDate>Mon, 19 Oct 2026 17:35:04 +0000</pubDate>
      <link>https://dev.to/maxxdev/stop-hardcoding-secrets-in-azure-devops-pipelines-a8f</link>
      <guid>https://dev.to/maxxdev/stop-hardcoding-secrets-in-azure-devops-pipelines-a8f</guid>
      <description>&lt;p&gt;Still storing your passwords as "secret" pipeline variables, clicking that little lock icon, and hoping for the best? 🤫&lt;/p&gt;

&lt;p&gt;It’s a convenient habit to fall into. But as your project grows, those secrets get scattered across dozens of pipelines and environments. Before long, you have no idea who created them, when they were last rotated, or where else that same password is being copied. That isn't secret management—it's secrets sprawl.&lt;/p&gt;

&lt;p&gt;In this guide, we are going one level deeper. I'll show you how to centralize your secrets in &lt;strong&gt;Azure Key Vault&lt;/strong&gt; and cleanly wire them into &lt;strong&gt;Azure DevOps YAML pipelines&lt;/strong&gt; the right way: cleanly, auditable, and without duplicate passwords scattered across your deployment configuration.&lt;/p&gt;

&lt;p&gt;Watch the full step-by-step setup demo here, or read on for the architectural breakdown and key gotchas:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/c-Qp-V3TEIE" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  The Secure Architecture Chain
&lt;/h2&gt;

&lt;p&gt;To set this up correctly, you need to understand how five distinct pieces connect. Without this mental model, it is incredibly easy to get lost clicking between the Azure Portal and Azure DevOps, wondering which permission goes where. &lt;/p&gt;

&lt;p&gt;Here is the exact chain we build in the video:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Azure Key Vault:&lt;/strong&gt; The single, central home where your actual sensitive values (API keys, connection strings, certificates) live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Connection:&lt;/strong&gt; The trust bridge. Created inside your Azure DevOps project, this provides an identity (backed by a Service Principal or Managed Identity in Microsoft Entra ID) to authenticate against Azure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure RBAC Permissions:&lt;/strong&gt; The authorization layer. You grant that specific Entra ID identity the &lt;strong&gt;Key Vault Secrets User&lt;/strong&gt; role so it has permission to read the secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linked Variable Group:&lt;/strong&gt; The bridge. You create a Variable Group in Azure DevOps, link it directly to your Key Vault, and select exactly which secrets you want to expose to your pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YAML Pipeline:&lt;/strong&gt; Your pipeline consumes the variables by referencing the group under its &lt;code&gt;variables:&lt;/code&gt; block (using the &lt;code&gt;group:&lt;/code&gt; attribute).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The beauty of this flow? &lt;strong&gt;Your secret never touches your repository or your YAML file.&lt;/strong&gt; The pipeline simply requests access to the secret at the exact moment it needs it.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Bonus Pattern: Key Vault App References
&lt;/h2&gt;

&lt;p&gt;If you are deploying an Azure Web App, Function App, or Standard Logic App, ask yourself: &lt;em&gt;Does the deployment pipeline actually need to see this secret?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Usually, the answer is no. Instead of pulling the raw secret into your pipeline and injecting it into the app's configuration, you can use a &lt;strong&gt;Key Vault Reference&lt;/strong&gt; directly in your App Settings:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@Microsoft.KeyVault(VaultName=KV-demo1-dev;SecretName=MySecret)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This string is completely non-sensitive. It tells Azure App Service to fetch the real value at runtime using the application's own Managed Identity. Your pipeline configuration stays entirely clean, and if you rotate the secret in Key Vault, you just restart the app—no redeployments required!&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 3 Critical Gotchas to Avoid
&lt;/h2&gt;

&lt;p&gt;When setting this up for the first time, keep these common tripwires in mind:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Authentication ≠ Authorization (The 403 Error)
&lt;/h3&gt;

&lt;p&gt;Your service connection can be perfectly valid, and Azure DevOps will successfully log in. But if you haven't assigned the &lt;strong&gt;Key Vault Secrets User&lt;/strong&gt; role to that identity inside the Azure Portal, your pipeline will crash with a frustrating &lt;code&gt;403 Forbidden&lt;/code&gt; error. Make sure you handle both sides of the coin.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Secrets are Fetched at Queue Time
&lt;/h3&gt;

&lt;p&gt;Azure DevOps pulls your linked secrets the exact moment a run is queued, &lt;em&gt;not&lt;/em&gt; in the middle of a run. If you perform an emergency secret rotation in Key Vault while a pipeline is already running, that specific run will continue using the old credentials. The new value will only kick in on the next queued run.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. RBAC vs. Access Policies
&lt;/h3&gt;

&lt;p&gt;Microsoft strongly recommends using the &lt;strong&gt;Azure role-based access control (RBAC)&lt;/strong&gt; model for new vaults. If your vault is set to RBAC, adding an old-school "Access Policy" will do absolutely nothing—Azure will ignore it entirely. Check your vault's configuration blade to ensure your permission model matches your assignment method.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Separate secrets from configuration:&lt;/strong&gt; Your YAML should describe &lt;em&gt;what&lt;/em&gt; to deploy and &lt;em&gt;where&lt;/em&gt;, never the passwords that make it happen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand your identity model:&lt;/strong&gt; Always trace exactly which identity is trying to talk to your vault.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't forget network access:&lt;/strong&gt; Even with perfect IAM permissions, firewall rules or private endpoints can block your pipeline. Ensure your runner has network reachability to the vault!&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;If you found this breakdown helpful and want to see more real-world cloud architecture patterns without the fluff, consider &lt;a href="https://www.youtube.com/@MaximKhoruzhiy" rel="noopener noreferrer"&gt;subscribing to my YouTube channel&lt;/a&gt; where I drop tutorials like this regularly!&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@MaximKhoruzhiy" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi8g6b0l7ng3lto0o93vh.png" alt=" " width="332" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>devops</category>
      <category>security</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
