How to activate Privileged Access Groups using Powershell? - azure

I am trying to activate my privileged access groups using powershell however so far unable to do so. All the examples either in MS Docs site or google search only have examples regarding instruction to activate roles using powershell for PIM.
Has anyone been successful or have an idea how to get privileged access groups activated using powershell?
Here is what i tried:
#variables
$upn = ""
$tenantId = ""
$reason = "Test"
$groupId = "" #privileged access groups Id retrieved from Azure Portal > Groups > <group which has roles>
#MFA setup
if(!(Get-Module | Where-Object {$_.Name -eq 'PowerShellGet' -and $_.Version -ge '2.2.4.1'})) { Install-Module PowerShellGet -Force }
if(!(Get-Package msal.ps)) { Install-Package msal.ps }
# Get token for MS Graph by prompting for MFA
$MsResponse = Get-MSALToken -Scopes #("https://graph.microsoft.com/.default") -ClientId "1b730954-1685-4b74-9bfd-dac224a7b894" -RedirectUri "urn:ietf:wg:oauth:2.0:oob" -Authority "https://login.microsoftonline.com/common" -Interactive -ExtraQueryParameters #{claims='{"access_token" : {"amr": { "values": ["mfa"] }}}'}
# Get token for AAD Graph
$AadResponse = Get-MSALToken -Scopes #("https://graph.windows.net/.default") -ClientId "1b730954-1685-4b74-9bfd-dac224a7b894" -RedirectUri "urn:ietf:wg:oauth:2.0:oob" -Authority "https://login.microsoftonline.com/common"
Connect-AzureAD -AadAccessToken $AadResponse.AccessToken -MsAccessToken $MsResponse.AccessToken -AccountId: $upn -tenantId: $tenantId
$roleDefinitionCollection = Get-AzureADMSPrivilegedRoleAssignment -ProviderId "aadRoles" -ResourceId $resource.Id -Filter "subjectId eq '$grouipId'"
#set schedule
$schedule = New-Object Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedSchedule
$schedule.Type = "Once"
$schedule.StartDateTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
$schedule.endDateTime = (Get-Date).AddHours($activateTime).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
$subject = Get-AzureADUser -Filter "userPrincipalName eq '$upn'"
foreach ($roleDefinition in $roleDefinitionCollection) {
Open-AzureADMSPrivilegedRoleAssignmentRequest -ProviderId AadRoles -Schedule $schedule -ResourceId $resource.Id -RoleDefinitionId $roleDefinition.RoleDefinitionId -SubjectId $subject.ObjectId -AssignmentState "Active" -Type "UserAdd" -Reason $reason
}
This returns error message:
Open-AzureADMSPrivilegedRoleAssignmentRequest : Error occurred while executing OpenAzureADMSPrivilegedRoleAssignmentRequest
Code: RoleAssignmentDoesNotExist
Message: The Role assignment does not exist.
InnerError:
RequestId: b6e750c4-acf4-4032-84ea-29d74fbc53ac
DateTimeStamp: Fri, 25 Mar 2022 19:00:10 GMT
HttpStatusCode: NotFound
HttpStatusDescription: Not Found
HttpResponseStatus: Completed
At line:2 char:5
+ Open-AzureADMSPrivilegedRoleAssignmentRequest -ProviderId AadRole ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Open-AzureADMSP...signmentRequest], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.MSGraphBeta.Client.ApiException,Microsoft.Open.MSGraphBeta.PowerShell.OpenAzureADMSPrivilegedRoleAssignmentRequest
These were some of the sites that i referred: (all only have example to activate the role)
http://www.anujchaudhary.com/2020/02/connect-to-azure-ad-powershell-with-mfa.html
https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/powershell-for-azure-ad-roles#activate-a-role-assignment
https://www.youtube.com/watch?v=OVfwO8_eDjs

Edit: Sorry I misread some part of your question actually.
In fact, you should adapt the provider id to "aadGroups" in order to use the group features.
This should help you to be on track depending on your environment:
$groupId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$upn="myyupn#domain.com"
Connect-AzureAD
$resource = Get-AzureADMSPrivilegedResource -ProviderId aadGroups
$subject = Get-AzureADUser -Filter "userPrincipalName eq '$upn'"
# here you will require some additionnal filtering depending on your environment
$roleDefinitionCollection = Get-AzureADMSPrivilegedRoleDefinition -ProviderId "aadGroups" -ResourceId $groupId
#this works only when pimed in my case:
#$roleDefinitionCollection = Get-AzureADMSPrivilegedRoleAssignment -ProviderId "aadGroups" -ResourceId $resource.id -Filter "ResourceId eq '$groupId' and AssignmentState eq 'Eligible'"
$reason = "test"
foreach ($roleDefinition in $roleDefinitionCollection) {
$schedule = New-Object Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedSchedule
$schedule.Type = "Once"
$schedule.Duration="PT1H"
$schedule.StartDateTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
Open-AzureADMSPrivilegedRoleAssignmentRequest -ProviderId "aadGroups" -Schedule $schedule -ResourceId $groupId -RoleDefinitionId $roleDefinition.id -SubjectId $subject.ObjectId -AssignmentState "Active" -Type "UserAdd" -Reason $reason
}

When you try to assign the Role, it will be
You Can't be assigned for a duration of less than five minutes.
You Can't be removed within five minutes of it being assigned
Here is your script, you need to wait for 5 minutes for every iteration to create a Group Role Assignment
foreach ($roleDefinition in $roleDefinitionCollection) {
Open-AzureADMSPrivilegedRoleAssignmentRequest -ProviderId AadRoles -Schedule $schedule -ResourceId $resource.Id -RoleDefinitionId $roleDefinition.RoleDefinitionId -SubjectId $subject.ObjectId -AssignmentState "Active" -Type "UserAdd" -Reason $reason
# wait for 5 minutes
Start-Sleep -s 300
}
Refer here for more information

Related

How to Add Api Permissions to an Azure App Registration using PowerShell

I am figure out the commands in Azure PowerShell to add an the User.Read Ape Permission to my App Registration in Azure.
I can find some examples using *Azure, but would prefer one that uses the *Az commands, e.g. https://learn.microsoft.com/en-us/powershell/azure/?view=azps-2.8.0.
Wonder if anybody knows how to do this? Thanks!
This can currently only be achieved using the Azure AD PowerShell. Please note that there is a difference between Azure AD PowerShell and Azure PowerShell. The Azure AD PowerShell is not simply the old Azure PowerShell module.
Azure AD PowerShell is a separate module. There is no "AZ*" for Azure AD yet. Only couple of most commonly used commands, that have Azure Resource Provider implementation.
Azure PowerShell has a limited set of features for working with Azure AD. If you need more features, like the one you mention, you must use Azure AD PowerShell. Azure AD PowerShell is not depricated and is the officially supported PowerShell module for working with Azure AD.
You can manage these required permissions by the Set-AzureAdApplication cmdlet and passing proper -RequiredResourceAccess object.
In order to construct this object, you must first get a reference to "exposed" permissions. Because permissions are exposed by other service principals.
as I cannot upload whole file, here is a PowerShell script that creates a sample application with required permission to some MS Graph and some Power BI permissions.
Function GetToken
{
param(
[String] $authority = "https://login.microsoftonline.com/dayzure.com/oauth2/token",
[String] $clientId,
[String] $clientSecret,
[String] $resourceId = "https://graph.windows.net"
)
$scope = [System.Web.HttpUtility]::UrlEncode($resourceId)
$encSecret = [System.Web.HttpUtility]::UrlEncode($clientSecret)
$body = "grant_type=client_credentials&resource=$($scope)&client_id=$($clientId)&client_secret=$($encSecret)"
$res = Invoke-WebRequest -Uri $authority -Body $body -Method Post
$authResult = $res.Content | ConvertFrom-Json
return $authResult.access_token
}
#`
# -RequiredResourceAccess #($requiredResourceAccess)
#
Function CreateChildApp
{
param (
[string] $displayName,
[string] $tenantName
)
# create your new application
Write-Output -InputObject ('Creating App Registration {0}' -f $displayName)
if (!(Get-AzureADApplication -SearchString $displayName)) {
$app = New-AzureADApplication -DisplayName $displayName `
-Homepage "https://localhost" `
-ReplyUrls "https://localhost" `
-IdentifierUris ('https://{0}/{1}' -f $tenantName, $displayName)
# create SPN for App Registration
Write-Output -InputObject ('Creating SPN for App Registration {0}' -f $displayName)
# create a password (spn key)
$appPwd = New-AzureADApplicationPasswordCredential -ObjectId $app.ObjectId
$appPwd
# create a service principal for your application
# you need this to be able to grant your application the required permission
$spForApp = New-AzureADServicePrincipal -AppId $app.AppId -PasswordCredentials #($appPwd)
}
else {
Write-Output -InputObject ('App Registration {0} already exists' -f $displayName)
$app = Get-AzureADApplication -SearchString $displayName
}
#endregion
return $app
}
Function GrantAllThePermissionsWeWant
{
param
(
[string] $targetServicePrincipalName,
$appPermissionsRequired,
$childApp,
$spForApp
)
$targetSp = Get-AzureADServicePrincipal -Filter "DisplayName eq '$($targetServicePrincipalName)'"
# Iterate Permissions array
Write-Output -InputObject ('Retrieve Role Assignments objects')
$RoleAssignments = #()
Foreach ($AppPermission in $appPermissionsRequired) {
$RoleAssignment = $targetSp.AppRoles | Where-Object { $_.Value -eq $AppPermission}
$RoleAssignments += $RoleAssignment
}
$ResourceAccessObjects = New-Object 'System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.ResourceAccess]'
foreach ($RoleAssignment in $RoleAssignments) {
$resourceAccess = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess"
$resourceAccess.Id = $RoleAssignment.Id
$resourceAccess.Type = 'Role'
$ResourceAccessObjects.Add($resourceAccess)
}
$requiredResourceAccess = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$requiredResourceAccess.ResourceAppId = $targetSp.AppId
$requiredResourceAccess.ResourceAccess = $ResourceAccessObjects
# set the required resource access
Set-AzureADApplication -ObjectId $childApp.ObjectId -RequiredResourceAccess $requiredResourceAccess
Start-Sleep -s 1
# grant the required resource access
foreach ($RoleAssignment in $RoleAssignments) {
Write-Output -InputObject ('Granting admin consent for App Role: {0}' -f $($RoleAssignment.Value))
New-AzureADServiceAppRoleAssignment -ObjectId $spForApp.ObjectId -Id $RoleAssignment.Id -PrincipalId $spForApp.ObjectId -ResourceId $targetSp.ObjectId
Start-Sleep -s 1
}
}
cls
#globaladminapp
$clientID = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
$key = "****"
$tenantId = "aaaaaaaa-bbbb-xxxx-yyyy-aaaaaaaaaaaa";
$TenantName = "customdomain.com";
$AppRegName = "globaladminChild-0003";
$token = GetToken -clientId $clientID -clientSecret $key
Disconnect-AzureAD
Connect-AzureAD -AadAccessToken $token -AccountId $clientID -TenantId $tenantId
$appPermissionsRequired = #('Application.ReadWrite.OwnedBy', 'Device.ReadWrite.All', 'Domain.ReadWrite.All')
$targetServicePrincipalName = 'Windows Azure Active Directory'
#$appPermissionsRequired = #('Files.ReadWrite.All','Sites.FullControl.All','Notes.ReadWrite.All')
#$targetServicePrincipalName = 'Microsoft Graph'
$app = CreateChildApp -displayName $AppRegName -tenantName $TenantName
$spForApp = Get-AzureADServicePrincipal -Filter "DisplayName eq '$($AppRegName)'"
$appPermissionsRequired = #('Tenant.ReadWrite.All')
$targetServicePrincipalName = 'Power BI Service'
GrantAllThePermissionsWeWant -targetServicePrincipalName $targetServicePrincipalName -appPermissionsRequired $appPermissionsRequired -childApp $app -spForApp $spForApp
$appPermissionsRequired = #('Files.ReadWrite.All','Sites.FullControl.All','Notes.ReadWrite.All')
$targetServicePrincipalName = 'Microsoft Graph'
GrantAllThePermissionsWeWant -targetServicePrincipalName $targetServicePrincipalName -appPermissionsRequired $appPermissionsRequired -childApp $app -spForApp $spForApp
The interesting parts are around "apppermissionrequired" and "targetserviceprincipalname" variables.
I can't reply to Rolfo's comment directly as I don't have enough clout yet. While it's true it's not dead simple, it's possible to use both in the same session as of July 2021. Not sure this was always the case, or something was updated to allow it.
#Import modules if needed
$mList = #("AzureAD","Az.Resources","Az.Accounts")
foreach($m in $mList){if ((gmo -l $m).Count -eq 0){Install-Module -Name $m -AllowClobber -Scope CurrentUser -Force}}
#Authentication Popup
Connect-AzAccount
#Use authentication context cached from above to authenticate to AAD graph
$IDObject = Get-AzAccessToken -Resource "https://graph.windows.net"
Connect-AzureAD -AadAccessToken $IDObject.token -AccountId $IDObject.UserId
UPDATE
With the new Graph API we can use the following command to add API permissions to an App Registration/Service Principal using PowerShell. It's much simpler than the old process.
Add-AzADAppPermission -ApplicationId "$spId" -ApiId "00000009-0000-0000-c000-000000000000" -PermissionId "7504609f-c495-4c64-8542-686125a5a36f"
(This is the case for the PowerBI API)
If deploying via an Azure Devops Pipeline I often recommend using the following script to authenticate into AAD:
echo "Install Azure AD module..."
Install-Module -Name "AzureAD" -Force
Import-Module AzureAD -Force
echo "Connect Azure AD..."
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
echo $context
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
echo $graphToken
$aadToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken
Write-Output "Hi I'm $($context.Account.Id)"
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id -MsAccessToken $graphToken
echo "Connection ends"

I am trying to make a powershell script to bulk import users to an enterprise application but keep receiving errors

Here is the code that I have written and modified several times, but still cannot get to work. Any help would be greatly appreciated. I keep receiving the following errors:
Get-AzureADUser : Cannot bind argument to parameter 'ObjectId' because it is null** and **New-AzureADUserAppRoleAssignment : Cannot bind argument to parameter 'ObjectId' because it is null.
# Assign the global values to the variables for the script.
$app_name = "App Name"
$app_role_name = "User"
$users = Get-Content 'Path\Users.txt'
$Credential=Get-StoredCredential -UserName #####
# Connect to Azure AD using Azure AD Powershell
Connect-AzureAD -Credential $Credential
# Get the user to assign, and the service principal for the app to assign to
foreach ($user in $users) {
$AADuser = Get-AzureADUser -ObjectId $user
$sp = Get-AzureADServicePrincipal -Filter "displayName eq '$app_name'"
$appRole = $sp.AppRoles | Where-Object { $_.DisplayName -eq $app_role_name }
# Assign the user to the app role
New-AzureADUserAppRoleAssignment -ObjectId $user.ObjectId -PrincipalId $user.ObjectId -ResourceId $sp.ObjectId -Id $appRole.Id
}'''

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Azure PowerShell script does not work when change to a different Azure Subscription

I am experiencing a very strange problem. I recently switched Azure subscription from free trial to pay-as-you-go. The PowerShell script i wrote to create Azure Resource Group, Azure Data Factory, Azure Active Directory App Azure SQL Server, Azure SQL Database does not work. below is the sample code from script and error messages
New-AzResourceGroup Test2ResourceGroupName2 -location 'westeurope'
$AzADAppName = "TestADApp1"
$AzADAppUri = "https://test.com/active-directory-app"
$AzADAppSecret = "TestSecret"
$AzADApp = Get-AzADApplication -DisplayName $AzADAppName
if (-not $AzADApp) {
if ($AzADApp.IdentifierUris -ne $AzADAppUri) {
$AzADApp = New-AzADApplication -DisplayName $AzADAppName -HomePage $AzADAppUri -IdentifierUris $AzADAppUri -Password $(ConvertTo-SecureString -String $AzADAppSecret -AsPlainText -Force)
}
}
New-AzResourceGroup : Your Azure credentials have not been set up or have expired, please run Connect-AzAccount to set up your Azure credentials.
At line:1 char:1
+ New-AzResourceGroup Test2ResourceGroupName2 -location 'westeurope'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzResourceGroup], ArgumentException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupCmdlet
Get-AzADApplication : User was not found.
At line:6 char:12
+ $AzADApp = Get-AzADApplication -DisplayName $AzADAppName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-AzADApplication], Exception
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ActiveDirectory.GetAzureADApplicationCommand
New-AzADApplication : User was not found.
At line:11 char:20
+ ... $AzADApp = New-AzADApplication -DisplayName $AzADAppName -HomePage $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-AzADApplication], Exception
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ActiveDirectory.NewAzureADApplicationCommand
However if i execute this command in Azure Cloud Shell it works.
New-AzResourceGroup Test2ResourceGroupName -location 'westeurope'
I am also able to create Resource Group and other resources in Azure Portal. We cannot use portal and we have to use powershell due to company policy. could anyone help why PowerShell is not working
Here is the full script as requested in comments
Connect-AzAccount -TenantID xxxxx-xxx-xxx-xxxxx-xxxxx
# Creating Azure Active Directory App
$AzADAppName = "xxxxx-active-directory-app"
$AzADAppUri = "https://xxxxx.com/xxxxx-app"
$AzADAppSecret = "xxxxx"
$AzADApp = Get-AzADApplication -DisplayName $AzADAppName
if (-not $AzADApp) {
if ($AzADApp.IdentifierUris -ne $AzADAppUri) {
$AzADApp = New-AzADApplication -DisplayName $AzADAppName -HomePage $AzADAppUri -IdentifierUris $AzADAppUri -Password $(ConvertTo-SecureString -String $AzADAppSecret -AsPlainText -Force)
$AzADServicePrincipal = New-AzADServicePrincipal -ApplicationId $AzADApp.ApplicationId
# Assign the Contributor RBAC role to the service principal
# If you get a PrincipalNotFound error: wait 15 seconds, then rerun the following until successful
$Retries = 0; While ($NewRole -eq $null -and $Retries -le 6) {
# Sleep here for a few seconds to allow the service principal application to become active (usually, it will take only a couple of seconds)
Sleep 15
New-AzRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $AzADApp.ApplicationId -ErrorAction SilentlyContinue
$NewRole = Get-AzRoleAssignment -ServicePrincipalName $AzADServicePrincipal.ApplicationId -ErrorAction SilentlyContinue
$Retries++;
}
"Application {0} Created Successfully" -f $AzADApp.DisplayName
# Display the values for your application
"Save these values for using them in your application"
"Subscription ID: {0}" -f (Get-AzContext).Subscription.SubscriptionId
"Tenant ID:{0}" -f (Get-AzContext).Tenant.TenantId
"Application ID:{0}" -f $AzADApp.ApplicationId
"Application AzADAppSecret :{0}" -f $AzADAppSecret
}
}
else {
"Application{0} Already Exists" -f $AzADApp.DisplayName
}
# Creating Azure Resource Group
$DataFactoryName = "xxxxx-DataFactory"
$ResourceGroupName = "xxxxx-ResourceGroup"
$ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName
$Location = 'westeurope'
if (-not $ResourceGroup) {
$ResourceGroup = New-AzResourceGroup $ResourceGroupName -location 'westeurope'
if ($ResourceGroup) {
"Resource Group {0} Created Successfully" -f $ResourceGroup.ResourceGroupName
}
else {
"ERROR: Resource Group Creation UNSUCCESSFUL"
}
}
else {
"Resource Group {0} Exists" -f $ResourceGroup.ResourceGroupName
}
# Creating Azure Data Factory
$DataFactory = Get-AzDataFactoryV2 -Name $DataFactoryName -ResourceGroupName $ResourceGroup.ResourceGroupName
if (-not $DataFactory) {
$DataFactory = Set-AzDataFactoryV2 -ResourceGroupName $ResourceGroup.ResourceGroupName -Location $ResourceGroup.Location -Name $DataFactoryName
if ($DataFactory) {
"Data Factory {0} Created Successfully" -f $DataFactory.DataFactoryName
}
else {
"ERROR: Data Factory Creation UNSUCCESSFUL"
}
}
else {
"Data Factory {0} Already Exists" -f $DataFactory.DataFactoryName
}
# Creating Azure SQL Server and Database
$ServerName = "xxxxx"
$DatabaseName = "xxxxx"
$AzSQLServer = Get-AzSqlServer -ServerName $ServerName
$Subscription = Get-AzSubscription
"Subscription Data" -f $Subscription.Id
if (-not $AzSQLServer) {
"Creating New Azure SQL Server"
$AdminSqlLogin = "xxxxx"
$Password = "xxxxx"
$StartIp = "xxxxx.xxxxx.xxxxx.xxxxx"
$EndIp = "xxxxx.xxxxx.xxxxx.xxxxx"
$AzSQLServer = New-AzSqlServer -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-Location $Location `
-SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AdminSqlLogin, $(ConvertTo-SecureString -String $Password -AsPlainText -Force))
if ($AzSQLServer) {
$FireWallRule = New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-FirewallRuleName "AllowedIPs" -StartIpAddress $StartIp -EndIpAddress $EndIp
if ($FireWallRule) {
"Server Created Successfully {0} with firewall Rule Setup" -f $AzSQLServer.ServerName
}
else {
"Server Created Successfully {0} No FireWall Setup" -f $AzSQLServer.ServerName
}
}
else {
"ERROR: Server Creation UNSUCCESSFUL"
}
}
else {
"Server Exists {0}" -f $AzSQLServer.ServerName
}
$AzSQLDatabase = Get-AzSqlDatabase -DatabaseName $DatabaseName -ServerName $ServerName -ResourceGroupName $ResourceGroup.ResourceGroupName
if (-not $AzSQLDatabase) {
"Creating New Azure SQL Database"
$Parameters = #{
ResourceGroupName = $ResourceGroupName
ServerName = $ServerName
DatabaseName = $DatabaseName
RequestedServiceObjectiveName = 'S0'
}
$AzSQLDatabase = New-AzSqlDatabase #Parameters
if ($AzSQLDatabase) {
"Azure SQL Database {0} Created Successfully " -f $AzSQLDatabase.DatabaseName
}
else {
"ERROR: Azure SQL Database Creation UNSUCCESSFUL"
}
}
else {
"Database {0} Exists " -f $AzSQLDatabase.DatabaseName
}
You could use Clear-AzContext to remove all Azure credentials, account, and subscription information. Then use Connect-AzAccount -Tenant xxxxx -Subscription xxxxx, it should work.

Start-AzureSqlDatabaseExport Object Reference not set to an instance of an object

I'm not sure how to debug this, assuming it's not a problem with the cmdlet. I'm trying to replace the automated SQL export with an automation workflow, but I can't seem to get Start-AzureSqlDatabaseExport to work -- it keeps getting the following warning and error messages.
d4fc0004-0c0b-443e-ad1b-310af7fd4e2a:[localhost]:Client Session Id: 'c12c92eb-acd5-424d-97dc-84c4e9c4f914-2017-01-04
19:00:23Z'
d4fc0004-0c0b-443e-ad1b-310af7fd4e2a:[localhost]:Client Request Id: 'd534f5fd-0fc0-4d68-8176-7508b35aa9d8-2017-01-04
19:00:33Z'
Start-AzureSqlDatabaseExport : Object reference not set to an instance of an object.
At DBBackup:11 char:11
+
+ CategoryInfo : NotSpecified: (:) [Start-AzureSqlDatabaseExport], NullReferenceException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.SqlDatabase.Database.Cmdlet.StartAzureSqlDatabaseExport
This seems similar to some other questions, but they seem to be unanswered or not applicable. I did have a similar procedure working in the Powershell environment. I replaced that procedure with the automated export from Azure, which seems like a poor choice now! I've tried a number of variations, using sqlcontext and databasename instead of database, for example.
Here's my code with sensitive parts replaced with ****:
workflow DBBackup {
param(
[parameter(Mandatory=$true)]
[string] $dbcode
)
$cred = Get-AutomationPSCredential -Name "admindbcredentials"
$VerbosePreference = "Continue"
inlineScript {
$dbcode = $using:dbcode
$cred = $using:cred
if ($dbcode -eq $null)
{
Write-Output "Database code must be specified"
}
Else
{
$dbcode = $dbcode.ToUpper()
$dbsize = 1
$dbrestorewait = 10
$dbserver = "kl8p7d444a"
$stacct = $dbcode.ToLower()
$stkey = "***storagekey***"
Write-Verbose "DB Server '$dbserver' DB Code '$dbcode'"
Write-Verbose "Storage Account '$stacct'"
$url = "https://$dbserver.database.windows.net"
$sqlctx = New-AzureSqlDatabaseServerContext -ManageUrl $url -Credential $cred
# $sqlctx = New-AzureSqlDatabaseServerContext -ManageUrl $url -Credential $cred
$stctx = New-AzureStorageContext -StorageAccountName $stacct -StorageAccountKey $stkey
$dbname = "FSUMS_" + $dbcode
$dt = Get-Date
$timestamp = $dt.ToString("yyyyMMdd") + "_" + $dt.ToString("HHmmss")
$bkupname = $dbname + "_" + $timestamp + ".bacpac"
$stcon = Get-AzureStorageContainer -Context $stctx -Name "backups"
$db = Get-AzureSqlDatabase -Context $sqlctx -DatabaseName $dbname
Write-Verbose "Backup $dbname to $bkupname in storage account $stacct"
Start-AzureSqlDatabaseExport $sqlctx -DatabaseName $dbname -StorageContainer $stcon -BlobName $bkupname
}
}
}
Try New-AzureRmSqlDatabaseExport instead. This command will return export status object. If you want a synchronous export you can check for "export status" in a loop.
Adding the following lines corrected the problem:
In the workflow before inlineScript:
$cred = Get-AutomationPSCredential -Name "admincredentials"
(where admincredentials was an asset with my admin login credentials)
and inside the inlineScript:
Add-AzureAccount $cred
Select-AzureSubscription "My subscription"
Some runbooks don't seem to need this, but probably best to always include it.

Resources