Previously I wrote up how to work with the Azure Instance Metadata Service (IMDS) with Azure Virtual Machines to utilize Azure Managed Identities.

Managed identities can provide many benefits and can be even considered a modern replacement for group managed service accounts (gMSA) in Active Directory (AD) Domain Services (DS). Especially as you have growing needs to work with process automation of your cloud services.

Now you can see an example of using this concept with four modern enhancements.

Contents:

Prerequisites

You will need six pieces to make this come together:

  • Familiarity with Azure and PowerShell
  • Entra ID Tenant
  • Azure Subscription
  • Azure Resource Group
  • A Windows Server instance
  • PowerShell 7.*

The Azure Arc Connected Machine Agent supports operating system environments other than Windows Server as well.

Setup Azure Arc

Your experience setting up Azure Arc should be painless.

Identify an Azure Resource Group

Within your Azure Subscription, identify an existing Azure Resource Group (RG) or create a new RG that your Azure Arc machines will reside in. Make sure you note the region you use as well.

image

Azure Resource Group “Arc” within the Azure Portal.

Setup Arc

Once you have an RG the machine will reside in. Open PowerShell on your instance and install the necessary modules, connect to Azure, and then connect the machine. You can see these commands shown below. You can replace Arc with your RG name, $env:COMPUTERNAME with a resource name you prefer, or eastus with another Azure Region.

You can use -UseDeviceAuthentication to do a device code flow authentication in case you are working in a headless environment like Windows Server Core.

Install-Module Az.ConnectedMachine, Az.Accounts
Connect-AzAccount -UseDeviceAuthentication
Connect-AzConnectedMachine  -ResourceGroupName Arc -Name $env:COMPUTERNAME -Location eastus

Depending on how you want to use your identity, it is worth taking note that the Connect-AzConnectedMachine cmdlet creates the IDENTITY_ENDPOINT machine environment variable. Meaning you may need to start a new PowerShell session, reboot, or manually set the environment variable equal to [System.Environment]::GetEnvironmentVariable("IDENTITY_ENDPOINT","Machine") for the following sections to work.

Use your machine’s identity

Now you can just append the -Identity property to your connect cmdlets and you will authenticate with your managed identity.

Connect-AzAccount -Identity

You will find that your managed identity does not have any subscription when it connects though.

Account   SubscriptionName TenantId                             Environment
-------   ---------------- --------                             -----------
MSI@<ID>                   <GUID>                               AzureCloud

You can confirm this by getting your current context.

Get-AzContext|Format-List
Name               : <GUID> - MSI@<ID>
Account            : MSI@<ID>
Environment        : AzureCloud
Subscription       :
Tenant             : <GUID>
TokenCache         :
VersionProfile     :
ExtendedProperties : {}

Once you add your managed identity to an Azure Role Assignment you can connect again and see your updated context includes the subscription.

If you make role assignments to multiple subscriptions ensure you set the appropriate subscription you want the Az cmdlets to use with Set-AzContext.

Use your machine’s identity token

You can also request a bearer token from the Azure Arc IMDS that you can then use with direct API calls. Microsoft’s documentation provides a Windows PowerShell example. The following is a PowerShell Core example.

$apiVersion = "2020-06-01"
$resource = "https://management.azure.com/"
$endpoint = "{0}?resource={1}&api-version={2}" -f $env:IDENTITY_ENDPOINT,$resource,$apiVersion
$secretFile = ""
try
{
    Invoke-WebRequest -Method GET -Uri $endpoint -Headers @{Metadata='True'} -UseBasicParsing
}
catch
{
    $wwwAuthHeader = $_.Exception.Response.Headers|?{$_.Key -eq "WWW-Authenticate"}|% value
    if ($wwwAuthHeader -match "Basic realm=.+")
    {
        $secretFile = ($wwwAuthHeader -split "Basic realm=")[1]
    }
}
Write-Host "Secret file path: " $secretFile`n
$secret = cat -Raw $secretFile
$response = Invoke-WebRequest -Method GET -Uri $endpoint -Headers @{Metadata='True'; Authorization="Basic $secret"} -UseBasicParsing
if ($response)
{
    $token = (ConvertFrom-Json -InputObject $response.Content).access_token
    Write-Host "Access token: " $token
}

You should treat bearer tokens as secrets. Be cautious with how you store, transfer, and use them.

Use your machine’s identity with the Graph API

Another use case that comes up is working with the Microsoft Graph API. The Connect-MgGraph cmdlet also supports managed identity authentication though. As simple as before, you can use your Azure Arc Connected Machine’s Managed Identity.

Install-Module Microsoft.Graph.Authentication
Connect-MgGraph -Identity
Get-MgContext

You may even want to start by using a managed identity with the https://learn.microsoft.com/en-us/powershell/exchange/connect-exo-powershell-managed-identity.

Security thoughts

As you look to use managed identities to simplify your operational environment, please be mindful that often the log events for any access will only show the managed identity service principal as the client. Meaning if you allow interactive access to an instance with a managed identity, you need to correlate the local systems security logs with the API authentication logs to see who the real identity is interacting with the API as the managed identity.

The Cybersecurity and Infrastructure Security Agency (CISA) in a joint effort with other national defense agencies around the world provided guidance on PowerShell configurations.


<
Previous Post
JupyterHub Configuration Example
>
Next Post
PowerShell Remoting over SSH