I have an Automation account and I have set up the Run-As-Account for non-classic resources. In my automation Account I have imported Az.Resources, Az.Account, Az.Storage and Az.KeyVault.
I have a script that does not work under the Automation service principle. The following error is a first of 3;
Get-AzRoleAssignment : Exception of type 'Microsoft.Rest.Azure.CloudException' was thrown. At line:26 char:10
I have granted the application registration the following set of application api permissions in Azure Active Directory (more than I anticipate needing);
At the start of the script I run the Connect-AzAccount cmdlet;
$servicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Connect-AzAccount -ServicePrincipal `
-Tenant $servicePrincipalConnection.TenantID `
-ApplicationId $servicePrincipalConnection.ApplicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
Followed by the failing command;
If(!(Get-AzRoleAssignment | Where-Object { $_.RoleDefinitionName -eq "Storage Blob Data Contributor" `
-and $_.scope -eq "/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$serviceName" `
-and $_.SignInName -eq (Get-AzContext).Account.Id})){
# There does not exist the requisite permission for the run-as-account context, grant; 'Storage Blob Data Contributor'.
New-AzRoleAssignment -RoleDefinitionName "Storage Blob Data Contributor" `
-ApplicationId (Get-AzADServicePrincipal | Where-Object { $_.DisplayName -eq "jupiterautomation01" }).ApplicationId `
-Scope "/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.Storage/storageAccounts/$serviceName"
}
I need to grant the right permissions, but do not know what they are.
The permissions assigned need to be consented to by an 'admin'. The button was only available when accessing Azure via the Microsoft account used to create the Active Directory tenant.
Sign in with an admin account that can consent.
Grant API permissions to read or read/write (i needed write as well) on Active Directory to the application.
Give admin consent using the button displayed in the image.
Related
I would like to assign Teams policies from an Azure Automation. For this I use the PowerShell module "MicrosoftTeams" in the current version.
When I log in to Teams with user credential, as shown below, the assignment works.
$Cred = Get-AutomationPSCredential -Name 'Teams-Admin'
Connect-MicrosoftTeams -TenantId $tenantId -Credential $Cred
# Grant policys
Grant-CsUserPolicyPackage -Identity $mailAddress -PackageName Test
However, I want to use the Run-As account to log in, as shown below. When I do that, I get an error.
$connection = Get-AutomationConnection –Name AzureRunAsConnection
Connect-MicrosoftTeams -TenantId $connection.TenantID `
-ApplicationId $connection.ApplicationID `
-CertificateThumbprint $connection.CertificateThumbprint
# Grant policys
Grant-CsUserPolicyPackage -Identity $mailAddress -PackageName Test
The error is as follows:
Grant-CsUserPolicyPackage : Powershell administered domain is unexpectedly null/empty
The app registry of the "Run-As" account has the Teams administrator and Skype for Business administrator role. In addition, I have delegated "AppCatalog.ReadWrite.All", "Group.ReadWrite.All", "User.Read.All" permissions to Microsoft Graph in the API permissions and "user_impersonation" permissions to Skype and Teams Tenant Admin API.
Service Principal names is currently not supported. We have backlog item for this but do not have an ETA to share.
I am trying to do some basic group management using Azure Automation, but I'm having a heck of a time getting the script to authenticate correctly.
I have added the Azure.Account modules to the runbook, and the connection seems to get established (at least, it doesn't throw an exception, and the returned object is not null).
When using "Get-AzAdGroup", I am getting:
Get-AzADGroup : Insufficient privileges to complete the operation.
The app account created is a "Contributor" in AAD, so as far as I understand, has full rights to the directory.
I have tried the solution listed at How to connect-azaccount in Azure DevOps release pipeline, to the same effect (Insufficient privileges). I have also applied "Group.Read.All", "Group.ReadWrite.All", "GroupMember.Read.All", "GroupMember.ReadWrite.All" based on what I can read from https://learn.microsoft.com/en-us/graph/permissions-reference#group-permissions - but I'm not 100% clear if the Az* cmdlets use the Microsoft Graph, or if that's separate altogether.
Code is as follows:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
<#
# Original, technically legacy.
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
#>
$connectState = Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
<#
# From https://stackoverflow.com/questions/56350960/how-to-connect-azaccount-in-azure-devops-release-pipeline, same result.
$AzurePassword = ConvertTo-SecureString "*****" -AsPlainText -force
$psCred = New-Object System.Management.Automation.PSCredential($servicePrincipalConnection.ApplicationId , $AzurePassword)
$connectState = Connect-AzAccount -Credential $psCred -TenantId $servicePrincipalConnection.TenantId -ServicePrincipal
#>
if ($connectState) {
"Connected."
} else {
"Doesn't seem to be connected."
}
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
# Get groups
Get-AzADGroup
My gut tells me that since both connect-azaccount methods yield the same result (connected, but no access) my issue isn't necessarily in the script, but short of creating a service account (which presents challenges with MFA), I don't know how to fix this.
From the solution How to connect-azaccount in Azure DevOps release pipeline I provided, in the screenshot, it is clear that you need to add the API permission of Azure Active Directory Graph, not Microsoft Graph.
Please add the Directory.Read.All in Azure Active Directory Graph for the AD App of your automation run as account.
I have faced a very similar issue. You have a problem with the API permissions Azure APP has.
In my case, my azure App was working as a Service Principal, and not only modifying some stuff in the Azure AD, but also some Azure resources, therefore, these were the api permissions that I had to grant:
Remember that you also need to grant admin consent from the Azure tenant for these permissions update.
If you just assign Contributor role to the service principal, you just can use the sp to get Azure resource(such as VM, app service). So if you want to use the sp tp get Azure AD resource, we need to assign Azure AD role (sucah as Directory Readers) to the sp. For more details, please refer to the document and the document
The detailed steps are as below
Get the RunAsAccount sp object id
Confugure Permisisons for the application
connect-AzureAD
$sp=Get-AzureADServicePrincipal -ObjectId <the sp object id your copy>
$role=Get-AzureADDirectoryRole | Where-Object{$_.DisplayName -eq "Directory Readers"}
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $sp.ObjectId
Test
a. create a new runbook
$servicePrincipalConnection=Get-AutomationConnection -Name 'AzureRunAsConnection'
$connectState = Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
if ($connectState) {
"Connected."
} else {
"Doesn't seem to be connected."
}
Get-AzADGroup
Go to Azure portal --> Azure AD --> roles and Administrator-->Directory Readers role --> assign this role to the runbook account name
I'm trying to run this script but I get this error :
New-AzureADApplication : Error occurred while executing NewApplication
Code: Authentication_MissingOrMalformed
Message: Access Token missing or malformed.
Import-Module AzureAD -Force
$rmAccount = Add-AzureRmAccount
$subscriptionId = $rmAccount.Context.Subscription.Id
$tenantId = $rmAccount.Context.Tenant.Id
$tokenCache = $rmAccount.Context.TokenCache
$cachedTokens = $tokenCache.ReadItems() `
| where { $_.TenantId -eq $tenantId } `
| Sort-Object -Property ExpiresOn -Descending
$infos = Connect-AzureAD -TenantId $tenantId `
-AadAccessToken $cachedTokens[0].AccessToken `
-AccountId $rmAccount.Context.Account.Id
$clientAadApplication = New-AzureADApplication -DisplayName "TodoListClient-NativeDotNet" `
-ReplyUrls "https://TodoListClient-NativeDotNet" `
-PublicClient $True
$currentAppId = $clientAadApplication.AppId
$clientServicePrincipal = New-AzureADServicePrincipal -AppId $currentAppId -Tags {WindowsAzureActiveDirectoryIntegratedApp}
$currentAppId = $clientAadApplication.AppIds
What I'm trying to do is to automatically register a native application in Azure Active Directory without dependency to Azure portal so I logged in using Add-AzureRmAccount to get TenantId and SubscriptionId then I used the cached token to connect to AzureAD to prevent double login.
The token that you obtain when you run Add-AzureRmAccount is for the https://management.core.windows.net audience, but Azure AD cmdlets need a token for Azure AD Graph audience (https://graph.windows.net). So you can't reuse that token while calling New-AzureADApplication. You should choose between Azure RM or Azure AD cmdlets, but not both. But as far as I know New-AzureRmADApplication doesn't support creating a native application, so then you should use only Azure AD cmdlets.
You were close, but the token you are passing from the AzureRMAccount is not the correct Audience/Resource for the actions you are doing. Just removing that bit and running something like this below will work with the correct Audience and Resource permissions for your Token. You can always check your Token Audience and scope by copying and pasting it at https://jwt.ms (a useful Token debugger by Microsoft).
Import-Module AzureAD -Force
Connect-AzureAD
$clientAadApplication = New-AzureADApplication -DisplayName "TodoListClient-NativeDotNet" `
-ReplyUrls "https://TodoListClient-NativeDotNet" `
-PublicClient $True
$currentAppId = $clientAadApplication.AppId
$clientServicePrincipal = New-AzureADServicePrincipal -AppId $currentAppId -Tags {WindowsAzureActiveDirectoryIntegratedApp}
$currentAppId = $clientAadApplication.AppIds
I am unable to perform the Azure Powershell command Add-AzureKeyVaultManagedStorageAccount, even though I am executing it under the subscription owner profile. I successfully create keyvault, storage account, and storage account key in the following manner:
$KeyVault = New-AzureRmKeyVault `
-VaultName "<redacted>" `
-ResourceGroupName $ResourceGroup.ResourceGroupName `
-Location $Location `
-EnabledForDiskEncryption `
-EnabledForDeployment `
-Tag $Tags
$StorageAccount = New-AzureRmStorageAccount `
-ResourceGroupName $ResourceGroup.ResourceGroupName `
-Name "<redacted>" `
-SkuName Standard_LRS `
-Location $Location `
-Kind "Storage" `
-EnableEncryptionService "Blob,File" `
-Tag $Tags `
-AssignIdentity
$StorageAccountKey = New-AzureRmStorageAccountKey `
-ResourceGroupName $ResourceGroup.ResourceGroupName `
-Name $StorageAccount.StorageAccountName `
-KeyName "key1"
but trying to manage the storage account key in my key vault fails
$KeyVaultManagedStorageAccount = Add-AzureKeyVaultManagedStorageAccount `
-VaultName $KeyVault.VaultName `
-AccountName $StorageAccount.StorageAccountName `
-AccountResourceId $StorageAccount.Id `
-ActiveKeyName "key1" `
-Tag $Tags
This is the error. As I mentioned, I am executing under the subscription owner profile, so how can it not have authorization? Secondly, the "same redacted object Id" identified below does not correspond to any object in my subscription that I can find. I first experienced this problem with Azure Powershell 4.2.1, and have since upgraded to 4.3.0 and still have the problem.
Add-AzureKeyVaultManagedStorageAccount : The client '<same redacted object Id>' with object id '<same redacted object Id>' does not have authorization to perform action
'Microsoft.Authorization/permissions/read' over scope
'/subscriptions/<subscription ID>/resourceGroups/<resource group name>/providers/Microsoft.Storage/storageAccounts/<storage account name>/providers/Microsoft.Authorization'.
At E:\BitSync\Scripts\Azure\Create-Environment.ps1:129 char:34
+ ... VaultManagedStorageAccount = Add-AzureKeyVaultManagedStorageAccount `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Add-AzureKeyVaultManagedStorageAccount], KeyVaultErrorException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.KeyVault.AddAzureKeyVaultManagedStorageAccount
BTW, there does not appear to be any way to manage Storage Account keys through Key Vault in the portal other than cut and paste.
According to your error message, it is a RBAC issue, the service principal you are using does not have rights within that tenant.
Tenants have subscriptions and service principals belong to tenants. Azure resource manager also exposes role based authorization for a given principal, which would give it rights on Azure resources. It appears the service principal doesn't have rights to read from that subscription.
We can assign RBAC roles at the resource scope via Azure portal, more information about assign RBAC, please refer to this link.
Note:
Key vault needs permissions to list and regenerate keys for a storage account.we can use the following steps to do it:
Get ObjectId of your account:
Get-AzureRmADServicePrincipal -SearchString "Azure Key Vault"
Assign Storage Key Operator role to Azure Key Vault Identity:
New-AzureRmRoleAssignment -ObjectId <objectId of AzureKeyVault from previous command> -RoleDefinitionName 'Storage Account Key Operator Service Role' -Scope '<azure resource id of storage account>'
More information about setup for role-based access control permissions, please refer to this article.
Update:
Also, we should set Azure key vault access policy permissions to storage.
Set-AzureRmKeyVaultAccessPolicy -VaultName 'jasonkey01' -ResourceGroupName 'jasontest' -ObjectId '556ca95d-2f50-4acd-b98e-a111b5b41b66' -PermissionsToStorage 'all'
Here is the screenshot about my keyvault:
In this way, we can use your script to add key vault for storage account.
Update2:
I have reproduce this error, the root cause is that we can't grant permission to service principal Azure Key Vault.
We can use this command to find object id, same as your error message.
Get-AzureRmADServicePrincipal -SearchString "Azure Key Vault"
Then we grant permission to this service principal, use this script:
New-AzureRmRoleAssignment -ObjectId '2f6d671f-6c8d-4104-812a-390c5648aed0' -RoleDefinitionName 'Storage Account Key Operator Service Role' -Scope '/subscriptions/53847abb-xxxx-xxxx-xxxx-xxxxe29axxxx/resou
rceGroups/jasonkey/providers/Microsoft.Storage/storageAccounts/jasondisk321'
Here is my result:
Update3:
After run Add-AzureKeyVaultManagedStorageAccount, we should run this command to get secret URI:
Set-AzureKeyVaultManagedStorageSasDefinition -Service Blob -ResourceType Container,Service -VaultName yourKV
-AccountName msak01 -Name blobsas1 -Protocol HttpsOnly -ValidityPeriod ([System.Timespan]::FromDays(1)) -Permission Read,List
Here is the result:
More information about get the secret URI, please refer to this article.
Using the new Azure portal, I am trying to add a powershell runbook that will start a specific VM. This is not something that will be run in powershell from my PC, it will instead run as an ARM job. I can't seem to find a way to successfully login.
If running from my desktop in powershell I can just call Login-AzureRmAccount and it will launch a login dialog before running any further steps. From what I've read on the web it seemed that what I needed to do was add a credential to my automation account, retrieve it and then call the same Login method. I've now done that, but still can't log in.
Import-Module AzureRM.Compute
$AutomationCredentialAssetName = "automation"
$Cred = Get-AutomationPSCredential -Name $AutomationCredentialAssetName
Write-Output $Cred
Login-AzureRmAccount -Credential $Cred
Start-AzureRmVm -Name 'myvmname' -ResourceGroupName 'myresourcegroupname'
The credential is being retrieved correctly (get's written to output) but the call to the Login-AzureRmAccount fails with:
Login-AzureRmAccount : unknown_user_type: Unknown User Type
At line:10 char:1
+ Login-AzureRmAccount -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Common.Authentication.AadAuthenticationFailedException,Microsoft.Azure.Com
mands.Profile.AddAzureRMAccountCommand
If I don't attempt to log in first I get a message telling me to call Login-AzureRmAccount first.
How do I authenticate from within a runbook so that I can run automation tasks? What am I doing wrong?
We have subsequently discovered the the automation account created a connection when created that can be used to login:
$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
}
}
At a guess you are trying to log in with a Microsoft account, which can only be done interactively (as it needs to redirect through live.com). You will need to create a user within the tenant (Active Directory) that you are authenticating against in order for non-interactive login to work.
The easiest method to make this work is to create an account in the old portal (the new portal doesn't support Active Directory management yet) and then to add that user as a co-administrator in settings > administrators.
You can create a user through Powershell, and assign much more granular permissions, but while you're working your way around things it is probably easier to stay within the portal.
There is no significant difference between a user created through the old portal and one created via AzureRm commands.
I just encountered the same problem and while the information posted here was helpful it didn't solve the problem completely.
The key insight I needed was that in order to use Azure Cmdlets one has to configure a 'Run as Account'. (See https://learn.microsoft.com/en-us/azure/automation/automation-sec-configure-azure-runas-account)
It can be set up under Account Settings section of the azure automation account.
Once you have the 'Run as Account' you can use the method proposed by BlackSpy to log in. Namely:
# Get the connection
$servicePrincipalConnection = Get-AutomationConnection -Name AzureRunAsConnection
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
Hope this might help someone.
The official advice is to use a ServicePrincipal for automation - you can either use Secret or Certificate credentials with a service principal, and certificates work the best.
It is still possible to use a work or school account for automated login (Login with just -Credential), but this requires that your organization does not require two-factor authentication. It is unfortunately not possible to use a Microsoft Account for this - microsoft accounts require user interaction for any login.