<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Piotr Wachulec</title>
    <description>The latest articles on DEV Community by Piotr Wachulec (@piotrwachulec).</description>
    <link>https://dev.to/piotrwachulec</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F617195%2Fdd83a853-f8e5-45f7-9325-6b7d9253474f.jpeg</url>
      <title>DEV Community: Piotr Wachulec</title>
      <link>https://dev.to/piotrwachulec</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/piotrwachulec"/>
    <language>en</language>
    <item>
      <title>Optimization of environmental costs in Azure. Disks. #01</title>
      <dc:creator>Piotr Wachulec</dc:creator>
      <pubDate>Mon, 26 Apr 2021 14:50:02 +0000</pubDate>
      <link>https://dev.to/piotrwachulec/optimization-of-environmental-costs-in-azure-disks-01-4cik</link>
      <guid>https://dev.to/piotrwachulec/optimization-of-environmental-costs-in-azure-disks-01-4cik</guid>
      <description>&lt;p&gt;The greater the environment, the more likely some resources are abandoned and unused. You know, someone requested a virtual machine, app service, but it turned out that it is unnecessary. Or some project or PoC finished and test resources are not removed. Due to this, it is important to look at your resources and check if can be removed or resized for example.&lt;/p&gt;

&lt;p&gt;If you have virtual machines in your Azure environment, it's always good to check some things related to disks. In this post, you can see how easy to check if some disks are not attached or if on some virtual machines disk space is unallocated.&lt;/p&gt;

&lt;p&gt;Checking if some disks are orphaned you can do with the below Powershell command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$existingDisks = Get-AzDisk

Write-Output "`nUnattached disks:"
foreach ($disk in $existingDisks) {
    If ($disk.DiskState.Contains('Unattached')) {
        $disk.Name
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Get-AzDisk&lt;/code&gt; gets all disks in the current subscription. Each disk has the property &lt;strong&gt;DiskState&lt;/strong&gt; which can tell you if the disk is attached to some virtual machine or not. The above script checks if the &lt;strong&gt;DiskState&lt;/strong&gt; property has value &lt;em&gt;Unattached&lt;/em&gt; which means that it isn't connected to any VM.&lt;/p&gt;

&lt;p&gt;Another thing is that the disk can be connected to the virtual machine, but it isn't initialized on the OS level. How to check that? It's a more complex operation. You can't do that from the Azure perspective, you have to check disk statuses directly on the OS. But relax, you don't have to log into each virtual machine and check that manually. Let's use the &lt;strong&gt;Run Command&lt;/strong&gt; interface. There are a few ways to &lt;a href="https://docs.microsoft.com/en-us/azure/virtual-machines/windows/run-scripts-in-vm"&gt;run custom scripts directly on virtual machine&lt;/a&gt;, each of them has its own pros and cons. &lt;strong&gt;Run Command&lt;/strong&gt; will be the best option for us.&lt;/p&gt;

&lt;p&gt;I prepared a small script which will be run through &lt;strong&gt;Run Command&lt;/strong&gt; interface on the virtual machine. Here it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$disksInfo = Get-Disk

foreach ($disk in $disksInfo) {
    If ($disk.PartitionStyle.Contains('RAW')) {
        Write-Output $true
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important information is that the disk with the unallocated space has something called &lt;a href="https://docs.microsoft.com/en-us/answers/questions/144362/how-to-get-unallocated-data-disk-details-from-os-l.html"&gt;&lt;strong&gt;PartitionStyle&lt;/strong&gt; with value &lt;em&gt;RAW&lt;/em&gt;&lt;/a&gt;. The above script takes info about all physical disks in the machine and checks if any of those disks have &lt;strong&gt;PartitionStyle&lt;/strong&gt; status equal &lt;em&gt;RAW&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The process is: get info about all virtual machines in the subscription with the information if the virtual machine is running, run on each of them the custom script, aggregate info about the statuses of calling &lt;strong&gt;Run Command&lt;/strong&gt; with the custom script, and show the list of virtual machines with unallocated spaces. The below scripts realize that process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# List of vms
$vms = Get-AzVm -Status
$vmsToCheck = @()

# List of VMs with unallocated disks
foreach ($vm in $vms) {
    If ($vm.PowerState.Contains('VM running') -and $vm.StorageProfile.DataDisks.Length -gt 0) {
        $vmsToCheck += $vm
    }
}

foreach ($vm in $vmsToCheck) {
    $scriptBlock = {
        $runOutput = Invoke-AzVMRunCommand -ResourceId $args[0].Id -CommandId 'RunPowerShellScript' -ScriptPath '.\Test-IfVmHasUnallocatedDisks.ps1'
        If ($runOutput.Value[0].Message.Contains('True')) {
            return $args[0].Name
        }
    }

    $jobName = "$($vm.Name)-DisksCheck"

    $job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $vm -Name $jobName
    $jobs += $job
}

Write-Host -NoNewline "`nChecking unallocated disks"
while ((Get-Job -Name "*-DisksCheck" | Where-Object State -eq Running)) {
    Write-Host -NoNewline "."
    Start-Sleep -Seconds 2
}

Write-Output "`nVMs with unallocated disks:"
Get-Job | Receive-Job
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small hack in the script above - calling &lt;strong&gt;Run Command&lt;/strong&gt; takes quite a long time, so I'm running checking for chosen machines in parallel and after that, I'm waiting for when all jobs will be done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wachulec.me/posts/optimization-of-environmental-costs-disks-vol-01/"&gt;Original post&lt;/a&gt; you can always find on &lt;a href="https://wachulec.me/"&gt;my blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>powershell</category>
      <category>costs</category>
    </item>
    <item>
      <title>Slack notifications on Azure budget consumption</title>
      <dc:creator>Piotr Wachulec</dc:creator>
      <pubDate>Wed, 21 Apr 2021 09:46:33 +0000</pubDate>
      <link>https://dev.to/piotrwachulec/slack-notifications-on-azure-budget-consumption-5abp</link>
      <guid>https://dev.to/piotrwachulec/slack-notifications-on-azure-budget-consumption-5abp</guid>
      <description>&lt;p&gt;In my free time (I don't have too much free time, to be honest 😋) I help my colleagues in the open-source project where juniors can learn something useful for their career. I started to deliver some infra for that stuff on Azure, but due to the fact that I'm paying for resources from my pocket, I want to have some nice notifications if something consumes a big amount of money and burns the budget. For AWS costs we have a dedicated channel on Slack where daily money consumption is sent. I would try to add an Azure budget alarm there too.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to integrate?
&lt;/h1&gt;

&lt;p&gt;For achieving my aim I will use the Incoming WebHooks app on Slack. There I will able to send messages to the chosen channel via webhook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oxXLngtF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/incoming-webhook-app.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oxXLngtF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/incoming-webhook-app.png" alt="Incoming WebHooks Slack App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We already have added that app and webhook for sending info about costs, so to avoid reaching the limits of the Incoming WebHooks app, I reused the existing webhook and channel for used for costs notification purposes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Budget
&lt;/h1&gt;

&lt;p&gt;The next step is to create the budget for the subscription.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zEJYsZCU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zEJYsZCU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget.png" alt="Azure Budget creation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next step, we have to configure notifications and alarms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K-Wc1Jbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget-alarms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K-Wc1Jbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget-alarms.png" alt="Azure Budget alarms page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There I added a new action group where I added sending email in the Notifications section. In the Actions section, I added a webhook URI.&lt;/p&gt;

&lt;p&gt;After that, I could add alarms:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3EnHuJV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget-alerts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3EnHuJV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/budget-alerts.png" alt="Azure Budget alarms ready"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The budget was created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_W3QptsP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/ready-budget.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_W3QptsP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-21-slack-notifications-on-azure-budget-consumption/ready-budget.png" alt="Azure Budget created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wachulec.me/posts/slack-notifications-on-azure-budget-consumption/"&gt;Original post&lt;/a&gt; you can always find on &lt;a href="https://wachulec.me/"&gt;my blog&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>slack</category>
      <category>costs</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How to manage resources in the external tenant in Azure?</title>
      <dc:creator>Piotr Wachulec</dc:creator>
      <pubDate>Mon, 19 Apr 2021 11:52:18 +0000</pubDate>
      <link>https://dev.to/piotrwachulec/how-to-manage-resources-in-the-external-tenant-in-azure-4cl0</link>
      <guid>https://dev.to/piotrwachulec/how-to-manage-resources-in-the-external-tenant-in-azure-4cl0</guid>
      <description>&lt;h1&gt;
  
  
  The case
&lt;/h1&gt;

&lt;p&gt;You want to manage resources in other tenants without additional workload around that like accounts creation for you and your teammates in the destination Azure tenant or disabling those accounts if someone leaves the team. Is there any solution for that?&lt;/p&gt;

&lt;p&gt;The answer is: yes! And it is called &lt;strong&gt;Azure Lighthouse&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Azure Lighthouse enables cross- and multi-tenant management, allowing for higher automation, scalability, and enhanced governance across resources and tenants. ~&lt;a href="%5Bhttps://docs.microsoft.com/en-us/azure/lighthouse/overview%5D(https://docs.microsoft.com/en-us/azure/lighthouse/overview)"&gt;What is Azure Lighthouse?&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  How does it work?
&lt;/h1&gt;

&lt;p&gt;Azure Lighthouse enables managing resources in another tenant directly from your 'home' tenant. You can define with that which users and/or Active Directory &lt;strong&gt;Security&lt;/strong&gt; groups should have access to which resources and with which roles.&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;p&gt;To set up the Azure Lighthouse solution, you have to fulfill some requirements and gather a bunch of information. The full list you can find here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your tenant ID&lt;/li&gt;
&lt;li&gt;Customer's tenant ID&lt;/li&gt;
&lt;li&gt;List of subscription IDs and/or resource group IDs to which you have to have access&lt;/li&gt;
&lt;li&gt;List of users and/or Active Directory groups which you want to assign to manage customer environments - &lt;strong&gt;IMPORTANT&lt;/strong&gt;: AD groups have to be &lt;strong&gt;Security&lt;/strong&gt; groups!&lt;/li&gt;
&lt;li&gt;List of roles and permissions (with their IDs) which you want to assign&lt;/li&gt;
&lt;li&gt;Someone with non-guest account in customer's tenant and &lt;code&gt;Microsoft.Authorization/roleAssignments/write&lt;/code&gt; permission - it is required to create assignment (&lt;a href="%5Bhttps://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#deploy-the-azure-resource-manager-templates%5D(https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#deploy-the-azure-resource-manager-templates)"&gt;Deploy the Azure Resource Manager templates&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Something called &lt;code&gt;mspOfferName&lt;/code&gt; and &lt;code&gt;mspOfferDescription&lt;/code&gt; - the first one defines the connection between both tenants and their 
resources. &lt;strong&gt;IMPORTANT: You can't have multiple assignments at the same scope with the same &lt;code&gt;mspOfferName&lt;/code&gt;.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How to onboard the customer?
&lt;/h1&gt;

&lt;p&gt;If you gathered all of the above requirements, on &lt;a href="%5Bhttps://github.com/Azure/Azure-Lighthouse-samples%5D(https://github.com/Azure/Azure-Lighthouse-samples)"&gt;Github&lt;/a&gt; you can find example ARM templates that allow you to onboard. You have to deploy prepared and fulfilled templates to each subscription separately. &lt;/p&gt;

&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;

&lt;p&gt;For preparing example I will use the template from the official &lt;a href="%5Bhttps://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer%5D(https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer)"&gt;docs&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspOfferName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specify a unique name for your offer"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"defaultValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;to be filled out by MSP&amp;gt; Specify a title for your offer"&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspOfferDescription"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Name of the Managed Service Provider offering"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"defaultValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;to be filled out by MSP&amp;gt; Provide a brief description of your offer"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"managedByTenantId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specify the tenant id of the Managed Service Provider"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"defaultValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;to be filled out by MSP&amp;gt; Provide your tenant id"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authorizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specify an array of objects, containing tuples of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider's Active Directory and the principalIdDisplayName is visible to customers."&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;              
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"variables"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspRegistrationName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[guid(parameters('mspOfferName'))]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspAssignmentName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[guid(parameters('mspOfferName'))]"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.ManagedServices/registrationDefinitions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"apiVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-09-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[variables('mspRegistrationName')]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"registrationDefinitionName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[parameters('mspOfferName')]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[parameters('mspOfferDescription')]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"managedByTenantId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[parameters('managedByTenantId')]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"authorizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[parameters('authorizations')]"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.ManagedServices/registrationAssignments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"apiVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2019-09-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[variables('mspAssignmentName')]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"dependsOn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"registrationDefinitionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with parameters file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentParameters.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspOfferName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test PW Lighthouse"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mspOfferDescription"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test PW Lighthouse"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"managedByTenantId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"11111111-1111-1111-1111-111111111111"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authorizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"principalId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"22222222-2222-2222-2222-222222222222"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"roleDefinitionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"b24988ac-6180-42a0-ab88-20f7382dd24c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"principalIdDisplayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PW MC"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I translated the above template to Bicep - it's much easier to read and edit for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@description&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Specify a unique name for your offer'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
param mspOfferName string

@description&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Name of the Managed Service Provider offering'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
param mspOfferDescription string

@description&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Specify the tenant id of the Managed Service Provider'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
param managedByTenantId string

@description&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Specify an array of objects, containing tuples of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider`s Active Directory and the principalIdDisplayName is visible to customers.'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
param authorizations array

var mspRegistrationName &lt;span class="o"&gt;=&lt;/span&gt; guid&lt;span class="o"&gt;(&lt;/span&gt;mspOfferName&lt;span class="o"&gt;)&lt;/span&gt;
var mspAssignmentName &lt;span class="o"&gt;=&lt;/span&gt; guid&lt;span class="o"&gt;(&lt;/span&gt;mspOfferName&lt;span class="o"&gt;)&lt;/span&gt;

targetScope &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'subscription'&lt;/span&gt;

resource regDefinintion &lt;span class="s1"&gt;'Microsoft.ManagedServices/registrationDefinitions@2019-09-01'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  name: mspRegistrationName
  properties: &lt;span class="o"&gt;{&lt;/span&gt;
    registrationDefinitionName: mspOfferName
    description: mspOfferDescription
    managedByTenantId: managedByTenantId
    authorizations: authorizations
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

resource regAssignment &lt;span class="s1"&gt;'Microsoft.ManagedServices/registrationAssignments@2019-09-01'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  name: mspAssignmentName
  properties: &lt;span class="o"&gt;{&lt;/span&gt;
    registrationDefinitionId: regDefinintion.id
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Bicep file can be used with the same parameters file as the classic ARM template.&lt;/p&gt;

&lt;p&gt;For test purposes, I used two different Azure tenants. I 'home' tenant I created AD Security group called '&lt;strong&gt;PW MC&lt;/strong&gt;'. I wanted to give to chosen subscription the Contributor rights for '&lt;strong&gt;PW MC&lt;/strong&gt;' AD group, so I deployed the above template with the Azure CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az deployment sub create &lt;span class="nt"&gt;--location&lt;/span&gt; WestEurope &lt;span class="nt"&gt;--template-file&lt;/span&gt; ./lighthouse.bicep &lt;span class="nt"&gt;--parameters&lt;/span&gt; lighthouse.parameters.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Previously I logged into the tenant with &lt;code&gt;az login --tenant&lt;/code&gt; command.&lt;/p&gt;

&lt;h1&gt;
  
  
  Effect
&lt;/h1&gt;

&lt;p&gt;The effect should be visible in two places, in both tenants. In the customer tenant when we will go to the &lt;strong&gt;Service providers&lt;/strong&gt; page, we will able to see something like on the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iukzih-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/customer-lighthouse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iukzih-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/customer-lighthouse.png" alt="Service providers in Customer's tenant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and in the 'home' tenant when we will visit the &lt;strong&gt;My customers&lt;/strong&gt; page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aXLYBQ4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/service-lighthouse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aXLYBQ4B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/service-lighthouse.png" alt="My customers page in home tenant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we click on 'Default directory':&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4UVk3Kqx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/service-lighthouse-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4UVk3Kqx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://wachulec.me/images/posts/2021-04-19-how-to-manage-resources-in-the-external-tenant-in-azure/service-lighthouse-2.png" alt="Subscription details"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can click on the subscription name and do whatever you want with the resources.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;You can see that implementing Azure Lighthouse is quite easy and reduce management concerns. And what is the most important - it is free!&lt;/p&gt;

&lt;p&gt;Original post you can find on &lt;a href="https://wachulec.me/posts/how-to-manage-resources-in-the-external-tenant-in-azure/"&gt;my website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>azure</category>
      <category>bicep</category>
      <category>management</category>
    </item>
  </channel>
</rss>
