<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PowerShell &#8211; Haikos Blog</title>
	<atom:link href="https://www.hertes.net/category/microsoft/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hertes.net</link>
	<description>Blog von Haiko Hertes zu allen Themen rund um Microsoft, Cloud und Datacenter</description>
	<lastBuildDate>Mon, 02 Oct 2023 08:18:33 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>CPU-Kompatibilität in Hyper-V-Cluster mittels PowerShell steuern</title>
		<link>https://www.hertes.net/2023/10/cpu-kompatibilitaet-in-hyper-v-cluster-mittels-powershell-steuern/</link>
					<comments>https://www.hertes.net/2023/10/cpu-kompatibilitaet-in-hyper-v-cluster-mittels-powershell-steuern/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Mon, 02 Oct 2023 16:00:00 +0000</pubDate>
				<category><![CDATA[Hyper-V]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[Failover-Cluster]]></category>
		<category><![CDATA[Kompatibilität]]></category>
		<category><![CDATA[Prozessor]]></category>
		<category><![CDATA[S2D]]></category>
		<category><![CDATA[Virtuelle Maschine]]></category>
		<category><![CDATA[VM]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=4225</guid>

					<description><![CDATA[Zu einem bestehenden 2-Knoten S2D-Hyper-V-Failover-Cluster aus 2 exakt gleichen Hosts hatte ich vor kurzem einen dritten Knoten hinzugefügt. Es handelte sich hierbei um das selbe HP-Server-Modell. Bei den ersten Live-Migrationen traten jedoch Fehler auf und eine Analyse brachte zu Tage, dass die CPUs am dritten Knoten geringfügig andere sind. Für dieses Problem gibt es im Allgemeinen das Feature &#8222;Processor compatibility&#8220; in Hyper-V (Im Deutschen als &#8222;Prozessorkompatibilitätsmodus&#8220; bezeichnet, in der GUI heisst es dann &#8222;Zu einem physischen Computer mit einer anderen Prozessorversion migrieren&#8220; bzw. &#8222;Migrate to physical computer with a different processor version&#8220;). Dieses Feature kann man natürlich problemlos über die&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Zu einem bestehenden 2-Knoten S2D-Hyper-V-Failover-Cluster aus 2 exakt gleichen Hosts hatte ich vor kurzem einen dritten Knoten hinzugefügt. Es handelte sich hierbei um das selbe HP-Server-Modell. Bei den ersten Live-Migrationen traten jedoch Fehler auf und eine Analyse brachte zu Tage, dass die CPUs am dritten Knoten geringfügig andere sind.</p>



<p>Für dieses Problem gibt es im Allgemeinen das Feature &#8222;Processor compatibility&#8220; in Hyper-V (Im Deutschen als &#8222;Prozessorkompatibilitätsmodus&#8220; bezeichnet, in der GUI heisst es dann &#8222;Zu einem physischen Computer mit einer anderen Prozessorversion migrieren&#8220; bzw. &#8222;Migrate to physical computer with a different processor version&#8220;). Dieses Feature kann man natürlich problemlos über die GUI ein- und ausschalten:</p>



<figure class="wp-block-image size-full"><a href="https://www.hertes.net/wp-content/uploads/2023/10/image.png"><img fetchpriority="high" decoding="async" width="872" height="266" src="https://www.hertes.net/wp-content/uploads/2023/10/image.png" alt="" class="wp-image-4226" srcset="https://www.hertes.net/wp-content/uploads/2023/10/image.png 872w, https://www.hertes.net/wp-content/uploads/2023/10/image-300x92.png 300w, https://www.hertes.net/wp-content/uploads/2023/10/image-768x234.png 768w" sizes="(max-width: 872px) 100vw, 872px" /></a></figure>



<p>Allerdings ergeben sich hier schnell 2 Herausforderungen:</p>



<ul class="wp-block-list">
<li>Das Feature lässt sich nur ändern, während die VM ausgeschaltet ist</li>



<li>In einem Cluster laufen schnell mal eine 2-stellige Anzahl VMs</li>
</ul>



<p>Das kann man natürlich wie so vieles sehr elegant per PowerShell lösen, also habe ich dafür ein passendes Skript geschrieben. Dieses kann entweder zum ein- oder ausschalten des Features benutzt werden und iteriert dabei über einen Cluster und behandelt dabei dann alle VMs im Cluster, bei denen das Feature noch nicht korrekt eingestellt ist, in dem die VMs bei Bedarf zuerst gestoppt, das Feature gesetzt und dann falls vorher laufend die VM wieder startet. Am Ende wird dann noch der Gesamtzustand ausgegeben.</p>



<p>Das Skript findet ihr auf meinem GitHub Repo, siehe hier:</p>



<p><a href="https://github.com/HaikoHertes/scripts/blob/master/HyperV/EnableOrDisableCPUCompatibilityOnHyperVCluster.ps1">scripts/HyperV/EnableOrDisableCPUCompatibilityOnHyperVCluster.ps1 at master · HaikoHertes/scripts (github.com)</a></p>



<p>Damit kann man nun also entweder bei unterschiedlicher Hardware die CPU-Kompatibilität für alle VMs erhöhen oder, nachdem man z.B. die CPUs überall auf den selben Stand gebracht hat, das Feature wieder deaktivieren.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2023/10/cpu-kompatibilitaet-in-hyper-v-cluster-mittels-powershell-steuern/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure Migrate &#8211; Gruppen automatisiert befüllen</title>
		<link>https://www.hertes.net/2022/02/azure-migrate-gruppen-automatisiert-befuellen/</link>
					<comments>https://www.hertes.net/2022/02/azure-migrate-gruppen-automatisiert-befuellen/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Wed, 09 Feb 2022 18:16:00 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Migrate]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Assessment]]></category>
		<category><![CDATA[Group]]></category>
		<category><![CDATA[Gruppen]]></category>
		<category><![CDATA[Migrate]]></category>
		<category><![CDATA[Skript]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=4148</guid>

					<description><![CDATA[Azure Migrate bietet im Alltag viele sehr nützliche Funktionen. Dabei können unter anderem Assessments auf bestehende on-premises Umgebung gefahren werden, um neben einer Kostenindikation auch einen ersten Überblick über die technische Machbarkeit einer Lift-and-Shift-Migration von Servern von on-premises zu erhalten. Insbesondere für diese Assessments (die dann u.a. auch eine Depency Analysis erlauben) werden Gruppen in Azure Migrate benötigt. Diese kann man im Portal nur sehr rudimentär anlegen. Dabei müssen aus der Liste von erkannten on-opremises Servern die gewünschten Systeme in mehreren Listen-Seiten zu je ca. 10 Systemen, die sich weder sortieren noch (sinnvoll) filtern lässt, ausgewählt und mit Checkboxen zur&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Azure Migrate bietet im Alltag viele sehr nützliche Funktionen. Dabei können unter anderem Assessments auf bestehende on-premises Umgebung gefahren werden, um neben einer Kostenindikation auch einen ersten Überblick über die technische Machbarkeit einer Lift-and-Shift-Migration von Servern von on-premises zu erhalten.</p>



<figure class="wp-block-image size-full"><a href="https://www.hertes.net/wp-content/uploads/2022/02/image-1.png"><img decoding="async" width="955" height="288" src="https://www.hertes.net/wp-content/uploads/2022/02/image-1.png" alt="" class="wp-image-4149" srcset="https://www.hertes.net/wp-content/uploads/2022/02/image-1.png 955w, https://www.hertes.net/wp-content/uploads/2022/02/image-1-300x90.png 300w, https://www.hertes.net/wp-content/uploads/2022/02/image-1-768x232.png 768w" sizes="(max-width: 955px) 100vw, 955px" /></a></figure>



<p>Insbesondere für diese Assessments (die dann u.a. auch eine Depency Analysis erlauben) werden Gruppen in Azure Migrate benötigt. Diese kann man im Portal nur sehr rudimentär anlegen. Dabei müssen aus der Liste von erkannten on-opremises Servern die gewünschten Systeme in mehreren Listen-Seiten zu je ca. 10 Systemen, die sich weder sortieren noch (sinnvoll) filtern lässt, ausgewählt und mit Checkboxen zur Gruppe hinzugefügt werden:</p>



<figure class="wp-block-image size-large"><a href="https://www.hertes.net/wp-content/uploads/2022/02/image-2.png"><img decoding="async" width="1024" height="278" src="https://www.hertes.net/wp-content/uploads/2022/02/image-2-1024x278.png" alt="" class="wp-image-4150" srcset="https://www.hertes.net/wp-content/uploads/2022/02/image-2-1024x278.png 1024w, https://www.hertes.net/wp-content/uploads/2022/02/image-2-300x82.png 300w, https://www.hertes.net/wp-content/uploads/2022/02/image-2-768x209.png 768w, https://www.hertes.net/wp-content/uploads/2022/02/image-2-1536x417.png 1536w, https://www.hertes.net/wp-content/uploads/2022/02/image-2-2048x556.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<p>Nun gibt es zwar seit Ende 2020 ein PowerShell-Modul für Azure Migrate &#8211; dieses kann aber bis heute in keinster Weise mit diesen Gruppen umgehen &#8211; weder diese Abfragen, noch anlegen oder verändern.</p>



<p>Aus diesem Grund &#8211; und weil es immer öfter nötig ist, aus hunderten oder tausenden erkannten on-prem Systemen nur einen Teil auszuwählen &#8211; habe ich ein passendes PowerShell-Skript erstellt, welches eine über Hostnamen gegebene Liste von Servern in eine entweder bereits vorhandene oder im Laufe des Skriptes angelegte Gruppe aufnimmt. Dazu werden verschiedene REST-Calls gegen die REST-API von Azure benutzt, um sowohl mit den Gruppen als auch den erkannten Servern umgehen zu können.</p>



<p>Das Skript ist auf meinem GitHub Repo zu finden:</p>



<p><a href="https://github.com/HaikoHertes/scripts/blob/master/Azure/AzureMigrate/GroupAzMigrateServers.ps1">scripts/GroupAzMigrateServers.ps1 at master · HaikoHertes/scripts (github.com)</a></p>



<p>Ich werde in den kommenden Tagen voraussichtlich noch ein paar kleine Verbesserungen vornehmen, das Skript ist aber bereits jetzt voll lauffähig.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2022/02/azure-migrate-gruppen-automatisiert-befuellen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure Automation &#8211; Neue Runbooks für VMs</title>
		<link>https://www.hertes.net/2021/03/azure-automation-neue-runbooks-fuer-vms/</link>
					<comments>https://www.hertes.net/2021/03/azure-automation-neue-runbooks-fuer-vms/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Wed, 24 Mar 2021 11:45:26 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[deallocate]]></category>
		<category><![CDATA[Runbook]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[Start]]></category>
		<category><![CDATA[Stop]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[Virtuelle Maschine]]></category>
		<category><![CDATA[VM]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=4094</guid>

					<description><![CDATA[Vor einiger Zeit (muss mehrere Jahre her sein) habe ich ein paar Azure Automation PowerShell Runbooks auf GitHub und hier veröffentlich, um VMs Zeit- und Tag- gesteuert starten und stoppen zu können und um heruntergefahren, nicht-deallokierte VMs zu deallokieren. Diese basierten auf AzureRM PowerShell Cmdlets / Modulen und einer etwas komplizierten Herangehensweise. Ich habe die Runbooks nun massiv überarbeitet, so dass diese erstens das neuere Az Modul verwenden und auch vom Aufbau her wesentlich einfacher sind. U.a. verwenden die Runbooks jetzt lokale Deutsche Zeit und sind robuster bei der Schreibweise der Tags (Groß-/Kleinschreibung). Ihr findet diese Runbooks wie immer in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Vor einiger Zeit (muss mehrere Jahre her sein) habe ich ein paar Azure Automation PowerShell Runbooks auf GitHub und hier veröffentlich, um VMs Zeit- und Tag- gesteuert starten und stoppen zu können und um heruntergefahren, nicht-deallokierte VMs zu deallokieren. Diese basierten auf AzureRM PowerShell Cmdlets / Modulen und einer etwas komplizierten Herangehensweise. Ich habe die Runbooks nun massiv überarbeitet, so dass diese erstens das neuere Az Modul verwenden und auch vom Aufbau her wesentlich einfacher sind. U.a. verwenden die Runbooks jetzt lokale Deutsche Zeit und sind robuster bei der Schreibweise der Tags (Groß-/Kleinschreibung).</p>



<p>Ihr findet diese Runbooks wie immer in meinem GitHub Repo, konkret genau hier:</p>



<p>VMs starten und stoppen:</p>



<p><a href="https://github.com/HaikoHertes/scripts/tree/master/Azure/Automation/Snoozing">https://github.com/HaikoHertes/scripts/tree/master/Azure/Automation/Snoozing</a></p>



<p>VMs deallokieren:</p>



<p><a href="https://github.com/HaikoHertes/scripts/tree/master/Azure/Automation/VmDeallocation">https://github.com/HaikoHertes/scripts/tree/master/Azure/Automation/VmDeallocation</a></p>



<p>Viel Spaß damit!</p>



<p>Weitere Informationen zu Azure Automation und Runbooks:</p>



<p><a href="https://docs.microsoft.com/en-us/azure/automation/automation-quickstart-create-account?WT.mc_id=AZ-MVP-5001882">Azure Quickstart &#8211; Create an Azure Automation account | Microsoft Docs</a><br><a href="https://docs.microsoft.com/en-us/azure/automation/create-run-as-account?WT.mc_id=AZ-MVP-5001882">Create an Azure Automation Run As account | Microsoft Docs</a><br><a href="https://docs.microsoft.com/en-us/azure/automation/automation-create-standalone-account?WT.mc_id=AZ-MVP-5001882">Create a standalone Azure Automation account | Microsoft Docs</a><br><a href="https://docs.microsoft.com/en-us/azure/automation/learn/automation-tutorial-runbook-textual?WT.mc_id=AZ-MVP-5001882">Create a PowerShell Workflow runbook in Azure Automation | Microsoft Docs</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2021/03/azure-automation-neue-runbooks-fuer-vms/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure und PowerShell &#8211; Preise abfragen</title>
		<link>https://www.hertes.net/2021/02/azure-und-powershell-preise-abfragen/</link>
					<comments>https://www.hertes.net/2021/02/azure-und-powershell-preise-abfragen/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Sun, 07 Feb 2021 12:12:21 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Billing]]></category>
		<category><![CDATA[Cost Management]]></category>
		<category><![CDATA[Kosten]]></category>
		<category><![CDATA[Optimierung]]></category>
		<category><![CDATA[Optimization]]></category>
		<category><![CDATA[Preise]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=4078</guid>

					<description><![CDATA[Immer wieder ist es für Automatisierungs- oder Optimierungsthemen sinnvoll, Preise für Azure Services abzufragen &#8211; und zwar so, dass man sie automatisiert bzw. in Skripten verwerten kann. Dazu gibt es eine recht simple Lösung &#8211; und natürlich hat sie mit PowerShell zu tun 🙂 Es gibt eine API, die man abfragen kann. Diese ist unter https://prices.azure.com/api/retail/prices zu erreichen. Sie liefert bei direkter Abfrage eine riesige Menge an Daten, so dass es sinnvoll ist, schon bei der Abfrage zu filtern. Außerdem muss man die Abfrage in mehreren Durchläufen verwenden, sonst kommt es ggf. zu Timeouts oder es kommenden nicht alle Daten&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Immer wieder ist es für Automatisierungs- oder Optimierungsthemen sinnvoll, Preise für Azure Services abzufragen &#8211; und zwar so, dass man sie automatisiert bzw. in Skripten verwerten kann.</p>



<p>Dazu gibt es eine recht simple Lösung &#8211; und natürlich hat sie mit PowerShell zu tun <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>Es gibt eine API, die man abfragen kann. Diese ist unter </p>



<p>https://prices.azure.com/api/retail/prices </p>



<p>zu erreichen. Sie liefert bei direkter Abfrage eine riesige Menge an Daten, so dass es sinnvoll ist, schon bei der Abfrage zu filtern. Außerdem muss man die Abfrage in mehreren Durchläufen verwenden, sonst kommt es ggf. zu Timeouts oder es kommenden nicht alle Daten zurück.</p>



<p>Das Code-Schnippselchen, dass das erledigt, sieht dann folgendermaßen aus:</p>


<pre lang="PowerShell"> 
$pricelistApiUrl = "https://prices.azure.com/api/retail/prices?`$filter=armRegionName eq 'westeurope' and serviceName eq 'Virtual Machines'"
$reponseSkus = @()
do
{
    $webRequest = Invoke-WebRequest -Uri $pricelistApiUrl | ConvertFrom-Json
    $pricelistApiUrl = $webRequest.NextPageLink
    $reponseSkus += $webRequest.Items
    #$pricelistApiUrl
}
while ($pricelistApiUrl -ne $null)
$vmPrices = $reponseSkus | Where-Object {($_.type -eq "Consumption") -and ($_.skuName -notlike "*Low Priority*") -and ($_.skuName -notlike "*Spot*") }|  Sort-Object armSkuName,retailPrice -Descending
$vMPrices | Export-Csv -Path "VMPrices.csv" -Encoding UTF8 -NoTypeInformation -ErrorAction SilentlyContinue # In case the CSV is still open; For German systems, use '-Delimiter ";"'<p></p></pre>


<p>Das Ganze lässt sich natürlich auch auf beliebige andere Regionen und Services oder auch auf die anderen Attribute / Spalten filtern. Allerdings werden die Preise ausschließlich in Dollar geliefert! Mehr dazu siehe: </p>



<p><a href="https://docs.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices?WT.mc_id=AZ-MVP-5001882">Azure Retail Prices REST API overview | Microsoft Docs</a></p>



<p>Es gibt noch weitere API für Preise, die teilweise auch andere Funktionen, z.B. auch Währungsumrechnung, haben. Diese sind aber erstens scheinbar nicht vollständig und zweitens auch komplizierter in der Handhabung.</p>



<p>Viel Spaß beim Ausprobieren und Verwenden!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2021/02/azure-und-powershell-preise-abfragen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Deploy multiple ARM templates to Azure using PowerShell and GitHub Actions</title>
		<link>https://www.hertes.net/2020/06/deploy-multiple-arm-templates-to-azure-using-powershell-and-github-actions/</link>
					<comments>https://www.hertes.net/2020/06/deploy-multiple-arm-templates-to-azure-using-powershell-and-github-actions/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Thu, 04 Jun 2020 16:23:00 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Actions]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[CI/CD]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[Template]]></category>
		<category><![CDATA[Workflow]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3929</guid>

					<description><![CDATA[This is kind of an experiment. Usually, I produce all my content in German language, but to see if englisch content is of higher use for the community, I will give it a try&#8230; In the last days, I dealt a lot with GitHub Actions to find out, how it can be used to deploy Azure ARM templates to the cloud. My last &#8222;evolution&#8220; step now &#8211; I was working on this because of the very valuable hint of a collegue &#8211; is able to deploy ARM templates to all 4 available scope levels: Tenant level Management Group level Subscription&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>This is kind of an experiment. Usually, I produce all my content in German language, but to see if englisch content is of higher use for the community, I will give it a try&#8230;</em></p>



<p>In the last days, I dealt a lot with GitHub Actions to find out, how it can be used to deploy Azure ARM templates to the cloud. My last &#8222;evolution&#8220; step now &#8211; I was working on this because of the very valuable hint of a collegue &#8211; is able to deploy ARM templates to all 4 available scope levels:</p>



<ul class="wp-block-list"><li>Tenant level</li><li>Management Group level</li><li>Subscription level</li><li>Resource Group level</li></ul>



<p>And it also could be used, even when you don&#8217;t use GitHub Actions! But let&#8217;s start from the beginning&#8230;</p>



<span id="more-3929"></span>



<h2 class="wp-block-heading">A brief history of evolution</h2>



<p>In my first appraoch, I have used a simple PowerShell script (based on a Script by Sarah Lean, <a href="https://gist.github.com/weeyin83/81e7a7bf3caf3d0bce787db5d562b47e">https://gist.github.com/weeyin83/81e7a7bf3caf3d0bce787db5d562b47e</a>) to just deploy something to Azure using GitHub Actions. This is fast &amp; simple, but not very flexible.</p>



<p>My second approach took me to the new Azure PowerShell Action, where you can just run PowerShell code from within the GitHub Action:</p>



<p><a href="https://github.com/HaikoHertes/ActionsDemo/blob/master/.github/workflows/DeployARMtoAzure.yml">https://github.com/HaikoHertes/ActionsDemo/blob/master/.github/workflows/DeployARMtoAzure.yml</a></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="637" src="https://www.hertes.net/wp-content/uploads/2020/06/image-3-1024x637.png" alt="" class="wp-image-3930" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-3-1024x637.png 1024w, https://www.hertes.net/wp-content/uploads/2020/06/image-3-300x187.png 300w, https://www.hertes.net/wp-content/uploads/2020/06/image-3-768x477.png 768w, https://www.hertes.net/wp-content/uploads/2020/06/image-3.png 1475w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>So I used some small code to deploy an ARM template with its parameters file that both reside in an GitHub repo. This is even more easy to use, but still not very flexible, especially, when it comes to multiple ARM templates. <br><br>You can still find the code and stuff here:<br><a href="https://github.com/HaikoHertes/ActionsDemo">https://github.com/HaikoHertes/ActionsDemo</a></p>



<p>Next step was to deploy just a bunch of Templates with their parameters from a repository to become more flexible. Here I wrote a PowerShell script that does the main work:<br><a href="https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/DeployARMtoAzure.ps1">https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/DeployARMtoAzure.ps1</a><br>This script is then just called from within the GitHub Action:</p>



<p><a href="https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/.github/workflows/DeployARMtoAzure.yml#L27">https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/.github/workflows/DeployARMtoAzure.yml#L27</a></p>



<p>This allready does a good job, so you can fetch everything from here:<br><a href="https://github.com/HaikoHertes/ActionsDemo.v2">https://github.com/HaikoHertes/ActionsDemo.v2</a></p>



<h2 class="wp-block-heading">The final solution</h2>



<p>But then, a colleague of mine gave me an hint on some new options to not just deploy to Resource Group level, but to higher levels as well. And so I spent a day to investigate and re-write my PowerShell script. And now I can offer a script, that does the job! Let me show you&#8230;</p>



<p>You can pick up the script from here:<br><a href="https://github.com/HaikoHertes/ActionsDemo.v3/blob/master/DeployARMtoAzure.ps1">https://github.com/HaikoHertes/ActionsDemo.v3/blob/master/DeployARMtoAzure.ps1</a></p>



<h2 class="wp-block-heading">How the script works</h2>



<p>As it is a little more complex, I want to explain what it does and how it works. The script is divided into 5 major parts:</p>



<ul class="wp-block-list"><li>Setting the variables and defining the functions</li><li>Deploying to Tenant level</li><li>Deploying to Management Group level</li><li>Deploying to Subscription level</li><li>Deploying to Resource Group level</li></ul>



<p>If there are no templates for one of these levels or if their folder does not exist, it will just be skipped.</p>



<p>The script expects a defined folder structure:<br></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="455" height="603" src="https://www.hertes.net/wp-content/uploads/2020/06/image-4.png" alt="" class="wp-image-3931" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-4.png 455w, https://www.hertes.net/wp-content/uploads/2020/06/image-4-226x300.png 226w" sizes="auto, (max-width: 455px) 100vw, 455px" /></figure>



<p>The names of folders and files can be adjusted in the PowerShell Script:<br></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="811" height="272" src="https://www.hertes.net/wp-content/uploads/2020/06/image-6.png" alt="" class="wp-image-3933" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-6.png 811w, https://www.hertes.net/wp-content/uploads/2020/06/image-6-300x101.png 300w, https://www.hertes.net/wp-content/uploads/2020/06/image-6-768x258.png 768w" sizes="auto, (max-width: 811px) 100vw, 811px" /></figure>



<p>After all the variables are set, two functions are declared: GetLocation and GetScop. They are made to fetch the location / region from a given directory&#8217;s location file or return the default location and to fetch the scope of the deployment either from a scope file or the folder name. Both functions will be used in the later deployments. All files allow the usage of comments that start with the hashtag symbol &#8218;#&#8216;.<br></p>



<p>The 4 major parts for the different deployment levels are mostly very similar just with slight differences, thats why I just explain how any of them works.</p>



<p>They first grab all JSON files, that are not in the naming format *parameters.json in any subdirectory (so you can organize your templates by topic or something else and group them into folders). If an order file is given, it will fetch the sorting order from the file (allowing sorting by foldername and filename (default) or filename-only) or just sort by the default order. That way, you can define a deployment order by using proper names for your templates.</p>



<p>Now it will run through the list of templates, getting the scope and location of that templates folder, fetching the tags if any given and then trigger the deployment with any of these Cmdlets, whatever is sufficient for the scope / level:</p>



<ul class="wp-block-list"><li>New-AzTenantDeployment</li><li>New-AzManagementGroupDeployment</li><li>New-AzSubscriptionDeployment</li><li>New-AzResourceGroupDeployment</li></ul>



<p>For a given template ABC.json , it allways expects a ABC.parameters.json file next to the template with the parameters. If no parameters are needed, just provide an empty file.</p>



<p>At the end, all templates in all of the 4 levels are deployed <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<h2 class="wp-block-heading">How to use the script</h2>



<p>The script was made to be used with GitHub Actions:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="656" src="https://www.hertes.net/wp-content/uploads/2020/06/image-7-1024x656.png" alt="" class="wp-image-3934" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-7-1024x656.png 1024w, https://www.hertes.net/wp-content/uploads/2020/06/image-7-300x192.png 300w, https://www.hertes.net/wp-content/uploads/2020/06/image-7-768x492.png 768w, https://www.hertes.net/wp-content/uploads/2020/06/image-7.png 1475w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Here it is just called after repo checkout and Azure login. You can get the stuff from here:<br><a href="https://github.com/HaikoHertes/ActionsDemo.v3/blob/master/.github/workflows/DeployARMtoAzure.yml">https://github.com/HaikoHertes/ActionsDemo.v3/blob/master/.github/workflows/DeployARMtoAzure.yml</a><br><a href="https://github.com/HaikoHertes/ActionsDemo.v3">https://github.com/HaikoHertes/ActionsDemo.v3</a><br><br>It expects the ARM templates in a subfolder &#8222;arm&#8220; within the same repo where the GitHub Action resides.</p>



<p>Be aware that as of today, you need to use ubuntu-20.04 and AzPS 4.1.0 (This is needed for the latest version of the deployment Cmdlets above, and AzPS 4.1.0 is only included in the ubuntu-20.04 container image used by GitHub Actions.</p>



<p>The other option would be to use the script without GitHub Actions and even without any repository. You could just run it locally with a given local folder structure containing the templates and other files. You would just need to add something like</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Connect-AzAccount</p></blockquote>



<p>to do the login. Be aware that you still need Az PS Module version 4.1.0 or higher, which you can install with</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Install-Module -Name Az -AllowClobber -MinimumVersion 4.1.0</p></blockquote>



<h2 class="wp-block-heading">Setting the proper rights on Azure</h2>



<p>To be able to deploy to Azure, you need a user with proper rights. Especially when using GitHub Actions, it is not recommended to use a regular named user, but service principals. In my video (German language, but it shows eveything on english UI) on YouTube, you can see how to do this:</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Microsoft Azure ?? Mit GitHub Actions ARM Templates ausrollen" width="500" height="281" src="https://www.youtube.com/embed/TRBw1RyRo_I?start=1238&#038;feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption>Start at 20:38 to just see the user account part&#8230;</figcaption></figure>



<p>You will need something like this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>az ad sp create-for-rbac &#8211;name &#8222;github&#8220; &#8211;role contributor &#8211;scopes /subscriptions/YOUR_SUB_ID &#8211;sdk-auth</p></blockquote>



<p>To be able to deploy to Tenant level, you will need the proper rights on root level. Some types of template also need owner rights, especially wheny you want to deploy role assignments or such. Either adjust the above command or (especially, when the user allready exists), extend the rights with somthing like this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>az role assignment create &#8211;role &#8222;Owner&#8220; &#8211;assignee &#8222;[USERID]&#8220; &#8211;scope &#8222;/&#8220;</p></blockquote>



<h2 class="wp-block-heading">About the different files that can be used</h2>



<p>There is several files that can be used to control how the script works:</p>



<h4 class="wp-block-heading">arm/DefaultLocation.txt</h4>



<p>This file defines the default location for any deployment, that needs a location to be set outside the ARM template. It also includes a list of all available location names. Treat this file as mandatory.</p>



<h4 class="wp-block-heading">arm/ANY_LEVEL/order.txt</h4>



<p>This file defines the sorting order and therefor the deployment order within that given level. There is two options:<br></p>



<ul class="wp-block-list"><li>SortByFolderName = Sorting by foldernames and then by filenames (default)</li><li>SortByFileName = Folder names are ignored, sorting just by templates filenames</li></ul>



<p>The file is optional; if no order is given through a file, the default order will be by foldername first and then by templates filename.</p>



<h4 class="wp-block-heading">scope.txt next to any template JSON</h4>



<p>By default, the deployment scope (i.e. Subscription ID) is fetched from the templates folder ANY_DEPLOYMENT. If needed (i.e. when you want to deploy multiple folders as seperate groups, but into the same scop), you can provide a scope.txt file instead. In here, give ID or name of the scope, both would work.</p>



<h4 class="wp-block-heading">tags.txt next to any template JSON</h4>



<p>You can provide a tags.txt file with the content like</p>



<p>KEY = VALUE</p>



<p>pairs to set tags right on the deployment.</p>



<h4 class="wp-block-heading">location.txt next to any template JSON</h4>



<p>Next to a template file, you can provide a location.txt file that will set the location for the deployment, if needed. If the template itself sets a location, then templates location will be used. If neither template nor location.txt provide a location, but one is needed, the defaultLocation will be used.</p>



<p>(The names are given as they would be with the parameters I provide with my script; they can be changed)</p>



<h2 class="wp-block-heading">Copyright / legal notice</h2>



<p><strong>Copyright 2020 Haiko Hertes</strong></p>



<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &#8222;Software&#8220;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>



<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>



<p>THE SOFTWARE IS PROVIDED &#8222;AS IS&#8220;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2020/06/deploy-multiple-arm-templates-to-azure-using-powershell-and-github-actions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure Regions / Locations auflisten</title>
		<link>https://www.hertes.net/2020/06/azure-regions-locations-auflisten/</link>
					<comments>https://www.hertes.net/2020/06/azure-regions-locations-auflisten/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Wed, 03 Jun 2020 12:42:50 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Location]]></category>
		<category><![CDATA[Region]]></category>
		<category><![CDATA[Regionen]]></category>
		<category><![CDATA[Shell]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3926</guid>

					<description><![CDATA[Immer wieder begegnet mir das Problem, dass ich z.B. für ARM Templates den &#8222;internen&#8220; Namen für eine Azure Region (dann als &#8222;Location&#8220; bezeichnet) brauche. Und immer wieder liefern Suchmaschinen-Anfragen nur die &#8222;Sprechenden Namen&#8220;. Daher hier für mich und den Rest der Welt als kleiner Cheat: Man kann die für den eigenen Tenant verfügbaren Regionen recht leicht mit Hilfe der Azure CLI (z.B. über Azure CloudShell) abfragen: az account list-locations --query "[].{Name:name, DisplayName:displayName}" -o table Regionen und Verfügbarkeitszonen in Azure &#124; Microsoft Docs]]></description>
										<content:encoded><![CDATA[
<p>Immer wieder begegnet mir das Problem, dass ich z.B. für ARM Templates den &#8222;internen&#8220; Namen für eine Azure Region (dann als &#8222;Location&#8220; bezeichnet) brauche. Und immer wieder liefern Suchmaschinen-Anfragen nur die &#8222;Sprechenden Namen&#8220;. Daher hier für mich und den Rest der Welt als kleiner Cheat:</p>


<p><span id="more-3926"></span></p>


<p>Man kann die für den eigenen Tenant verfügbaren Regionen recht leicht mit Hilfe der Azure CLI (z.B. über Azure CloudShell) abfragen:</p>


<pre lang="PowerShell" line="1">az account list-locations --query "[].{Name:name, DisplayName:displayName}" -o table</pre>


<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="830" height="498" src="https://www.hertes.net/wp-content/uploads/2020/06/image-2.png" alt="" class="wp-image-3927" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-2.png 830w, https://www.hertes.net/wp-content/uploads/2020/06/image-2-300x180.png 300w, https://www.hertes.net/wp-content/uploads/2020/06/image-2-768x461.png 768w" sizes="auto, (max-width: 830px) 100vw, 830px" /></figure>



<p><a href="https://docs.microsoft.com/de-de/azure/availability-zones/az-overview?WT.mc_id=AZ-MVP-5001882#regions">Regionen und Verfügbarkeitszonen in Azure | Microsoft Docs</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2020/06/azure-regions-locations-auflisten/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure ARM Templates mit GitHub Actions deployen</title>
		<link>https://www.hertes.net/2020/06/azure-arm-templates-mit-github-actions-deployen/</link>
					<comments>https://www.hertes.net/2020/06/azure-arm-templates-mit-github-actions-deployen/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Tue, 02 Jun 2020 18:02:33 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Actions]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[CI/CD]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Deploy]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[IaC]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[Script]]></category>
		<category><![CDATA[Skript]]></category>
		<category><![CDATA[Template]]></category>
		<category><![CDATA[Templates]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3922</guid>

					<description><![CDATA[Geht es um den Aufbau automatisierter CI/CD Pipelines für Azure, so denken die meisten wohl eher an Azure DevOps. Aber auch mit GitHub lässt sich so etwas erreichen &#8211; und zwar völlig kostenlos. Das Werkzeug dazu heißt GitHub Actions. Zu GitHub Actions selbst will ich hier gar nicht so viel schreiben &#8211; es gibt bereits einige Blogartikel und co. dazu. Ich verweise aber gerne auf mein Video, welches ich dazu gemacht habe: Nun kam von einem meiner geschätzten Kollegen zu Recht die Frage, wie man denn in dieser (ersten, im Video gezeigten) Variante mehrere ARM Templates bereitstellen kann. Und dazu&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Geht es um den Aufbau automatisierter CI/CD Pipelines für Azure, so denken die meisten wohl eher an Azure DevOps. Aber auch mit GitHub lässt sich so etwas erreichen &#8211; und zwar völlig kostenlos. Das Werkzeug dazu heißt GitHub Actions. Zu GitHub Actions selbst will ich hier gar nicht so viel schreiben &#8211; es gibt bereits einige Blogartikel und co. dazu. Ich verweise aber gerne auf mein Video, welches ich dazu gemacht habe:</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Microsoft Azure ?? Mit GitHub Actions ARM Templates ausrollen" width="500" height="281" src="https://www.youtube.com/embed/TRBw1RyRo_I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption>Mein YouTube Video zu GitHub Actions</figcaption></figure>



<p>Nun kam von einem meiner geschätzten Kollegen zu Recht die Frage, wie man denn in dieser (ersten, im Video gezeigten) Variante mehrere ARM Templates bereitstellen kann. Und dazu möchte ich hier die passende Antwort liefern&#8230;</p>



<span id="more-3922"></span>



<p>Eine Variante wäre sicherlich, in diesem Skript </p>



<p><a href="https://github.com/HaikoHertes/ActionsDemo/blob/master/.github/workflows/DeployARMtoAzure.yml#L23">https://github.com/HaikoHertes/ActionsDemo/blob/master/.github/workflows/DeployARMtoAzure.yml#L23</a></p>



<p>mehrfach das &#8222;az deployment group create&#8220; aufzurufen &#8211; aber dann müssten man wissen, wie viele Templates es sind und das Skript würde auch schnell sehr lang.</p>



<p>Als aus meiner Sicht bessere Lösung habe ich ein PowerShell Skript geschrieben, dass in der Verzeichnisstruktur des Repositories einen Ordner &#8222;arm\&#8220; erwartet und darin Unterordner mit den Namen der gewünschten Resource Groups. Diese werden falls nötig vom Skript angelegt. Außerdem sucht das Skript Templates im Format XYZ.json und dazugehörige Parameter-Files im Format XYZ.parameters.json. Diese Templates werden nun alphabetisch geordnet mittels ARM bereitgestellt &#8211; egal, wie viele es sind. Dabei werden aus einer Datei &#8222;tags.txt&#8220; falls gewünscht die Tages im Format</p>



<p>Tag = Wert</p>



<p>geladen und bei der Bereitstellung der RGs und Ressourcen mit angewendet. Die zu verwendende Location (nur eine pro RG ist erlaubt, aber das entspricht weitgehend dem üblichen Vorgehen) wird ebenfalls aus einer TXT-Datei location.txt gelesen.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="501" height="308" src="https://www.hertes.net/wp-content/uploads/2020/06/image-1.png" alt="" class="wp-image-3924" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-1.png 501w, https://www.hertes.net/wp-content/uploads/2020/06/image-1-300x184.png 300w" sizes="auto, (max-width: 501px) 100vw, 501px" /><figcaption>Der erwartete Verzeichnisbaum</figcaption></figure>



<p>Im GitHub Repo müssen zwei Secrets hinterlegt werden:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="473" src="https://www.hertes.net/wp-content/uploads/2020/06/image-1024x473.png" alt="" class="wp-image-3923" srcset="https://www.hertes.net/wp-content/uploads/2020/06/image-1024x473.png 1024w, https://www.hertes.net/wp-content/uploads/2020/06/image-300x139.png 300w, https://www.hertes.net/wp-content/uploads/2020/06/image-768x355.png 768w, https://www.hertes.net/wp-content/uploads/2020/06/image.png 1148w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Screenshot der GitHub Secrets</figcaption></figure>



<p>Einmal ein Secret für die Credentials (wie man die anlegt zeige ich im <a rel="noreferrer noopener" href="https://youtu.be/TRBw1RyRo_I?t=1227" target="_blank">Video ab 20:27</a>) und einmal die Subscription ID der zu verwendenden Subscription. Ergo ist ein Repo pro Subscription nötig&#8230;</p>



<p>Das PowerShell Script selbst könnt ihr hier herunterladen:</p>



<p><a href="https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/DeployARMtoAzure.ps1">https://github.com/HaikoHertes/ActionsDemo.v2/blob/master/DeployARMtoAzure.ps1</a></p>



<p>Alternativ könnt ihr gleich mein ganzes Demo Repo auf GitHub clonen:</p>



<p><a rel="noreferrer noopener" href="https://github.com/HaikoHertes/ActionsDemo.v2" target="_blank">https://github.com/HaikoHertes/ActionsDemo.v2</a> bzw<br><a rel="noreferrer noopener" href="https://github.com/HaikoHertes/ActionsDemo.v2.git" target="_blank">https://github.com/HaikoHertes/ActionsDemo.v2.git</a> <br><br>Wichtig: Damit mit -Tag bzw. -Tags auch die tags gleich mit bereitgestellt werden können braucht man das Az Modul in Version 4.1.0 und das wiederum ist derzeit nur im Ubuntu-20.04 Image auf GitHub enthalten. Siehe dazu auch hier:</p>



<p><a href="https://github.com/marketplace/actions/azure-powershell-action">https://github.com/marketplace/actions/azure-powershell-action</a><br><a href="https://github.com/actions/virtual-environments/blob/master/images/linux/Ubuntu2004-README.md">https://github.com/actions/virtual-environments/blob/master/images/linux/Ubuntu2004-README.md</a><br><a href="https://github.com/actions/virtual-environments/tree/master/images">https://github.com/actions/virtual-environments/tree/master/images</a></p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2020/06/azure-arm-templates-mit-github-actions-deployen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Azure &#8211; RBAC Custom Role für das starten und stoppen von VMs</title>
		<link>https://www.hertes.net/2020/02/azure-rbac-custom-role-fuer-das-starten-und-stoppen-von-vms/</link>
					<comments>https://www.hertes.net/2020/02/azure-rbac-custom-role-fuer-das-starten-und-stoppen-von-vms/#comments</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Tue, 18 Feb 2020 18:21:15 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Az]]></category>
		<category><![CDATA[Berechtigungen]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[RBAC]]></category>
		<category><![CDATA[Rechte]]></category>
		<category><![CDATA[Role]]></category>
		<category><![CDATA[Rolle]]></category>
		<category><![CDATA[Rollen]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[Virtuelle Maschine]]></category>
		<category><![CDATA[VM]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3893</guid>

					<description><![CDATA[Weil es die Tage bei einem meiner Kunden wieder mal ein Thema war, möchte ich es hier nun mal im Detail beleuchten. Und zwar geht es um die Anforderung, Virtuelle Maschinen in Azure starten und stoppen zu können, ohne beispielsweise die VM löschen zu können oder ihre SKU zu verändern. Natürlich gibt es den &#8222;Virtual Machine Contributor&#8220; als built-in Role, aber diese darf eben deutlich zu viel. Wie geht man nun an das Thema heran? Zunächst muss man zwei Dinge in Erfahrung bringen: Den Namen des Resource-Providers um den es geht Die Operationen auf diesem Provider, die man erlauben oder&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Weil es die Tage bei einem meiner Kunden wieder mal ein Thema war, möchte ich es hier nun mal im Detail beleuchten. Und zwar geht es um die Anforderung, Virtuelle Maschinen in Azure starten und stoppen zu können, ohne beispielsweise die VM löschen zu können oder ihre SKU zu verändern. Natürlich gibt es den &#8222;Virtual Machine Contributor&#8220; als built-in Role, aber diese darf eben deutlich zu viel.</p>



<p>Wie geht man nun an das Thema heran? Zunächst muss man zwei Dinge in Erfahrung bringen:</p>



<ul class="wp-block-list"><li>Den <strong>Namen </strong>des <strong>Resource-Providers </strong>um den es geht</li><li>Die <strong>Operationen </strong>auf diesem Provider, die man erlauben oder verbieten möchte</li></ul>



<span id="more-3893"></span>



<p>Dazu kann man sich in den Microsoft Docs informieren:</p>



<ul class="wp-block-list"><li> <a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers?WT.mc_id=AZ-MVP-5001882">https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers</a>  &#8211; hier findet man die <strong>Resource Provider</strong> zu dein einzelnen Azure Services</li><li> <a href="https://docs.microsoft.com/de-de/azure/role-based-access-control/resource-provider-operations?WT.mc_id=AZ-MVP-5001882">https://docs.microsoft.com/de-de/azure/role-based-access-control/resource-provider-operations</a>  &#8211; und hier die auf den jeweiligen Resource Providern möglichen <strong>Operationen</strong></li></ul>



<p>Für den Fall der Virtual Machine finden wir dazu also:</p>



<ul class="wp-block-list"><li>Der Resource Provider heisst &#8222;<strong>Microsoft.Compute</strong>&#8222;</li><li>Auf diesem sind u.a. folgende Aktionen vorgesehen:<ul><li>Microsoft.Compute/virtualMachines/powerOff/action    <ul><li>Powers off the virtual machine. Note that the virtual machine will continue to be billed.</li></ul></li><li>Microsoft.Compute/virtualMachines/read            <ul><li>Get the properties of a virtual machine</li></ul></li><li> Microsoft.Compute/virtualMachines/restart/action    <ul><li>Restarts the virtual machine</li></ul></li><li> Microsoft.Compute/virtualMachines/start/action<ul><li>Starts the virtual machine</li></ul></li></ul></li></ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="336" src="https://www.hertes.net/wp-content/uploads/2020/02/image-1024x336.png" alt="" class="wp-image-3894" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-1024x336.png 1024w, https://www.hertes.net/wp-content/uploads/2020/02/image-300x99.png 300w, https://www.hertes.net/wp-content/uploads/2020/02/image-768x252.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-1536x505.png 1536w, https://www.hertes.net/wp-content/uploads/2020/02/image.png 2045w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="536" src="https://www.hertes.net/wp-content/uploads/2020/02/image-1-1024x536.png" alt="" class="wp-image-3895" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-1-1024x536.png 1024w, https://www.hertes.net/wp-content/uploads/2020/02/image-1-300x157.png 300w, https://www.hertes.net/wp-content/uploads/2020/02/image-1-768x402.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-1-1536x804.png 1536w, https://www.hertes.net/wp-content/uploads/2020/02/image-1-2048x1072.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Die Liste der möglichen Aktionen auf einem Resource Provider kann man auch via PowerShell bekommen, z.B.:</p>



<p><pre lang="PowerShell" line="1">Get-AzProviderOperation "Microsoft.Compute/*" | FT Operation, Description -AutoSize</pre></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="208" src="https://www.hertes.net/wp-content/uploads/2020/02/image-2-1024x208.png" alt="" class="wp-image-3896" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-2-1024x208.png 1024w, https://www.hertes.net/wp-content/uploads/2020/02/image-2-300x61.png 300w, https://www.hertes.net/wp-content/uploads/2020/02/image-2-768x156.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-2-1536x311.png 1536w, https://www.hertes.net/wp-content/uploads/2020/02/image-2-2048x415.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Man muss allerdings berücksichtigen, dass es zum Starten einer VM auch erstmal nötig ist, die VM überhaupt sehen zu dürfen&#8230;</p>



<p>Als nächstes muss man die Rollen-Definition im JSON-Format schreiben. Dazu kann man sich auch vorab eine bereits existierende Rollendefinition herunterladen, z.B. mit</p>



<p><pre lang="PowerShell" line="1">Get-AzRoleDefinition -Name "Virtual Machine Contributor" | ConvertTo-Json</pre></p>



<p>Nun passt man sich das JSON so an, dass die gewünschten Aktionen abgedeckt sind. Dabei wird die &#8222;ID&#8220; Zeile entfernt und &#8222;IsCustom&#8220; auf &#8222;true&#8220; gesetzt. Außerdem muss der AssignableScope gesetzt werden. In unserem Fall führt das in etwa zu dieser Definition:</p>



<p><pre lang="Javascript" line="1">
{
  "Name": "Virtual Machine Starter-Stopper",
  "IsCustom": true,
  "Description": "Lets you see, start, restart and stop Virtual Machines.",
  "Actions": [
	"Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.Compute/virtualMachines/read",
	"Microsoft.Compute/virtualMachines/start/action",
	"Microsoft.Compute/virtualMachines/restart/action",
	"Microsoft.Compute/virtualMachines/powerOff/action",
	"Microsoft.Compute/virtualMachines/deallocate/action"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/00000000-1234-5678-91234-000000000000"
  ]
}
</pre></p>



<p>Diese Definition kann man z.B. mit vi in der Azure Cloud Shell in ein File schreiben. Diese kann man dann wiederum mit </p>



<p><pre lang="PowerShell" line="1">New-AzRoleDefinition -InputFile myRole.json</pre></p>



<p>in eine neue Rolle schreiben lassen.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="339" src="https://www.hertes.net/wp-content/uploads/2020/02/image-3-1024x339.png" alt="" class="wp-image-3898" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-3-1024x339.png 1024w, https://www.hertes.net/wp-content/uploads/2020/02/image-3-300x99.png 300w, https://www.hertes.net/wp-content/uploads/2020/02/image-3-768x254.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-3-1536x508.png 1536w, https://www.hertes.net/wp-content/uploads/2020/02/image-3.png 1963w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Nun kann man die Rolle bspw. über das Azure Portal zuweisen:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="755" height="1024" src="https://www.hertes.net/wp-content/uploads/2020/02/image-4-755x1024.png" alt="" class="wp-image-3899" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-4-755x1024.png 755w, https://www.hertes.net/wp-content/uploads/2020/02/image-4-221x300.png 221w, https://www.hertes.net/wp-content/uploads/2020/02/image-4-768x1042.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-4.png 896w" sizes="auto, (max-width: 755px) 100vw, 755px" /></figure>



<p>Und damit kann der Benutzer dann genau die definierten Rechte wahrnehmen &#8211; und nicht mehr!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="345" src="https://www.hertes.net/wp-content/uploads/2020/02/image-5-1024x345.png" alt="" class="wp-image-3900" srcset="https://www.hertes.net/wp-content/uploads/2020/02/image-5-1024x345.png 1024w, https://www.hertes.net/wp-content/uploads/2020/02/image-5-300x101.png 300w, https://www.hertes.net/wp-content/uploads/2020/02/image-5-768x259.png 768w, https://www.hertes.net/wp-content/uploads/2020/02/image-5-1536x518.png 1536w, https://www.hertes.net/wp-content/uploads/2020/02/image-5-2048x690.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Viel Spaß beim Ausprobieren!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2020/02/azure-rbac-custom-role-fuer-das-starten-und-stoppen-von-vms/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Azure &#038; PowerShell &#8211; Das UsageDetails CSV nach Tags auswerten</title>
		<link>https://www.hertes.net/2020/01/azure-powershell-das-usagedetails-csv-nach-tags-auswerten/</link>
					<comments>https://www.hertes.net/2020/01/azure-powershell-das-usagedetails-csv-nach-tags-auswerten/#comments</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Sat, 11 Jan 2020 16:04:43 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Abrechnung]]></category>
		<category><![CDATA[Auswerten]]></category>
		<category><![CDATA[CSV]]></category>
		<category><![CDATA[Finanzen]]></category>
		<category><![CDATA[Kosten]]></category>
		<category><![CDATA[Rechnung]]></category>
		<category><![CDATA[Tagging]]></category>
		<category><![CDATA[Tags]]></category>
		<category><![CDATA[Umwandeln]]></category>
		<category><![CDATA[Usage Details]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3853</guid>

					<description><![CDATA[Hinweis: Der Großteil des Artikels ist auch in meinem YouTube-Video zu diesem Thema enthalten: Auf Grund vieler Nachfragen aus Community und Kunden habe ich mich dazu entschieden, dieses Thema etwas genauer zu beleuchten&#8230; Wenn man Azure in größerem Umfang nutzt, dann kommt schnell die Frage nach interner Kostenverrechnung (&#8222;Innerbetriebliche Leistungsverrechnung&#8220; / &#8222;Charge back&#8220;) oder zumindest der Möglichkeit, die Kosten den jeweiligen Verursachern zuzuordnen und transparent darzustellen. Ein wesentliches Hilfsmittel dafür ist das Tagging von Ressourcen. Klar, man könnte die Ressourcen auch nach Kostenstellen getrennt in unterschiedlichen Subscriptions unterbringen, das stößt in der Praxis aber schnell an Grenzen und auf Probleme.&#8230;]]></description>
										<content:encoded><![CDATA[
<p><em>Hinweis: Der Großteil des Artikels ist auch in meinem YouTube-Video zu diesem Thema enthalten:</em></p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Microsoft Azure - Detaillierte Kostenaufstellung mit Tags auswerten" width="500" height="281" src="https://www.youtube.com/embed/DPSAySYhexU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Auf Grund vieler Nachfragen aus Community und Kunden habe ich mich dazu entschieden, dieses Thema etwas genauer zu beleuchten&#8230; Wenn man Azure in größerem Umfang nutzt, dann kommt schnell die Frage nach interner Kostenverrechnung (&#8222;Innerbetriebliche Leistungsverrechnung&#8220; / &#8222;Charge back&#8220;) oder zumindest der Möglichkeit, die Kosten den jeweiligen Verursachern zuzuordnen und transparent darzustellen. Ein wesentliches Hilfsmittel dafür ist das Tagging von Ressourcen. Klar, man könnte die Ressourcen auch nach Kostenstellen getrennt in unterschiedlichen Subscriptions unterbringen, das stößt in der Praxis aber schnell an Grenzen und auf Probleme. </p>



<p>Hat man nun seine Ressourcen mit den entsprechenden Tags versehen, z.B. nach Besitzer (&#8222;Owner&#8220;), Kostenstelle (&#8222;Cost center&#8220;) oder Abteilung (&#8222;Department&#8220;), dann tauchen diese Tags leider noch nicht in der regulären Rechnung auf.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="431" src="https://www.hertes.net/wp-content/uploads/2020/01/image-1024x431.png" alt="" class="wp-image-3854" srcset="https://www.hertes.net/wp-content/uploads/2020/01/image-1024x431.png 1024w, https://www.hertes.net/wp-content/uploads/2020/01/image-300x126.png 300w, https://www.hertes.net/wp-content/uploads/2020/01/image-768x323.png 768w, https://www.hertes.net/wp-content/uploads/2020/01/image.png 1522w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>Nun kann man sich aus dem Azure Portal (oder auch aus dem EA / Enterprise Portal oder via REST API) eine Detail-Aufstellung der Kosten herunterladen. Dazu muss man zu &#8222;Cost Management + Billing&#8220; / Billing-Scope auswählen / &#8222;Usage + Charges&#8220; / Monat wählen / Download-Button klicken / Kurz warten / &#8220; Usage Details Version 2&#8243; auswählen. Diese &#8222;Usage Details&#8220; enthalten dann auch die Tags. Allerdings: Selbst wenn man das CSV-File so umformatiert, dass Excel damit umgehen kann, ergibt sich noch ein Problem:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="439" src="https://www.hertes.net/wp-content/uploads/2020/01/image-1-1024x439.png" alt="" class="wp-image-3856" srcset="https://www.hertes.net/wp-content/uploads/2020/01/image-1-1024x439.png 1024w, https://www.hertes.net/wp-content/uploads/2020/01/image-1-300x129.png 300w, https://www.hertes.net/wp-content/uploads/2020/01/image-1-768x329.png 768w, https://www.hertes.net/wp-content/uploads/2020/01/image-1-1536x659.png 1536w, https://www.hertes.net/wp-content/uploads/2020/01/image-1.png 1800w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Die einzelnen Tags werden alle zusammen geworfen und in einer &#8222;Spalte&#8220; vermischt. Damit ist das Suchen oder Filtern nach einzelnen Tags schon recht schwer &#8211; eine bestimmte Kombination aus Tags ist damit unmöglich zu filtern. Dazu müsste man die Tags jeweils in einzelnen Spalten ablegen. Und da kommt PowerShell und dessen Möglichkeit, mit dem JSON-Format umzugehen, ins Spiel! Ich habe eine Script geschrieben, was die Spalte in die einzelnen Tags aufteilt. Dabei werden auch gleich Zahlen und Daten in das lokale Format überführt.</p>



<p><pre lang="Powershell" line="1">
# Script to expand tags from the usage details CSV provided by Azure / Microsoft
# to filter usage by tags; also converts some numbers to local format
# Download CSV file by hand first!


# This is needed for the FileOpen Dialog	
Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
    InitialDirectory = [Environment]::GetFolderPath('Desktop') 
    Filter = 'CSV-Files (*.csv)|*.csv'
}
$null = $FileBrowser.ShowDialog() # Just to open the dialog

If($FileBrowser.FileName -eq "")
{
    Write-Verbose "No file selected - aborting."
    Break    
}

$CSV = Import-Csv $FileBrowser.FileName -Delimiter ","

for ($i=0; $i -lt $CSV.length; $i++) 
{
    # Showing progress
    Write-Progress -Activity "Expanding in Progress..." -Status "$([math]::truncate($i / $($CSV.length) * 100))% complete..." -PercentComplete $($i / $($CSV.length) * 100)
    
    # Converting dates and numbers to local format
    $CSV[$i].Date = [datetime]::ParseExact( $CSV[$i].Date, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].BillingPeriodStartDate = [datetime]::ParseExact( $CSV[$i].BillingPeriodStartDate, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].BillingPeriodEndDate = [datetime]::ParseExact( $CSV[$i].BillingPeriodEndDate, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].Quantity = [float]$CSV[$i].Quantity
    $CSV[$i].EffectivePrice = [float]$CSV[$i].EffectivePrice
    $CSV[$i].Cost = [float]$CSV[$i].Cost
    $CSV[$i].UnitPrice = [float]$CSV[$i].UnitPrice


    # Expand Tags
    $Tags = "{ $($CSV[$i].Tags) }" | ConvertFrom-Json # We need to add some brackets here...
    if ($Tags -ne $null) {
         $Tags.PSObject.Properties | ForEach { 
            $TagName = "Tag-$($_.Name)" 
            Add-Member -InputObject $CSV[$i] $TagName $_.Value 
            # Adding the heading - what a rhyme (; ...
            if ($CSV[0].PSObject.Properties[$TagName] -eq $null) {
                Add-Member -InputObject $CSV[0] $TagName $null -Force
            }
        }
    }

}

# Saving as Excel-readable CSV
$CSV | Export-Csv "$([System.IO.Path]::GetDirectoryName($FileBrowser.FileName))\$([io.path]::GetFileNameWithoutExtension($FileBrowser.FileName))_expanded.csv" -NoTypeInformation -Delimiter ";"

</pre></p>


<p>Das Script findet ihr natürlich auch auf meinem GitHub Repo:</p>
<p><a href="https://github.com/HaikoHertes/scripts/blob/master/Azure/Management/Expand-AzureTagsFromUsageDetails.ps1">https://github.com/HaikoHertes/scripts/blob/master/Azure/Management/Expand-AzureTagsFromUsageDetails.ps1 </a></p>
<p>Das Resultat der Umwandlung wird dann in eine neue Excel-Datei im selben Folder wie die Originaldatei abgespeichert und kann dann problemlos in Excel geöffnet werden:</p>


<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="486" src="https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt-1024x486.png" alt="" class="wp-image-3859" srcset="https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt-1024x486.png 1024w, https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt-300x143.png 300w, https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt-768x365.png 768w, https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt-1536x730.png 1536w, https://www.hertes.net/wp-content/uploads/2020/01/Unbenannt.png 1800w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>Wie man hier sieht sind die Tags nun in separaten Spalten untergebracht, so dass man sehr gut danach sortieren, darauf filtern oder mehr tun kann.</p>



<p>Viel Spaß beim Ausprobieren bzw. Benutzen!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2020/01/azure-powershell-das-usagedetails-csv-nach-tags-auswerten/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>PowerShell &#8211; Nicht verwendete Azure Ressourcen finden</title>
		<link>https://www.hertes.net/2019/09/powershell-nicht-verwendete-azure-ressourcen-finden/</link>
					<comments>https://www.hertes.net/2019/09/powershell-nicht-verwendete-azure-ressourcen-finden/#respond</comments>
		
		<dc:creator><![CDATA[Haiko]]></dc:creator>
		<pubDate>Tue, 17 Sep 2019 15:17:30 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Kosten]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Public Cloud]]></category>
		<category><![CDATA[Ressources]]></category>
		<guid isPermaLink="false">https://www.hertes.net/?p=3833</guid>

					<description><![CDATA[Ein regelmäßiges Problem im Azure-Alltag ist das Aufräumen nicht mehr benötigter Azure-Ressourcen. Diese kosten in der Regel unnötig Geld und stellen zum Teil auch ein (Sicherheits-)Risiko dar (wenn zum Beispiel eine nicht mehr verwendete VM aus dem Fokus gerät und über Jahre nicht gepatcht wird). Um dieser Herausforderung zu begegnen gilt es zunächst, die Ressourcen, die &#8222;weg&#8220; können, zu identifizieren. Dazu habe ich eine erste Version eines PowerShell Skriptes erstellt, welches: Nicht verwendete Public IPs Nicht verwendete NICs Nicht verwendete NSGs Nicht verwendete Managed Disks findet und aufführt. Über die Zeit möchte ich das Skript weiter ausbauen. Ihr findet es&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Ein regelmäßiges Problem im Azure-Alltag ist das Aufräumen nicht mehr benötigter Azure-Ressourcen. Diese kosten in der Regel unnötig Geld und stellen zum Teil auch ein (Sicherheits-)Risiko dar (wenn zum Beispiel eine nicht mehr verwendete VM aus dem Fokus gerät und über Jahre nicht gepatcht wird).</p>



<p>Um dieser Herausforderung zu begegnen gilt es zunächst, die Ressourcen, die &#8222;weg&#8220; können, zu identifizieren. Dazu habe ich eine erste Version eines PowerShell Skriptes erstellt, welches:</p>



<ul class="wp-block-list"><li>Nicht verwendete Public IPs</li><li>Nicht verwendete NICs</li><li>Nicht verwendete NSGs</li><li>Nicht verwendete Managed Disks</li></ul>



<p>findet und aufführt. </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="508" src="https://www.hertes.net/wp-content/uploads/2019/09/image-1024x508-1-1024x508.png" alt="" class="wp-image-3837" srcset="https://www.hertes.net/wp-content/uploads/2019/09/image-1024x508-1.png 1024w, https://www.hertes.net/wp-content/uploads/2019/09/image-1024x508-1-300x149.png 300w, https://www.hertes.net/wp-content/uploads/2019/09/image-1024x508-1-768x381.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p>Über die Zeit möchte ich das Skript weiter ausbauen.</p>



<p>Ihr findet es in meinem GitHub Repository:</p>



<p><a href="https://github.com/HaikoHertes/scripts/blob/master/Azure/CostOptimization/GetOrphanedAzureRessources.ps1">https://github.com/HaikoHertes/scripts/blob/master/Azure/CostOptimization/GetOrphanedAzureRessources.ps1</a></p>



<p>Und ja, natürlich bietet Azure mit seinen Recommendations hier auch schon einiges, allerdings eben nicht &#8222;live&#8220;&#8230;</p>



<p>Viel Spaß beim Ausprobieren &#8211; über Kommentare freue ich mich!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.hertes.net/2019/09/powershell-nicht-verwendete-azure-ressourcen-finden/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
