<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://woivre.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://woivre.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-15T17:25:18+00:00</updated><id>https://woivre.com/feed.xml</id><title type="html">Wilfried Woivré</title><subtitle>Personal Blog by Wilfried Woivré. My favorites subjects are Azure, Cloud, Serverless, Container, ...</subtitle><author><name>Wilfried Woivré</name></author><entry><title type="html">Copilot for Azure - Remove access for your users</title><link href="https://woivre.com/blog/2025/06/copilot-for-azure-remove-access-for-your-users" rel="alternate" type="text/html" title="Copilot for Azure - Remove access for your users" /><published>2025-06-30T00:00:00+00:00</published><updated>2025-06-30T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/06/copilot-for-azure-remove-access-for-your-users</id><content type="html" xml:base="https://woivre.com/blog/2025/06/copilot-for-azure-remove-access-for-your-users"><![CDATA[<p>Azure Copilot is a powerful tool that can transform the way your users interact with Microsoft’s public cloud.</p>

<p>However, it is essential to set up appropriate access controls to ensure that only authorized persons can use this tool.</p>

<p>To do this, in the Azure portal, with an account that has global Admin rights on your tenant, and User Access Administrator rights on your Root Management Group, you can restrict access to Azure Copilot by following these steps:</p>

<ul>
  <li>Go to the Azure portal.</li>
  <li>Navigate to <strong>Copilot in Azure Admin Center</strong></li>
  <li>Click on <strong>Access Management</strong>.</li>
  <li>Change the setting <strong>Available to all users</strong> to <strong>Not available to all users</strong></li>
  <li>Grant access rights to eligible users by adding a role on the root tenant Group <strong>Copilot in Azure User</strong></li>
</ul>

<p>Now there may be several reasons to take this action:</p>

<ul>
  <li>You want to prevent Microsoft from collecting data on your prompts. <a href="https://learn.microsoft.com/en-us/azure/copilot/responsible-ai-faq?WT.mc_id=AZ-MVP-4039694#what-data-does-microsoft-copilot-in-azure-collect">FAQ Azure Copilot</a> <em>Prompts provided by users and responses from Microsoft Azure Copilot are collected and used to improve Microsoft products and services only when users have given their explicit consent to include this information in feedback</em></li>
  <li>You want to establish strict governance over the use of AI in your organization.</li>
  <li>For large enterprises, you want to guard against a wait time on the use of Copilot by only providing it to a limited number of users. <a href="https://learn.microsoft.com/en-us/azure/copilot/capabilities?WT.mc_id=AZ-MVP-4039694#current-limitations">Current limitations</a></li>
</ul>

<p>And finally, it is important to be aware that blocking this feature may impact your user’s productivity, as they will not be able to benefit from the advantages of AI in their daily tasks.
Indeed, Azure Copilot can help users automate tasks, find information more quickly, and improve their overall efficiency. Today, the service contains many features and is enriched week by week.</p>

<p><a href="https://learn.microsoft.com/en-us/azure/copilot/capabilities?WT.mc_id=AZ-MVP-4039694#perform-tasks">Copilot Capabilities</a>, to this day:</p>

<ul>
  <li>
    <p>Understand your Azure environment:</p>

    <ul>
      <li>Get insights into resources via Azure Resource Graph queries</li>
      <li>Understand service events and health status</li>
      <li>Analyze, estimate, and optimize costs</li>
      <li>Search for Azure Advisor recommendations</li>
      <li>Visualize network topology</li>
      <li>Analyze your attack surface</li>
      <li>Review Azure Firewall IDPS attacks</li>
    </ul>
  </li>
  <li>
    <p>Work smarter with Azure services:</p>

    <ul>
      <li>Run commands</li>
      <li>Deploy and manage virtual machines</li>
      <li>Discover and deploy workload templates</li>
      <li>Use AKS clusters effectively</li>
      <li>Get insights into Azure Monitor metrics and logs</li>
    </ul>
  </li>
  <li>
    <p>Work smarter with Azure Local</p>

    <ul>
      <li>Manage and troubleshoot storage accounts</li>
      <li>Resolve disk performance issues</li>
      <li>Design, troubleshoot, and secure networks</li>
      <li>Resolve Azure Arc extension issues</li>
      <li>Improve Azure SQL Database-based applications</li>
    </ul>
  </li>
  <li>
    <p>Write and optimize code:</p>

    <ul>
      <li>Generate Azure CLI scripts</li>
      <li>Generate PowerShell scripts</li>
      <li>Generate Terraform and Bicep configurations</li>
      <li>Create API management policies</li>
      <li>Generate Kubernetes YAML files</li>
      <li>Resolve application issues faster with App Service</li>
    </ul>
  </li>
</ul>

<p>In my opinion, in 2025, having a corporate policy that prohibits the use of AI is counterproductive. Companies that do not leverage AI risk falling behind their competitors who adopt it. It is essential to find a balance between governance and innovation to remain competitive in the market.</p>

<p>Azure Copilot is an essential tool for all profiles using the Cloud, whether as a developer, architect, infrastructure, SRE, Cyber Expert, FinOps, and more. So weigh the pros and cons carefully before limiting the use of Copilot in the enterprise.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Copilot" /><summary type="html"><![CDATA[Azure Copilot is a powerful tool that can transform the way your users interact with Microsoft’s public cloud.]]></summary></entry><entry><title type="html">Azure Tags - Use hidden tags</title><link href="https://woivre.com/blog/2025/05/azure-tags-use-hidden-tags" rel="alternate" type="text/html" title="Azure Tags - Use hidden tags" /><published>2025-05-14T00:00:00+00:00</published><updated>2025-05-14T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/05/azure-tags-use-hidden-tags</id><content type="html" xml:base="https://woivre.com/blog/2025/05/azure-tags-use-hidden-tags"><![CDATA[<p>Azure tags are very useful from a governance point of view. They allow you to organize your resources, whether cross Resource Groups or cross subscriptions. Or even to filter simply within a <em>global trash</em> resource group.</p>

<p>Now on Azure, as you know, the name of a resource is used to identify it within Azure and therefore cannot be modified.
You therefore have three main choices to name your resources :</p>

<ul>
  <li>a Well-defined and respected naming agreement respected by all.</li>
  <li>Naming based on your use cases.</li>
  <li>The <em>Cat Naming Convention</em> which consists in named any way your resources by typing anything on your keyboard. My favorite method for demonstrations.</li>
</ul>

<p>Now in the life of a business, it is often occur to change the names of the teams, projects, applications, etc. And we therefore end up with resources with obsolete names.</p>

<p>It is possible to add a tag called <em>hidden-title</em> which allows you to add an additional name to your resource as below:</p>

<p><img src="https://woivre.com/images/2025/05/14/azure-tags-use-hidden-tags-img0.png" alt="alt text" /></p>

<p>And as you can see, the tag is not visible from the portal. but it is visible when you retrieve the information about your resource in powershell for example.</p>

<pre><code class="language-powershell">Get-AzResource -ResourceGroupName $rgName

Name              : jhyblmpw
ResourceGroupName : tags-rg
ResourceType      : Microsoft.Storage/storageAccounts
Location          : westeurope
ResourceId        : /subscriptions/c4dc16cad0f/resourceGroups/tags-rg/providers/Microsoft.Storage/storageAccounts/jhyblmpw
Tags              :
                    Name          Value
                    ============  ========================
                    hidden-title  Awesome storage for demo

</code></pre>

<p>It is of course possible to remove the tags via the portal by creating a new tag with the same name and an empty value.</p>

<p>You can use other hidden tags while of course respecting the limit of 50 tags per resource.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><summary type="html"><![CDATA[Azure tags are very useful from a governance point of view. They allow you to organize your resources, whether cross Resource Groups or cross subscriptions. Or even to filter simply within a global trash resource group.]]></summary></entry><entry><title type="html">Azure PowerShell - Update from Get-AzAccessToken for Az 14</title><link href="https://woivre.com/blog/2025/04/azure-powershell-update-from-getazaccesstoken-for-az-14" rel="alternate" type="text/html" title="Azure PowerShell - Update from Get-AzAccessToken for Az 14" /><published>2025-04-23T00:00:00+00:00</published><updated>2025-04-23T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/04/azure-powershell-update-from-getazaccesstoken-for-az-14</id><content type="html" xml:base="https://woivre.com/blog/2025/04/azure-powershell-update-from-getazaccesstoken-for-az-14"><![CDATA[<p>In the next major version of the Az module for PowerShell, there is a significant breaking change that can potentially impact all your automation scripts.</p>

<p>It is about Get-AzAccessToken a very practical method to get a valid token to interact with Azure APIs.</p>

<p>As we can see below:</p>

<pre><code class="language-powershell">get-azaccesstoken
WARNING: Upcoming breaking changes in the cmdlet 'Get-AzAccessToken' :
The Token property of the output type will be changed from String to SecureString. Add the [-AsSecureString] switch to avoid the impact of this upcoming breaking change.
- The change is expected to take effect in Az version : '14.0.0'
- The change is expected to take effect in Az.Accounts version : '5.0.0'
Note : Go to https://aka.ms/azps-changewarnings for steps to suppress this breaking change warning, and other information on breaking changes in Azure PowerShell.
</code></pre>

<p>To make the change, you have to pass -AsSecureString to have the same result you will have in version 14.</p>

<pre><code class="language-powershell">$token = Get-AzAccessToken  -AsSecureString

$token.Token
System.Security.SecureString
</code></pre>

<p>The problem is that the token is now in a SecureString format, which is not usable as is for using it in REST calls.</p>

<p>You need to convert it to a plain text string.</p>

<pre><code class="language-powershell">ConvertFrom-SecureString $token.Token -AsPlainText

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkNOdjBPSTNSd3FsSEZFVm5hb01Bc2hDSDJYRSIsImtpZCI6IkNOdjBPSTNSd3FsSEZFVm5hb01Bc2hDS...
</code></pre>

<p>And now you can use it in your REST calls.</p>

<p>So make the change in your scripts before updating your module.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Powershell" /><summary type="html"><![CDATA[In the next major version of the Az module for PowerShell, there is a significant breaking change that can potentially impact all your automation scripts.]]></summary></entry><entry><title type="html">Azure Policy - Finally versions for the Built-in definitions</title><link href="https://woivre.com/blog/2025/03/azure-policy-finally-versions-for-the-built-in-definitions" rel="alternate" type="text/html" title="Azure Policy - Finally versions for the Built-in definitions" /><published>2025-03-25T00:00:00+00:00</published><updated>2025-03-25T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/03/azure-policy-finally-versions-for-the-built-in-definitions</id><content type="html" xml:base="https://woivre.com/blog/2025/03/azure-policy-finally-versions-for-the-built-in-definitions"><![CDATA[<p>During the last ignite, Microsoft announced a feature that I expected a lot around the Azure Policy, they are versioned.</p>

<p>If like me, you have been using Azure Policy for a long time, you should see that the definition of the policy provided by Microsoft can vary from one release to another. Technically these versions provide that new useful features, but hey I don’t really like having deployed safety elements without my eye.</p>

<p>So now these police have versions, and to use them it’s very simple, you just need to make this order to list the versions of a policy:</p>

<pre><code class="language-powershell">get-azpolicyDefinition -Name '36fd7371-8eb7-4321-9c30-a7100022d048' | Select DisplayName, Versions

DisplayName                                    Versions
-----------                                    --------
Requires resources to not have a specific tag. {2.0.0, 1.1.1, 1.0.1, 1.0.0}

</code></pre>

<p>And to assign the one you want just make this order:</p>

<pre><code class="language-powershell"># Select your definition
$definition = get-azpolicyDefinition -Name '36fd7371-8eb7-4321-9c30-a7100022d048' -Version 1.1.1

# Assign your policy
$policyparams = @{
    Name = 'test-policy-version'
    DisplayName = 'Test policy version'
    Scope = $rg.ResourceId
    PolicyDefinition = $definition
    Description = 'Test policy version'
}

New-AzPolicyAssignment @policyparams
</code></pre>

<p>And good news, this respects the management of semantic versions, and not versions with more or less obscure dates such as Azure Providers resources.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Policy" /><summary type="html"><![CDATA[During the last ignite, Microsoft announced a feature that I expected a lot around the Azure Policy, they are versioned.]]></summary></entry><entry><title type="html">Azure Private Endpoint - Useful improvement for DNS resolution</title><link href="https://woivre.com/blog/2025/02/azure-private-endpoint-useful-improvement-for-dns-resolution" rel="alternate" type="text/html" title="Azure Private Endpoint - Useful improvement for DNS resolution" /><published>2025-02-19T00:00:00+00:00</published><updated>2025-02-19T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/02/azure-private-endpoint-useful-improvement-for-dns-resolution</id><content type="html" xml:base="https://woivre.com/blog/2025/02/azure-private-endpoint-useful-improvement-for-dns-resolution"><![CDATA[<p>In a previous <a href="https://woivre.com/blog/2023/11/azure-policy-api-version-hell">post</a>, I told you about the DNS resolution of the private endpoint and how it can be complicated when you have several actors in play, or that you use managed private endpoint.</p>

<p>At the time I had offered a solution based on Azure DNS Resolver to redirect the Forward DNS to a public DNS like Google.</p>

<p>Well, know that from Microsoft has released a new feature where it is possible to bring this configuration to the level of your private DNS zone. Thanks to this bicep there <strong>Resolutionpolicy: ‘nxdomainredirect’</strong>:</p>

<pre><code class="language-bicep">resource vnetLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
  name: 'link-to-vnet-${uniqueString(deployment().name)}'
  parent: privateDnsZone
  tags: tags
  location: 'global'
  properties: {
    virtualNetwork: {
      id: vnetId
    }
    registrationEnabled: false
    resolutionPolicy: 'NxDomainRedirect'
  }
}
</code></pre>

<p>This option is very practical, since in our Lab we go from this result:</p>

<pre><code class="language-bash">
[VM]
vm
[Run cmd]
nslookup labprivatelinkv5b65ik.blob.core.windows.net
Enable succeeded:
[stdout]
Server:         127.0.0.53
Address:        127.0.0.53#53

** server can't find labprivatelinkv5b65ik.blob.core.windows.net: NXDOMAIN


[stderr]

------------------------------------------
[VM]
vm
[Run cmd]
nslookup labprivatelinkv5b65ik.blob.core.windows.net 8.8.8.8
Enable succeeded:
[stdout]
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
labprivatelinkv5b65ik.blob.core.windows.net     canonical name = labprivatelinkv5b65ik.privatelink.blob.core.windows.net.
labprivatelinkv5b65ik.privatelink.blob.core.windows.net canonical name = blob.ams09prdstr07a.store.core.windows.net.
Name:   blob.ams09prdstr07a.store.core.windows.net
Address: 20.60.223.100


[stderr]
</code></pre>

<p>à celui là :</p>

<pre><code class="language-bash">[VM]
vm
[Run cmd]
nslookup labprivatelinkv5b65ik.blob.core.windows.net
Enable succeeded:
[stdout]
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
labprivatelinkv5b65ik.blob.core.windows.net     canonical name = labprivatelinkv5b65ik.privatelink.blob.core.windows.net.
labprivatelinkv5b65ik.privatelink.blob.core.windows.net canonical name = blob.ams09prdstr07a.store.core.windows.net.
Name:   blob.ams09prdstr07a.store.core.windows.net
Address: 20.60.223.100


[stderr]

------------------------------------------
[VM]
vm
[Run cmd]
nslookup labprivatelinkv5b65ik.blob.core.windows.net 8.8.8.8
Enable succeeded:
[stdout]
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
labprivatelinkv5b65ik.blob.core.windows.net     canonical name = labprivatelinkv5b65ik.privatelink.blob.core.windows.net.
labprivatelinkv5b65ik.privatelink.blob.core.windows.net canonical name = blob.ams09prdstr07a.store.core.windows.net.
Name:   blob.ams09prdstr07a.store.core.windows.net
Address: 20.60.223.100


[stderr]

------------------------------------------
</code></pre>

<p>So no need to set up unitary forWarde, and you can let azure manage this part there for you. A time saving especially when you work with tools like Synapse or Fabric which offers to create Managed Private Endpoint for many of your services.</p>

<p>I would update the lab to add this use box to the list.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Network" /><category term="Private Endpoint" /><summary type="html"><![CDATA[In a previous post, I told you about the DNS resolution of the private endpoint and how it can be complicated when you have several actors in play, or that you use managed private endpoint.]]></summary></entry><entry><title type="html">Azure Virtual Network Manager - Manage your IPs with an Azure IPAM built in</title><link href="https://woivre.com/blog/2025/02/azure-virtual-network-manager-manage-your-ips-with-an-azure-ipam-built-in" rel="alternate" type="text/html" title="Azure Virtual Network Manager - Manage your IPs with an Azure IPAM built in" /><published>2025-02-08T00:00:00+00:00</published><updated>2025-02-08T00:00:00+00:00</updated><id>https://woivre.com/blog/2025/02/azure-virtual-network-manager-manage-your-ips-with-an-azure-ipam-built-in</id><content type="html" xml:base="https://woivre.com/blog/2025/02/azure-virtual-network-manager-manage-your-ips-with-an-azure-ipam-built-in"><![CDATA[<p>Azure Virtual Manager is a tool to help you manage governance in the public cloud, and here particularly the network part.</p>

<p>For those who handle everyday network elements, you know that IPs management is an important point in order to avoid overlap, to identify your components or your environments. It is therefore necessary to have a mapping at one point to find out which IP belongs to whom and where it is in my ecosystem.</p>

<p>So it is possible to manage your IPS via different tools, passing from the Excel sheet (because Excel can do everything, even be the pillar of the worst tool idea to manage your tools) up to different IP Address Manager (IPAM) of the market, and there are a lot according to <a href="https://fr.wikipedia.org/wiki/Gestion_des_adresses_IP">Wikipedia</a></p>

<p>For me the essential elements of an IPAM are:</p>

<ul>
  <li>The management of access to this one to add new ranges, and draw into these.</li>
  <li>Recover IPs from our infrastructure as code, namely reserving a range for my virtual network, and keep it even if I launch my stack 200 times.</li>
  <li>View the place available in my ranges.</li>
  <li>Research to know where my asset is in a search and not 2 hours of investigation, namely I type an IP type 10.0.0.4, I want to find the Pool of IP which corresponds, if a range has been allocated and to whom.</li>
</ul>

<p>We will therefore look at what Microsoft provides us with, which has the advantage of being integrated into Azure, and therefore in the APIs of this one, that means that you can do bicep.</p>

<p>So we are going to create our Network Manager and our IPS Address Ranges.</p>

<pre><code class="language-bicep">param location string = 'northeurope'

var cidr = '10.0.0.0/20'
var envPrefix = [for i in range(0, 2): cidrSubnet(cidr, 21, i)]

resource networkManager 'Microsoft.Network/networkManagers@2024-05-01' = {
  name: 'demo-networkmanager'
  location: location
  properties: {
    networkManagerScopes: {
      subscriptions: [
        subscription().id
      ]
    }
  }
}

resource globalPrefix 'Microsoft.Network/networkManagers/ipamPools@2024-05-01' = {
  name: 'azure-rf1918-global'
  location: location
  parent: networkManager
  properties: {
    addressPrefixes: [
      cidr
    ]
  }
}

resource prdPrefix 'Microsoft.Network/networkManagers/ipamPools@2024-05-01' = {
  name: 'azure-rf1918-prd'
  location: location
  parent: networkManager
  properties: {
    addressPrefixes: [
      envPrefix[0]
    ]
    parentPoolName: globalPrefix.name
  }
}

resource devPrefix 'Microsoft.Network/networkManagers/ipamPools@2024-05-01' = {
  name: 'azure-rf1918-dev'
  location: location
  parent: networkManager
  properties: {
    addressPrefixes: [
      envPrefix[1]
    ]
    parentPoolName: globalPrefix.name
  }
}
</code></pre>

<p>Good point here, the creation is simple, we can quite easily add ranges, and even managed a notion of inheritance to subdivide our ranges.</p>

<p>Now for the allowance within a virtual network, it is possible to do like this, here I create 10 virtual networks, to make sure that it takes many different ranges:</p>

<pre><code class="language-bicep">resource vnets 'Microsoft.Network/virtualNetworks@2024-05-01' = [
  for i in range(0, 8): {
    name: 'vnet-dev-${i}'
    location: location
    properties: {
      addressSpace: {
        ipamPoolPrefixAllocations: [
          {
            numberOfIpAddresses: '128'
            pool: {
              id: devPrefix.id
            }
          }
        ]
      }
    }
  }
]
</code></pre>

<p>Second good point, we can easily create our virtual network from bicep so that it can recover an IP from our IPAM.</p>

<p>For the occupation part of our ranges, here again we can see it simply from Azure:</p>

<p><img src="https://woivre.com/images/2025/02/08/azure-virtual-network-manager-manage-your-ips-with-an-azure-ipam-built-in-img0.png" alt="alt text" /></p>

<p>So a good point for that.</p>

<p>And now for the search, we will say that it’s brand new and that all the tools is improving over time. But to date the proposed search feature is only useful if you know what to look for and where.</p>

<p>In conclusion, Microsoft offers with this functionality something that had been eagerly awaited for several years, properly integrated with the APIs and the management of our network stacks, but which in my opinion still lacks some features to decide to change IPAM to this day.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Network" /><summary type="html"><![CDATA[Azure Virtual Manager is a tool to help you manage governance in the public cloud, and here particularly the network part.]]></summary></entry><entry><title type="html">Azure API - Find all the versions available for each resource provider operations</title><link href="https://woivre.com/blog/2024/12/azure-api-find-all-the-versions-available-for-each-resource-provider-operations" rel="alternate" type="text/html" title="Azure API - Find all the versions available for each resource provider operations" /><published>2024-12-12T00:00:00+00:00</published><updated>2024-12-12T00:00:00+00:00</updated><id>https://woivre.com/blog/2024/12/azure-api-find-all-the-versions-available-for-each-resource-provider-operations</id><content type="html" xml:base="https://woivre.com/blog/2024/12/azure-api-find-all-the-versions-available-for-each-resource-provider-operations"><![CDATA[<p>Last year, I talked about the challenges of managing Azure Policies APIs.</p>

<p>Now, if you want to automate tests to verify all API versions, you need to know all of them.</p>

<p>To discover the different API versions, there are several methods. The first is to consult the Azure REST API documentation provided by Microsoft, but this can be tedious.</p>

<p>The second (and probably the most commonly used so far) is to trigger an error and check the list of available APIs in the error message, as shown below:</p>

<pre><code class="language-powershell">$header = @{ 'Content-Type' = 'application/json'; 'Authorization' = 'Bearer ' + (Get-AzAccessToken).Token }
$url = "https://management.azure.com/subscriptions/$((Get-AzContext).Subscription.Id)/providers/Microsoft.Authorization/roleAssignments?api-version=dummyapi"
Invoke-WebRequest -headers $header $url

--- 
Invoke-WebRequest:
{
  "error": {
    "code": "InvalidResourceType",
}

</code></pre>

<p>However, you will agree, there are better ways to find all the available versions.</p>

<p>It is therefore possible to retrieve the different APIs using the following command:</p>

<pre><code class="language-powershell">(Get-AzResourceProvider -ProviderNamespace "Microsoft.Authorization" | Where-Object { $_.ResourceTypes.ResourceTypeName -eq "roleAssignments" } | Select-Object ResourceTypes).ResourceTypes.ApiVersions

--- 
2022-04-01
2022-01-01-preview
2021-04-01-preview
2020-10-01-preview
2020-08-01-preview
2020-04-01-preview
2020-03-01-preview
2019-04-01-preview
2018-12-01-preview
2018-09-01-preview
2018-07-01
2018-01-01-preview
2017-10-01-preview
2017-09-01
2017-05-01
2016-07-01
2015-07-01
2015-06-01
2015-05-01-preview
2014-10-01-preview
2014-07-01-preview
2014-04-01-preview
</code></pre>

<p>And there you have it, all that’s left is to integrate this into a proper test CI pipeline.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><summary type="html"><![CDATA[Last year, I talked about the challenges of managing Azure Policies APIs.]]></summary></entry><entry><title type="html">Azure Network Security Perimeter - Centrally manage your ACLs</title><link href="https://woivre.com/blog/2024/12/azure-network-security-perimeter-centrally-manage-your-acls" rel="alternate" type="text/html" title="Azure Network Security Perimeter - Centrally manage your ACLs" /><published>2024-12-04T00:00:00+00:00</published><updated>2024-12-04T00:00:00+00:00</updated><id>https://woivre.com/blog/2024/12/azure-network-security-perimeter-centrally-manage-your-acls</id><content type="html" xml:base="https://woivre.com/blog/2024/12/azure-network-security-perimeter-centrally-manage-your-acls"><![CDATA[<p>During Microsoft Ignite 2024, Microsoft announced the public preview of Network Security Perimeter.
Today, it’s a public preview, and for my point of view, this product is a game changer for Azure Security (If all feature i dream will be here one day)
AS this product offer multiple features, i think i will be write multiple posts on this blog.</p>

<p>In this post, we will focus on managing ACL for your Azure services, and more specifically on the inbound IP source.</p>

<p>Start with how to create a Network Security Perimeter with bicep:</p>

<pre><code class="language-bicep">resource nsp 'Microsoft.Network/networkSecurityPerimeters@2023-08-01-preview' = {
  name: 'demo${uniqueString(resourceGroup().id)}'
  location: loc
}
</code></pre>

<p>The service is created, now you need a profile. And my advice is to create at least 2 profiles, one with the Learning Mode for the tests, and one with the enforce mode to apply the rules. With the bicep autocompletion, its appears you have only this two mode available.
Today we will focus on the enforced mode, we will see the learning mode later, and how to exploit the learning phase to build the security around your services.</p>

<pre><code class="language-bicep">resource nsp_enforce 'Microsoft.Network/networkSecurityPerimeters/profiles@2023-08-01-preview' = {
  name: 'enforce_profile'
  parent: nsp
  location: loc
  properties: {}
}

resource nsp_enforce_accessrule 'Microsoft.Network/networkSecurityPerimeters/profiles/accessRules@2023-08-01-preview' = {
  name: 'allowed_ip'
  parent: nsp_enforce
  location: loc
  properties: {
    direction: 'Inbound'
    addressPrefixes: [
      '28.38.76.11/32'
      '52.51.0.0/24'
    ]
  }
}
</code></pre>

<p>It is important to know that the possible IPS to be put here must absolutely be public, no RFC1918 here.</p>

<p>And to finish you must associate your profile with your Azure resources, and this is where you will define the mode of access to know: <em>Enforced</em>, <em>Learning</em></p>

<pre><code class="language-bicep">resource nsp_association_storage 'Microsoft.Network/networkSecurityPerimeters/resourceAssociations@2023-08-01-preview' = {
  name: 'testwwonsp${uniqueString(resourceGroup().id, sto.id)}'
  parent: nsp
  location: loc
  properties: {
    accessMode: 'Enforced'
    profile: {
      id: nsp_enforce.id
    }
    privateLinkResource: {
      id: sto.id
    }
  }
}

resource nsp_association_keyvault 'Microsoft.Network/networkSecurityPerimeters/resourceAssociations@2023-08-01-preview' = {
  name: 'testwwonsp${uniqueString(resourceGroup().id, key.id)}'
  parent: nsp
  location: loc
  properties: {
    accessMode:'Enforced'
    profile: {
      id: nsp_enforce.id
    }
    privateLinkResource: {
      id: key.id
    }
  }
}

resource nsp_association_eventhub 'Microsoft.Network/networkSecurityPerimeters/resourceAssociations@2023-08-01-preview' = {
  name: 'testwwonsp${uniqueString(resourceGroup().id, eventhub.id)}'
  parent: nsp
  location: loc
  properties: {
    accessMode: 'Enforced'
    profile: {
      id: nsp_enforce.id
    }
    privateLinkResource: {
      id: eventhub.id
    }
  }
}

</code></pre>

<p>Now why I am ultra fan of Network Security Perimeter, it’s simply because I define the list of my IPs only in one place, and I especially don’t have to worry about applying it to all types of resources that I protect.
As a reminder if I wanted to do the same in bicep for my storage and keyvault services I would do the next bicep:</p>

<pre><code class="language-bicep">
resource sto_without_nsp 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'stononsp${uniqueString(resourceGroup().id)}'
  location: loc
  kind: 'StorageV2'
  identity: {
    type: 'SystemAssigned'
  }
  sku: {
    name: 'standard_lrs'
  }
  properties: {
    supportsHttpsTrafficOnly: true
    networkAcls: {
      bypass: 'AzureServices'
      ipRules: [
        {
          value: '28.38.76.11'
          action: 'Allow'
        }
        {
          value: '52.51.0.0/24'
          action: 'Allow'
        }
      ]
      defaultAction: 'Deny'
    }
  }
}

resource key_without_nsp 'Microsoft.KeyVault/vaults@2023-07-01' = {
  name: 'keynonsp${uniqueString(resourceGroup().id)}'
  location: loc
  properties: {
    sku: {
      family: 'A'
      name: 'standard'
    }
    tenantId: subscription().tenantId
    enableRbacAuthorization: true
    networkAcls: {
      bypass: 'AzureServices'
      ipRules: [
        {
          value: '28.38.76.11/32'
        }
        {
          value: '52.51.0.0/24'
        }
      ]
      defaultAction: 'Deny'
    }
  }
}

resource eventhub_without_nsp 'Microsoft.EventHub/namespaces@2024-05-01-preview' = {
  name: 'eventhubnonsp${uniqueString(resourceGroup().id)}'
  location: loc
  identity: {
    type: 'SystemAssigned'
  }
  sku: {
    name: 'Standard'
    tier: 'Standard'
  }
  properties: {
    isAutoInflateEnabled: false
    disableLocalAuth: true  
  }
}

resource eventhub_without_nspacl 'Microsoft.EventHub/namespaces/networkRuleSets@2024-05-01-preview' = {
  name: 'default'
  parent: eventhub_without_nsp
  properties: {
    defaultAction: 'Deny'
    ipRules: [
      {
        ipMask: '28.38.76.11/32'
        action: 'Allow'
      }
      {
        ipMask: '52.51.0.0/24'
        action: 'Allow'
      }
    ]
  }
}
</code></pre>

<p>So I have for my storage, Keyvault and EventHub 3 different implementations to put my rules.
Here Azure Storage does not support the ranges in /32, we are therefore obliged to put the IP, and for event hub it is an inner resource.</p>

<p>So we see that Network Security Perimeter will help us simplify our infra as code without being concerned about this part.
Or even a complex management of Policy to be set up to automatically add all the IPs you want.</p>

<p>Now it is a preview, and therefore I hope that other features will arrive because for the moment the big blockers that I see by adoption today are as follows:</p>

<ul>
  <li>We don’t see the security elements if we look at the details of the service via the portal, or via the PowerShell commands, for example:</li>
</ul>

<pre><code class="language-powershell">➜  (Get-AzKeyVault -name $keyVaultName -ResourceGroupName nsp).NetworkAcls

DefaultAction                 : Allow
Bypass                        : AzureServices
IpAddressRanges               :
IpAddressRangesText           :
VirtualNetworkResourceIds     :
VirtualNetworkResourceIdsText :
</code></pre>

<ul>
  <li>
    <p>No integration into Microsoft Defender for Cloud, my resources always seem exposed. And I guess it’s the same for other CNAPPs.</p>
  </li>
  <li>
    <p>Not all Azure services are supported for example for this inbound IPs control.</p>
  </li>
</ul>

<p>But for me it is a service to monitor because it will be a game changer for the future of perimeter security in the public cloud.</p>

<p>Tell me in comments if you have other aspects of the service you want me to dig.</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Network Security Perimeter" /><summary type="html"><![CDATA[During Microsoft Ignite 2024, Microsoft announced the public preview of Network Security Perimeter. Today, it’s a public preview, and for my point of view, this product is a game changer for Azure Security (If all feature i dream will be here one day) AS this product offer multiple features, i think i will be write multiple posts on this blog.]]></summary></entry><entry><title type="html">Azure Policy - Manage conflicts in your modify policies</title><link href="https://woivre.com/blog/2024/10/azure-policy-manage-conflicts-in-your-modify-policies" rel="alternate" type="text/html" title="Azure Policy - Manage conflicts in your modify policies" /><published>2024-10-17T00:00:00+00:00</published><updated>2024-10-17T00:00:00+00:00</updated><id>https://woivre.com/blog/2024/10/azure-policy-manage-conflicts-in-your-modify-policies</id><content type="html" xml:base="https://woivre.com/blog/2024/10/azure-policy-manage-conflicts-in-your-modify-policies"><![CDATA[<p>Policies with modify effect are very useful to enforce a rule, and prevent automatic modification from a legacy infrastructure as code to update TLS version from 1.2 to 1.0 for example.</p>

<p>However, if you have several policies that change the same field. What can happen if you assign the same policy twice on different scopes with different parameters, or if you have a governance problem, it can be complicated to know which prime on the other</p>

<p>There is <strong>conflicteffect</strong> that exists, and this one offer a control to prioritize which policy take over on the other. This field has multiple values: <strong>audit</strong>, <strong>deny</strong> ou <strong>disabled</strong>.</p>

<p>And good news, by default the value is <strong>deny</strong> and it’s the value i advise for your policy.</p>

<p>Indeed, if we have a policy conflict, we will have an error when updating the resource, while a policy with an audit effect will simply not play the modification operations in the event of a conflict.</p>

<p>Here is an example of a policy with a configured conflict effect.</p>

<pre><code class="language-json">{
  "mode": "Indexed",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Storage/storageAccounts"
        },
        {
          "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
          "equals": "false"
        }
      ]
    },
    "then": {
      "effect": "[parameters('effect')]",
      "details": {
        "conflictEffect": "deny",
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab"
        ],
        "operations": [
          {
            "condition": "[greaterOrEquals(requestContext().apiVersion, '2019-04-01')]",
            "operation": "addOrReplace",
            "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
            "value": true
          }
        ]
      }
    }
  },
  "parameters": {
    "effect": {
      "type": "String",
      "metadata": {
        "displayName": "Effect",
        "description": "The effect determines what happens when the policy rule is evaluated to match"
      },
      "allowedValues": [
        "Modify",
        "Disabled"
      ],
      "defaultValue": "Modify"
    }
  }
}
</code></pre>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Policy" /><summary type="html"><![CDATA[Policies with modify effect are very useful to enforce a rule, and prevent automatic modification from a legacy infrastructure as code to update TLS version from 1.2 to 1.0 for example.]]></summary></entry><entry><title type="html">Bicep - Azure Verified Module, a registry to help you</title><link href="https://woivre.com/blog/2024/09/bicep-azure-verified-module-a-registry-to-help-you" rel="alternate" type="text/html" title="Bicep - Azure Verified Module, a registry to help you" /><published>2024-09-10T00:00:00+00:00</published><updated>2024-09-10T00:00:00+00:00</updated><id>https://woivre.com/blog/2024/09/bicep-azure-verified-module-a-registry-to-help-you</id><content type="html" xml:base="https://woivre.com/blog/2024/09/bicep-azure-verified-module-a-registry-to-help-you"><![CDATA[<p>If you have not followed the new features around Bicep, it is possible to create modules, and put them in a private registration via Azure Container Registry, I would surely make an article soon.</p>

<p>And now if we want to make a public registry, well today it is not possible, but Microsoft hosts for you Azure Verified Module which is also based on Azure Container Registry but which contains a set of modules validated by Microsoft based on Open Source Restity: <a href="https://github.com/Azure/bicep-registry-modules">Azure Verified Module</a></p>

<p>Recently I updated my Sandbox Toolkit based on Azure Function, and I decided among other things to redo my infra as code thanks to AVM, so I suggest making a feedback on it.</p>

<p>Let’s start by creating an Azure storage:</p>

<pre><code class="language-bicep">module stg 'br/public:avm/res/storage/storage-account:0.11.1' = {
  name: 'sandbox-storage'
  scope: resourceGroup
  params: {
    name: 'stg${uniqueString(resourceGroup.id)}'
    skuName: 'Standard_LRS'
    publicNetworkAccess: 'Enabled'
    networkAcls: {
      bypass: 'AzureServices'
      defaultAction: 'Allow'
    }
  }
}
</code></pre>

<p>So firstly it is very simple to access via VsCode since the search for modules is done directly with autocompletion, it remains up to know Azure Resource Providers you want to use.
And good news, it is easily to explore the contents of the module that you simply use via a click in VsCode, no need to refer to the Github.</p>

<p>For having implemented modules which is important to define is the management of your input and output parameters of the module, and good news AVM contains standards on these elements and offers a lot of parameter with default values For all (apart from the name of course), and good news these parameters are typical, so you will be well guided when creating your templates, and in the build of your bicep file will fail if you have not followed the typing .</p>

<p>Now, everything is not perfect, and it is an open source project, so the level of templates is not always the same, for example if I take storage I have these elements for the NetworkAcls part:</p>

<pre><code class="language-bicep">@description('Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. If in use, bypass needs to be supplied. For security reasons, it is recommended to set the DefaultAction Deny.')
param networkAcls networkAclsType?

type networkAclsType = {
  @description('Optional. Sets the resource access rules. Array entries must consist of "tenantId" and "resourceId" fields only.')
  resourceAccessRules: {
    @description('Required. The ID of the tenant in which the resource resides in.')
    tenantId: string

    @description('Required. The resource ID of the target service. Can also contain a wildcard, if multiple services e.g. in a resource group should be included.')
    resourceId: string
  }[]?

  @description('Optional. Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Possible values are any combination of Logging,Metrics,AzureServices (For example, "Logging, Metrics"), or None to bypass none of those traffics.')
  bypass: (
    | 'None'
    | 'AzureServices'
    | 'Logging'
    | 'Metrics'
    | 'AzureServices, Logging'
    | 'AzureServices, Metrics'
    | 'AzureServices, Logging, Metrics'
    | 'Logging, Metrics')?

  @description('Optional. Sets the virtual network rules.')
  virtualNetworkRules: array?

  @description('Optional. Sets the IP ACL rules.')
  ipRules: array?

  @description('Optional. Specifies the default action of allow or deny when no other rules match.')
  defaultAction: ('Allow' | 'Deny')?
}
</code></pre>

<p>While for Keyvault, it’s much more light:</p>

<pre><code class="language-bicep">@description('Optional. Rules governing the accessibility of the resource from specific network locations.')
param networkAcls object?
</code></pre>

<p>Afterwards, I remind you that this is an open source project, so I strongly encourage you to contribute if something is missing, of course if you have time. They are also looking for: <a href="https://github.com/Azure/Azure-Verified-Modules/issues?q=is:issue+label:%22Needs:+Module+Contributor+:mega:%22+">Needs Contributor</a></p>

<p>The use of this type of module will allow you to speed up the implementation of your templates based on these modules, and not to have to redo them on your side.
And as a bonus, since it is a module you can always use yours if you wish.</p>

<p>Since good news never comes alone, this registry also contains tests for each of the resources you can press to find the settings you need, for example for storage:</p>

<p>For example, the implementation of a Kind type <code>BlockBlobStorage</code></p>

<pre><code class="language-bicep">targetScope = 'subscription'

metadata name = 'Deploying as a Block Blob Storage'
metadata description = 'This instance deploys the module as a Premium Block Blob Storage account.'

// ========== //
// Parameters //
// ========== //

@description('Optional. The name of the resource group to deploy for testing purposes.')
@maxLength(90)
param resourceGroupName string = 'dep-${namePrefix}-storage.storageaccounts-${serviceShort}-rg'

@description('Optional. The location to deploy resources to.')
param resourceLocation string = deployment().location

@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.')
param serviceShort string = 'ssablock'

@description('Optional. A token to inject into the name of each resource.')
param namePrefix string = '#_namePrefix_#'

// ============ //
// Dependencies //
// ============ //

// General resources
// =================
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: resourceGroupName
  location: resourceLocation
}

// ============== //
// Test Execution //
// ============== //

@batchSize(1)
module testDeployment '../../../main.bicep' = [
  for iteration in ['init', 'idem']: {
    scope: resourceGroup
    name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}'
    params: {
      location: resourceLocation
      name: '${namePrefix}${serviceShort}001'
      skuName: 'Premium_LRS'
      kind: 'BlockBlobStorage'
    }
  }
]
</code></pre>

<p>But also lots of others, such as the management of encryption keys.</p>

<p>AVM does not only contain modules for Azure Resources, but also for user patterns, such as the implementation of the Landing Zone of Test (given the criticality of the subject, I advise you to use an external module only for tests)</p>

<p>And finally, Azure Verified Module is not an initiative that for Bicep, but also for Terraform!</p>

<p>Well and if I was going to make a request for a request now…</p>]]></content><author><name>Wilfried Woivré</name></author><category term="Azure" /><category term="Bicep" /><summary type="html"><![CDATA[If you have not followed the new features around Bicep, it is possible to create modules, and put them in a private registration via Azure Container Registry, I would surely make an article soon.]]></summary></entry></feed>