<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>cloudchristoph</title><description>Azure networking, built and run in the real world. Articles, talks and tools by Christoph Vollmann, Senior Cloud Architect and Microsoft MVP for Azure Networking.</description><link>https://cloudchristoph.com/</link><language>en</language><item><title>Apply Tenant Restrictions with Azure Firewall</title><link>https://cloudchristoph.com/articles/apply-tenant-restrictions-with-azure-firewall/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/apply-tenant-restrictions-with-azure-firewall/</guid><description>Use the Azure Firewall Header Insertion to secure your environment against accessing foreign tenants.</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Picture a perfectly normal day in an AVD environment. An external consultant (&lt;em&gt;cough&lt;/em&gt;) — someone from the systems integrator that supports your ERP, say — signs in to one of your session hosts to do exactly the work you hired them for. Their employer runs Microsoft 365 … like everybody else.&lt;/p&gt;
&lt;p&gt;So at some point they open the browser on the session host, go to OneDrive and sign in to their &lt;strong&gt;own company’s&lt;/strong&gt; OneDrive. Valid account, MFA passes, everything green. Now a foreign tenant’s OneDrive is open inside your corporate environment, one drag-and-drop away from your file shares.&lt;/p&gt;
&lt;p&gt;Nobody &lt;em&gt;attacked&lt;/em&gt; anything in that story, and that is exactly what makes it uncomfortable: it happens every day wherever external people work on internal machines. And often none of your controls reacted. Your Conditional Access policies never fired. Why? The consultant authenticated against their employer’s tenant, not yours, so there was nothing for your policies to evaluate. Your firewall saw an allowed HTTPS session to a Microsoft sign-in endpoint, which is exactly what it was.&lt;/p&gt;
&lt;p&gt;The same door is open for the less innocent variants: a private Microsoft account, or a throwaway free-trial tenant created purely as an exfiltration target. Same endpoints, same non-reaction.&lt;/p&gt;
&lt;p&gt;Microsoft Entra &lt;a href=&quot;https://learn.microsoft.com/en-us/entra/external-id/tenant-restrictions-v2&quot;&gt;Tenant restrictions v2 (TRv2)&lt;/a&gt; closes this. Entra itself refuses the sign-in when the target tenant isn’t on your allow list.
However, TRv2 is kind of “inactive” on its own: Client restrictions are enforced only when outbound login traffic is &lt;em&gt;marked&lt;/em&gt; with your policy from some system. Historically that “something” was Global Secure Access, a Windows GPO, or a TLS-terminating proxy you had to own and operate.&lt;/p&gt;
&lt;p&gt;Azure Firewall can now be that something: HTTP header insertion &lt;a href=&quot;https://azure.microsoft.com/en-us/updates/?id=568115&quot;&gt;went generally available at the end of July 2026&lt;/a&gt;. Application rules can add or overwrite request headers — on every SKU for plain HTTP, but only Premium can do it inside TLS-inspected HTTPS. Two constraints follow directly and shape everything below: the sign-in endpoints are of course HTTPS, so you need Azure Firewall Premium with TLS inspection, and header insertion exists only on application rules (because you know, that network rules never touch HTTP). This post is how I actually made it work, and everything that went wrong on the way.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Firewall: Azure Firewall Premium SKU,&lt;/li&gt;
&lt;li&gt;Licensing: Microsoft Entra ID P1 or P2,&lt;/li&gt;
&lt;li&gt;Entra Roles: At least the Security Administrator role to configure it.&lt;/li&gt;
&lt;li&gt;Azure RBAC: Contributor on the Firewall Policy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-the-network-path-when-you-dont-manage-the-devices&quot;&gt;Why the network path, when you don’t manage the devices&lt;/h2&gt;
&lt;p&gt;TRv2 has three enforcement paths, and they are different products with different coverage:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Covers&lt;/th&gt;
&lt;th&gt;Requires&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Universal tenant restrictions (Global Secure Access)&lt;/td&gt;
&lt;td&gt;Any device with the GSA client, on or off network&lt;/td&gt;
&lt;td&gt;Managed device, GSA client installed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows GPO (preview)&lt;/td&gt;
&lt;td&gt;Windows + Edge / Windows networking stack; auth &lt;strong&gt;and&lt;/strong&gt; data plane&lt;/td&gt;
&lt;td&gt;Domain- or Intune-managed Windows devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxy/firewall header injection&lt;/td&gt;
&lt;td&gt;Everything routed through that egress, any OS&lt;/td&gt;
&lt;td&gt;Central egress with TLS inspection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you manage the endpoints, use Global Secure Access. It’s per-device, works off-network, and involves no CA distribution. I’d reach for it first, and the Windows GPO path is the only one of the three that also protects the data plane.&lt;/p&gt;
&lt;p&gt;Neither of the other two paths can enforce anything on a machine you don’t manage. The firewall path doesn’t care. It enforces on the network, so every VM, container, appliance and BYO laptop behind that egress is covered whether it’s Windows, macOS or Linux, with nothing installed on it.&lt;/p&gt;
&lt;p&gt;The flip side is equally blunt: devices &lt;em&gt;not&lt;/em&gt; behind that egress are untouched — this is a control on a network path, not on an identity. Fine for AVD session hosts and cloud workloads, which never leave; useless for a roaming fleet.&lt;/p&gt;
&lt;h2 id=&quot;step-1-make-sure-the-policy-exist-in-entra-id&quot;&gt;Step 1: Make sure the policy exist in Entra ID&lt;/h2&gt;
&lt;h3 id=&quot;option-a-the-entra-admin-portal&quot;&gt;Option A: The Entra Admin Portal&lt;/h3&gt;
&lt;p&gt;In the Entra admin center: &lt;strong&gt;Entra ID &amp;gt; External Identities &amp;gt; Cross-tenant access settings &amp;gt; Default settings &amp;gt; Tenant restrictions &amp;gt; Edit tenant restrictions defaults&lt;/strong&gt;.
If no default policy exists yet, you can create the policy there. The pane then shows your &lt;strong&gt;Tenant ID&lt;/strong&gt; and a generated &lt;strong&gt;Policy ID&lt;/strong&gt; — you need both.&lt;/p&gt;
&lt;p&gt;Two tabs control what the policy does. &lt;strong&gt;External users and groups&lt;/strong&gt; sets Access status to Allow or Block for accounts from other tenants. &lt;strong&gt;External applications&lt;/strong&gt; does the same for apps, either all of them or a selected list of app IDs. The default policy always applies to all users in your tenant — you cannot scope it at the default level. And note the portal’s own warning: blocking all users also blocks all external applications, so the two tabs are not independent.&lt;/p&gt;
&lt;p&gt;Partners you want to keep working go under &lt;strong&gt;Organizational settings &amp;gt; Add organization&lt;/strong&gt;, by domain or tenant ID, each with its own allow rules. This is where the consultant from the intro belongs: allow-list their employer’s tenant here as a deliberate decision, instead of leaving every tenant in the world reachable by default. By the way … Consumer Microsoft accounts live in the well-known tenant &lt;code&gt;9188040d-6c67-4c5b-b112-36a304b66dad&lt;/code&gt; if you want to add those too.&lt;/p&gt;
&lt;h3 id=&quot;option-b-microsoft-graph&quot;&gt;Option B: Microsoft Graph&lt;/h3&gt;
&lt;p&gt;You can also query the Microsoft Graph for this. Ensure you have “Policy.ReadWrite.CrossTenantAccess” or “Policy.Read.All” permissions and send a GET request to:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;text&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://graph.microsoft.com/beta/policies/crossTenantAccessPolicy/default&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; field in the response &lt;em&gt;is&lt;/em&gt; the policy GUID. That’s the value people spend twenty minutes hunting for in the portal.&lt;/p&gt;
&lt;h2 id=&quot;step-2-inject-the-header-in-azure-firewall&quot;&gt;Step 2: Inject the header in Azure Firewall&lt;/h2&gt;
&lt;h3 id=&quot;the-header&quot;&gt;The header&lt;/h3&gt;
&lt;p&gt;This is the expected header:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;text&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;sec-Restrict-Tenant-Access-Policy: &amp;lt;your-tenant-id&amp;gt;:&amp;lt;your-policy-id&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It goes onto these four Microsoft sign-in domains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;login.live.com&lt;/li&gt;
&lt;li&gt;login.microsoft.com&lt;/li&gt;
&lt;li&gt;login.microsoftonline.com&lt;/li&gt;
&lt;li&gt;login.windows.net&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Microsoft &lt;a href=&quot;https://learn.microsoft.com/en-us/entra/external-id/tenant-restrictions-v2?utm_source=chatgpt.com#prerequisites:~:text=Microsoft%20supports%20the%20decryption%20of%20traffic%20for%20those%20sign%2Din%20domains%20for%20the%20purpose%20of%20header%20insertion%20for%20tenant%20restrictions.%20This%20decryption%20is%20a%20valid%20exception%20to%20the%20policies%20at%20Use%20third%2Dparty%20network%20devices%20or%20solutions%20with%20Microsoft%20365.&quot;&gt;explicitly sanctions TLS decryption of those four domains&lt;/a&gt; for this purpose. That’s a narrow exception to the general “don’t break-and-inspect Microsoft 365” guidance. Do not inspect Microsoft 365 traffic broadly.&lt;/p&gt;
&lt;h3 id=&quot;the-rule&quot;&gt;The rule&lt;/h3&gt;
&lt;p&gt;You can configure it using the portal. Just edit your Firewall Policy and add a new application rule.&lt;/p&gt;
&lt;aside class=&quot;callout is-tip&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; class=&quot;callout-icon&quot; width=&quot;24&quot; height=&quot;24&quot;&gt;&lt;path d=&quot;M9 18h6&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M10 22h4&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M12 2a7 7 0 0 0-4 12.7V16h8v-1.3A7 7 0 0 0 12 2z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;div class=&quot;callout-body&quot;&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Make sure there isn’t a Network Rule that’s already intercepting this traffic, since network rules are &lt;strong&gt;evaluated before application rules.&lt;/strong&gt; In my test environment, a broad network rule that allowed traffic on port :433 disrupted my plans at first.&lt;/p&gt;
&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;In the App Rule configure your source and then:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Destination Type: FQDN&lt;/li&gt;
&lt;li&gt;Target FQDNs: login.live.com,login.microsoft.com,login.microsoftonline.com,login.windows.net&lt;/li&gt;
&lt;li&gt;Enable TLS Inspection&lt;/li&gt;
&lt;li&gt;Protocol: Https:443&lt;/li&gt;
&lt;li&gt;In the HTTP Header Insertion add &lt;code&gt;sec-Restrict-Tenant-Access-Policy&lt;/code&gt; with the value &lt;code&gt;&amp;lt;your-tenant-id&amp;gt;:&amp;lt;your-policy-id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;Azure portal, Edit application rules: destination type FQDN, the four Microsoft sign-in FQDNs as targets, TLS inspection enabled, protocol Https:443 and an HTTP header insertion for sec-Restrict-Tenant-Access-Policy, marked 1 to 5&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1136px) 1136px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1136&quot; height=&quot;1754&quot; src=&quot;https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_Z1bKLIN.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_SV4M6.webp 640w, https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_Z15qdP9.webp 750w, https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_Ze19B7.webp 828w, https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_ZQ2NxU.webp 1080w, https://cloudchristoph.com/_astro/app-rule-header-insertion.DDJTbhEj_Z1bKLIN.webp 1136w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Or configure it using IaC (my preferred and recommended way!). Here is a Terraform snippet for your Application Rule Collection Group. Adapt to your needs:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#8577A7;font-style:italic&quot;&gt;# inside azurerm_firewall_policy_rule_collection_group&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;application_rule&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;allow-entra-signin&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  source_addresses&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;10.2.3.0/24&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  destination_fqdns&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;login.live.com&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;login.microsoft.com&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;login.microsoftonline.com&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;login.windows.net&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  terminate_tls&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  protocols&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Https&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    port&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 443&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  http_headers&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;sec-Restrict-Tenant-Access-Policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    value&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;tenant_id&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;trv2_policy_id&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Do not copy Microsoft’s own header-insertion how-to here.&lt;/strong&gt; That article uses tenant restrictions as its worked example, and the example still shows the &lt;strong&gt;v1&lt;/strong&gt; headers: &lt;code&gt;Restrict-Access-To-Tenants&lt;/code&gt; and &lt;code&gt;Restrict-Access-Context&lt;/code&gt;. Follow it and you’ll build a legacy TRv1 setup with a tenant allow-list crammed into a header value.
TRv2 replaces all three v1 headers — including &lt;code&gt;sec-Restrict-Tenant-Access-Policy: restrict-msa&lt;/code&gt; for &lt;code&gt;login.live.com&lt;/code&gt; — with the single policy reference above. If you’re migrating, please remove the old ones. Because leaving both in place causes conflicts.&lt;/p&gt;
&lt;h2 id=&quot;step-3-prove-it-actually-works&quot;&gt;Step 3: Prove it actually works&lt;/h2&gt;
&lt;p&gt;Three checks, in order, because each one rules out a different failure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is TLS interception happening?&lt;/strong&gt; From a VM behind the firewall you can use a command prompt (Linux or WSL):&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bash&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;openssl&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; s_client&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; -connect&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; postman-echo.com:443&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It should show you something like this:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;text&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 0 s:CN = Azure Firewall Manager CA, CN = postman-echo.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 1 s:CN = Azure Firewall Manager CA&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; 2 s:O = Contoso Lab, CN = Contoso Firewall Intermediate CA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Is the firewall actually inspecting?&lt;/strong&gt; Check the log:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;kql&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;kusto&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;AZFWApplicationRule&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; TimeGenerated &amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;ago&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;15m&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; Fqdn &lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;has&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;login.&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;project&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; TimeGenerated, SourceIp, Fqdn, Action, Rule, IsTlsInspected, TargetUrl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;IsTlsInspected&lt;/code&gt; is the column that matters. It is entirely possible to have &lt;code&gt;Action = Allow&lt;/code&gt;, the correct rule matched, &lt;code&gt;provisioningState = Succeeded&lt;/code&gt; on every resource — and &lt;code&gt;IsTlsInspected = False&lt;/code&gt;. In that state the rule works, the traffic flows, the user is happy, and no header is being inserted at all. The control is off and nothing tells you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The end-to-end test.&lt;/strong&gt; From behind the firewall, sign in against a tenant that isn’t allow-listed — in the intro scenario, that would be the consultant opening their employer’s OneDrive on your session host. The error that is shown is:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;text&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Access is blocked&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;The Contoso IT department has restricted which organizations can be accessed.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in the Troubleshooting Details (or in PowerShell or Az CLI) you’ll find the message:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;text&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;AADSTS5000211: A tenant restrictions policy added to this request by a device or&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;network administrator does not allow access to &apos;tenant name&apos;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;Microsoft sign-in page saying “Access is blocked”: the CloudChristoph IT department has restricted which organizations can be accessed. The troubleshooting details show error AADSTS500211, a tenant restrictions policy added by a network administrator&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1500px) 1500px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1500&quot; height=&quot;1440&quot; src=&quot;https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_ZWhDHE.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_203c8q.webp 640w, https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_Z2kqh2a.webp 750w, https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_2q8bCg.webp 828w, https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_Z1TVt5v.webp 1080w, https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_Z2g8TLl.webp 1280w, https://cloudchristoph.com/_astro/access-blocked-message.BOUTlPVK_ZWhDHE.webp 1500w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-could-go-wrong&quot;&gt;What could go wrong&lt;/h2&gt;
&lt;p&gt;(Everything that can go wrong with the TLS inspection setup itself — Key Vault permissions, certificate rotation, client trust — I think this deserves a separate post 😉. Here I’ll stick to what’s specific to this.)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;QUIC bypasses inspection entirely.&lt;/strong&gt; Azure Firewall does no FQDN, URL or TLS inspection for QUIC on UDP 80/443. If you never allowed UDP 443 outbound, browsers fall back to TCP and this is a non-issue. If you did allow it in a network rule, you’ve built a bypass around your own control.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scope.&lt;/strong&gt; This is authentication-plane protection only. It does not stop anonymous access to Teams meetings, SharePoint links or Forms — that needs Global Secure Access or the Windows GPO path. It is not DLP: a user already signed in to &lt;em&gt;your&lt;/em&gt; tenant can still move data wherever they’re permitted to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Logs never show the header.&lt;/strong&gt; &lt;code&gt;AZFWApplicationRule&lt;/code&gt; has no column for inserted header names or values. You get &lt;code&gt;IsTlsInspected&lt;/code&gt;, the matched rule, and &lt;code&gt;TargetUrl&lt;/code&gt;. If you want proof that enforcement happened, it’s in the Entra sign-in logs.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is the right tool when you have a central egress that all the relevant VMs/systems already traverse, and you cannot install anything on those.
AVD estates, jump hosts, build agents, appliances. In that shape it’s the only one of the three TRv2 paths that can enforce anything at all.
The consultant from the intro either gets blocked at sign-in, or their employer’s tenant is on your allow list because you put it there. And this is a informed decision you made and not a gap you simply didn’t know about.&lt;/p&gt;
&lt;p&gt;It’s the wrong tool if your fleet is managed. Global Secure Access gives you the same authentication-plane outcome per device, and also works when people are at home or on the road.&lt;/p&gt;
&lt;p&gt;Hope it helps!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/updates/?id=568115&quot;&gt;Generally Available: HTTP header insertion in Azure Firewall&lt;/a&gt; (Azure update, July 2026)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/entra/external-id/tenant-restrictions-v2&quot;&gt;Set up tenant restrictions v2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/azure/firewall/configure-http-header-insertion&quot;&gt;Configure HTTP header insertion in Azure Firewall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/azure/firewall/premium-certificates&quot;&gt;Azure Firewall Premium certificates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learn.microsoft.com/azure/azure-monitor/reference/tables/azfwapplicationrule&quot;&gt;AZFWApplicationRule table reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>Networking</category></item><item><title>Hub-Deployment mit Azure Verified Modules</title><link>https://cloudchristoph.com/articles/hub-deployment-mit-azure-verified-modules/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/hub-deployment-mit-azure-verified-modules/</guid><description>Ein Hub-and-Spoke-Netzwerk in Azure mit einem AVM-Pattern-Modul aufbauen: Adressplanung, Firewall Policy und Firewall-Regeln Schritt für Schritt.</description><pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Azure Verified Modules (AVM) haben in der letzten Zeit an Bedeutung gewonnen und sind seit einiger Zeit mein präferierter Ansatz für Infrastructure-as-Code Implementierungen. In diesem Beitrag zeige ich euch, wie ihr mit AVM ein Hub-and-Spoke Netzwerk in Azure aufbauen könnt. Dabei verwende ich ein AVM Pattern-Modul, um eine oft genutzte Konfiguration zu demonstrieren.&lt;/p&gt;
&lt;h2 id=&quot;auf-github-verfügbar&quot;&gt;Auf GitHub verfügbar&lt;/h2&gt;
&lt;p&gt;Den vollständigen Code für dieses Beispiel findet ihr in meinem GitHub Repository:
&lt;a href=&quot;https://github.com/cloudchristoph/lab-connectivity-hub-with-avm&quot;&gt;https://github.com/cloudchristoph/lab-connectivity-hub-with-avm&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;was-ist-avm-was-ist-ein-pattern-modul&quot;&gt;Was ist AVM? Was ist ein Pattern-Modul?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://aka.ms/avm&quot;&gt;Azure Verified Modules (AVM)&lt;/a&gt; sind von Microsoft unterstützte und empfohlene Terraform- oder Bicep-Module, die Best Practices für die Bereitstellung von Azure-Ressourcen implementieren. Sie bieten vor allem eine standardisierte und getestete Implementierung für häufig verwendete Funktionalitäten, wie Diagnostics Settings, Tags, Private Link, etc.&lt;/p&gt;
&lt;p&gt;Ein Pattern-Modul ist eine spezielle Art von AVM, die ein komplettes Architektur- oder Designmuster implementiert. Es enthält nicht nur die Ressourcen, sondern auch die Logik und Konfiguration, um ein bestimmtes Szenario oder Muster in Azure umzusetzen. In diesem Fall implementiert das Pattern-Modul &lt;a href=&quot;https://registry.terraform.io/modules/Azure/avm-ptn-alz-connectivity-hub-and-spoke-vnet/azurerm/latest&quot;&gt;&lt;code&gt;avm-ptn-alz-connectivity-hub-and-spoke-vnet&lt;/code&gt;&lt;/a&gt; das Hub-and-Spoke Netzwerkdesign, das häufig in Azure-Umgebungen verwendet wird.&lt;/p&gt;
&lt;h2 id=&quot;warum-avm-für-hub-and-spoke&quot;&gt;Warum AVM für Hub-and-Spoke?&lt;/h2&gt;
&lt;p&gt;Bisher hatten wir verschiedenste Möglichkeiten, ein Hub-and-Spoke Netzwerk in Azure zu implementieren, sei es durch eigene Terraform- oder Bicep-Module oder auch das altbekannte &lt;code&gt;terraform-azurerm-caf-enterprise-scale&lt;/code&gt; Modul. Dieses Modul war sehr mächtig und hat versucht quasi alles abzudecken - von Netzwerk, über Management Strukturen bis hin zu Policies. Dieser All-in-one-Ansatz hatte jedoch den Nachteil, dass er oft zu komplex und schwergewichtig war. Man war quasi gezwungen, das Modul mehrfach mit verschiedenen Parametern zu verwenden um nicht einen monolithischen Aufruf in seinen IaC Code zu haben.&lt;/p&gt;
&lt;p&gt;Der neue Ansatz mit AVM ermöglicht uns es jetzt die einzelnen Komponenten des Hub-and-Spoke Designs modular und flexibel zu implementieren. Die &lt;a href=&quot;https://azure.github.io/Azure-Verified-Modules/indexes/terraform/tf-pattern-modules/&quot;&gt;Pattern-Module&lt;/a&gt; wiederrum bündeln jetzt einzelne Themenbereiche und verwenden dabei die AVM Module als Bausteine.
In unserem Beispiel beschäftigen wir uns jetzt mit dem Connectivity-Stack, aber in einer realen Umgebung kommen noch weitere Module wie das `avm-ptn-alz’ dazu. Dieses kümmert sich dann um Management-Struktur und Policies.&lt;/p&gt;
&lt;h2 id=&quot;wie-fangen-wir-an&quot;&gt;Wie fangen wir an?&lt;/h2&gt;
&lt;p&gt;Mit Planung. Klar! Der erste Schritt ist die Zielarchitektur zu definieren. In unserem Fall wollen wir einen vollständigen Connectivity-Stack in der Region &lt;code&gt;germanywestcentral&lt;/code&gt; aufbauen, der als zentrale Plattform für Hub-and-Spoke dient.&lt;/p&gt;
&lt;h3 id=&quot;komponenten-der-zielarchitektur&quot;&gt;Komponenten der Zielarchitektur&lt;/h3&gt;
&lt;p&gt;Wir benötigen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ein Hub-VNet mit den entsprechenden Subnetzen für Firewall + Management, VPN Gateway und Bastion Host&lt;/li&gt;
&lt;li&gt;Eine Azure Firewall Standard&lt;/li&gt;
&lt;li&gt;Ein VPN Gateway für die Verbindung zum On-Premises Netzwerk&lt;/li&gt;
&lt;li&gt;Routing, um den Traffic über die Firewall zu leiten&lt;/li&gt;
&lt;li&gt;Logging, um die Aktivitäten der Firewall zu überwachen&lt;/li&gt;
&lt;li&gt;Ein Bastion Host für den Zugriff auf alle Ressourcen in den Spokes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Zusätzlich stellen wir uns die Frage nach dem Lebenszyklus der Ressourcen.
Beispielsweise gehe ich davon aus, dass Firewall-Regeln wesentlich häufiger angepasst werden als die Firewall selbst. Daher könnte es Sinn ergeben, die Basis-Komponenten wie Firewall/VPN/Bastion/Netz in einem eigenen Terraform-Projekt zu verwalten, während die Regeln in einem separaten Projekt liegen.&lt;/p&gt;
&lt;p&gt;Das ist aber natürlich abhängig von der individuellen Umgebung und den Anforderungen.&lt;/p&gt;
&lt;h3 id=&quot;datei-struktur&quot;&gt;Datei-Struktur&lt;/h3&gt;
&lt;p&gt;Unser Code-Beispiel verzichtet auf die Trennung in mehrere Projekte, damit ihr den Code in einem GitHub-Repository einfacher nachvollziehen könnt.
Wir “simulieren” die Trennung der Projekte hier durch simple Ordner-Struktur.&lt;/p&gt;
&lt;h2 id=&quot;aufbau-des-hub-deployments&quot;&gt;Aufbau des Hub-Deployments&lt;/h2&gt;
&lt;h3 id=&quot;schritt-1-modul-einbinden-und-grundsätzliche-konfiguration&quot;&gt;Schritt 1: Modul einbinden und grundsätzliche Konfiguration&lt;/h3&gt;
&lt;p&gt;Zunächst binden wir das Pattern-Modul &lt;code&gt;avm-ptn-alz-connectivity-hub-and-spoke-vnet&lt;/code&gt; in unserem &lt;code&gt;main.tf&lt;/code&gt; ein und bauen uns eine passende Resource Group.&lt;/p&gt;
&lt;p&gt;Am Modul konfigureren wir im ersten Schritt, welche Ressourcen wir überhaupt bereitstellen wollen. &lt;em&gt;Wie&lt;/em&gt; diese Ressourcen konfiguriert werden, also z.B. die Adressbereiche, die Firewall- und VPN-Einstellungen, etc. wird in den nächsten Schritten angepasst.&lt;/p&gt;
&lt;p&gt;Das Modul erlaubt es, mehrere Hubs gleichzeitig bereitzustellen.
Deshalb können wir einerseits die auszurollenden Ressourcen global angeben und andererseits pro Hub anpassen. In diesem Beispiel verwenden wir die globale Konfiguration, um DDoS Protection Pläne zu deaktivieren und die Hub-spezifische Konfiguration, um Firewall, VPN Gateway und Bastion Host zu aktivieren.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;connectivity&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  source&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Azure/avm-ptn-alz-connectivity-hub-and-spoke-vnet/azurerm&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  version&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;0.16.13&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  hub_and_spoke_networks_settings&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    enabled_resources&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      ddos_protection_plan&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  hub_virtual_networks&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;germanywestcentral&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      default_parent_id&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; azurerm_resource_group.hub.id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      enabled_resources&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        firewall&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                              =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        firewall_policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                       =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        virtual_network_gateway_vpn&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;           =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        virtual_network_gateway_express_route&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        bastion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                               =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        private_dns_zones&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                     =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        private_dns_resolver&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                  =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;azurerm_resource_group&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;hub&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rg-hub-network-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;germanywestcentral&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;schritt-2-ip-addressplanung&quot;&gt;Schritt 2: IP-Addressplanung&lt;/h3&gt;
&lt;p&gt;An sich müssten wir keine IP-Adressbereiche angeben, da das Modul automatisch Adressbereiche für die Firewall, VPN Gateway, etc. generiert. Es ist aber natürlich sinnvoll, die Adressplanung selbst in der Hand zu haben und nicht dem Modul zu überlassen. Zumal das Modul &lt;code&gt;10.0.0.0/22&lt;/code&gt; als Hub-Adressraum nutzen möchte. Das ist für einen Test okay, aber meistens nicht für produktive Umgebungen geeignet (weil bereits besetzt) und ich die Größe auch für etwas übertriebe groß halte (/22 sind rund 1000 nutzbare Adressen).&lt;/p&gt;
&lt;p&gt;Wir planen für unsere Hub-Umgebung den Adressraum &lt;code&gt;10.20.0.0/23&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tipp:&lt;/strong&gt; Zur Addressplanung nutze ich das wunderbare Tool &lt;a href=&quot;https://visualsubnetcalc.com/&quot;&gt;Visual Subnet Calculator&lt;/a&gt;. Unsere Planung mit Aufteilung der Subnetze könnt ihr hier sehen: &lt;a href=&quot;https://visualsubnetcalc.com/index.html?c=1N4IgbiBcIEwgNCARlEBGADAOhtvB6GAZgRAFtUBBALQFUAlAUVIGcpQMA7dkDAex4YADoICOPbtEoAvAK4AnAKYAxAJZKA7gEMANjoDKspJ0UAXUgGNUAYgBmtrQBMnIAL6I04yKEkgZClXVFbT0AWS1OLQBzRTJFTlNDYzNLG3snF1d3dBFvLI8Bb1hc4GyiEpAANi8fKjklACEtFlNVPk4kk3NEK2hrLQwLABZ7N0QAdhqQXwBxLVNgrQBPTpSemwBOJFtK0az91yA&quot;&gt;Hub-Subnetze auf Visual Subnet Calculator&lt;/a&gt;. Ich stelle gerne die Firewall vorne in’s Netzwerk und Gateway ganz hinten in das Netzwerk.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wie bilden wir die Subnetze?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In Terraform nutze ich dafür die Funktion &lt;a href=&quot;https://developer.hashicorp.com/terraform/language/functions/cidrsubnet&quot;&gt;&lt;code&gt;cidrsubnet()&lt;/code&gt;&lt;/a&gt;, um aus dem Hub-Adressraum konsistent Subnetze für Firewall, Firewall Management, VPN Gateway und Bastion Host zu generieren. So vermeide ich manuelle Fehler bei der Subnetzplanung und kann für weitere Hubs einfach einen neuen Adressraum definieren und die Subnetze errechnen sich automatisch.&lt;/p&gt;
&lt;p&gt;Die Funktion ist etwas tricky zu verstehen (finde ich). Der erste Parameter ist der Adressraum - klar, der zweite Parameter gibt an, wie viele zusätzliche Bits angefügt werden sollen (bei uns /23 + 3 = /26) und der dritte Parameter ist die Nummer des Subnetzes, das generiert werden soll - beginned bei 0 (bei uns bspw. für Bastion das siebente /26 Subnetz aus /23 = 10.20.1.128/26).&lt;/p&gt;
&lt;p&gt;Um die Übersicht zu behalten, definiere ich die Adressräume für Hub und Subnetze als &lt;code&gt;locals&lt;/code&gt; und nutze diese dann in der Modul-Konfiguration.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;locals&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  hub_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;10.20.0.0/23&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_firewall_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;            =&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt; cidrsubnet&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;hub_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_firewall_management_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt; cidrsubnet&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;hub_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_bastion_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt; cidrsubnet&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;hub_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_gateway_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt; cidrsubnet&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;hub_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 7&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Über den Parameter &lt;code&gt;hub_virtual_network&lt;/code&gt; und den Unter-Parameter &lt;code&gt;address_space&lt;/code&gt;  können wir diesen Adressraum angeben und dann für unsere Komponenten die Subnetze definieren. Diese folgen immer dem gleichen Muster. Komponententyp als Parameter und &lt;code&gt;subnet_address_prefix&lt;/code&gt; als Unter-Parameter. Die Azure Firewall bekommt zwei Subnetze, eines für die Firewall selbst und eines für das Management-Interface. Ich empfehle euch sehr, neue Firewall-Deployments mit Management Subnetz zu planen, selbst wenn dies noch nicht verpflichtend ist. Das lohnt sich in Zukunft!&lt;/p&gt;
&lt;p&gt;Im Code nutzen wir dann diese locals.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;hub_virtual_networks&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;germanywestcentral&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    default_parent_id&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; azurerm_resource_group.hub.id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    enabled_resources&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      firewall&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                              =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      firewall_policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                       =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      virtual_network_gateway_vpn&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;           =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      virtual_network_gateway_express_route&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      bastion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                               =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      private_dns_zones&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                     =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      private_dns_resolver&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                  =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    hub_virtual_network&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      address_space&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; [local.hub_address_prefix]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    firewall&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;            =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_firewall_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      management_subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_firewall_management_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    virtual_network_gateways&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_gateway_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    bastion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_bastion_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;schritt-3-ausgestaltung-unserer-komponenten&quot;&gt;Schritt 3: Ausgestaltung unserer Komponenten&lt;/h3&gt;
&lt;p&gt;Nachdem wir die grundlegende Struktur unseres Hubs definiert haben, können wir jetzt die einzelnen Komponenten weiter konfigurieren.
Wir werden eine Azure Firewall Standard bereistellen, ein zonen-redundantes VPN Gateway kleinerer Größe und für den Bastion Host aktivieren wir uns noch ein paar gute Funktionen.&lt;/p&gt;
&lt;p&gt;Unser Firewall-Parameterblock wird jetzt so aussehen:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;firewall&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;            =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_firewall_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  management_subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_firewall_management_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  sku_name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                         =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;AZFW_VNet&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  sku_tier&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                         =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Standard&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  management_ip_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;            =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Für das VPN Gateway wählen wir die SKU &lt;code&gt;VpnGw1AZ&lt;/code&gt;. Wir können hier auch gleich einen Tunnel konfigurieren und damit sofort die Verbindung zum On-Premises Netzwerk herstellen - es sprengt nur unser Beispiel. Dinge, wie die Erstellung einer Route Table für das GatewaySubnet steuern wir ebenfalls direkt in der Config.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;virtual_network_gateways&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                      =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_gateway_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  route_table_creation_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;               =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  route_table_gateway_firewall_route_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  vpn&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    sku&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;VpnGw1AZ&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    vpn_bgp_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Für unseren Bastion Host aktivieren wir einige Funktionen, die das Leben erleichtern.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;bastion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  subnet_address_prefix&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; local.subnet_bastion_prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  zones&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                 =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  bastion_public_ip&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    zones&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  file_copy_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  copy_paste_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  ip_connect_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  tunneling_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  shareable_link_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;schritt-4-firewall-policy-in-anderer-resource-group&quot;&gt;Schritt 4: Firewall Policy in anderer Resource Group&lt;/h3&gt;
&lt;p&gt;Die Firewall Policy wird in einer eigenen Resource Group bereitgestellt. Wir haben ja am Anfang definiert, dass die Policy einem anderen Lebenszyklus unterliegen könnte als die Firewall selbst.
Auch dies können wir einfach über die Parameter steuern.&lt;/p&gt;
&lt;p&gt;DNS Proxy Funktionalität schalten wir hier direkt mit ein, damit die Firewall auch in Netzwerk-Regeln / Layer 3 mit FQDNs umgehen kann.&lt;/p&gt;
&lt;p&gt;Der Firewall-Policy Parameterblock sieht dann so aus:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;firewall_policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  resource_group_name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; azurerm_resource_group.firewall_policy.name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  dns&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    proxy_enabled&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    servers&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Die Resource Group für die Firewall Policy definieren wir weiter unten im Code:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;azurerm_resource_group&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;firewall_policy&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rg-hub-firewallpolicy-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;germanywestcentral&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Huch. Was haben wir denn hier?! Ein Osterei.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Merkt euch die Farbe für euren &lt;a href=&quot;https://www.mvptreff.de/beitraege-aus-der-community/&quot;&gt;Eggs of Knowledge&lt;/a&gt; Preis.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Violettes Osterei mit einem weißen Netz aus Punkten, Linien, Wolken und Server-Symbolen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 512px) 512px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;512&quot; height=&quot;512&quot; src=&quot;https://cloudchristoph.com/_astro/egg-of-knowledge.DNdWAqxU_Z2hB4Ed.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/egg-of-knowledge.DNdWAqxU_Z2hB4Ed.webp 512w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;firewall-regeln&quot;&gt;Firewall-Regeln&lt;/h2&gt;
&lt;p&gt;Die Firewall-Regeln werden nicht über das Pattern-Modul konfiguriert, sondern über ein separates Projekt (oder simpler in unserem Beispiel als separater Ordner). Das hat den Vorteil, dass wir die Regeln unabhängig von der Firewall selbst anpassen können, ohne Gefahr zu laufen, die Firewall oder andere Ressourcen zu verändern.&lt;/p&gt;
&lt;h3 id=&quot;schritt-1-firewall-policy-data-source&quot;&gt;Schritt 1: Firewall Policy Data Source&lt;/h3&gt;
&lt;p&gt;Zunächst müssen wir die Firewall Policy, die wir im Hub-Deployment erstellt haben, in unserem Firewall-Regel-Projekt referenzieren. Dafür gibt es zwei Möglichkeiten - entweder direkt die Resource ID als Variable übergeben oder die Firewall Policy über eine Data Source referenzieren.&lt;/p&gt;
&lt;p&gt;In diesem Fall halte ich eine Data Source für sinnvoll.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;azurerm_firewall_policy&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;hub_fw_policy&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;fwp-hub-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  resource_group_name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rg-hub-firewallpolicy-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;schritt-2-firewall-regeln-definieren&quot;&gt;Schritt 2: Firewall-Regeln definieren&lt;/h3&gt;
&lt;p&gt;Für unser Beispiel habe ich uns ein paar einfache Network und Application Rules überlegt und diese auch mit IP Groups umgsetzt.
Schaut euch gerne den Code im GitHub Repository an, um die vollständige Konfiguration zu sehen. Hier zeige ich euch exemplarisch, wie eine einfache Network Rule Collection definiert wird.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;terraform&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;azurerm_firewall_policy_rule_collection_group&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt; &quot;example&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rcg-hub-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  firewall_policy_id&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;azurerm_firewall_policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;hub_fw_policy&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  priority&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;            =&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    rule_collections&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rc-hub-gwc&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        action&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;   =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Allow&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        rules&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;                  =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Allow-OnPrem-Server&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        rule_type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;NetworkRule&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        source_addresses&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        destination_addresses&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;10.1.0.0/23&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        destination_ports&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;3389&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;        protocols&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;             =&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;TCP&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;weitere-gedanken-und-tipps&quot;&gt;Weitere Gedanken und Tipps&lt;/h2&gt;
&lt;p&gt;Das Pattern-Modul ist meines Erachtens noch nicht vollständig ausgereift, aber es bietet schon jetzt eine solide Grundlage für die Bereitstellung eines Hub-and-Spoke Netzwerks in Azure.&lt;/p&gt;
&lt;p&gt;Bspw. fehlt mir momentan noch ein guter Weg, um die Diagnostics Settings für die Firewall zu konfigurieren. Im Beispiel-Repository hab ich zusätzlich noch &lt;code&gt;main.firewalldiagnostics.tf&lt;/code&gt; angelegt, um die Diagnostics Settings für die Firewall zu konfigurieren.&lt;/p&gt;
&lt;p&gt;Auch bin ich über seltene Rand-Konfigurationen gestolpert, die bisher noch nicht mit dem Modul abgebildet werden können. Beispielsweise ein Active-Active VPN Gateway mit zusätzlicher P2S VPN Konfiguration.&lt;/p&gt;
&lt;h2 id=&quot;ausgerollte-umgebung&quot;&gt;Ausgerollte Umgebung&lt;/h2&gt;
&lt;p&gt;Nach der Bereitstellung unserer Hub-Umgebung können wir uns - dieses mal mit Hilfe von AI - ein Diagramm der ausgerollten Ressourcen generieren lassen. Das sieht dann für unsere Umgebung so aus:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Architektur-Zeichnung der ausgerollten Umgebung&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1824px) 1824px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1824&quot; height=&quot;1131&quot; src=&quot;https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_Z2jfppr.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_95c4D.webp 640w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_wGfhl.webp 750w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_Z17JpCx.webp 828w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_WSPgd.webp 1080w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_1tIDXH.webp 1280w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_54d6T.webp 1668w, https://cloudchristoph.com/_astro/hub-architecture.CCA62eHw_Z2jfppr.webp 1824w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ich experimentiere noch ein wenig mit den Skills und MCP-Servern. Wahrscheinlich gibts hier noch ein paar Updates über die nächsten Tage.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;AVM und die Pattern-Module bieten eine moderne und flexible Möglichkeit, Azure-Infrastruktur zu implementieren. Sie ermöglichen es uns, Best Practices zu nutzen und gleichzeitig die Kontrolle über die Konfiguration zu behalten. Das Hub-and-Spoke Pattern-Modul ist ein großartiges Beispiel dafür, wie wir komplexe Netzwerkarchitekturen in Azure mit AVM umsetzen können.&lt;/p&gt;
&lt;h2 id=&quot;eggs-of-knowledge&quot;&gt;Eggs of Knowledge&lt;/h2&gt;
&lt;p&gt;Dieser Beitrag ist Teil der “Eggs of Knowledge” Serie des MVP-Treffs.
Schaut gerne auf der Webseite vorbei, um weitere spannende Beiträge zu entdecken: &lt;a href=&quot;https://www.mvptreff.de/beitraege-aus-der-community/&quot;&gt;https://www.mvptreff.de/beitraege-aus-der-community/&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>Infrastructure as Code</category></item><item><title>Santa Claus&apos; Cloud-Powered Christmas: Optimizing Deliveries with Azure Multi-Hub Deployments 🎅🎄🎁</title><link>https://cloudchristoph.com/articles/azure-multi-hub-for-santa/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/azure-multi-hub-for-santa/</guid><description>Festive Tech Calendar 2024: connecting regional Azure hubs in a full mesh while keeping spokes isolated, with careful IP planning and simple route tables.</description><pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This post is part of the Festive Tech Calendar 2024 - organized by the &lt;a href=&quot;https://cloudfamily.info/&quot;&gt;CloudFamily&lt;/a&gt;. Find all speakers and sessions on the &lt;a href=&quot;https://festivetechcalendar.com/&quot;&gt;Festive Tech Calendar website&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;This year we are &lt;strong&gt;raising money for the &lt;a href=&quot;https://www.beatsoncancercharity.org/&quot;&gt;Beatson Cancer Charity&lt;/a&gt; and appreciate any contribution.&lt;/strong&gt; Go to the &lt;a href=&quot;https://www.justgiving.com/page/festive-tech-calendar-2024&quot;&gt;Just Giving Page&lt;/a&gt; to find out more. Thanks!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Festive Tech Calendar 2024 banner with Christmas baubles, snowflakes, trees and a snowman&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 699px) 699px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;699&quot; height=&quot;400&quot; src=&quot;https://cloudchristoph.com/_astro/festive-tech-calendar-banner.oWCjRSPv_Z1iXi3R.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/festive-tech-calendar-banner.oWCjRSPv_Z1NscUr.webp 640w, https://cloudchristoph.com/_astro/festive-tech-calendar-banner.oWCjRSPv_Z1iXi3R.webp 699w&quot;&gt;&lt;/p&gt;
&lt;p&gt;As the holiday season approaches, Santa Claus faces the challenge of delivering millions of gifts worldwide in a single night.&lt;/p&gt;
&lt;p&gt;To achieve this feat efficiently, Santa’s North Pole IT team has turned to modern cloud infrastructure — specifically, an Azure Multi-Hub Deployment — to optimize his global delivery network. But not only our beloved Santa faces this…&lt;/p&gt;
&lt;h2 id=&quot;the-challenge&quot;&gt;The Challenge&lt;/h2&gt;
&lt;p&gt;Azure provides the ability to deploy workloads in multiple regions. This is essential not only to be closer to end customers but also to guarantee resilience. What if an Azure region goes down—how long can we afford such downtime before it seriously impacts our business?&lt;/p&gt;
&lt;p&gt;If customers or business locations are spread across the globe, it is crucial to ensure that necessary applications and services are deployed close to these customers (Remember: Santa has a global clientele, who would be sad if the gifts arrived too late). This improves both performance and user experience.&lt;/p&gt;
&lt;p&gt;But how do we achieve this in Azure?&lt;/p&gt;
&lt;h2 id=&quot;hub-and-spoke-in-a-single-region&quot;&gt;Hub-and-Spoke in a single region&lt;/h2&gt;
&lt;p&gt;A common approach is the hub-and-spoke architecture, which is well-understood. A central hub network contains key components for communication and securing workloads through a central firewall. Each workload (spoke) is connected only to the hub, ensuring clear separation of workloads, as well as centralized monitoring and security.&lt;/p&gt;
&lt;p&gt;An alternative, full-mesh networking, where every workload is connected to every other workload, is generally discouraged as it leads to a complex and hard-to-manage network structure.&lt;/p&gt;
&lt;p&gt;So far, so good. Let’s scale.&lt;/p&gt;
&lt;h2 id=&quot;hub-and-spoke-across-multiple-regions&quot;&gt;Hub-and-Spoke across multiple regions&lt;/h2&gt;
&lt;p&gt;What if we operate in multiple regions? It makes sense to retain the hub-and-spoke model in these regions, with each region having its own hub network connected to its respective spoke networks. But how do we connect the hubs across regions, ensuring communication between workloads in different regions?&lt;/p&gt;
&lt;h2 id=&quot;enter-full-mesh-networking---but-for-the-right-purpose&quot;&gt;Enter Full-Mesh networking - but for the right purpose&lt;/h2&gt;
&lt;p&gt;While we avoid the full-mesh model within a single region, it is beneficial to connect all hub networks across regions. This enables fast communication between workloads in different regions. However, we still avoid direct connectivity between all workloads. We aim to maintain workload segregation and centralized monitoring.&lt;/p&gt;
&lt;p&gt;In short: Use a full-mesh model for hub networks and a hub-and-spoke model for spoke networks.&lt;/p&gt;
&lt;p&gt;Let’s have a look at a fully deployed Multi-Hub environment (Simplified illustration):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Full mesh of five regional hubs (EUS, WEU, GWC, EAS, IND), each with its own /24 range and firewalls, globally peered with each other; spokes connect only to the hub in their region&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1655&quot; src=&quot;https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__2d5KCt.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__Zx2d7I.webp 640w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__Z2i3Fps.webp 750w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__ZQGWni.webp 828w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__Z1voi4f.webp 1080w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__CNC6f.webp 1280w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__Z2sRV0U.webp 1668w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__Z2iwWt7.webp 2048w, https://cloudchristoph.com/_astro/multi-hub-full-example.B8sXLkg__2d5KCt.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can see, that each Hub is peered with each other hub, but spokes are only peered to the regional hub and also never to other spokes.&lt;/p&gt;
&lt;h2 id=&quot;key-considerations&quot;&gt;Key Considerations&lt;/h2&gt;
&lt;h3 id=&quot;vnet-address-planning&quot;&gt;VNET Address Planning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why is this important?&lt;/strong&gt;&lt;br&gt;
Proactive address planning is foundational for achieving our scenario. We need to avoid address conflicts between VNETs to ensure seamless communication and also need contiguous ranges. I’ll explain why.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do we proceed?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define a sufficiently large address space for the entire Azure environment, including all regions.&lt;/li&gt;
&lt;li&gt;Allocate a unique address range for each region.&lt;/li&gt;
&lt;li&gt;Subdivide each region’s address range for hubs and spokes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Avoid overlaps and ensure continuous address ranges within each region to simplify routing table configurations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example IP Address Planning&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Address range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Azure Environment&lt;/td&gt;
&lt;td&gt;10.64.0.0/13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌎 Azure Region East US&lt;/td&gt;
&lt;td&gt;10.64.0.0/16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;- Hub Network EUS&lt;/td&gt;
&lt;td&gt;10.64.0.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;- Spoke Networks EUS&lt;/td&gt;
&lt;td&gt;10.64.&amp;lt;1-255&amp;gt;.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌍 Azure Region West Europe&lt;/td&gt;
&lt;td&gt;10.65.0.0/16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;- Hub Network WEU&lt;/td&gt;
&lt;td&gt;10.65.0.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;- Spoke Networks WEU&lt;/td&gt;
&lt;td&gt;10.64.&amp;lt;1-255&amp;gt;.0/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌍 Azure Region Germany West Central&lt;/td&gt;
&lt;td&gt;10.66.0.0/16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;vnet-peering&quot;&gt;VNET Peering&lt;/h3&gt;
&lt;p&gt;Within a single region, spokes connect only to the hub, avoiding direct peering between spokes.&lt;/p&gt;
&lt;p&gt;Across multiple regions, all hubs are peered with one another. This ensures traffic from a spoke in one region to a spoke in another region always flows through the respective hubs, avoiding intermediate hubs.&lt;/p&gt;
&lt;h3 id=&quot;hub-components&quot;&gt;Hub Components&lt;/h3&gt;
&lt;p&gt;Azure VNETs are non-transitive, meaning direct connectivity is required between networks for communication.&lt;/p&gt;
&lt;p&gt;Take for example those VNET peerings:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;VNET A &amp;lt;–&amp;gt; VNET B &amp;lt;–&amp;gt; VNET C&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1688px) 1688px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1688&quot; height=&quot;341&quot; src=&quot;https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_Z1CB138.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_tOjFa.webp 640w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_XtWwB.webp 750w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_ZjYIsC.webp 828w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_ZExDPC.webp 1080w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_Bhdm9.webp 1280w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_up1cR.webp 1668w, https://cloudchristoph.com/_astro/non-transitive.DYh2sxUc_Z1CB138.webp 1688w&quot;&gt;&lt;/p&gt;
&lt;p&gt;VNET A can communicate with VNET B, and VNET B with VNET C, but VNET A cannot directly communicate with VNET C unless there’s a routing component in VNET B.&lt;/p&gt;
&lt;p&gt;When traffic flows from a spoke in one region to a spoke in another, it must pass through both regional hubs. Therefore, hubs must have the necessary components to route traffic between them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recommended Components:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;VPN or ExpressRoute Gateway&lt;/li&gt;
&lt;li&gt;Azure Firewall&lt;/li&gt;
&lt;li&gt;Third-party virtual appliances (e.g., Check Point, Palo Alto, Fortinet)&lt;/li&gt;
&lt;li&gt;VM acting as a router (e.g., checkout the &lt;a href=&quot;https://github.com/dmauser/AzureVM-Router&quot;&gt;AzureVM-Router by Daniel Mauser&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Use Azure Firewall or third-party virtual appliances for centralized monitoring and security.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What about other Components in Hubs?&lt;/strong&gt;&lt;br&gt;
Avoid adding other components to hubs. Deploy services like DNS, domain controllers, or … Zscaler Private Access Connectors … whatever … in &lt;strong&gt;dedicated spokes&lt;/strong&gt; to simplify routing.&lt;/p&gt;
&lt;h2 id=&quot;routing&quot;&gt;Routing&lt;/h2&gt;
&lt;p&gt;Routing is a critical part of this scenario. We need to ensure that traffic from a spoke in one region to a spoke in another region passes through the hubs in the respective regions. This requires appropriate configuration of the routing tables in the VNETs. Why is this configuration necessary? I’ll answer that in the next section.&lt;/p&gt;
&lt;h3 id=&quot;what-routes-does-a-vnet-know&quot;&gt;What routes does a VNET know?&lt;/h3&gt;
&lt;p&gt;An Azure VNET typically knows the following routes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Local routes: All address ranges defined within this VNET.&lt;/li&gt;
&lt;li&gt;Routes to peered VNETs: All address ranges defined in directly peered VNETs.&lt;/li&gt;
&lt;li&gt;Routes learned from a gateway (VPN or ExpressRoute).&lt;/li&gt;
&lt;li&gt;Default route: &lt;code&gt;0.0.0.0/0 -&amp;gt; Internet&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Some private network ranges with next hop to &lt;code&gt;None&lt;/code&gt; (We will ignore it here because it is not relevant to our scenario)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key here is point 2. Because, a VNET &lt;strong&gt;only&lt;/strong&gt; knows the address ranges of &lt;strong&gt;directly peered VNETs.&lt;/strong&gt; This means a VNET does not know it could communicate with a third VNET via another VNET.&lt;/p&gt;
&lt;p&gt;Our example is just showing two regional Hubs in East US and West Europe and only one Spoke per region to make it easier to understand :&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Spoke EUS &amp;lt;–&amp;gt; Hub EUS &amp;lt;–&amp;gt; Hub WEU &amp;lt;–&amp;gt; Spoke WEU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;513&quot; src=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_Z22yQz6.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_2uDEuy.webp 640w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_Z25RPrV.webp 750w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_Z26QKy9.webp 828w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_FBiTE.webp 1080w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_1atQws.webp 1280w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_1COqje.webp 1668w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_ZtkcW6.webp 2048w, https://cloudchristoph.com/_astro/spoke-to-spoke.MT0tCFaL_Z22yQz6.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this example, the Routing Table for Spoke EUS looks like this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address prefixes&lt;/th&gt;
&lt;th&gt;Next hop type&lt;/th&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.64.1.0/24&lt;/td&gt;
&lt;td&gt;Virtual Network&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.64.0.0/24&lt;/td&gt;
&lt;td&gt;VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.0.0.0/0&lt;/td&gt;
&lt;td&gt;Internet&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Routing Table of Spoke EUS&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Following what we know - since the Spoke EUS is only peered with the Hub EUS: The Spoke EUS knows only the address ranges of Hub EUS (10.64.0.0/24). It does not know the address ranges of Hub WEU, because they’re not directly peered. Thus, Spoke EUS cannot send traffic to Spoke WEU or Hub WEU. Additionally, Spoke EUS can directly communicate with the internet, which we want to avoid — this is why we have firewalls in the hubs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Spoke EUS knows only Hub EUS: it talks directly to the internet, and neither Hub WEU nor Spoke WEU is known&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1150&quot; src=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_uGJqx.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_Z1AWPfy.webp 640w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_qaI51.webp 750w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_oVd8u.webp 828w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_2gn8li.webp 1080w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_Z1oDgHb.webp 1280w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_Z10sRLa.webp 1668w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_1iBvbv.webp 2048w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-1.Dqc2A39A_uGJqx.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;direct-the-traffic-to-the-regional-hub&quot;&gt;Direct the traffic to the regional hub&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;How do we solve this problem?&lt;/strong&gt;&lt;br&gt;
Each spoke in a region gets a routing table that directs traffic to the regional hub. This is straightforward. In the routing table, we override the default route:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Address prefix: &lt;code&gt;0.0.0.0/0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Next hop type: &lt;code&gt;Virtual Appliance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;IP: &lt;code&gt;Hub EUS Firewall IP&lt;/code&gt;  (10.64.0.4 in this case).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From now on, any traffic from a spoke that is not destined for a system within the spoke itself is routed through the hub.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address prefixes&lt;/th&gt;
&lt;th&gt;Next hop type&lt;/th&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.64.1.0/24&lt;/td&gt;
&lt;td&gt;Virtual Network&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.64.0.0/24&lt;/td&gt;
&lt;td&gt;VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;0.0.0.0/0&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;Internet&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.0.0.0/0&lt;/td&gt;
&lt;td&gt;Virtual Appliance&lt;/td&gt;
&lt;td&gt;10.64.0.4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Routing Table of Spoke EUS with added route to the firewall&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Observant readers may notice that the spoke network still has a valid and functional route to the hub’s entire address range because of the peering. This route is more specific than the default route.&lt;br&gt;
&lt;strong&gt;Is this a problem?&lt;/strong&gt; Only if additional components have been deployed in the hubs (which we aim to avoid). These additional components can be directly reached by a spoke system without passing through the firewall, as the spoke knows the route. To prevent this, we would also need to override the hub’s address range in the spoke’s routing table. This is possible but not ideal.&lt;/p&gt;
&lt;p&gt;Great, we can now communicate between Spoke EUS and Hub EUS Firewall. Also the Internet traffic flows through our firewall.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;With a default route to the firewall, Spoke EUS sends traffic to Azure Firewall EUS, which knows Hub WEU and talks to the internet, but Spoke WEU is still unknown&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1150&quot; src=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_Z1ubPAm.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_WcyLx.webp 640w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_Z25Q0GO.webp 750w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_Z275vDl.webp 828w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_gtxjo.webp 1080w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_1FEh4Q.webp 1280w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_24OF0R.webp 1668w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_ZGh4Po.webp 2048w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-2.CVnpZLpo_Z1ubPAm.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But how do we reach the Spoke WEU?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hub EUS knows the following routes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Local routes: The address range of Hub EUS.&lt;/li&gt;
&lt;li&gt;Routes to peered VNETs: The address ranges of Spoke EUS and Hub WEU.&lt;/li&gt;
&lt;li&gt;Routes learned from a gateway (VPN or ExpressRoute).&lt;/li&gt;
&lt;li&gt;Default route: &lt;code&gt;0.0.0.0/0 -&amp;gt; Internet&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address prefixes&lt;/th&gt;
&lt;th&gt;Next hop type&lt;/th&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.64.0.0/24&lt;/td&gt;
&lt;td&gt;Virtual Network&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.64.1.0/24&lt;/td&gt;
&lt;td&gt;VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.65.0.0/24&lt;/td&gt;
&lt;td&gt;Global VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.0.0.0/0&lt;/td&gt;
&lt;td&gt;Internet&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Routing Table of Hub EUS&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What’s missing?&lt;/strong&gt; The route to the address range of Spoke WEU (10.65.1.0/24).&lt;/p&gt;
&lt;h3 id=&quot;regional-routes&quot;&gt;Regional routes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Do we simply add this route to the spoke?&lt;/strong&gt;&lt;br&gt;
It’s possible, but do we want to add a route for &lt;strong&gt;every new spoke&lt;/strong&gt; in any region, in &lt;strong&gt;every hub?&lt;/strong&gt; Even with Infrastructure as Code, this would create a significant workload, not to mention the potential for confusion and errors.&lt;/p&gt;
&lt;p&gt;Fortunately, our careful IP address planning pays off here.&lt;br&gt;
We already know the entire address range of the other regions. We can add a route for the entire address range of each region, which requires adding just one route per region.&lt;/p&gt;
&lt;p&gt;In the routing table for Hub EUS, we add:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adress Prefix: &lt;code&gt;10.65.0.0/16&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Next hop type: &lt;code&gt;Virtual Appliance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;IP: &lt;code&gt;Hub WEU Firewall IP&lt;/code&gt; (10.65.0.4 in this case).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We don’t need to specify which spoke network in WEU we want to reach because we know Hub WEU will route the traffic correctly—it is peered with the spokes in its region.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address prefixes&lt;/th&gt;
&lt;th&gt;Next hop type&lt;/th&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.64.0.0/24&lt;/td&gt;
&lt;td&gt;Virtual Network&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.64.1.0/24&lt;/td&gt;
&lt;td&gt;VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.65.0.0/24&lt;/td&gt;
&lt;td&gt;Global VNET Peering&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.0.0.0/0&lt;/td&gt;
&lt;td&gt;Internet&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.65.0.0/16&lt;/td&gt;
&lt;td&gt;Virtual Appliance&lt;/td&gt;
&lt;td&gt;10.65.0.4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Routing Table of Hub EUS with added route to complete WEU region&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;With regional routes, Azure Firewall EUS knows Hub WEU and its regional range, Azure Firewall WEU knows Spoke WEU, so traffic from Spoke EUS reaches Spoke WEU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1150&quot; src=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Z1mb86Y.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Z29E6Bd.webp 640w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Z7vxgD.webp 750w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Z8K3da.webp 828w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_oufML.webp 1080w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_1NEYye.webp 1280w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_2cPnuf.webp 1668w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Zygmm1.webp 2048w, https://cloudchristoph.com/_astro/spoke-to-spoke-route-3.CQ6X226B_Z1mb86Y.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;rinse-and-repeat&quot;&gt;Rinse and repeat&lt;/h3&gt;
&lt;p&gt;We apply this approach to all hubs in all regions. For each hub, we add a route for the entire address range of the other regions. Additionally, for each spoke, we add a route to the regional hub.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;With careful planning of IP address ranges and routing tables, we can implement a multi-hub scenario in Azure. This ensures that workloads in different regions can communicate while traffic passes through the required security components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;…and for Santa’s IT team?&lt;/strong&gt;&lt;br&gt;
Santa’s IT team can in fact implement a nice multi-hub scenario in Azure. This setup here allows Santa’s regional operations — from toy workshops to delivery hubs — seamlessly communication across the globe. At the same time, all traffic passes through the North Pole’s advanced security systems, ensuring that the Naughty/Nice lists and other critical data remain protected.&lt;/p&gt;
&lt;p&gt;Hope this approach was useful for you.&lt;br&gt;
🎄 Happy Holidays Y’all&lt;/p&gt;
</content:encoded><category>Networking</category></item><item><title>Outbound Internet Access for Azure VMs - your options</title><link>https://cloudchristoph.com/articles/outbound-internet-access-for-azure-vms-your-options/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/outbound-internet-access-for-azure-vms-your-options/</guid><description>Since Microsoft is retiring default outbound connectivity for Azure Virtual Machines, we should have a look at the other options.</description><pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Since Microsoft is &lt;a href=&quot;https://azure.microsoft.com/en-us/updates/default-outbound-access-for-vms-in-azure-will-be-retired-transition-to-a-new-method-of-internet-access/&quot;&gt;retiring default outbound connectivity for Azure Virtual Machines&lt;/a&gt;, we should have a look at the other options.&lt;/p&gt;
&lt;h2 id=&quot;dont-panic--yet&quot;&gt;Don’t panic … yet&lt;/h2&gt;
&lt;p&gt;The retirement is announced for 30 September, 2025. Almost two years from now.&lt;/p&gt;
&lt;p&gt;But since we all know how long projects and especially migration projects can drag on, I wouldn’t wait too much longer to start planning.&lt;/p&gt;
&lt;p&gt;Furthermore, I recommend not deploying new workloads this way from now on. It was never really a good idea, by the way - no control over the public IP of the machine, risk of using up NAT space quickly, no inbound connections possible, etc.&lt;/p&gt;
&lt;h2 id=&quot;general-approach&quot;&gt;General approach&lt;/h2&gt;
&lt;p&gt;It is generally not a good idea to allow VMs direct access to the Internet. Normally, we have a hub and spoke architecture in Azure and traffic from a VM in a spoke is routed through a firewall in the hub. In this case, nothing changes.&lt;/p&gt;
&lt;p&gt;But of course, there are test environments, isolated systems, or very small deployments where such access needs to be enabled directly from the VM. So…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What are our options?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;attach-a-public-ip-address&quot;&gt;Attach a public IP address&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Virtual Machine accessing internet via Public IP address&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1845px) 1845px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1845&quot; height=&quot;559&quot; src=&quot;https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_901Cd.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_ZK6JdU.webp 640w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_Zetk40.webp 750w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_ZTYUsd.webp 828w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_2ePHxC.webp 1080w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_WSSfP.webp 1280w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_Z2vyMH3.webp 1668w, https://cloudchristoph.com/_astro/public-ip.pXk0yG1k_901Cd.webp 1845w&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can attach a Basic or Standard Public IP address to the NIC. I wouldn’t recommend adding a Basic Public IP, since they’re also &lt;a href=&quot;https://azure.microsoft.com/en-us/updates/upgrade-to-standard-sku-public-ip-addresses-in-azure-by-30-september-2025-basic-sku-will-be-retired/&quot;&gt;deprecated&lt;/a&gt; and will retire at the same date.&lt;/p&gt;
&lt;p&gt;You can add either a Public IPv4 or IPv6 to the interface. For IPv6, you’ll have to add an IPv6 range to your VNET and the subnet and add a new IP Configuration to the NIC before attaching this Public IP. If you attach a Public IPv4, you can do this directly to first IP Configuration.&lt;/p&gt;
&lt;p&gt;I recommend this approach, if you have only a few VMs within this VNET. If you choose an IPv4 this IP will cost you money. IPv6 addresses are &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/ipv6-overview#pricing&quot;&gt;free of charge right now.&lt;/a&gt;. You’ll still pay for outgoing bandwith with both options.&lt;/p&gt;
&lt;p&gt;Keep in mind: Standard Public IP addresses are closed by default for &lt;strong&gt;incoming&lt;/strong&gt; connections, so you have to attach a Network Security Group (NSG) which allows Internet access to the NIC of the VM or the subnet the VM NIC is deployed to, to get connectivity from the &lt;strong&gt;outside&lt;/strong&gt;. Allowed connection &lt;strong&gt;to&lt;/strong&gt; Internet is one of the default rules of an NSG, so you actually don’t have to change anything else within the NSG (though you should).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Costs:&lt;/em&gt; Free - Public IPv6; or Low - Public IPv4 (€3.47*)&lt;/p&gt;
&lt;h2 id=&quot;use-a-azure-load-balancer&quot;&gt;Use a Azure Load Balancer&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Virtual Machines access the internet via an Azure Load Balancer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2124px) 2124px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2124&quot; height=&quot;878&quot; src=&quot;https://cloudchristoph.com/_astro/load-balancer.91ay9ns__md66o.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/load-balancer.91ay9ns__Z1pj53N.webp 640w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__Z2tDX9D.webp 750w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__1l60xl.webp 828w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__Z2dMSSF.webp 1080w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__zbrOx.webp 1280w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__1MeODR.webp 1668w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__Z4MMWo.webp 2048w, https://cloudchristoph.com/_astro/load-balancer.91ay9ns__md66o.webp 2124w&quot;&gt;&lt;/p&gt;
&lt;p&gt;A public Azure Load Balancer (LB) can be configured with Outbound Rules. So if you’re going to add your VMs to a Backend Pool on the LB, the LB will be used for outgoing traffic.&lt;/p&gt;
&lt;p&gt;Using only one Public IP can be an upside (costs), but only if you have more than ~4 VMs using the LB.&lt;/p&gt;
&lt;p&gt;To be honest, I wouldn’t recommend this approach. The SNAT allocation is &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-outbound-connections#preallocatedports&quot;&gt;mostly static or has other downsides&lt;/a&gt; and doesn’t scale well. Only if you also have to provide inbound connectivity, I think this can be a viable option.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Costs:&lt;/em&gt; Okay - Standard Load Balancer (€17.36*) + Data Processed by LB (€4.87* for 1TB) + Public IP (€3.47*)&lt;/p&gt;
&lt;h2 id=&quot;use-a-azure-nat-gateway&quot;&gt;Use a Azure NAT Gateway&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Virtual Machines accessing the internet via a Azure NAT Gateway&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2124px) 2124px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2124&quot; height=&quot;878&quot; src=&quot;https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_kwc6G.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_2RpdI.webp 640w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_x4CIr.webp 750w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_1UOQ0G.webp 828w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_1NiKxK.webp 1080w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_Z1WJpdh.webp 1280w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_Z1iQ4ED.webp 1668w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_Z2jrXsC.webp 2048w, https://cloudchristoph.com/_astro/nat-gateway.FkWo76JU_kwc6G.webp 2124w&quot;&gt;&lt;/p&gt;
&lt;p&gt;A Azure NAT Gateway gives you SNAT port functionality for automatically scaling outbound connectivity and reduce the risk of SNAT port exhaustion. It’s not possible to use it for inbound connectivity (of course), but you can add another Public IP to the VM NIC or use another Load Balancer for this.&lt;/p&gt;
&lt;p&gt;I would recommend this, if you have many VMs within your VNET and cannot live with the risk of exhausting your SNAT ports.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Costs:&lt;/em&gt; Questionable (my opinion!) - NAT Gateway (€31.25*) + Data Processed by NAT Gateway (€43,84* for 1TB) - Public IP (€3.47*)&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I strongly recommend avoiding &lt;strong&gt;all&lt;/strong&gt; these options and building a reasonable Hub-and-Spoke architecture. Direct connection to the Internet is mostly a security nightmare.
But if you want to use it for test scenarios or very small deployments, then use the first option (Public IP) if possible.
If you need to configure dedicated traffic for multiple VMs or VM scale sets anyway, use the load balancer.
Only if SNAT port exhaustion is really a risk in your environment, then use a NAT gateway.&lt;/p&gt;
&lt;p&gt;Please remember: This reflects only my personal opinion, which does not have to be that of Microsoft or my employer. Your feedback is always welcome!&lt;/p&gt;
&lt;p&gt;* = based on retail prices as of October 2023 in the Azure Region West Europe; Your costs might be different&lt;/p&gt;
</content:encoded><category>Networking</category></item><item><title>Find Azure RBAC Roles with specific permissions</title><link>https://cloudchristoph.com/articles/find-azure-rbac-roles-with-specific-permissions/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/find-azure-rbac-roles-with-specific-permissions/</guid><description>How to find the best fitting Azure RBAC role for a job by searching the role assignment dialog for a specific permission.</description><pubDate>Mon, 03 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In order to apply the Least Privilege Principle in Azure you sometimes need to find the best fitting Azure RBAC role for the job. The default roles Owner, Contributor, Reader are just too much in most cases.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;br&gt;
You want to give an Automation Account the permission to Start, Stop and Restart Virtual Machines in your environment.&lt;/p&gt;
&lt;p&gt;The permissions needed to perform the actions are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft.Compute/virtualMachines/start/action&lt;/li&gt;
&lt;li&gt;Microsoft.Compute/virtualMachines/stop/action&lt;/li&gt;
&lt;li&gt;Microsoft.Compute/virtualMachines/restart/action&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See: &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor&quot;&gt;Azure Built-in Roles for Virtual Machines&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;but-how-do-you-find-the-roles-with-those-permissions&quot;&gt;But how do you find the Roles with those permissions?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the Portal navigate to the Resource (or one of the levels above)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to “Access Control (IAM)”, choose “Add” and then “Add role assignment”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Access Control - Add Role Assignment&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1484px) 1484px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1484&quot; height=&quot;762&quot; src=&quot;https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_QjMJm.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_ZQDErY.webp 640w, https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_1U8iM1.webp 750w, https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_1BEMWV.webp 828w, https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_Z1DaMpV.webp 1080w, https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_Z5Kq5p.webp 1280w, https://cloudchristoph.com/_astro/rbac-add-role-assignment.CLvQv3d-_QjMJm.webp 1484w&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type in the &lt;em&gt;specific action&lt;/em&gt; in the search field.&lt;br&gt;
In our case we’re searching for ‘Microsoft.Compute/virtualMachines/start/action’&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Azure Portal will show you all Role Definitions that have this permission included.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Access Control - Search Role by specific permission&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1432px) 1432px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1432&quot; height=&quot;1368&quot; src=&quot;https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_TuI3D.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_2jqdGX.webp 640w, https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_Z1j4wod.webp 750w, https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_DSG43.webp 828w, https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_Z1jJbVl.webp 1080w, https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_1Eh2Jb.webp 1280w, https://cloudchristoph.com/_astro/rbac-search-role-by-permission.BjK0-0Qe_TuI3D.webp 1432w&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be aware that Microsoft has started to split the Role Definitions by “Job function roles” and “Privileged administrator roles” (the tabs above the search field).&lt;/p&gt;
&lt;p&gt;You should aim for using a &lt;strong&gt;“Job function role”&lt;/strong&gt; to actually follow the Least Privileges Principle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have a look at the Details view to check for the Role with the least permissions needed to perform the job.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Access Control - Show Role Details&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1257&quot; src=&quot;https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_ZhiUNC.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_1CIeI9.webp 640w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_1EcyFO.webp 750w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_1eDrgt.webp 828w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_OO8Ad.webp 1080w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_BvHjn.webp 1280w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_1XRGOw.webp 1668w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_yG1xU.webp 2048w, https://cloudchristoph.com/_astro/rbac-role-details.BmD8nSzA_ZhiUNC.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In our case we have two viable options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Virtual Machine Contributor - but with quite broad permissions.&lt;/li&gt;
&lt;li&gt;One Custom Role we called “Virtual Machine Operator” with necessary permissions for starting/stopping VMs and Scale Sets.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hope that helps.&lt;/p&gt;
</content:encoded><category>Identity &amp; Governance</category></item><item><title>Erste Schritte mit Azure Bicep 💪</title><link>https://cloudchristoph.com/articles/erste-schritte-mit-azure-bicep/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/erste-schritte-mit-azure-bicep/</guid><description>Die Grundlagen von Azure Bicep 0.1: Parameter, Variablen, Ressourcen und Ausgaben, und wie aus einer Bicep-Datei ein ARM-Template wird.</description><pubDate>Mon, 07 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Anfang letzter Woche hat Microsoft die erste Version (0.1) von &lt;a href=&quot;https://github.com/Azure/bicep&quot;&gt;Azure Bicep&lt;/a&gt; veröffentlicht.&lt;/p&gt;
&lt;p&gt;Azure Bicep stellt eine domänenspezifische Sprache (DSL) dar, mit denen wir Azure Ressourcen deklarativ beschreiben können. Die Sprache ist kein ARM Ersatz. Vielmehr werden Bicep Templates in ARM Templates übersetzt und wir werden weiterhin ARM Templates in Azure ausrollen. ARM Templates werden damit zu einer Intermediate Language (IL)&lt;/p&gt;
&lt;p&gt;Ziele sind, dass wir wesentlich leichter modulare Templates bauen können, eine saubere und besser lesbare Syntax erhalten und unseren Template Code besser wiederverwenden können.&lt;/p&gt;
&lt;h2 id=&quot;voraussetzungen&quot;&gt;Voraussetzungen&lt;/h2&gt;
&lt;p&gt;Zum Start ist nicht viel nötig. Wir benötigen die Bicep CLI und zum leichteren Schreiben die Bicep VS Code Erweiterung.&lt;/p&gt;
&lt;p&gt;Die Schritte für macOS, Linux und Windows sind gut &lt;a href=&quot;https://github.com/Azure/bicep/blob/master/docs/installing.md#install-the-bicep-cli&quot;&gt;dokumentiert im GitHub Repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;erstes-template&quot;&gt;Erstes Template&lt;/h2&gt;
&lt;p&gt;Heute beginnen wir mit ein paar Grundlagen. Parameter, Variablen, Ressourcen, Ausgaben.&lt;/p&gt;
&lt;h3 id=&quot;parameter&quot;&gt;Parameter&lt;/h3&gt;
&lt;p&gt;Wir legen zunächst einen &lt;a href=&quot;https://github.com/Azure/bicep/blob/master/docs/spec/parameters.md&quot;&gt;Parameter&lt;/a&gt; fest:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageAccountName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;mycoolstorage&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Es ist fast selbsterklärend. “param” ist das Schlüsselwort, danach folgt der Parameter-Name, dann der Parameter-Typ (string, int, bool, array, object) und ein Default Wert.&lt;/p&gt;
&lt;h3 id=&quot;variablen&quot;&gt;Variablen&lt;/h3&gt;
&lt;p&gt;Eine &lt;a href=&quot;https://github.com/Azure/bicep/blob/master/docs/spec/variables.md&quot;&gt;Variable&lt;/a&gt; kommt ohne den Typ aus (genau wie in einem ARM Template):&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;location&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;westeurope&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Um einen Parameter oder eine Variable zu nutzen, benötigen wir keine Funktionsaufrufe mehr. Einfach den Namen nutzen! Ein Beispiel:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;dev&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;MyApp&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;vmName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;vm-&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#8577A7;font-style:italic&quot;&gt; // Ergebnis: &quot;vm-MyApp-dev&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;ressourcen&quot;&gt;Ressourcen&lt;/h3&gt;
&lt;p&gt;Bauen wir uns eine Ressource. Einen Storage Account.&lt;br&gt;
Wir benötigen einen Namen, eine Location und eine Angabe über Redundanz.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Microsoft.Storage/storageAccounts@2019-06-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;mycoolstorage&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;westeurope&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  kind&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Storage&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  sku&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Standard_LRS&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;“resource” ist wieder das Schlüsselwort, “MyStorageAccount” ist meine Ressourcen-Referenz, die ich später im Template nutzen kann (Achtung: Das ist nicht der Name der Ressource!), dann folgt der Ressourcen-Typ mit API-Version.&lt;/p&gt;
&lt;p&gt;Wir sollten ein paar Parameter und Variablen für unser Template nutzen:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;location&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;resourceGroup()&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;.location&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;dev&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;myapp&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageAccountName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;st&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Der “Location” Parameter nutzt eine Expression (auch ähnlich zu ARM Templates). Der Ausdruck hier verweist auf die Location der Ressource Group, in der das Deployment ausgeführt wird.&lt;/p&gt;
&lt;p&gt;Dazu passen wir die Ressourcen-Beschreibung an:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Microsoft.Storage/storageAccounts@2019-06-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageAccountName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;location&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  kind&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Storage&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;  sku&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Standard_LRS&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Wie man an den Eigenschaften “name” und “location” erkennen kann: Sollten wir nichts verketten oder umschreiben, können wir die Variablen oder Parameter ohne weitere Funktionen nutzen. Eine - im Vergleich zu ARM - erfrischend kurze Schreibweise.&lt;/p&gt;
&lt;h3 id=&quot;ausgaben&quot;&gt;Ausgaben&lt;/h3&gt;
&lt;p&gt;Zum Schluss lassen wir uns noch beispielhaft die ID und den Blob-Endpunkt unseres Storage Accounts ausgeben:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;output&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageId&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount.id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;output&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;blobEndpoint&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount.properties.primaryEndpoints.blob&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Für &lt;a href=&quot;https://github.com/Azure/bicep/blob/master/docs/spec/outputs.md&quot;&gt;Ausgaben&lt;/a&gt; ist “output” das Schlüsselwort, dann der Name, dann der Typ. Danach nutzen wir die Ressourcen-Referenz “MyStorageAccount” und greifen auf Eigenschaften zu.&lt;br&gt;
Wir können auf alle Eigenschaften zugreifen, auf die wir auch im ARM-Template Zugriff hätten.&lt;/p&gt;
&lt;h3 id=&quot;zu-arm-übersetzen&quot;&gt;Zu ARM übersetzen&lt;/h3&gt;
&lt;p&gt;Zunächst die vollständige Bicep-Datei (wir nennen sie “mytemplate.bicep”):&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;bicep&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bicep&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;location&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;resourceGroup()&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;.location&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;dev&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;myapp&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageAccountName&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;st&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}${&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Microsoft.Storage/storageAccounts@2019-06-01&apos;&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageAccountName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;location&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    kind&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Storage&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;    sku&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;      name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;&apos;Standard_LRS&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;output&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;storageId&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount.id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;output&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;blobEndpoint&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;MyStorageAccount.properties.primaryEndpoints.blob&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In einer PowerShell können wir jetzt die Datei zu ARM übersetzen lassen:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;bicep build .\mytemplate.bicep&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;PowerShell: bicep build .\mytemplate.bicep läuft ohne Ausgabe durch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1248px) 1248px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1248&quot; height=&quot;231&quot; src=&quot;https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_ZglOXT.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_1YDB7q.webp 640w, https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_Z11sXCo.webp 750w, https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_eJ6rJ.webp 828w, https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_1a5wGt.webp 1080w, https://cloudchristoph.com/_astro/bicep-build.DqIErhmP_ZglOXT.webp 1248w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Bicep erzeugt eine “mytemplate.json” Datei. Ein, wie wir ja vermutet hatten, ARM-Template:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;json&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;$schema&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;contentVersion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;1.0.0.0&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;parameters&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;defaultValue&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[resourceGroup().location]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;defaultValue&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;appName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;defaultValue&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;myapp&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;functions&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;variables&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;storageAccountName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[format(&apos;st{0}{1}&apos;, parameters(&apos;appName&apos;), parameters(&apos;environment&apos;))]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Microsoft.Storage/storageAccounts&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;2019-06-01&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[variables(&apos;storageAccountName&apos;)]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;location&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[parameters(&apos;location&apos;)]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Storage&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;sku&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;        &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Standard_LRS&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;storageId&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[resourceId(&apos;Microsoft.Storage/storageAccounts&apos;, variables(&apos;storageAccountName&apos;))]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;blobEndpoint&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;      &quot;&lt;/span&gt;&lt;span style=&quot;color:#FF9FCB&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;[reference(resourceId(&apos;Microsoft.Storage/storageAccounts&apos;, variables(&apos;storageAccountName&apos;))).primaryEndpoints.blob]&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Schon beim Lesen hier im Blog sieht man den Vergleich, wie kurz und knackig Bicep-Dateien im Vergleich zu den sehr “geschwätzigen” ARM-Templates sind.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Visual Studio Code nebeneinander: links mytemplate.bicep mit 16 Zeilen, rechts das erzeugte ARM-Template mytemplate.json mit über 40 Zeilen&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1472&quot; src=&quot;https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_BypuJ.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_Z2dsSW3.webp 640w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_1tlFKp.webp 750w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_ZzwCNc.webp 828w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_nWjkE.webp 1080w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_1C21RV.webp 1280w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_1mfJKt.webp 1668w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_Z18pybK.webp 2048w, https://cloudchristoph.com/_astro/bicep-vs-arm.BkuPepRU_BypuJ.webp 2400w&quot;&gt;
&lt;em&gt;Links: Azure Bicep Datei, Rechts: Erzeugtes ARM-Template&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;was-ist-gut-gelungen&quot;&gt;Was ist gut gelungen?&lt;/h2&gt;
&lt;p&gt;Die Templates sind wesentlich schmaler und lesbarer. Es erinnert sehr an Terraform.&lt;/p&gt;
&lt;p&gt;Automatische Dependencies. Wenn ich eine Resource in einer anderen referenziere, dann fügt Bicep automatisch eine Abhängigkeit (“dependsOn”) ein.&lt;/p&gt;
&lt;p&gt;“concat” ist Geschichte. Einfach &lt;code&gt;&apos;${appName}-abc-${environment}&apos;&lt;/code&gt; schreiben. Das ist wesentlich leichter lesbar als &lt;code&gt;&quot;[concat(parameters(&apos;appName&apos;), &apos;-abc&apos;, variables(&apos;environment&apos;)]&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Referenzen auf andere Ressourcen und deren Eigenschaften ist auch gut gelungen.&lt;br&gt;
&lt;em&gt;Vorher:&lt;/em&gt; “&lt;code&gt;reference(resourceId(&apos;Microsoft.insights/components&apos;, variables(&apos;appInsightsName&apos;))).InstrumentationKey]&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Nachher:&lt;/em&gt; &lt;code&gt;AppInsights.properties.InstrumentationKey&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;was-funktioniert-noch-nicht&quot;&gt;Was funktioniert (noch) nicht?&lt;/h2&gt;
&lt;p&gt;Bicep ist im Alpha-Stadium (momentan Version 0.1). Das heißt, da gibt es sicher noch jede Menge fehlende Funktionalität.&lt;/p&gt;
&lt;p&gt;Was ist mir bisher beim Testen aufgefallen?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keine Parameter-Datei:&lt;br&gt;
Bicep 0.1 erzeugt noch eine Parameter-Datei. Es steht uns aber frei einfach eine “mytemplate.parameters.json” Datei anzulegen. Dann natürlich im ARM-Format.&lt;/li&gt;
&lt;li&gt;Subscription Level Templates nutzen momentan das falsche Schema. Es werden nur ARM-Templates mit Resource Group Deployments erzeugt.&lt;br&gt;
Das erzeugte Template kann man trotzdem auf Subscription-Ebene anwenden.&lt;/li&gt;
&lt;li&gt;Die API-Version muss fest angegeben werden, du kannst keine Variable dafür nutzen (das ist aber eh &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices#general-recommendations-for-parameters&quot;&gt;gegen die Best Practices&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Verschacheltung von Funktionen: Ich habe es nicht geschafft bspw. einen String zusammen zu stellen und diesen dann direkt durch “toLower” zu schicken. Momentan regele ich das über zwei Variablen.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;referenzen-version-quellcode&quot;&gt;Referenzen, Version, Quellcode&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Das kleine Beispiel findet ihr als Gist hier:  &lt;a href=&quot;https://gist.github.com/cloudchristoph/865c8cd2130ed4fa3700053d8c95902c&quot;&gt;https://gist.github.com/cloudchristoph/865c8cd2130ed4fa3700053d8c95902c&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Azure Bicep GitHub Repository: &lt;a href=&quot;https://github.com/Azure/bicep&quot;&gt;https://github.com/Azure/bicep&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Verwendete Bicep Version für diesen Blog-Beitrag: &lt;strong&gt;0.1&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Zum Schluss: &lt;em&gt;Bicep? Warum denn nun gerade Bicep? “Well, your biceps let’s you flex your ARM.”&lt;/em&gt; 😎 … Ich bin ja schon weg…&lt;/p&gt;
</content:encoded><category>Infrastructure as Code</category></item><item><title>Save money using Azure Hybrid Benefit for your VMs</title><link>https://cloudchristoph.com/articles/save-money-using-azure-hybrid-benefit-for-your-vms/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/save-money-using-azure-hybrid-benefit-for-your-vms/</guid><description>How to activate Azure Hybrid Benefit for Windows Server VMs, how to find out which VMs use it and how many VMs you may activate it for.</description><pubDate>Mon, 02 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;what-is-the-hybrid-use-benefit&quot;&gt;What is the Hybrid (Use) Benefit?&lt;/h2&gt;
&lt;p&gt;Azure Hybrid Benefit (a.k.a. Azure Hybrid Use Benefit or HUB) is a offer by Microsoft for (re)using already existing On-premises licenses for Windows Server or SQL Server on Azure if they are under Software Assurance.&lt;/p&gt;
&lt;p&gt;There are a few rules in place as to when and if you’re eligible for  this.&lt;/p&gt;
&lt;p&gt;A short exerpt from the &lt;a href=&quot;https://azure.microsoft.com/en-us/pricing/hybrid-benefit/faq/&quot;&gt;Azure Hybrid Use FAQ&lt;/a&gt; regarding Windows Server:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Each 2-processor license or each set of 16-core licenses, Datacenter or Standard Editions, are entitled to two instances of up to 8 cores, or one instance of up to 16 cores. Datacenter Edition licenses allow for simultaneous usage both on-premises and in Azure. Standard Edition licenses must be used either on-premises or in Azure, although customers get 180 days of concurrent use rights while they are migrating their servers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the end, you only pay the Linux price of a virtual machine (only Compute costs), without the added minute price for the Windows Server license.&lt;/p&gt;
&lt;h2 id=&quot;how-can-i-use-hybrid-benefit-for-my-vm&quot;&gt;How can I use Hybrid Benefit for my VM?&lt;/h2&gt;
&lt;p&gt;You can activate this benefit while deploying your VM from the Portal.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure portal, create a virtual machine: in the Save money section “Already have a Windows Server license?” is set to Yes and the Software Assurance confirmation is checked&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1657px) 1657px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1657&quot; height=&quot;457&quot; src=&quot;https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_kCpaX.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_Z5jCC6.webp 640w, https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_Z2ssHcl.webp 750w, https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_VF2be.webp 828w, https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_Z21tToU.webp 1080w, https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_21RWXq.webp 1280w, https://cloudchristoph.com/_astro/azure-hub-create-new-vm.CIwOkXwH_kCpaX.webp 1657w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Activate Azure Hybrid Use while deploying your VM&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you’re deploying your VM via PowerShell or Azure CLI you have to provide the “LicenseType” parameter.&lt;/p&gt;
&lt;p&gt;Here is an example creating a new Windows Server 2016 VM with activated Hybrid Benefit.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;New-AzVM&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;ResourceGroupName &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;rg-workload1&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;Name &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;vm-srvwithhub&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;Location &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;West Europe&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;ImageName &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Win2016Datacenter&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;LicenseType &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Windows_Server&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;how-can-i-see-how-many-vms-are-using-hybrid-benefit&quot;&gt;How can I see how many VMs are using Hybrid Benefit?&lt;/h2&gt;
&lt;p&gt;It’s really just a parameter on the VM. So you can easily query all VMs within your subscription and look at the “LicenseType” parameter.&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;Get-AzVM&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;    Where-Object&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#D8C6FF&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;_.LicenseType &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;-like&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;Windows_Server&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;    Select-Object&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; ResourceGroupName&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; Name&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt; LicenseType &lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#C9B6F5&quot;&gt;ExpandProperty &lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#8EE6B8&quot;&gt;HardwareProfile&lt;/span&gt;&lt;span style=&quot;color:#A99BC4&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Be sure to also view and export the hardware size to determine exactly how many Windows Server licenses you are using.&lt;/p&gt;
&lt;h2 id=&quot;for-how-many-vms-may-i-activate-the-hybrid-benefit&quot;&gt;For how many VMs may I activate the Hybrid Benefit?&lt;/h2&gt;
&lt;p&gt;Use this calculator to get your maximum server count with activated HUB: &lt;a href=&quot;https://azure.microsoft.com/en-us/pricing/hybrid-benefit/&quot;&gt;https://azure.microsoft.com/en-us/pricing/hybrid-benefit/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Hybrid Benefit calculator for Windows Server VMs: 40 core licenses, region West Europe, instance size D4 v2, 730 hours per month, result: 5 eligible virtual machines&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1214px) 1214px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1214&quot; height=&quot;1126&quot; src=&quot;https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_Z1hB1VO.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_Z8X6ua.webp 640w, https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_1aH6pl.webp 750w, https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_Z1TH03u.webp 828w, https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_Z1UfMhQ.webp 1080w, https://cloudchristoph.com/_astro/azure-hub-calculator.BSMOf6cb_Z1hB1VO.webp 1214w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hybrid Benefit Calculator for Windows Server VMs&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I hope this helps you to save further (also unnecessary) costs in Azure.&lt;/p&gt;
</content:encoded><category>Cost</category></item><item><title>Export your Azure inventory as CSV files</title><link>https://cloudchristoph.com/articles/export-your-azure-inventory-as-csv-files/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/export-your-azure-inventory-as-csv-files/</guid><description>A PowerShell script that exports your Azure inventory as one CSV file per subscription, including a separate file for marketplace resources.</description><pubDate>Tue, 18 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You can always use the Azure portal to export all your resources to one CSV file (Use the “All resources” blade and then click “Export to CSV”).&lt;/p&gt;
&lt;h2 id=&quot;script-for-exporting-your-inventory&quot;&gt;Script for exporting your inventory&lt;/h2&gt;
&lt;p&gt;Or you can use &lt;a href=&quot;https://github.com/cloudchristoph/AzureInventory&quot;&gt;this script to export your Azure inventory&lt;/a&gt;. It builds different CSV files for each subscription with resources.&lt;br&gt;
After downloading open your favorite PowerShell and type:&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-head&quot; data-pagefind-ignore=&quot;&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;powershell&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code cloudchristoph&quot; style=&quot;background-color:#1A0730;color:#EDE6F8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#EDE6F8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B794FF&quot;&gt;\Get-AzureInventory.ps1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;PowerShell running .\Get-AzureInventory.ps1 -Verbose: it finds three subscriptions, collects their resources and writes inventory, marketplace and subscriptions CSV files&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1106&quot; src=&quot;https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_2hc3wv.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_gr1vW.webp 640w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_RPGBR.webp 750w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_1YP6R9.webp 828w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_14Yhn.webp 1080w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_Z1Pdp9r.webp 1280w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_17Ebsj.webp 1668w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_1zpi8z.webp 2048w, https://cloudchristoph.com/_astro/azure-inventory-example-powershell.BLVZ5a49_2hc3wv.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;marketplace-resources-vs-csp-contracts&quot;&gt;Marketplace resources vs. CSP contracts&lt;/h2&gt;
&lt;p&gt;It also creates a CSV file thats contains only your marketplace items. This is most useful if you change your Azure contract model.&lt;/p&gt;
&lt;p&gt;For example you switch from your EA/SCE or Pay-As-You-Go to a CSP contract then some of the marketplace resources aren’t available yet in CSP.&lt;/p&gt;
&lt;p&gt;So you can send your CSP provider this files to give them an overview about your Azure environment and then discuss with them if all your resources will be available.&lt;/p&gt;
&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cloudchristoph/AzureInventory/archive/master.zip&quot;&gt;Download ZIP file&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;or view the repository on GitHub:&lt;br&gt;
&lt;a href=&quot;https://github.com/cloudchristoph/AzureInventory&quot;&gt;https://github.com/cloudchristoph/AzureInventory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve tested this with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PowerShell 5.1&lt;/li&gt;
&lt;li&gt;PowerShell 6.0 Core&lt;/li&gt;
&lt;li&gt;Azure Az Module Version 3.3.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don’t hesitate to contact me if you have questions or ideas for this script.&lt;/p&gt;
</content:encoded><category>Tooling &amp; Workshops</category></item><item><title>What are the default security settings for an Azure VNet?</title><link>https://cloudchristoph.com/articles/what-are-the-default-security-settings-for-an-azure-vnet/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/what-are-the-default-security-settings-for-an-azure-vnet/</guid><description>An Azure VNet has no security settings of its own, but the NSGs on its subnets come with default rules, and port 25 is blocked by default.</description><pubDate>Mon, 17 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My client has asked me in our workshop:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What are the default security settings for an Azure VNet?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On an Azure VNet you cannot initially apply things like a Network Security Group, only things like allowed services (via Service endpoints or Private endpoints). So there are no default security settings except those that Microsoft itself always applies (e.g. DDoS Protection).&lt;/p&gt;
&lt;p&gt;However, each VNet consists of at least one subnet. Network Security Groups (NSGs) can (&lt;strong&gt;and should&lt;/strong&gt;) then be applied at the subnet level.&lt;/p&gt;
&lt;h2 id=&quot;whats-a-network-security-group&quot;&gt;Whats a Network Security Group?&lt;/h2&gt;
&lt;p&gt;An NSG contains security rules in the form of a 5-tuple ACL.&lt;br&gt;
So you define source IP (or IP range), destination IP (or IP range), source port, destination port and protocol (TCP or UPD). Furthermore you define the action - Allow or Deny.&lt;/p&gt;
&lt;p&gt;The order is determined by priority. Higher priority (lower number) means that the rule will beat a rule with lower priority.&lt;/p&gt;
&lt;h2 id=&quot;what-are-the-default-rules&quot;&gt;What are the default rules?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Azure portal, Network Security Group overview: the default inbound rules AllowVnetInBound, AllowAzureLoadBalancerInBound and DenyAllInBound and the default outbound rules AllowVnetOutBound, AllowInternetOutBound and DenyAllOutBound&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1085&quot; src=&quot;https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_215T8n.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_Z2mXxMr.webp 640w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_JNQne.webp 750w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_1Hy4bL.webp 828w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_1NF7BE.webp 1080w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_2a0nzK.webp 1280w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_6gTYQ.webp 1668w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_1o0xif.webp 2048w, https://cloudchristoph.com/_astro/default-nsg-rules.Cbjtqv6u_215T8n.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Default Network Security Group rules&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;for-outgoing-connections-youll-find-these-rules&quot;&gt;For outgoing connections you’ll find these rules:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Allow any outgoing connections to other resources in the same VNet&lt;/li&gt;
&lt;li&gt;Allow any outgoing connections to the Internet&lt;/li&gt;
&lt;li&gt;Everything else outgoing? Deny&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;for-incoming-connections-youll-find-these-rules&quot;&gt;For incoming connections you’ll find these rules:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Allow any incoming connections from other resources in the same VNet&lt;/li&gt;
&lt;li&gt;Allow any connections from Azure Load Balancer probes&lt;/li&gt;
&lt;li&gt;Everything else incoming? Deny&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;unwritten-rule---port-25&quot;&gt;“Unwritten rule” - Port 25&lt;/h2&gt;
&lt;p&gt;Port 25 (used for sending Emails over SMTP) is blocked by default if you’re not on an EA contract or your agreement was made after November 2017. If you want to send Mails from your VMs over Port 25, you’ll have to open a support case at Microsoft.&lt;br&gt;
Why does this rule exist? I think that Microsoft wants to prevent spambots from running in Azure on a large scale and messing up the entire IP address space.&lt;/p&gt;
&lt;h2 id=&quot;should-i-adjust-these-default-rules&quot;&gt;Should I adjust these default rules?&lt;/h2&gt;
&lt;p&gt;It depends (of course). For example, if you don’t want your resources in this VNet to communicate directly with the Internet, you have to adapt this rule.&lt;br&gt;
Very often a rule is also set up that opens the RDP port for Windows or SSH for Linux. For this you should rather use modern methods like &lt;a href=&quot;https://azure.microsoft.com/en-us/services/azure-bastion/&quot;&gt;Azure Bastion&lt;/a&gt; or &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/security-center/security-center-just-in-time&quot;&gt;Just-in-time Access&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn more&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/azure/virtual-network/security-overview&quot;&gt;Microsoft Docs about Network Security Groups&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>Networking</category></item><item><title>4 useful sites for your next Azure Workshop</title><link>https://cloudchristoph.com/articles/4-useful-sites-for-your-next-azure-workshop/</link><guid isPermaLink="true">https://cloudchristoph.com/articles/4-useful-sites-for-your-next-azure-workshop/</guid><description>Four nicely done websites I use during my Azure workshops: Azure Charts, Azure Speed, azureprice.net and the AAD Application Proxy Port Check.</description><pubDate>Wed, 12 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Besides the Azure Portal of course, there are some useful and nicely done websites that I use during my workshops. Maybe they are also helpful for your next meeting.&lt;/p&gt;
&lt;h2 id=&quot;azure-charts&quot;&gt;&lt;a href=&quot;https://azurecharts.com/&quot;&gt;Azure Charts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This site from &lt;a href=&quot;https://github.com/AlekseiPolkovnikov&quot;&gt;Alexey Polkovnikov&lt;/a&gt; gives you a great overview over all Azure services and their latest updates. At this moment the region comparison tool is very useful to me. I use it for example to show my customers &lt;a href=&quot;https://azurecharts.com/regions/?r=germany-west-central&amp;amp;c=europe-west&quot;&gt;what services are still missing in the new Germany datacenters compared to West Europe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Charts, Azure Region Scope: service presence in Germany West Central compared to West Europe, grouped by category&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2400px) 2400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2400&quot; height=&quot;1163&quot; src=&quot;https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_2rPxHw.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_15IWyJ.webp 640w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_Z25kfLC.webp 750w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_Z1eKvAS.webp 828w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_1Uq7P7.webp 1080w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_4VQgj.webp 1280w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_12F9QF.webp 1668w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_Z2v1eAt.webp 2048w, https://cloudchristoph.com/_astro/azure-charts.BrAcIebN_2rPxHw.webp 2400w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;azure-speed&quot;&gt;&lt;a href=&quot;http://www.azurespeed.com/&quot;&gt;Azure Speed&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If my customers asking me about the “best” Azure region for they workloads from their location, i’ll open up &lt;a href=&quot;http://www.azurespeed.com/&quot;&gt;Azure Speed&lt;/a&gt; and then discuss with them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Azure Speed: the closest datacenters (Germany West Central, France Central, Switzerland North) and a latency chart for the selected regions&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1359px) 1359px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1359&quot; height=&quot;1489&quot; src=&quot;https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_Z1qTBSk.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_1e5Med.webp 640w, https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_lmzYd.webp 750w, https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_Z1usV7O.webp 828w, https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_Z14aI0y.webp 1080w, https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_A29y2.webp 1280w, https://cloudchristoph.com/_astro/azure-speed.DB2P1hsA_Z1qTBSk.webp 1359w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;azurepricenet&quot;&gt;&lt;a href=&quot;https://azureprice.net/&quot;&gt;azureprice.net&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When talking about different prices for the same service in each region, I’m opening &lt;a href=&quot;https://azureprice.net/Region&quot;&gt;azureprice.net/region&lt;/a&gt; and show them the difference in VM pricing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;azureprice.net: bar chart of the average VM price in USD per hour for each Azure region, from East US 2 as the cheapest to West Europe as the most expensive&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2342px) 2342px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2342&quot; height=&quot;1553&quot; src=&quot;https://cloudchristoph.com/_astro/azure-prices.C076v9RY_ZlD1Ie.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/azure-prices.C076v9RY_21r5Sl.webp 640w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_7RDr0.webp 750w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_WIWDT.webp 828w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_Z1D3KsQ.webp 1080w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_1J8mbp.webp 1280w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_Z2tVGnu.webp 1668w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_1csuPH.webp 2048w, https://cloudchristoph.com/_astro/azure-prices.C076v9RY_ZlD1Ie.webp 2342w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;aad-application-proxy-port-check&quot;&gt;&lt;a href=&quot;https://aadap-portcheck.connectorporttest.msappproxy.net/&quot;&gt;AAD Application Proxy Port Check&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“Are we ready for AAD App Proxy?” - Start with checking the connections from your designated server. It’s a nice starting point.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;msappproxy.net domain Ports Test Tool: port 443 is reachable in all listed Azure regions, green check marks from Central US to Japan East&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2105px) 2105px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2105&quot; height=&quot;926&quot; src=&quot;https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_LKBH8.webp&quot; srcset=&quot;https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_ZhdYXF.webp 640w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_ZylCDC.webp 750w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_LA7zi.webp 828w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_ZQffMP.webp 1080w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_ZjV2Gj.webp 1280w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_Z1CWfRy.webp 1668w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_ZpkSUX.webp 2048w, https://cloudchristoph.com/_astro/aad-app-proxy-check.B8I-K53I_LKBH8.webp 2105w&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you have more useful sites, let me know!&lt;/p&gt;
</content:encoded><category>Tooling &amp; Workshops</category></item></channel></rss>