Using Event Grid/Azure Functions to automatically assign tag:owner to Azure resources

Solution outlined below will help with identifying resource owners for Azure resources. Frequent issue in any Azure environment is to figure out why some resource exists and who created it. Unless Azure policy was enabled to enforce tagging rules there is no built in mechanism to find this information easily.

Create Azure Functions App

Azure function is used to react to Event Grid event tied to Azure Activity Log and hence a new function app shall be created as first. Use Powershell Core as runtime stack.

The rest of Functions requirements can be left at default. Once App is created we need to assign it managed identity (either System or User assigned). Assign role of Tag Contributor to this object to Azure subscription.

If using user assigned Identity modify file profile.ps1 to replace Connect-AzAccount -Identity with below where $userID is client ID from User Managed Identity

    Connect-AzAccount -Identity -AccountId <client ID>

Create function of type Azure Event Grid Trigger

Cut and paste following code into run.ps1

param($eventGridEvent, $TriggerMetadata)
Write-Output ($eventGridEvent.data | convertto-JSON -depth 50)

$caller = "{0} ({1})" -f $eventGridEvent.data.claims.name, $eventGridEvent.data.claims."http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
if ($null -eq $eventGridEvent.data.claims.name) {
    if ($eventGridEvent.data.authorization.evidence.principalType -eq "ServicePrincipal") {
        $caller = (Get-AzADServicePrincipal -ObjectId $eventGridEvent.data.authorization.evidence.principalId).DisplayName
        if ($null -eq $caller) {
            Write-Host "MSI may not have permission to read the applications from the directory"
            $caller = $eventGridEvent.data.authorization.evidence.principalId
            
        }
    }
}
Write-Host "Caller: $caller"
$resourceId = $eventGridEvent.data.resourceUri
Write-Host "ResourceId: $resourceId"

if (($null -eq $caller) -or ($null -eq $resourceId)) {
    Write-Host "ResourceId or Caller is null"
    exit;
}

$ignore = @("providers/Microsoft.Resources/deployments", "providers/Microsoft.Resources/tags")

foreach ($case in $ignore) {
    if ($resourceId -match $case) {
        Write-Host "Skipping event as resourceId contains: $case"
        exit;
    }
}

$tags = (Get-AzTag -ResourceId $resourceId).Properties

if (!($tags.TagsProperty.ContainsKey('Creator')) -or ($null -eq $tags)) {
    $tag = @{
        'Creator' = $caller
    }
    Update-AzTag -ResourceId $resourceId -Operation Merge -Tag $tag
    Write-Host "Added creator tag with user: $caller"
}
else {
    Write-Host "Tag already exists"
}

Switch to Function overview and make sure it’s enabled

Edit requirements.psd1 file in Function to import powershell modules required for function to run (Az.Resources, Az.Accounts) and restart Function App for settings to take effect.

@{
    # For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'. 
    # To use the Az module in your function app, please uncomment the line below.
    # 'Az' = '6.*'
    'Az.Accounts'  = '2.*'
    'Az.Resources' = '4.*'
}

Event Grid setup

Event Grid facilitates tying together event of resource creation to Azure resource creation event. Navigate to Event Subscription pane and create event subscription to Azure subscription.

Azure Active Directory setup

Azure Activity Log contains UPN name of who created resources for end users in Azure Active Directory but only object ID for resources created by service principal. You have to assign Global Reader role to managed identity of Function in Azure AD to be able to convert ObjectID into service principal name.

At this point you shall be able to test functionality by creating a new resources and monitoring function execution

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s