How can I transfer a subscription in API Management from one user to another in Azure PowerShell? - azure-powershell

I want to transfer control on API Management subscriptions from one user to another in case the original user e.g. left the company or changed job roles.

Have email address of source and target user prepared, adapt and use these Azure PowerShell commands:
$ctx = New-AzApiManagementContext -ResourceGroupName {your-resource-group} -ServiceName {your-APIM-service-name}
$from = Get-AzApiManagementUser -Context $ctx -Email "from.user#my-company.com"
$to = Get-AzApiManagementUser -Context $ctx -Email "to.user#my-company.com"
Get-AzApiManagementSubscription -Context $ctx -UserId $from.UserId | ConvertTo-Json | Set-Content ./SubscriptionDump.json
Get-Content .\SubscriptionDump.json | ConvertFrom-Json | %{Set-AzApiManagementSubscription -Context $ctx -SubscriptionId $_.SubscriptionId -UserId $to.UserId}

Related

Az PowerShell CmdLet Get-AzDataLakeGen2ChildItem Proxy Authentication Error

I am running simple ps cmdlets to connect to azure datalake gen2 storage, some of the cmdlets are working and authenticating through corporate proxy (powershell is configured to use proxy on my machine). however some commands are failing with "Proxy Authentication is required".
Can someone share ideas or reason or fix ?
$subscription = "subscription"
$storageAccount = "storage"
$filesystem = "rawdata"
Connect-AzAccount -Subscription $subscription | Out-Null
$context = New-AzStorageContext -StorageAccountName $storageAccount -UseConnectedAccount
Below commands are throwing an error
Get-AzDataLakeGen2Item -Context $ctx -FileSystem $fileSystem
Get-AzDataLakeGen2ChildItem -Context $context -FileSystem $fileSystem
Get-AzDataLakeGen2ChildItem : Proxy Authentication Required At line:1
char:1
Get-AzDataLakeGen2ChildItem -Context $ctx
+ CategoryInfo : CloseError: (:) [Get-AzDataLakeGen2ChildItem], RequestFailedException
+ FullyQualifiedErrorId : RequestFailedException,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.GetAzDataLakeGen2ChildItemCommand
But this command is working fine.
Get-AzDatalakeGen2FileSystem -Context $ctx
One of the workaround for connecting to the Azure Data Lake Gen2 Storage account using PowerShell through Proxy by using following Code:
$browser = New-Object System.Net.WebClient
$browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials
Run this Code before connecting to the Azure Account.
I have executed this code to list the files available in the directory of my container in Azure Data Lake Gen2 Storage locally (Windows PowerShell ISE)
Windows PowerShell ISE:
Reference: Access web using PowerShell and Proxy

Azure Runbook Running Sql Query: The target principal name is incorrect. Cannot generate SSPI context."

Hi I am trying to run a SQL query on one of my databases using an Azure Runbook. My setup is listed below. When I test this, I get the error The target principal name is incorrect. Cannot generate SSPI context." I have looked around and have not found anything related to an Azure setup. Does anyone have any ideas?
$myCred = Get-AutomationPSCredential -Name 'my-cred'
$userName = $myCred.UserName
$securePassword = $myCred.Password
$password = $myCred.GetNetworkCredential().Password
#Query to execute
# Invoke to Azure SQL DB
invoke-sqlcmd2 -ServerInstance $ServerName -Database $DatabaseName -Credential $SQLServerCred -Query $SqlQuery -Encrypt
As mentioned in the comment, looks you did not set $SQLServerCred before.
Try:
$myCred = Get-AutomationPSCredential -Name 'my-cred'
$userName = $myCred.UserName
$securePassword = $myCred.Password
$SQLServerCred = New-Object System.Management.Automation.PSCredential($userName , $securePassword)
#Query to execute
# Invoke to Azure SQL DB
invoke-sqlcmd2 -ServerInstance $ServerName -Database $DatabaseName -Credential $SQLServerCred -Query $SqlQuery -Encrypt

Azure Backup. Wait Only Until Snapshot Is Taken, Not Until It's Transferred to Vault

I'm writing a PowerShell script for starting MySQL Server process, initiating backups from Azure Recovery Services, then starting MySQL Server process again.
For my purposes Wait-AzRecoveryServicesBackupJob cmdlet is not suitable, as Azure Backup always takes 10 minutes to take a snapshot and takes 3-24 hours to transfer that snapshot to Vault. How can I wait only until snapshot is taken?
You will need to set up your own polling loop, but unfortunately the Get-AzRecoveryServicesBackupJob doesn't have the properties you need. There are two options available to you in Powershell-- the REST API or the CLI.
Once you've gotten the job info, you can find the individual tasks under properties.extendedInfo.tasksList
Implementing this under the CLI would look something like this:
$resourceGroup = "resourceGroup"
$vaultName = "vaultName"
$jobs = az backup job list --resource-group $resourceGroup --vault-name $vaultName --start-date 28-8-2020 | convertfrom-json
$jobName = $jobs[0].name
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
While ( $taskStatus.status -ne Completed ) {
Write-Host -Object "Waiting for completion..."
Start-Sleep -minutes 1
$jobStatus = az backup job show --name $jobName --resource-group $resourceGroup --vault-name $vaultName
$taskStatus = $jobStatus.properties.extendedInfo.tasksList | Where-Object { $_.taskId -eq "Take Snapshot"}
}
Write-Host -Object "Done!"

Automate Powershell Script to connect to MSOnline while MFA is applied

Thanks in advance.
Quick brief, I work in a team managing multiple Microsoft CSPs (Partner Centers), every now and then somebody asks us to run a script that does specific activities or grab specific info from all 30 CSPs we manage and all customers under them.
Previously we used to keep all usernames, passwords, TenantIDs, WebApp IDs in a CSV file and we create a script that runs on every raw to get the required info for each CSP Automatically without prompting credentials using below command:
$credential = (New-Object –TypeName System.Management.Automation.PSCredential –argumentlist $AdminName ,(ConvertTo-SecureString $AdminPassword –AsPlainText –Force))
And then call it in all modules like the below:
#MSonline
Connect-Msolservice –Credential $Credential
#ExchangeOnline
$session = New-PSSession –ConfigurationName Microsoft.Exchange –ConnectionUri https://outlook.office365.com/powershell-liveid?DelegatedOrg=$Customerdomain –Credential $credential –Authentication Basic –AllowRedirection
Import-PSSession $Session
#Partner Center
Add-PCAuthentication -cspappID $NAtive_clientid -cspDomain $domain -credential $credentials
Connect-MsolService -Credential $credentials
Then MFA was applied on all CSPs, though secure, it presented a problem with automating our scripts. Every time we're asked to run a script we would have to login manually at least 1 time to enter our MFA credentials to be able to run the script on each CSP individually.
The Modules we usually connect to are:
PartnerCenter
MSOnline
CsOnline
AzureRM
AzureAD
Microsoft provided steps to work around this by using secure API Modules: https://learn.microsoft.com/en-us/powershell/partnercenter/secure-app-model?view=partnercenterps-1.5
I've created New APPs with new secrets and call backs , managed to get refresh token and integrated it in PartnerCenter module successfully as follows:
Connect-PartnerCenter -ApplicationId $NAtive_clientid -RefreshToken $refresh_token
Now I'm tying to do the same for the other Modules I'm addressing, as per the above document I could do the same for MS Online and for Azure AD simply by getting 3 other tokens (Graph Token , Azure AD token and Azure token)
$credential = Get-Credential
$refreshToken = 'Your-Refresh-Token-Value'
$azureToken = New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://management.azure.com/ -Credential $credential -TenantId '<Your Tenant Id>'
$graphToken = New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://graph.microsoft.com -Credential $credential -TenantId '<Your Tenant Id>'
$aadGraphToken = New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://graph.windows.net -Credential $credential -TenantId '<Your Tenant Id>'
#MS Module
Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken
# Az Module
Connect-AzAccount -AccessToken $azureToken.AccessToken -GraphAccessToken $graphToken.AccessToken -TenantId '<TenantId>'
# AzureRM Module
Connect-AzureRmAccount -AccessToken $azureToken.AccessToken -GraphAccessToken $graphToken.AccessToken -TenantId '<TenantId>'
When Applying this and running the below command I get an error:
New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://management.azure.com/ -Credential $credential -TenantId '<Your Tenant Id>'
New-PartnerAccessToken : Cannot validate argument on parameter 'RefreshToken'. The argument is null or empty. Provide an argument
that is not null or empty, and then try the command again.
At line:1 char:38
+ New-PartnerAccessToken -RefreshToken $refreshToken -Resource https:// ...
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [New-PartnerAccessToken], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Store.PartnerCenter.PowerShell.Commands.NewPartnerAccessT
oken
After some investigation I found that the parameter "-resource" no longer exists as per the documentation: https://learn.microsoft.com/en-us/powershell/module/partnercenter/new-partneraccesstoken?view=partnercenterps-3.0
Yet as per the documentation related to MSOnline, it shows I should be able to use it : https://learn.microsoft.com/en-us/powershell/module/msonline/connect-msolservice?view=azureadps-1.0
Now I'm stuck without the resource parameter I can't get the tokens required to use the 3 modules.
My question, is there another way to use App ID, refresh token, secret, Tenant ID to authenticate using powershell without human interference , if not how can I make the above method work for other modules the same way I did with the partner center.
According to my research. if the version of your PartnerCenter module is larger than 2.0.1909.1, it has rplaced the Resource parameter with the Scopes parameter for the Connect-PartnerCenter and New-PartnerAccessToken cmdlets. So please use the following script to get access token
New-PartnerAccessToken -ApplicationId 'xxxx-xxxx-xxxx-xxxx' -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant 'xxxx-xxxx-xxxx-xxxx'

Using Powershell to create user in RabbitMQ via API

I'm trying to create a powershell script that setups user "George" after installing RabbitMQ on a new machine.
I can't figure out why this script doesn't work.
The last step gives me a 404 {"error":"Object Not Found","reason":"\"Not Found\"\n"}
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'george' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('george', $secpasswd2)
$body = #{
'password' = 'george'
'tags' = 'administrator'
} | ConvertTo-Json
$vhosts1 = ''
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
write '1:' $vhosts1
$vhosts2 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/' -Method get -credential $credAdmin2
write '2:' $vhosts2
$body2 = #{
'username' = 'george'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
write '3:' $body2
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
write '4:' $vhosts3
I've also tried formatting the last step like this:
http://localhost:15672/api/permissions/george
Same 404 error.
I've tried about 20,000 different ways of sending the command in. From matching other examples perfectly to trying some abstract art and voodoo magic. While watching the managment tool for RabbitMQ I can see George is created. And he has an empty vhost. So the first 3 steps work perfectly.
Alright man, you know that I love you, because I'd never heard of RabbitMQ before tonight. In the last hour, I've installed it on my Windows machine, and now have used this awesome guide here to the API and kind of learned about how it works.
So, when I run your same process step by step , I see everything happen as you state:
George gets created:
Since your second step is listing the current permissions of the user running the API call, I next see output of the guest account, which has full perms. Then onto step 3, which builds the target permissions for George.
username : george
write : .*
read : .*
configure : .*
vhost : /
From here, Step 4. When I run this step manually after the previous step...it works! However, if I run this too quickly, if I run the whole script at once, I will get a 404 error. It seems that behind the scenes in RabbitMQ a slight pause is needed for the files to be updated with the new user. When I deleted the user and tried the whole script again too quickly, I got 404's for every step, pretty much.
However, if I add a little Start-Sleep 5 to pause 5 seconds...
The whole process completed. The key place to add a pause is after Step 1 and it seems to need about four or five seconds.
Making it pretty
Now of course, I couldn't stop there, so I decided to add a few more minor pauses to improve output readability and also ensure that each operation completes. I added some purty looking "OK" messages after the step completes, and then added a finishing confirmation of permissions by doing one last API call for the current user.
Here's the completed output
Completed Script
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'stephen' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('stephen', $secpasswd2)
$body = #{
'password' = 'stephen'
'tags' = 'administrator'
} | ConvertTo-Json
Write-host "About to create new user $(($body | ConvertFrom-Json).Password)..." -NoNewline
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
Write-Host '1: Results:' $vhosts1
$body2 = #{
'username' = 'stephen'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
Write-Output "Desired perms for new user $(($body | ConvertFrom-Json).Password)" $body2
Write-host "Setting perms for new user..." -NoNewline
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
Start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
write '4:' $vhosts3
'Retrieiving perms for new user to confirm...'
Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -Method get -credential $credAdmin2
Now I just hope I'll get a chance to use RabbitMQ ever again...
finally stumpled upon a powershell library someone else wrote for interacting with the RabbitMQ api.
https://github.com/mariuszwojcik/RabbitMQTools/blob/master/en-US/about_UnEsapingDotsAndSlashes.help.txt
I found out that certain versions of powershell replace %2f with the / before sending it to rabbit. If you use this guys functions found here:
https://github.com/mariuszwojcik/RabbitMQTools
Everything runs beautifully. Really great library he put together.
I'm late to this question. I love Powershell too, but I used a .bat file to run the native RabbitMQ commands as shown below. I needed to add a user, a vhost, and hook those two up. I wanted a script so any new developer could run it.
cd /D c:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14\sbin
echo cd completed
call rabbitmqctl add_user bts mypass
call rabbitmqctl set_user_tags bts administrator
call rabbitmqctl add_vhost base
call rabbitmqctl set_permissions -p base bts ".*" ".*" ".*"
Echo ----List Command to confirm results --------
call rabbitmqctl list_vhosts
call rabbitmqctl list_user_permissions bts
I suppose you could call these from Powershell too. I guess downside of this is that you have to be on the machine running RabbitMQ.