Jekyll2023-10-10T17:53:06+02:00https://nicolgit.github.io/feed.xmlNicolD blogNicola Delfino's blogNicola Delfinonicola.delfino@outlook.comMoving a virtual machine between availability zones in Azure2023-10-10T10:00:00+02:002023-10-10T10:00:00+02:00https://nicolgit.github.io/Moving-a-virtual-machine-between-availability-zones-in-Azure<p>In this blog post, I show how to handle 2 typical virtual machine move operations on Azure.</p>
<h1 id="move-a-vm-from-no-infrasstructure-redundancy-to-a-specific-availability-zone">Move a VM from “no infrasstructure redundancy” to a specific Availability Zone</h1>
<p>This scenario is supported by the Azure portal. Let’s start from a VM with the following characteristics:</p>
<ul>
<li>Name: <code class="language-plaintext highlighter-rouge">machine-01</code></li>
<li>Linux</li>
<li>OS disk LRS 30Gb</li>
</ul>
<p>to move this VM to a specific Availability Zone, from Azure portal go to:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">machine-01</code> > availability + scaling > Availability Zones > get Started</li>
<li>select Target Availability Zone > <code class="language-plaintext highlighter-rouge">Zone 1</code></li>
</ul>
<p>in this migration:</p>
<ul>
<li>A new virtual machine is created</li>
<li>New NIC is created along with the zonal VM</li>
<li>you can optionally change target virtual network and subnet</li>
<li>VM will be stopped during the process to avoid data loss. There will be a brief downtime of few minutes and copy of VM(s) will be created in the target zone</li>
<li>the machine created will be in another resource group</li>
</ul>
<p>at the end of the moving process, you can safetly delete the source machine.</p>
<h1 id="move-a-vm-from-an-availability-zone-to-another">Move a VM from an availability zone to another</h1>
<p>This is unsupported.</p>
<p>Transform a VM from “availability zone xx” to “no infrastructure redundancy” is also not supported.</p>
<p>If you need to change availability zone to a VM you can follow these steps:</p>
<ul>
<li>Turn-off source VM</li>
<li>Create a full snapshot (ZRS) of the OS disk</li>
<li>Create a managed disk from the snapshot, in the availability zone target</li>
<li>Select the OS disk created, and select [create VM] from the disk</li>
</ul>
<p>More information:</p>
<ul>
<li>Availiability Zones: https://learn.microsoft.com/en-gb/azure/reliability/availability-zones-overview?tabs=azure-cli</li>
<li>https://learn.microsoft.com/en-us/azure/virtual-machines/attach-os-disk?tabs=portal</li>
</ul>Nicola Delfinonicola.delfino@outlook.comIn this blog post, I show how to handle some typical virtual machine move operations on Azure.Implementing cross HUBs routing in Azure2023-01-04T10:00:00+01:002023-01-04T10:00:00+01:00https://nicolgit.github.io/Implementing%20routing%20cross%20HUBs%20in%20Azure<p>Hub and spoke topology is often recommended in cloud architectures for several reasons:</p>
<ul>
<li><strong>Simplicity</strong>: Hub and spoke networks are relatively simple to set up and manage, which makes them a good choice for cloud environments where resources may be scarce or limited.</li>
<li><strong>Cost-effectiveness</strong>: In a cloud environment, resources are typically shared among multiple users or tenants, which makes cost-effectiveness a key consideration. Hub and spoke networks are generally more cost-effective than other types of network topologies, as they require fewer connections and a simpler management.</li>
<li><strong>Scalability</strong>: Cloud environments are designed to be highly scalable, and the hub and spoke topology is easily scalable, as additional spokes can be easily added to the network by connecting them to the central hub.</li>
<li><strong>Performance</strong>: In a cloud environment, it is important to optimize performance to ensure that users have a good experience. Hub and spoke networks can be configured to optimize performance, as the central hub can be used to route traffic and balance the load on the network.</li>
<li><strong>Security</strong>: Hub and spoke networks can be configured to provide enhanced security by implementing measures such as firewalls and intrusion detection systems at the central hub. This can help protect the network and the data it carries from external threats.</li>
</ul>
<blockquote>
<p>Overall, the simplicity, cost-effectiveness, scalability, performance, and security of hub and spoke networks make them a good choice for many cloud architectures.</p>
</blockquote>
<p><strong>Often a single hub may not be sufficient for an organization</strong>. There are several reasons why an organization might need to implement more than one hub and spoke topology in a cloud environment:</p>
<ul>
<li><strong>Redundancy</strong>: In a cloud environment, it is important to have redundancy in place to ensure that the network is highly available and resilient to failures. Implementing multiple hub and spoke topologies can provide additional redundancy and ensure that the network remains operational in the event of a failure.</li>
<li><strong>Scale</strong>: As an organization’s cloud environment grows, it may need to implement additional hub and spoke topologies to support the increased number of devices, services and users on the network.</li>
<li><strong>Performance</strong>: If an organization has a large number of devices and users on its network, it may need to implement multiple hub and spoke topologies to optimize performance. By distributing the load across multiple hubs, the organization can ensure that the network performs well and provides a good experience for all users.</li>
<li><strong>Security</strong>: Implementing multiple hub and spoke topologies can help to enhance security in a cloud environment. For example, an organization might use separate hub and spoke topologies for different types of data or for different user groups, in order to better protect sensitive information (test, production…)</li>
<li><strong>Geography</strong>: If an organization has users and devices located in different geographic regions, it might need to implement multiple hub and spoke topologies to provide local connectivity and optimize performance for users in each region.</li>
</ul>
<blockquote>
<p>Overall, there are many reasons why an organization might need to implement more than one hub and spoke topology in a cloud environment. By carefully planning and designing the network, an organization can ensure that it has the resources and capabilities it needs to support its cloud environment and its users.</p>
</blockquote>
<p>When multiple Hubs are in place, often a cross hub communication and routing is required.</p>
<p><strong>In this blog article, I’ll show you how to arrange the routing between two Hubs that are peering with each other so that all spokes in both Hubs can communicate with one other.</strong></p>
<blockquote>
<p>This is an approach that, once understood, can be extended to scenarios with more than 2 Hubs easily.</p>
</blockquote>
<p>The entire configuration is described by the following schema:</p>
<p><img src="https://raw.githubusercontent.com/nicolgit/hub-and-spoke-playground/main/images/routing-without-bgp-fw.png" alt="multi-hub routing architecture" /></p>
<p>As you can see, we have 2 Hubs, the first one with 3 peering networks and the second with one peered network. These 2 Hubs are connected to each other with an additional peering.</p>
<p><em>The first step</em> is to ensure that all outbound traffic from each peered network is forwarded to the corresponding firewall in the Hub. This is easly accomplished with a user-defined route as described below:</p>
<table>
<thead>
<tr>
<th>spoke</th>
<th>user defined route table</th>
</tr>
</thead>
<tbody>
<tr>
<td>spoke-01</td>
<td>0.0.0.0/0 -> 10.12.3.4 (firewall IP on Hub 1)</td>
</tr>
<tr>
<td>spoke-02</td>
<td>0.0.0.0/0 -> 10.12.3.4 (firewall IP on Hub 1)</td>
</tr>
<tr>
<td>spoke-03</td>
<td>0.0.0.0/0 -> 10.12.3.4 (firewall IP on Hub 1)</td>
</tr>
<tr>
<td>spoke-04</td>
<td>0.0.0.0/0 -> 10.14.3.4 (firewall IP on Hub 2)</td>
</tr>
</tbody>
</table>
<p><em>The second step</em> regards tjhe firewalls, on each firewall (here we are using 2 Azure Firewalls), we need to ensure that any source network can reach any target network. This is possibile with the following network policy rule, associated to both firewalls:</p>
<table>
<thead>
<tr>
<th>source</th>
<th>port</th>
<th>destination</th>
<th>action</th>
</tr>
</thead>
<tbody>
<tr>
<td>10.13.1.0/24</td>
<td>any</td>
<td>*</td>
<td>allow</td>
</tr>
<tr>
<td>10.13.2.0/24</td>
<td>any</td>
<td>*</td>
<td>allow</td>
</tr>
<tr>
<td>10.13.3.0/24</td>
<td>any</td>
<td>*</td>
<td>allow</td>
</tr>
<tr>
<td>10.13.4.0/24</td>
<td>any</td>
<td>*</td>
<td>allow</td>
</tr>
</tbody>
</table>
<p>If you want to block some protocol, port or IP, this is easily possible working on the specific Hub policy.</p>
<p><em>As third step</em>, you have to instruct the <em>hub-lab-net</em> firewall that <code class="language-plaintext highlighter-rouge">spoke-04</code> is reachable through the <code class="language-plaintext highlighter-rouge">hub-lab-02-net</code> firewall. Also, all outbound traffic must be routed to the Internet. This is possible with the following user-defined route on firewall’s subnet:</p>
<ul>
<li>10.15.1.0/24 (spoke-04 network) -> 10.14.3.4 (firewall in hub-lab-02-net)</li>
<li>0.0.0.0/0 -> internet</li>
</ul>
<p>In the same way the <code class="language-plaintext highlighter-rouge">hub-lab-02-net</code> firewasll needs to know where to forward traffic for <code class="language-plaintext highlighter-rouge">hub-lab-net</code>’s spokes</p>
<ul>
<li>10.13.1.0/24 (spoke-01 network) -> 10.13.3.4 (firewall in hub-lab-net)</li>
<li>10.13.2.0/24 (spoke-02 network) -> 10.13.3.4 (firewall in hub-lab-net)</li>
<li>10.13.3.0/24 (spoke-03 network) -> 10.13.3.4 (firewall in hub-lab-net)</li>
<li>0.0.0.0/0 -> internet</li>
</ul>
<p><strong>…and that’all folks!</strong> Now, from <strong>any</strong> machine, on any spoke, you can reach all the others.</p>
<p>On <a href="https://github.com/nicolgit/hub-and-spoke-playground/blob/main/scenarios/routing-without-bgp-fw.md">this page</a> you can find a <em>detailed step by step walktrough</em> to implement this scenario.</p>
<blockquote>
<p>The above walktrough is part of <a href="https://github.com/nicolgit/hub-and-spoke-playground"><strong>The Azure hub and spoke playground</strong></a>: a GitHub repo where you can find a reference network architecture I use as common base to implement configurations and test networking and connectivity scenarios.</p>
</blockquote>
<p>More information:</p>
<ul>
<li>Azure <a href="https://github.com/nicolgit/hub-and-spoke-playground">Hub and Spoke playground</a> on GitHub</li>
<li>Azure <a href="https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli">hub-spoke network topology</a> explained in the Azure Architecture center</li>
<li>What is the <a href="https://learn.microsoft.com/en-us/azure/firewall/overview">Azure Firewall</a></li>
<li>Understanding <a href="https://learn.microsoft.com/en-us/azure/firewall-manager/policy-overview">Azure Firewall policies</a></li>
<li>How Azure <a href="https://learn.microsoft.com/en-us/azure/virtual-network/virtual-networks-udr-overview#custom-routes">custom routes</a> work.</li>
</ul>Nicola Delfinonicola.delfino@outlook.comIn this blog article, I'll show you how to arrange the routing between two Hubs that are peering with each other so that all spokes in both Hubs can communicate with one other.Measuring latency between Azure Availabity Zones and the impact of an NVA in between2022-10-10T10:00:00+02:002022-10-10T10:00:00+02:00https://nicolgit.github.io/azure-measuring-latency-across-availability-zones-in-we<p><a href="https://www.techtarget.com/whatis/definition/latency">Latency</a> is an expression of how much time it takes for a data packet to travel from one designated point to another. Ideally, latency will be as close to zero as possible. High network latency can <strong>dramatically increase webpage load times</strong>, interrupt video and audio streams, and render an application unusable. Depending on the application, even a relatively small increase in latency can ruin UX.</p>
<p><a href="https://docs.microsoft.com/en-us/azure/availability-zones/az-overview">Azure availability zones</a> are physically separate locations within each Azure region that are tolerant to local failures. <strong>Azure availability zones are connected by a high-performance network with a round-trip latency of less than 2ms</strong>.</p>
<p>Each data center is assigned to a physical zone. Physical zones are mapped to logical zones in your Azure subscription. You can design resilient solutions by using Azure services that use availability zones. Co-locate your compute, storage, networking, and data resources across an availability zone, and replicate this arrangement in other availability zones.</p>
<p>A <a href="https://azure.microsoft.com/en-us/blog/announcing-the-general-availability-of-proximity-placement-groups/">proximity placement group</a> is an Azure Virtual Machine logical grouping capability that you can use to decrease the inter-VM network latency associated with your applications. When the VMs are deployed within the same proximity placement group, they are physically located as close as possible to each other.</p>
<p>Understanding the latency implications of different network configurations when designing an architecture is <strong>essential</strong>.</p>
<p>In this blog post I measure the latency between virtual machines deployed in Azure’s <strong>West Europe region</strong> in the following configurations:</p>
<ul>
<li>same v-net, same availability zone, same proximty placement group</li>
<li>same v-net, across availability zones</li>
<li>multiple v-nets (in peering), same availability zone</li>
<li>multiple v-nets (in peering), across availability zones</li>
<li>multiple v-nets connected in a Hub & Spoke topology and Routing via <a href="https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpngateways">Azure Virtual Network Gateway</a></li>
<li>multiple v-nets connected in a Hub & Spoke topology and Routing via <a href="https://docs.microsoft.com/en-us/azure/firewall/overview">Azure Firewall</a></li>
</ul>
<p>Rather than the absolute values, my focus is on assessing the impact in terms of latency of various network configurations.</p>
<p>To measure latency, I’ve used <a href="https://en.wikipedia.org/wiki/MTR_(software)">MTR</a>, which combines the functions of the traceroute and ping programs in one single network diagnostic tool.</p>
<blockquote>
<p>please note that MTR are the round-trip times for an ICMP packet to reach the hop at which its TTL expires, for the device processing that expiration to generate an ICMP Time Exceeded packet, and for that packet to return to the originating device. For many routers, performing the ICMP response for dropped packets is a low priority–and on some devices, it’s disabled entirely.</p>
</blockquote>
<blockquote>
<p>The <a href="https://github.com/nicolgit/hub-and-spoke-playground"><strong>Azure hub and spoke playground</strong></a> is a GitHub repo where you can find a reference network architecture I use as common base to implement configurations and test networking and connectivity scenarios. I have used it also here as starting point to build the lab used in this post.</p>
</blockquote>
<h1 id="scenario-1---one-virtual-network">Scenario 1 - one virtual network</h1>
<p>In this scenario I have a calling machine in one availability zone and 3 additional machines each in a different availability zone. In availability zone 1 I have also placed both machines in the same proximity placement group to have the best possible latency.</p>
<p><img src="../../assets/post/2022/latency-scenario-1.png" alt="same network" /></p>
<p>Here the measures from <code class="language-plaintext highlighter-rouge">spoke01-az-01</code> (availability zone 1).</p>
<table>
<thead>
<tr>
<th>commamd</th>
<th>Av Zone</th>
<th>Snt</th>
<th>Last</th>
<th>Avg</th>
<th>Best</th>
<th>Wrst</th>
<th>StDev</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.1.6</code></td>
<td>1</td>
<td>89</td>
<td>1.1</td>
<td><strong>1.4</strong></td>
<td>0.8</td>
<td>8.4</td>
<td>1.1</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.1.7</code></td>
<td>2</td>
<td>32</td>
<td>2.4</td>
<td><strong>2.1</strong></td>
<td>1.8</td>
<td>2.6</td>
<td>0.2</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.1.8</code></td>
<td>3</td>
<td>32</td>
<td>2.0</td>
<td><strong>2.1</strong></td>
<td>1.8</td>
<td>2.5</td>
<td>0.2</td>
</tr>
</tbody>
</table>
<p>Takeaways:</p>
<ul>
<li><strong>Proximity Placement Group does a great job</strong>, latency is at an average of 1.4ms</li>
<li>Jumping between availability zones, I have measured an average latency of 2.1ms, more than the 2ms declared but more than acceptable considering how this measure has been done.</li>
</ul>
<h1 id="scenario-2---two-virtual-networks-in-peering">Scenario 2 - two virtual networks in peering</h1>
<p>In this scenario I have measured the impact of a network peering. I have created 3 more machines, in 3 availability zones, on another network, in peering.</p>
<p><img src="../../assets/post/2022/latency-scenario-2.png" alt="peering" /></p>
<p>Here the measures from <code class="language-plaintext highlighter-rouge">spoke01-az-01</code> (availability zone 1) to machines in another virtual network in peering.</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Av Zone</th>
<th>Snt</th>
<th>Last</th>
<th>Avg</th>
<th>Best</th>
<th>Wrst</th>
<th>StDev</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.5</code></td>
<td>1</td>
<td>13</td>
<td>15.5</td>
<td><strong>2.3</strong></td>
<td>0.9</td>
<td>15.5</td>
<td>4.0</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.6</code></td>
<td>2</td>
<td>32</td>
<td>3.1</td>
<td><strong>2.3</strong></td>
<td>2.0</td>
<td>3.5</td>
<td>0.3</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.7</code></td>
<td>3</td>
<td>39</td>
<td>2.3</td>
<td><strong>2.4</strong></td>
<td>1.8</td>
<td>3.3</td>
<td>0.3</td>
</tr>
</tbody>
</table>
<p>Takeaways:</p>
<ul>
<li>Network peering adds an average overhead of just 0.2ms, still a more than acceptable value</li>
<li>Here I am not using a proximity group anymore and the result is that <strong>average latency doesn’t change so much if the machine is within same availability zone, or on another one</strong></li>
</ul>
<h1 id="scenario-3---two-virtual-networks-in-hs-configuration-with-a-virtual-network-gateway-in-between">Scenario 3 - two virtual networks in H&S configuration with a Virtual Network Gateway in between</h1>
<p>In this scenario I moved to a more classic configuration: I eliminated peering and routed traffic through a central hub and an Azure Virtual Network Gateway.</p>
<p><img src="../../assets/post/2022/latency-scenario-3-4.png" alt="hub-and-spoke" /></p>
<p>Here the measures from <code class="language-plaintext highlighter-rouge">spoke01-az-01</code> (availability zone 1) to machines in another virtual network via an Azure Virtual Network Gateway in the Hub Network.</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Av Zone</th>
<th>Snt</th>
<th>Last</th>
<th>Avg</th>
<th>Best</th>
<th>Wrst</th>
<th>StDev</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.5</code></td>
<td>1</td>
<td>47</td>
<td>4.2</td>
<td><strong>3.4</strong></td>
<td>1.6</td>
<td>24.4</td>
<td>4.2</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.6</code></td>
<td>2</td>
<td>35</td>
<td>2.9</td>
<td><strong>4.3</strong></td>
<td>2.8</td>
<td>12.3</td>
<td>2.6</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.7</code></td>
<td>3</td>
<td>36</td>
<td>3.4</td>
<td><strong>4.5</strong></td>
<td>2.8</td>
<td>15.7</td>
<td>3.1</td>
</tr>
</tbody>
</table>
<p>Takeaways</p>
<ul>
<li>Latency increased up to <strong>3.4/4.5ms</strong>, because each packet have to cross 2 peerings and a virtual appliace (Azure Virtual Network Gateway)</li>
<li><strong>Staying in the same availability zone also have a positive impact on latency</strong>: an average of +1ms in cross availability zone topology is not huge in se, but is a relative increase quite high (+50%)</li>
</ul>
<h1 id="scenario-4---two-virtual-networks-in-hs-configuration-with-an-azure-firewall-in-between">Scenario 4 - two virtual networks in H&S configuration with an Azure Firewall in between</h1>
<p>In this last scenario I implemented the <a href="https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke">reference architecture described in the cloud adoption framework</a>, that is a hub and spoke, with an Azure Firewall to control all the traffic.</p>
<p><img src="../../assets/post/2022/latency-scenario-3-4.png" alt="hub and spoke" /></p>
<p>Here the measures from <code class="language-plaintext highlighter-rouge">spoke01-az-01</code> (availability zone 1) to machines in another virtual network and different availability zones, via Azure Firewall in the Hub Network.</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Av Zone</th>
<th>Snt</th>
<th>Last</th>
<th>Avg</th>
<th>Best</th>
<th>Wrst</th>
<th>StDev</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.5</code></td>
<td>1</td>
<td>58</td>
<td>2.4</td>
<td><strong>2.3</strong></td>
<td>1.8</td>
<td>5.7</td>
<td>0.6</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.6</code></td>
<td>2</td>
<td>34</td>
<td>3.4</td>
<td><strong>3.1</strong></td>
<td>2.6</td>
<td>4.3</td>
<td>0.3</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">mtr 10.13.2.7</code></td>
<td>3</td>
<td>30</td>
<td>3.7</td>
<td><strong>3.4</strong></td>
<td>2.9</td>
<td>3.9</td>
<td>0.3</td>
</tr>
</tbody>
</table>
<p>Takeaways</p>
<ul>
<li>Latency is far better than an Azure Virtual Network Gateway with Azure Firewall in between</li>
<li><strong>When source and destination are in the same availability zone it has almost the same as for a simple peering</strong></li>
<li>When source and destination are <strong>in different availabity zones, latency grows up to 3.1/3.4ms</strong></li>
</ul>
<h1 id="final-thoughts">Final thoughts</h1>
<ul>
<li>Where possible use <strong>always Proximity Placement Groups</strong> to have sub 2ms latency</li>
<li>Traffic between zones is confirmed to be <strong>on the order of 2ms</strong></li>
<li>Peerings and hub-and-spoke <strong>have no real impac</strong>t if a Firewall is used in the middle</li>
<li>I would avoid to use a VPN Gateway for <strong>cross spokes communications</strong></li>
</ul>Nicola Delfinonicola.delfino@outlook.comIn this post I measure the latency between virtual machines in various network configurations on AzureAzure AD OAuth client credential flow with custom certificate walk-through2022-06-01T10:00:00+02:002022-06-01T10:00:00+02:00https://nicolgit.github.io/azure-ad-oauth-client-credential-flow-certificate-walk-through<p>You can use the OAuth 2.0 client credentials grant specified in RFC 6749, to access web-hosted resources by using the identity of an application. This type of grant is commonly used for server-to-server interactions that must run in the background, without immediate interaction with a user.</p>
<p>The OAuth 2.0 client credentials grant flow permits a web service (confidential client) to use its own credentials, instead of impersonating a user, to authenticate when calling another web service. For a higher level of assurance, the Microsoft Identity Platform also allows the calling service to authenticate using a certificate or federated credential instead of a shared secret.</p>
<p>In this walk-through I show how to <strong>use a certificate to request an access token to Azure Active Directory</strong>, using the OAuth 2.0 client credential flow. As client I use a custom c# DotNet 6 application and MSAL Library.</p>
<blockquote>
<p>Alternatively, it is possible to use any other library able <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format">to compute an assertion</a>, and <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#second-case-access-token-request-with-a-certificate">post it</a> to Azure Active Directory.</p>
</blockquote>
<h1 id="01---app-registration">01 - App registration</h1>
<p>On your <a href="https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-whatis">Azure Active Directory</a>, create an app registration:</p>
<ul>
<li>Open https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps</li>
<li>Click [New Registration]</li>
</ul>
<p>use the following parameters:</p>
<ul>
<li>Name: <code class="language-plaintext highlighter-rouge">my-sample-app-registration</code></li>
<li>Supported account Types: <code class="language-plaintext highlighter-rouge">Accounts in this organizational directory only</code></li>
<li>click [Register]</li>
</ul>
<h1 id="02---create-and-upload-a-certificate-in-azure-ad">02 - Create and upload a certificate in Azure AD</h1>
<p>You can use Azure to create a self signed certificate.</p>
<ul>
<li>Open an instance of <a href="https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts">Azure Key Vault</a> or create a new one if needed.</li>
<li>From Azure Key vault open <code class="language-plaintext highlighter-rouge">Certificates</code> blade and click on [Generate or Import]</li>
</ul>
<p>use the following parameters:</p>
<ul>
<li>Method: <code class="language-plaintext highlighter-rouge">Generate</code></li>
<li>Certificate Name: <code class="language-plaintext highlighter-rouge">my-sample-certificate</code></li>
<li>Type of CA: <code class="language-plaintext highlighter-rouge">Self-signed Certificate</code></li>
<li>Subject: <code class="language-plaintext highlighter-rouge">CN=my-sample-common-name</code></li>
<li>Valid Period: <code class="language-plaintext highlighter-rouge">12 months</code></li>
<li>Type:<code class="language-plaintext highlighter-rouge">PKCS #12</code></li>
<li>Click [Create]</li>
</ul>
<p>When certificate creation is completed:</p>
<ol>
<li>Download certificate in PFX/PEM format (with private key).</li>
<li>Download certificate in .CER format (without private key).</li>
</ol>
<blockquote>
<p>NOTE: A .pfx file includes both the <strong>public and private key</strong> for the associated certificate. A .cer file only has the <strong>public key</strong>, it can be used to verify tokens or client authentication requests.</p>
</blockquote>
<p>Now, go to the <code class="language-plaintext highlighter-rouge">Application Registration</code> just created, select <code class="language-plaintext highlighter-rouge">Certificates and Secrets</code> and upload the certificate <strong>.CER</strong> just created.</p>
<p>The result will be something like:</p>
<table>
<thead>
<tr>
<th>Thumbprint</th>
<th>description</th>
<th>start date</th>
<th>expires</th>
<th>id</th>
</tr>
</thead>
<tbody>
<tr>
<td>4DDASE(sample)…</td>
<td>my-sample-certificate</td>
<td>…</td>
<td>…</td>
<td>1aa986a(sample) …</td>
</tr>
</tbody>
</table>
<h1 id="03---create-dotnet-6-client-application">03 - Create DotNet 6 client application</h1>
<p>Create a directory on your machine, and copy there the <strong>.PFX</strong> file downloaded previously.</p>
<p>Create the following <code class="language-plaintext highlighter-rouge">client-certificate-test.csproj</code> file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>client_certificate_test</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Identity.Web.Certificate" Version="1.25.0" />
<PackageReference Include="Microsoft.Identity.Web.TokenCache" Version="1.25.0" />
</ItemGroup>
</Project>
</code></pre></div></div>
<p>create also the following <code class="language-plaintext highlighter-rouge">program.cs</code> file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
namespace daemon_console
{
// For more information see https://aka.ms/msal-net-client-credentials
class Program
{
static void Main(string[] args)
{
try
{ RunAsync().GetAwaiter().GetResult(); }
catch (Exception ex)
{ Console.WriteLine(ex.Message); }
}
private static string certificateFullPath = "C:\\temp\\client-certificate-test\\nicold-my-sample-certificate-20220614.pfx"; // Replace with your certificate path
private static string applicationID="ace7a10d-aaaa-4a01-8663-1440b6b78cb9"; // replace with your application ID
private static string authority="https://login.microsoftonline.com/dac2b1d5-5420-4fad-889e-1280ffdc8003/"; // replace with your AAD authority
private static async Task RunAsync()
{
ICertificateLoader certificateLoader = new DefaultCertificateLoader();
// full path Certificate File
var myCertificate = X509Certificate2.CreateFromCertFile(certificateFullPath);
X509Certificate2 myCertificate2 = new X509Certificate2(myCertificate);
var app = ConfidentialClientApplicationBuilder.Create(applicationID)
.WithCertificate(myCertificate2)
.WithAuthority(new Uri(authority)) // Tenant ID
.Build();
app.AddInMemoryTokenCache();
// With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the
// application permissions need to be set statically (in the portal or by PowerShell), and then granted by
// a tenant administrator.
string[] scopes = new string[] { "https://graph.microsoft.com/.default" }; // Generates a scope -> "https://graph.microsoft.com/.default"
//string[] scopes = new string[] { "api://ace7a10d-aaaa-4a01-8663-1440b6b78cb9/.default" }; // custom API on same tenant
AuthenticationResult result = null;
try
{
result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
Console.WriteLine("Token acquired");
Console.WriteLine("Token: " + result.AccessToken);
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
// Invalid scope. The scope has to be of the form "https://resourceurl/.default"
// Mitigation: change the scope to be as expected
Console.WriteLine("Scope provided is not supported");
}
}
}
}
</code></pre></div></div>
<blockquote>
<p>Note. Update this code with your <strong>ApplicationId</strong>, <strong>certificate file path</strong> and your <strong>authority URI</strong></p>
</blockquote>
<p>Execute this application from Visual Studio Code. If everything works you will receive an output similar to:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Token acquired
Token: eyJ0eXAiOi(more...).eyJhdWQiOiJodHRwczovL2dyYXBoL(more...)HyKJ.fGZvr(more...)1QbbdYQ
</code></pre></div></div>
<p>copy encoded Token and paste it in https://jwt.ms. You should see something similar to the following:</p>
<p><img src="/assets/post/2022/jwt-token-sample.png" alt="jwt.ms" /></p>
<p>As you can see you have an <strong>Access Token</strong> able to call <strong>Migrosoft Graph</strong> (<code class="language-plaintext highlighter-rouge">aud</code> field), issued by <strong>Azure AD</strong> (<code class="language-plaintext highlighter-rouge">iid</code> and <code class="language-plaintext highlighter-rouge">idp</code> fields).</p>
<h1 id="more-information">More information</h1>
<ul>
<li>Microsoft Identity OAuth 2.0 client credentials flow: <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow">https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow</a></li>
<li>Create a certificate in Azure Key Vault: <a href="https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal ">https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal </a></li>
<li>Certificate Credential, Assertion Format: <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials">https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials</a></li>
<li>MSAL Microsoft Authenticatio Library: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-overview</li>
<li>A .NET Core daemon console application using MSAL.NET to acquire tokens for resources: <a href="https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2">https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2</a></li>
<li>.NET 6: <a href="https://docs.microsoft.com/it-it/dotnet/fundamentals/">https://docs.microsoft.com/it-it/dotnet/fundamentals/</a></li>
<li>Visual Studio Code: <a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></li>
</ul>Nicola Delfinonicola.delfino@outlook.comIn this walk-through I show how to use a certificate to request an access token to Azure Active Directory, using the OAuth 2.0 client credential flowAllowing DNS resolution of Azure resources from on-premise2022-04-27T10:00:00+02:002022-04-27T10:00:00+02:00https://nicolgit.github.io/dns-forwarding-azure-hub-and-spoke<p>For many organizations, the <a href="https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/">Azure landing zone conceptual architecture</a> represents the destination in their cloud adoption journey. It’s a mature, scaled-out target architecture intended to help organizations operate successful cloud environments that drive their business while maintaining best practices for security and governance.</p>
<p>In this architecture, the <a href="https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke">hub virtual network</a> acts as a central point of connectivity to many spoke virtual networks. The hub can also be used as the connectivity point to your on-premises networks. The spoke virtual networks peer with the hub and can be used to isolate workloads. The benefits of using a hub and spoke configuration include cost savings, overcoming subscription limits, and workload isolation.</p>
<p>Typical uses for this architecture include:</p>
<ul>
<li>Workloads deployed in different environments, such as development, testing, and production, that require shared services such as DNS, IDS, NTP, or AD DS.</li>
<li>Shared services are placed in the hub virtual network, while each environment is deployed to a spoke to maintain isolation.</li>
<li>Workloads that don’t require connectivity to each other but require access to shared services.</li>
<li>Enterprises that require central control over security aspects, such as a firewall in the hub as a DMZ, and segregated management for the workloads in each spoke.</li>
</ul>
<p>The architecture consists of the following aspects:</p>
<ul>
<li><strong>Hub virtual network</strong>: The hub virtual network is the central point of connectivity to your on-premises network. It’s a place to host services that can be consumed by the different workloads hosted in the spoke virtual networks.</li>
<li><strong>Spoke virtual networks</strong>: Spoke virtual networks are used to isolate workloads in their own virtual networks, managed separately from other spokes. Each workload might include multiple tiers, with multiple subnets connected through Azure load balancers.</li>
<li><strong>Virtual network peering</strong>: Two virtual networks can be connected using a peering connection. Peering connections are non-transitive, low latency connections between virtual networks. Once peered, the virtual networks exchange traffic by using the Azure backbone without the need for a router.</li>
<li><strong>Bastion Host</strong>: Azure Bastion lets you securely connect to a virtual machine using your browser and the Azure portal. An Azure Bastion host is deployed inside an Azure Virtual Network and can access virtual machines in the VNet, or virtual machines in peered VNets.</li>
<li><strong>Azure Firewall</strong>: Azure Firewall is a managed firewall as a service. The Firewall instance is placed in its own subnet.</li>
<li><strong>VPN virtual network gateway or ExpressRoute gateway</strong>. The virtual network gateway enables the virtual network to connect to the VPN device, or ExpressRoute circuit, used for connectivity with your on-premises network.</li>
</ul>
<p><strong>One of the problems to address in this type of deployment is the DNS resolultion: resources on-premises, connected via S2S VPN to Azure need to resolve names for services hosted on Azure.</strong></p>
<p>To simplify the private DNS resolution, Azure provides <a href="https://docs.microsoft.com/en-us/azure/dns/private-dns-overview">Azure Private DNS Service</a>: a reliable and secure DNS service for your virtual network. Azure Private DNS manages and resolves domain names in the virtual network without the need to configure a custom DNS solution. By using private DNS zones, you can use your own custom domain name instead of the Azure-provided names during deployment. Using a custom domain name helps you tailor your virtual network architecture to best suit your organization’s needs. It provides a naming resolution for virtual machines (VMs) within a virtual network and connected virtual networks.</p>
<p>Once created, an <a href="https://docs.microsoft.com/en-us/azure/dns/private-dns-virtual-network-links">Azure private DNS Zone can be linked to an Azure Virtual Network</a>: in this way all VM and services connected to it <strong>automagically</strong> can resolve names managed by the private zone.</p>
<p><strong>This means that this service is available only within Azure. On premise resources even if connected via VPN S2S can’t benefit of this names resolution.</strong></p>
<h1 id="how-can-i-integrate-my-on-premises-dns-with-azure">How can I integrate my on premises DNS with Azure?</h1>
<p>As mentioned above, Azure Firewall is a cloud-native firewall as a service (FWaaS) offering that allows you to centrally govern and log all your traffic flows using a DevOps approach. The service supports both application, NAT, and network-level filtering and is integrated with the Microsoft Threat Intelligence feed for filtering known malicious IP addresses and domains. Azure Firewall is highly available with built-in auto scaling. <a href="https://azure.microsoft.com/it-it/blog/new-enhanced-dns-features-in-azure-firewall-now-generally-available/">Azure Firewall is also well integrated with Azure DNS resolution</a>. With his DNS proxy enabled, Azure Firewall can process and forward DNS queries from a Virtual Network(s) to your desired DNS server. You can enable DNS proxy in Azure Firewall and Firewall Policy settings.</p>
<p>In an Hub and Spoke architecture, with an on premises datacenter connected, Azure Firewall can act as DNS forwarder, as described in the schema below:</p>
<p><img src="https://github.com/nicolgit/hub-and-spoke-playground/blob/main/images/dns.png?raw=true" alt="dns architecture" /></p>
<ul>
<li>Lin-onprem-2 is a server/PC “outside” Azure, in your own datacenter.</li>
<li>Lin-onprem-2 uses Lin-onprem as default DNS server (1)</li>
<li>Your datacenter is connected to Azure via a S2S VPN</li>
<li>On Azure, you have <strong>cloudasset.internal</strong>: a private DNS zone you are using to resolve names of your VMs on Azure</li>
<li>You have linked to this private DNS zone all your Azure Virtual Networks with <strong>auto registration</strong> enabled: so all VM have an FQDN on that domain</li>
<li>on Lin-onprem you are running <a href="https://www.isc.org/bind/">Bind9</a> as DNS. Because you have the Azure Firewall DNS Proxy service enabled in the hub, you can configure Azure Firewall private IP as DNS Forwarder (2)</li>
<li>on Azure Firewall, you configure Azure Managed DNS as default DNS service, so the firewall can forward all request coming to it to Azure (3).</li>
</ul>
<p><strong>In this way on premises systems can benefit of Azure DNS resolution and Azure Private DNS Service.</strong></p>
<p>As PLUS, if you set as DNS server on all Azure Virtual Networks, Azure Firewall’s internal IP, you can avoid DNS resolution mismatches, and enable FQDN filtering in the network rules. This functionality is required to have reliable FQDN filtering in network rules. If you don’t enable DNS proxy, then DNS requests from the clients might travel to a DNS server at a different time or return a different response compared to that of the firewall. DNS proxy puts Azure Firewall in the path of the client requests to avoid inconsistency.</p>
<p>The <a href="https://github.com/nicolgit/hub-and-spoke-playground"><strong>hub and spoke playground</strong></a> is a repo I use as common baseline to implement configurations and test connectivity scenarios. On <a href="https://github.com/nicolgit/hub-and-spoke-playground/blob/main/scenarios/dns-on-prem.md"><strong>this page of the repo</strong></a>, you can find a step-by-step implementation of the scenario covered by this blog post.</p>Nicola Delfinonicola.delfino@outlook.comHow can I integrate my on-premises DNS with Azure?Azure Disk Burst in a nutshell2022-02-24T10:00:00+01:002022-02-24T10:00:00+01:00https://nicolgit.github.io/azure-disk-burst-in-a-nutshell<p>Azure offers the ability to boost disk storage <strong>IOPS</strong> and MB/s (<strong>throughput</strong>) performance. Currently, there are two managed disk types that can burst, premium SSDs, and standard SSDs. Other disk types cannot currently burst.</p>
<p>Disk bursting can be credit based or on demand.</p>
<h1 id="credit-based-bursting">Credit based bursting</h1>
<p>A burstable disk has for both IOPS and throughput, 2 values: max and bursting-max.</p>
<p>I.E. Azure Disk P1 have the following values:</p>
<ul>
<li>IOPS max: 120</li>
<li>IOPS max with burst: 3500</li>
<li>Throughput Max: 25Mb/sec</li>
<li>Throughput Max with burst: 170Mb/s</li>
</ul>
<p>during the disk usage, when the IOPS and throughput are below the max value, you earn <em><strong>credits</strong></em> you can use later. When a usage peak arrives, if you have credits, you can burst performance up to the <strong>max with burst</strong> value. During the burst the credits are used, so, when the credit finish or you have used the burst for 30 minutes in a day, the IOPS or the throughput are limited again to the <strong>max</strong> value.</p>
<p>30 minutes is a daily cap, you can use it consecutively or sporadically throughout the day.</p>
<p><img src="../../assets/post/2022/disk-bursting.png" alt="credit based bursting explained" /></p>
<p>This process is <strong>automatic</strong> and <strong>free of charge</strong>.</p>
<h1 id="on-demand-bursting">On demand bursting</h1>
<p>You can activate and deactivate on-demand burst via powershell or AZ CLI. It hasn’t a time limit, but have a cost (monthly fee + hourly fee). Generally must be verified the convenience of on demand bursting vs a disk with better performances. On demand bursting is ok for short load peaks well defined in time.</p>
<p>Note that <strong>also Azure virtual machines have a max IOPS and max throughput</strong>, so during the bursting, the real speed achieved is the minimum between the machine and disk max value.</p>
<h1 id="burstable-virtual-machines">Burstable Virtual Machines</h1>
<p>The concept of the burst can be applied also to Azure Virtual Machines. B-series machines have a base CPU performance and a max CPU performance. When the machine have CPU below the <strong>base</strong> value, collects credits to spend in performance bursts when necessary.</p>
<ul>
<li><a href="https://azure.microsoft.com/en-us/pricing/details/managed-disks/">https://azure.microsoft.com/en-us/pricing/details/managed-disks/</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-bursting?tabs=azure-powershell">https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-bursting?tabs=azure-powershell</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/virtual-machines/sizes-b-series-burstable">https://docs.microsoft.com/en-us/azure/virtual-machines/sizes-b-series-burstable</a></li>
</ul>Nicola Delfinonicola.delfino@outlook.comAzure offers the ability to boost disk storage IOPS and MB/s (throughput) performance. Currently, there are two managed disk types that can burst, premium SSDs, and standard SSDs. Other disk types cannot currently burst.Azure App Service Certificate2022-02-22T10:00:00+01:002022-02-22T10:00:00+01:00https://nicolgit.github.io/app-service-certificate-application-gateway<p>Azure <a href="https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.CertificateRegistration%2FcertificateOrders">App Service Certificate</a> can be also be used for other Azure services and not just App Service Web App. The list includes Virtual Machines and Azure Application Gateway.</p>
<p>In order to use the certificate outside Azure, you can export it from the Azure Portal.</p>
<p>Simply select:</p>
<ul>
<li>Settings</li>
<li>Export Certificate</li>
<li>click Key Vault</li>
<li>click on the current version and <strong>download as certificate</strong> button. (the script in the link below does not work correctly so you need to do it in this way).</li>
</ul>
<p>The .pfx created above will not include the chain certificates. Services such ad Azure App Services expect uploaded certificates to have all chain certificates included in the pfx file. In order for the chain certificates to be part of the pfx file, you must install the exported certificate on your computer. In this step <strong>make sure you have marked the certificate as exportable</strong>.</p>
<ul>
<li><a href="https://azure.github.io/AppService/2017/02/24/Creating-a-local-PFX-copy-of-App-Service-Certificate.html">https://azure.github.io/AppService/2017/02/24/Creating-a-local-PFX-copy-of-App-Service-Certificate.html</a></li>
</ul>
<p>It is possible to use App Cervice Certificate on Application Gateway, <a href="https://docs.microsoft.com/en-us/azure/application-gateway/key-vault-certs#supported-certificates">here there is the setup guide</a>.</p>
<p>Things to be noted:</p>
<ul>
<li>App Service Certificate puts the certificate under <strong>Key Vault</strong> > <strong>Secrets</strong> section</li>
<li>Application Gateway portal UI allows only to select a certificate available under <strong>Key Vault</strong> > <strong>Certificates Section</strong></li>
<li>in order to use a certificate in <strong>secrets</strong> section <strong>az cli</strong> or <strong>powershell</strong> must be used (see link above)</li>
<li>if you configure Application Gateway to use a certificate under Secrets <strong>you can benefit of the autorenew feature of the Azure App Service Certificate</strong>.</li>
</ul>
<p>Here insted you can find a guide to manually renew an Application Gateway Certificate: <a href="https://docs.microsoft.com/en-us/azure/application-gateway/renew-certificates">https://docs.microsoft.com/en-us/azure/application-gateway/renew-certificates</a></p>Nicola Delfinonicola.delfino@outlook.comnotes on how to use App Svc CertificatesAzure - Hub and Spoke - Playground2022-01-12T10:00:00+01:002022-01-12T10:00:00+01:00https://nicolgit.github.io/azure-hub-and-spoke-playground<p>For my current job, often I have to do tests and/or double-checks on network configurations.</p>
<p>For a 5 minutes test, however, can happen that an entire hub-and-spoke, fully configured is required. Maintaining such type of architecture always-on, on my test subscription is <strong>expensive</strong>, so I often found myself loosing 2 hours to prepare everything, and after 3-clicks, my test, to delete everything.</p>
<p>To reduce this waste of time I have created a pre-configured <em>playground</em> with the schema below, deployable with just a click (ok maybe 3 if you want to deploy all pieces). It has saved me a lot of valuable time, and even some colleagues have found it particularly useful and practical to create and destroy.</p>
<p><img src="https://raw.githubusercontent.com/nicolgit/hub-and-spoke-playground/main/images/architecture.png" alt="hub and spoke playground" /></p>
<p>So I thought of making the repo public on github, hoping it would be useful to anyone. You can <strong>find</strong> the link at the end of this post.</p>
<p>On the same repo, there are also <em>some</em> “scenarios” that I have documented very synthetically, useful in this format to me as fast KB to preserve. Nothing that is not already available in various sauces on the net, the plus here is that the <strong>solution</strong> is implemented on the playground above, so names, IPs, networks, everything is consistent and easy to understand and verify.</p>
<p>Each Scenario have:</p>
<ul>
<li><strong>prerequisites</strong>: component to deploy required to implement the solutions (only the hub, also one on-prem playground or both)</li>
<li><strong>solution</strong>: a step-by-step sequence to implement the solution</li>
<li><strong>test solution</strong>: a procedure to follow, to verify if the scenario is working as expected</li>
</ul>
<p>at this time, I have already implemented the following scenarios:</p>
<ol>
<li>how to allow machines in any spoke to communicate with any machine in any other spoke</li>
<li>how to filter HTTP(S) outbound traffic</li>
<li>how to expose machines IP via the Azure Firewall</li>
<li>how to configure Site to Site VPN via vNet connection and IPSec</li>
<li>how to enable cross on-premises communication and routing</li>
</ol>
<p>more will be implemented in the future.</p>
<p>As any worthwhile alive repo on GitHub, you can <strong>star</strong> it, <strong>fork</strong> it, and <strong>use</strong> it as you like. If you’d like to see more scenarios implemented, or if you find an error, open an issue in GitHub or write me. If you want to collaborate adding <strong>YOU</strong> more scenarios, fork the repo and do a <strong>pull request</strong>, I’ll be happy to review it and add your contribution to the repo.</p>
<ul>
<li><strong>Here the repo link <a href="https://github.com/nicolgit/hub-and-spoke-playground">https://github.com/nicolgit/hub-and-spoke-playground</a></strong></li>
</ul>
<p>Thank you!</p>Nicola Delfinonicola.delfino@outlook.coma handy hub-and-spoke playground for your experiments, on Azure.NICOLTIP033 How to rename a virtual machine on Azure2022-01-05T10:00:00+01:002022-01-05T10:00:00+01:00https://nicolgit.github.io/how-to-rename-a-virtual-machine<p>It is not possible to rename a VM on azure. the only viable solution is to delete and re-create the machine.
This is the script I use to execute this task.</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#Set variables</span><span class="w">
</span><span class="nv">$resourceGroup</span><span class="o">=</span><span class="s2">"my-resource-group"</span><span class="w">
</span><span class="nv">$oldvmName</span><span class="o">=</span><span class="s2">"old-machine-name"</span><span class="w">
</span><span class="nv">$newvmName</span><span class="o">=</span><span class="s2">"new-machine-name"</span><span class="w">
</span><span class="c">#Get the details of the VM</span><span class="w">
</span><span class="nv">$originalVM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Get-AzVM</span><span class="w"> </span><span class="nt">-ResourceGroupName</span><span class="w"> </span><span class="nv">$resourceGroup</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="nv">$oldvmName</span><span class="w">
</span><span class="c">#Remove the original VM</span><span class="w">
</span><span class="n">Remove-AzVM</span><span class="w"> </span><span class="nt">-ResourceGroupName</span><span class="w"> </span><span class="nv">$resourceGroup</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="nv">$oldvmName</span><span class="w">
</span><span class="c">#Create the basic configuration for the replacement VM</span><span class="w">
</span><span class="nv">$newVM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">New-AzVMConfig</span><span class="w"> </span><span class="nt">-VMName</span><span class="w"> </span><span class="nv">$newvmName</span><span class="w"> </span><span class="nt">-VMSize</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">HardwareProfile</span><span class="o">.</span><span class="nf">VmSize</span><span class="w">
</span><span class="nx">Set-AzVMOSDisk</span><span class="w"> </span><span class="nt">-VM</span><span class="w"> </span><span class="nv">$newVM</span><span class="w"> </span><span class="nt">-CreateOption</span><span class="w"> </span><span class="nx">Attach</span><span class="w"> </span><span class="nt">-ManagedDiskId</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">StorageProfile</span><span class="o">.</span><span class="nf">OsDisk</span><span class="o">.</span><span class="nf">ManagedDisk</span><span class="o">.</span><span class="nf">Id</span><span class="w"> </span><span class="nt">-Name</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">StorageProfile</span><span class="o">.</span><span class="nf">OsDisk</span><span class="o">.</span><span class="nf">Name</span><span class="w"> </span><span class="nt">-Windows</span><span class="w">
</span><span class="c">#Add Data Disks</span><span class="w">
</span><span class="kr">foreach</span><span class="w"> </span><span class="p">(</span><span class="nv">$disk</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">StorageProfile</span><span class="o">.</span><span class="nf">DataDisks</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="n">Add-AzVMDataDisk-VM</span><span class="w"> </span><span class="nv">$newVM</span><span class="w"> </span><span class="se">`
</span><span class="nt">-Name</span><span class="nv">$disk</span><span class="o">.</span><span class="nf">Name</span><span class="w"> </span><span class="se">`
</span><span class="nt">-ManagedDiskId</span><span class="w"> </span><span class="nv">$disk</span><span class="o">.</span><span class="nf">ManagedDisk</span><span class="o">.</span><span class="nf">Id</span><span class="w"> </span><span class="se">`
</span><span class="nt">-Caching</span><span class="nv">$disk</span><span class="o">.</span><span class="nf">Caching</span><span class="w"> </span><span class="se">`
</span><span class="nt">-Lun</span><span class="nv">$disk</span><span class="o">.</span><span class="nf">Lun</span><span class="w"> </span><span class="se">`
</span><span class="nt">-DiskSizeInGB</span><span class="w"> </span><span class="nv">$disk</span><span class="o">.</span><span class="nf">DiskSizeGB</span><span class="w"> </span><span class="se">`
</span><span class="nt">-CreateOption</span><span class="w"> </span><span class="nx">Attach</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="c">#Add NICs</span><span class="w">
</span><span class="kr">foreach</span><span class="w"> </span><span class="p">(</span><span class="nv">$nic</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">NetworkProfile</span><span class="o">.</span><span class="nf">NetworkInterfaces</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="n">Add-AzVMNetworkInterface</span><span class="w"> </span><span class="se">`
</span><span class="nt">-VM</span><span class="w"> </span><span class="nv">$newVM</span><span class="w"> </span><span class="se">`
</span><span class="nt">-Id</span><span class="w"> </span><span class="nv">$nic</span><span class="o">.</span><span class="nf">Id</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="c">#Recreate the VM</span><span class="w">
</span><span class="n">New-AzVM</span><span class="w"> </span><span class="nt">-ResourceGroupName</span><span class="w"> </span><span class="nv">$resourceGroup</span><span class="w"> </span><span class="nt">-Location</span><span class="w"> </span><span class="nv">$originalVM</span><span class="o">.</span><span class="nf">Location</span><span class="w"> </span><span class="nt">-VM</span><span class="w"> </span><span class="nv">$newVM</span><span class="nt">-DisableBginfoExtension</span><span class="w">
</span></code></pre></div></div>Nicola Delfinonicola.delfino@outlook.comDo you remember that it is not possibile to rename a VM on Azure?How to quickly deploy a test web server on an Azure VM2021-09-21T10:00:00+02:002021-09-21T10:00:00+02:00https://nicolgit.github.io/provision-a-test-vm-webserver-on-azure<p>For my <strong>Labs</strong>, I often need to create and build virtual machines. <strong>Many virtual machines</strong> :-). One of the most “popular” machine recently is for me the web server. The requirement for my needs is often very simple: <strong>create a web server that responds on port 80, that is able to make me understand “what machine I’m interacting with”</strong>, so, the ideal response message to the request <em>http://my-machine-ip</em> should be “<em>myMachineName</em>”.</p>
<p>From Azure portal is quick enough to create a virtual machines. In particular I use as the starting image “<strong>windows 2019 datacenter gen1</strong>”.</p>
<p>Once the machine is created, you can automate the installation and configuration of a web server in this way:</p>
<p>From the Azure Portal:</p>
<ol>
<li>create an azure storage account, or like me use the azure storage account created by your cloudshell</li>
<li>create a container named “scripts”</li>
<li>create the file named “install-iis.ps1”</li>
<li>put the following in the file just created:</li>
</ol>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">powershell.exe</span><span class="w"> </span><span class="nx">Install-WindowsFeature</span><span class="w"> </span><span class="nt">-name</span><span class="w"> </span><span class="nx">Web-Server</span><span class="w"> </span><span class="nt">-IncludeManagementTools</span><span class="w">
</span><span class="n">powershell.exe</span><span class="w"> </span><span class="nx">Remove-Item</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="s1">'C:\inetpub\wwwroot\iisstart.htm'</span><span class="w">
</span><span class="n">powershell.exe</span><span class="w"> </span><span class="nx">Add-Content</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="s1">'C:\inetpub\wwwroot\iisstart.htm'</span><span class="w"> </span><span class="nt">-Value</span><span class="w"> </span><span class="err">$</span><span class="p">(</span><span class="nv">$</span><span class="nn">env</span><span class="p">:</span><span class="nv">computername</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>
<p>Go to your virtual machine blade, then go to:</p>
<ul>
<li>Extensions</li>
<li>+Add</li>
<li>CustomScript Extension</li>
<li>on “Script file” click browse and select the file created above.</li>
</ul>
<p>Go to [<strong>Review + Create</strong>] and then [<strong>Create</strong>].</p>
<p>After a couple of minutes the script will be executed, and IIS will be provisioned and working.</p>
<p><img src="../assets/post/2021/install-iis-output.png" alt="browser output" /></p>Nicola Delfinonicola.delfino@outlook.comFor my Labs, I often need to create and build virtual machines. Many virtual machines :-). One of the most “popular” machine recently is for me the web server. The requirement for my needs is often very simple: create a web server that responds on port 80, that is able to make me understand “what machine I’m interacting with”, so, the ideal response message to the request http://my-machine-ip should be “myMachineName”.