Service principal monitoring in azure - azure

I have created a script in powershell for checking the expiry date of services principal in azure.The script itself works fine if i will execute it directly in cloud shell.But this is not what i want.I want that the script can be executed by a runbook in azure,so i created the runbook and also "run as account" user.The problem is that "run as account" does not have rights to run the cmdlet "get-azadapplication" & "get-azadserviceprincipal".After some research i find out that this user needs global reader rights to AAD.Is there another way how to monitor the services principal without global reader?Does anybody implemented a similar solution?
E.g this a simply code to show the error which i get
#Connect to Azure
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
#get all subscriptions
get-azsubscription
# read the credential for user sp-acr-c4r-pull
get-azadserviceprincipal -displayname sp-acr-c4r-pull | get-azadspcredential
Then i get this error when i run the runbook
Account SubscriptionName TenantId
------- ---------------- --------
* Cloud_Test… *
Cloud_Test
Get-AzADServicePrincipal: C:\Temp\3s0vpqu0.tms
Line |
30 | get-azadserviceprincipal -displayname sp-acr-c4r-pull | get-azadspcre …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Insufficient privileges to complete the operation.
As you can see i can run the get-azadsubscription but not get-azadserviceprincipal

How do you expect your runbook to read data from your directory if you are unwilling to give it the permissions it needs?
Your only option is to assign the Service Principal some kind of permissions. Global reader doesn't seem so bad to me, but if that is unacceptable you could look into making a custom role: https://learn.microsoft.com/en-us/azure/active-directory/roles/custom-create

You can make an entry (e.g. secret) in Key Vault with expiry date equal to expiry date of secret of service principal. Then just apply event grid from that Key Vault (https://learn.microsoft.com/en-us/azure/key-vault/general/event-grid-overview) and send event for e.g. Microsoft.KeyVault.SecretNearExpiry or Microsoft.KeyVault.SecretExpired (https://learn.microsoft.com/en-us/azure/event-grid/event-schema-key-vault?tabs=event-grid-event-schema) and process the event with the logic you need.

Related

Get-AzSubscription won't show my subscription

I have a subscription I want to pause/resume with a PowerShell script (Azure Analysis Services). I use this exact same script to pause my Embedded Capacity and that works fine, but when I run my script for my new subscription it wont work. This is the script I use:
$userPassword = "myappsecret"
$userPassword2 = ConvertTo-SecureString -String $userPassword -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "appid", $userPassword2
Connect-AzAccount -ServicePrincipal -TenantId "tenantid" -Credential $Credential
Select-AzSubscription -SubscriptionId "subscriptionname here"
Get-AzPowerBIEmbeddedCapacity -ResourceGroupName "groupnamehere" -Name "namehere"
Suspend-AzPowerBIEmbeddedCapacity -Name "namehere" -ResourceGroupName "groupnamehere" -PassThru
To check why this won't work I tried to simply use Get-AzSubscription to see if something was wrong and it wont show any subscription.
If I try the same for my Embedded Capacity it works just fine.
What could be wrong?
To get the list of all Azure Ad subscriptions by using Get-AzSubscription, make sure that you have owner/admin role.
You can make use of the below command to get Azure Ad subscriptions for a specific tenant:
Make sure to connect-azaccount with Administrator details.
Get-AzSubscription -TenantId "your_tenant_id"
Get-AzContext command list the information of the Azure Subscription that is currently selected.
To use a specific subscription, you can make use of below command:
Get-AzSubscription -SubscriptionId "xxxx-xxxx-xxxx-xxxx" -TenantId "yyyy-yyyy-yyyy-yyyy" | Set-AzContext
Or please modify your code by adding the below snippet:
$subscriptionId = 'Your_Subscription_ID';
Select-AzSubscription -SubscriptionId $subscriptionId
You can check the Subscription Id via Azure Portal too.
Reference:
Get-AzSubscription (Az.Accounts) | Microsoft Docs

Azure Automation Job runs fine manually but fails when triggered by webhook

I've got an Automation Account in Azure that runs a Powershell runbook.
It runs perfectly fine when I trigger it via the portal, manually specifying the inputs
I've created a webhook with the same input settings. I call it from CURL like
curl -d '' https://800b2bec-b1ae-4fa1-ba30-8c7d32096828.webhook.ae.azure-automation.net/webhooks?[redactedtoken]
The webhook shows as triggered successfully in the portal, however the job fails with no visible error.
There is no output, even though the first line in my powershell function is Write-Output "Hello"
There are no exception messages, no logs at all.
Any idea how I might get more information as to what might be going wrong?
I've updated the Az modules and enabled verbose logging in the runbook.
Full source below, if it helps.
Param(
[string]$resourceGroup,
[string]$VMName,
[string]$method,
[string]$UAMI
)
Write-Output "Hello"
$automationAccount = "AlsAutomation"
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process | Out-Null
# Connect using a Managed Service Identity
try {
$AzureContext = (Connect-AzAccount -Identity).context
}
catch{
Write-Output "There is no system-assigned user identity. Aborting.";
exit
}
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
if ($method -eq "SA")
{
Write-Output "Using system-assigned managed identity"
}
elseif ($method -eq "UA")
{
Write-Output "Using user-assigned managed identity"
# Connects using the Managed Service Identity of the named user-assigned managed identity
$identity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroup `
-Name $UAMI -DefaultProfile $AzureContext
# validates assignment only, not perms
if ((Get-AzAutomationAccount -ResourceGroupName $resourceGroup `
-Name $automationAccount `
-DefaultProfile $AzureContext).Identity.UserAssignedIdentities.Values.PrincipalId.Contains($identity.PrincipalId))
{
$AzureContext = (Connect-AzAccount -Identity -AccountId $identity.ClientId).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
}
else {
Write-Output "Invalid or unassigned user-assigned managed identity"
exit
}
}
else {
Write-Output "Invalid method. Choose UA or SA."
exit
}
# Get current state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName `
-Status -DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Beginning VM status: $status `r`n"
# Start or stop VM based on current state
if($status -eq "Powerstate/deallocated")
{
Start-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext
}
elseif ($status -eq "Powerstate/running")
{
Stop-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext -Force
}
# Get new state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName -Status `
-DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Ending VM status: $status `r`n `r`n"
Write-Output "Account ID of current context: " $AzureContext.Account.Id
We have tested this in our local environment it is working fine, Below statements are based on the analysis.
In our local environment, We have created a Powershell runbook running with different PowerShell Versions 7.1 & Version 5.1.
Using the above share Script & webhook URI, when we are trying to invoke the runbook (PowerShell version 7.1) using the `Invoke-webRequest method it is continuously failing.
Alternatively, We have tried to invoke the runbook (PowerShell version 5.1) using the Invoke-webRequest method it is working fine.
We would suggest you to use Powershell Version 5.1 instead of 7.1 in your Runbook.
Here is the sample Output for reference:

Azure Automation - Unable to get AzRoleAssignement

In order to automate some processes, I'm using Azure Automation with Owner rights for RunAsAccount.
$connection = Get-AutomationConnection -Name AzureRunAsConnection
while(!($connectionResult) -And ($logonAttempt -le 10))
{
$LogonAttempt++
# Logging in to Azure...
$connectionResult = Connect-AzAccount `
-ServicePrincipal `
-Tenant $connection.TenantID `
-ApplicationId $connection.ApplicationID `
-CertificateThumbprint $connection.CertificateThumbprint
Start-Sleep -Seconds 30
Write-Output $connectionResult
}
Get-AzRoleAssignment -ResourceGroupName $USERRGNAME -SignInName $USEREMAIL -verbos
An error is being thrown each time I execute the script:
Get-AzRoleAssignment: Cannot find principal using the specified options
Any idea to solve this issue?
Probably you need to give RunAsAccount with the Application permission Directory.Read.All of the Azure AD Graph(not Microsoft Graph, not Delegated permission). By default, RunAsAccount doesn't have the Azure AD permission.
You could read Joy's answer for more details.
This error is showing when there is no Role Assignment for name that is provided in the SignInName option.

How can I assure that newly created prod azure resources are locked by policy?

I'm an Azure administrator. I want to assure that new resources created in production are automatically locked when they're created. Is there a way to set that policy? I know I can create locks with the CLI/GUI. I need to do it automatically without scripting az commands.
Thanks
You can use Azure Blueprints to do this.
https://learn.microsoft.com/en-us/azure/governance/blueprints/tutorials/protect-new-resources
or you can do it by scheduling a Runbook in an automation account. I have built a script for this that locks the Resource Groups that i have scheduled every night. Locking can have a negative impact on functionallity and sometimes its enoying if your resources gets locked to early.
In my code below i have excluded AzureBackup_RG_ since it breaks the functionallity of deleting snapshots which causes the backup to fail after a while.
<###########################################################################################################
#
# LckResourceGroup
#
# This script is intended to run daily to lock all resource groups to prevent accidential deletion
# of resources.
#
# Written by Daniel Björk - 2018-02-27
# Designed for Accigo AB
#
#
# Ver 1.0 Date 2018-02-27
# First Version
#
Instructions
1. Import Az.Accounts to the Automation Account
2. Import Az.Resources to the Automation Account
3. Create Runbook (Copy Powershell)
4. Schedule runbook
#
###########################################################################################################>
# INFORMATION: Change Subscription name to enable on other subscriptions
$SubScriptionName = "SubscriptionName"
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint | Out-Null
Write-Output "Select Subscription"
Select-AzSubscription -SubscriptionName $SubScriptionName
$resourceGroups = Get-AzResourceGroup | where {!$_.ResourceGroupName.StartsWith("AzureBackup")}
foreach ($resourceGroup in $resourceGroups) {
Write-Output $resourceGroup.ResourceGroupName
$lockId = (Get-AzResourceLock -ResourceGroupName $resourceGroup.ResourceGroupName).LockId
#Remove-AzureRmResourceLock -LockId $lockId
if (!$lockId -and !$resourceGroup.ResourceGroupName.StartsWith("AzureBackupRG_")){
Write-Output "Locking Resource Group"
New-AzResourceLock `
-LockName ResourceGroupLock `
-LockLevel CanNotDelete `
-LockNotes 'Locks all resources in the resource group' `
-ResourceGroupName $resourceGroup.ResourceGroupName `
-Force
}
}

Select-AzureRmSubscription : Please provide a valid tenant or a valid subscription

I have created the Powershell Runbook, and added all the required details and valid values. Still I am facing the error for Select-AzureRmSubscription command. The error I am getting all the time is
Select-AzureRmSubscription : Please provide a valid tenant or a valid subscription.
I am using below connection setting in Powershell runbook:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRmAccount -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId
$servicePrincipalConnection.ApplicationId -CertificateThumbprint
$servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection
$connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
fetch-group-memberships | Select-Object UserName, PrincipalName, GroupName, AzureGroupName |Sort-Object GroupName| Export-Csv -NoTypeInformation -Path
'MEMBERSHIP.csv'
#=======================================================================================
# Select the subscription you are going to work with
#=======================================================================================
Select-AzureRmSubscription -SubscriptionId
"[removed for security purpose]"
#Get-AzureRmSubscription -SubscriptionName "BIG" | Select-AzureRmSubscription
#=======================================================================================
# Set the Current Storage Account to the approperiate location
#=======================================================================================
Set-AzureRmCurrentStorageAccount -StorageAccountName devapacbi01 -ResourceGroupName dev-rgp-apac-01
#=======================================================================================
# Capture the file that is local to automation and save to Storage Blob
#=======================================================================================
Set-AzureStorageBlobContent -Container bi-app-carm-im -File ADGROUP_MEMBERSHIP.csv -Blob _MEMBERSHIP_AL.csv -Force
Even if the subscription id is correct it keeps throwing an error as above.
this means you do not have permissions to do so. you need to assign proper permissions to the account you are using for the runbook
You do not need to Select-AzureRmSubscription because runbook connection is only tied to on subscription.
Also keep in mid the runbook is running on a environment setup to run your script, I prefer to stay away from Set environment commands.
Removing the subscription line and fixing lines below should work.
$storageAccount = Get-AzureRmStorageAccount -StorageAccountName devapacbi01 -ResourceGroupName dev-rgp-apac-01
Set-AzureStorageBlobContent -Container bi-app-carm-im -File ADGROUP_MEMBERSHIP.csv -Blob _MEMBERSHIP_AL.csv -Context $storageAccount.Context -Force
Hope this helps.
Its Solved! You guys were correct, it was an issue with correct permissions with Automation Account only. We should have a access as a contributor on your storage account. After giving right permissions to automation RunAs (contributor on your storage account) it worked and ran successfully. Than you all again.

Resources