Visual Studio Team Services release issue - deployment

When I try to create a release within Visual Studio, I run into this error
azure deployment
Given that I have full permissions on my Azure account and I have no issues logging into my azure session
I think this is a bug within VSTS, the questions are, how to tweak this situation? can I use the Release management tool for visual studio 2013 temporary until I find out how to do a release
Rem: I tried the old method which uses powershell to get info about principal id, tenant id and so on but this method needs that my app has to be backed by AAD which is not the case for our situation and second this method is supposed deprecated for now
Any help will be highly appreciated
Thank you

It is working fine for me. (Success configuring Azure service connection by clicking Authorize button).
You can clear Internet browser cache, then Start InPrivate Browsing, you can try it in other machine.
》I tried the old method which uses powershell to get info about principal id, tenant id and so on but this method needs that my app has to be backed by AAD which is not the case for our situation
You don’t need to configure app that backed by ADD manually, just need to run this PowerShell script directly (refer to this article)
param
(
[Parameter(Mandatory=$true, HelpMessage="Enter Azure Subscription name. You need to be Subscription Admin to execute the script")]
[string] $subscriptionName,
[Parameter(Mandatory=$true, HelpMessage="Provide a password for SPN application that you would create")]
[string] $password,
[Parameter(Mandatory=$false, HelpMessage="Provide a SPN role assignment")]
[string] $spnRole = "owner"
)
#Initialize
$ErrorActionPreference = "Stop"
$VerbosePreference = "SilentlyContinue"
$userName = $env:USERNAME
$newguid = [guid]::NewGuid()
$displayName = [String]::Format("VSO.{0}.{1}", $userName, $newguid)
$homePage = "http://" + $displayName
$identifierUri = $homePage
#Initialize subscription
$isAzureModulePresent = Get-Module -Name AzureRM* -ListAvailable
if ([String]::IsNullOrEmpty($isAzureModulePresent) -eq $true)
{
Write-Output "Script requires AzureRM modules to be present. Obtain AzureRM from https://github.com/Azure/azure-powershell/releases. Please refer https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/DeployAzureResourceGroup/README.md for recommended AzureRM versions." -Verbose
return
}
Import-Module -Name AzureRM.Profile
Write-Output "Provide your credentials to access Azure subscription $subscriptionName" -Verbose
Login-AzureRmAccount -SubscriptionName $subscriptionName
$azureSubscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName
$connectionName = $azureSubscription.SubscriptionName
$tenantId = $azureSubscription.TenantId
$id = $azureSubscription.SubscriptionId
#Create a new AD Application
Write-Output "Creating a new Application in AAD (App URI - $identifierUri)" -Verbose
$azureAdApplication = New-AzureRmADApplication -DisplayName $displayName -HomePage $homePage -IdentifierUris $identifierUri -Password $password -Verbose
$appId = $azureAdApplication.ApplicationId
Write-Output "Azure AAD Application creation completed successfully (Application Id: $appId)" -Verbose
#Create new SPN
Write-Output "Creating a new SPN" -Verbose
$spn = New-AzureRmADServicePrincipal -ApplicationId $appId
$spnName = $spn.ServicePrincipalName
Write-Output "SPN creation completed successfully (SPN Name: $spnName)" -Verbose
#Assign role to SPN
Write-Output "Waiting for SPN creation to reflect in Directory before Role assignment"
Start-Sleep 20
Write-Output "Assigning role ($spnRole) to SPN App ($appId)" -Verbose
New-AzureRmRoleAssignment -RoleDefinitionName $spnRole -ServicePrincipalName $appId
Write-Output "SPN role assignment completed successfully" -Verbose
#Print the values
Write-Output "`nCopy and Paste below values for Service Connection" -Verbose
Write-Output "***************************************************************************"
Write-Output "Connection Name: $connectionName(SPN)"
Write-Output "Subscription Id: $id"
Write-Output "Subscription Name: $connectionName"
Write-Output "Service Principal Id: $appId"
Write-Output "Service Principal key: <Password that you typed in>"
Write-Output "Tenant Id: $tenantId"
Write-Output "***************************************************************************"

Related

Azure Automation Runbooks, Connect-AzAccount, Assigning rights

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

Auto Azure SQL DB Creation -DACPAC task how to configure database Azure pricing model

I have just found out that MS are changing the default Azure PaaS DB config setting on create to use Vcore instead of DTU. I am using Azure Devops to build DBs from a GithHub repository via DACPACs using the Azure SQL Task. I would like to keep the DTU model for my builds.
The options I can see for implementing this are :
Configure during the DACPAC Deploy task... I have not been able to find how to do this anywhere.
Pre-create the DB and then run the DACPAC file into it.
Set an azure default for any new DBs created. I have not been able to find a way of doing this.
For the second option I have successfully used the code snippet below for DB creation though cant find how I would create one with "standard S0 10 DTUs for example.
Any advice gratefully received..
New-AzureRmSqlDatabase -ResourceGroupName $ResourceGroup -ServerName $Servername -DatabaseName $DataBaseName
In general, you want to provision your Azure resources via some variety of idempotent configuration language. ARM templates are native, Terraform is a popular alternative. Run your ARM template deployment at the start of every deployment, then all of the necessary infrastructure for your application to run will be in place and properly configured.
If you want to do it with PowerShell, though, the parameters you're looking for are Edition and RequestedServiceObjectiveName. I.E. -Edition Standard -RequestedServiceObjectiveName S0.
After many false starts due to deficiencies in the documentation due to the constant Azure churn I have a working script. This Script works and the web hooks allow it to be called from Azure Devops CI.
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
Write-Output $WebhookData
# If runbook was called from Webhook, WebhookData will not be null.
if ($WebhookData) {
# Retrieve Params from Webhook request body
$params = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
foreach ($param in $params)
{
$DatabaseName = $param.DatabaseName
$Edition = $param.Edition
$PricingTier=$param.PricingTier
Write-Output "Found $DatabaseName"
Write-Output "Found $Edition"
Write-Output "Found $PricingTier"
}
$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
}
}
$ServerName = "ServerName"
$ResourceGroup = "ResourceGroupName"
#$PricingTierLocal ="S2"
#$EditionLocal ="Standard"
Set-AzureRmSqlDatabase -ResourceGroupName $ResourceGroup -ServerName $ServerName -DatabaseName $DatabaseName -Edition $Edition -RequestedServiceObjectiveName $PricingTier
}
else {
# Error
write-Error "This runbook is meant to be started from an Azure webhook only."
}

How do I deploy to Azure App Service with PowerShell?

I have looked around and with the thousands of commands in the Azure and AzureRM commandlets in PowerShell, I'm still not sure how to do this.
What I have working so far:
Installed Azure and AzureRM modules and imported them to the script
Generated the "*.publishsettings" file from the get-AzurePublishSettingsFile command
Imported the "*.publishsettings" file
Can acccess the website with the "Stop-AzureWebsite" and "Start-AzureWebsite" commandlets
What I need to do:
create a new deployment and push files to the app-service site.
Notes: I do not have a Visual Studio project and .csproj file configs. I simply want to take the contents of a folder and push that to the website.
Any help would be useful as the documentation is really bad on details and there are thousands of commands in PowerShell to go through.
You could check this blog:Deploy an App Service using Azure PowerShell to a Deployment Slot.
Get-AzurePublishSettingsFile
Import-AzurePublishSettingsFile .\Your-Publish-Settings-credentials.publishsettings
Get-AzureSubscription
Select-AzureSubscription -SubscriptionName "The Subscription Name containing the slot"
Set-AzureSubscription -SubscriptionId "ID of subscription"
$WebAppName = "standard(staging)"
Get-AzureWebsite -Name $WebAppName
Publish-AzureWebsiteProject -Name $WebAppName -Package "C:\PowerShell\standard.zip" -Slot "staging"
The above link (https://blogs.msdn.microsoft.com/benjaminperkins/2016/10/01/deploy-an-app-service-using-azure-powershell-to-a-deployment-slot/)talks about a GIT based deployment. OP wanted something from a folder.
Check this one out -
Create an Azure Website with PowerShell and FTP
Unfortunately the accepted answer gave me the following error:
Get-AzureWebSite : Requested value 'PremiumV2' was not found
This StackOverflow answer suggests to use Get-AzureRmWebApp instead, but this introduces some challenges with authentication. After some searching I found the following article which explained exactly what I needed: an approach to do a publish to Azure without any human interaction.
Please see a very simplified version of the script below.
#In the Azure portal go to (search for) "Azure Active Directory" ->
#"Properties" -> Directory ID
$TenantId = "<Azure Active Directory Id>"
#In the Azure portal go to (search for) "Subscriptions" -> Subscription ID
$SubscriptionId = "<Azure Subscription Id>"
#In the Azure portal go to (search for) "Azure Active Directory" -> "App registrations" ->
#Create a new registration, this will give you the ID and Secret below.
#Make sure to give your new app registration sufficient rights to your app service
$ServicePrincipleApplicationId = "<Service Principle Id>"
$ServicePrincipleApplicationSecret = "<Service Principle Secret>"
$WebAppPath = "<Local folder where your package is located>"
$ResourceGroupName = "<The name of the Azure resource group that contains your app service>"
$WebAppName = "<The name of your Azure app service>"
$WebAppSlot = "<The name of the deployment slot you want to publish to>"
$MSDeployPath = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe"
$source = "-source:contentPath=$WebAppPath"
$publishProfileOutputPath = Join-Path -Path $ENV:Temp -ChildPath 'publishprofile.xml'
$dest = "-dest:contentPath=d:\home\site\wwwroot\,publishSettings=$publishProfileOutputPath"
$SecurePassword = $ServicePrincipleApplicationSecret | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ServicePrincipleApplicationId, $securePassword
$connectParameters = #{
Credential = $Credential
TenantId = $TenantId
SubscriptionId = $SubscriptionId
}
Add-AzureRmAccount #connectParameters -ServicePrincipal
Get-AzureRmWebAppSlotPublishingProfile -OutputFile $publishProfileOutputPath -Format WebDeploy -ResourceGroupName $ResourceGroupName -Name $WebAppName -Slot $WebAppSlot
Stop-AzureRmWebAppSlot -ResourceGroupName $ResourceGroupName -Name $WebAppName -Slot $WebAppSlot
& $MSDeployPath #('-verb:sync', $source, $dest)
Start-AzureRmWebAppSlot -ResourceGroupName $ResourceGroupName -Name $WebAppName -Slot $WebAppSlot
To deploy your zip package to Azure Web App Service using PowerShell cmdlet.
Refer MS Docs.
Connect to Azure Subscription via PowerShell. Execute Publish-AzWebApp to deploy Web App.
$webAppName = "<NameOfWebAppService>"
$resourceGroup = "<WebAppResourceGroupName>"
$zipArchiveFullPath = "<zip-package-filePath\FileName.zip>"
Publish-AzWebApp -ResourceGroupName "$resourceGroup" -Name "$webAppName" -ArchivePath "$($zipArchiveFullPath)" -Force

Azure Runbook Error, AzureRmStorageAccountKey Cannot Index into null array

I am trying to run this command within an Azure Run book
(Get-AzureRmStorageAccountKey -Name $defaultStorageAccountName -ResourceGroupName $defaultResourceGroupName).Value[0]
It runs fine on my local machine and I can see the Storage Account Key. However, when I run the same command in Azure Runbook it throws the following error
Cannot index into a null array
If I just run Get-AzureRmStorageAccountKey -Name $defaultStorageAccountName -ResourceGroupName $defaultResourceGroupName in the Azure Runbook, it runs fine and I can see the Keys. It is just when I am selecting an element from an Array that it fails and throws an error.
The PowerShell version is 5 on my local machine and on Azure Runbook.
Update:
My issue was resolved after updating the Modules from the Gallery in my automation account.
According to your description, I test your cmdlets in my runbook, I could get storage key.
You could use the following commands to login your subscriptions.
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$connectionName = Get-AutomationConnection -Name "AzureRunAsConnection"
$AzureCredentialAssetName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $AzureCredentialAssetName
"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
}
}
$key=(Get-AzureRmStorageAccountKey -Name <storage account name> -ResourceGroupName <resource group name>).Value[0]
"The storage account key is $key"
More information please refer to this link.
Update
You need update Azure Storage account module version in automation account, then you could solve this issue.

Get job status in Azure Runbook

I would like to have a runbook run on a schedule but exit if the last job hasn't finished running (i.e. if the schedule is every 2 hours and a job takes 2.5 hours then the next job shouldn't run).
I've tried to use Get-AzureAutomationJob to get the last job status (https://azure.microsoft.com/en-gb/documentation/articles/automation-runbook-execution/#retrieving-job-status-using-windows-powershell), but I can't get it to work. I presume all the preamble to get the subscription etc is required.
"Get-AzureAutomationJob : The Automation account was not found."
$ConnectionAssetName = "AzureClassicRunAsConnection"
# Get the connection
$connection = Get-AutomationConnection -Name $connectionAssetName
# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
throw "Could not retrieve connection asset: $ConnectionAssetName. Assure that this asset exists in the Automation account."
}
$CertificateAssetName = $Conn.CertificateAssetName
Write-Verbose "Getting the certificate: $CertificateAssetName" -Verbose
$AzureCert = Get-AutomationCertificate -Name $CertificateAssetName
if ($AzureCert -eq $null)
{
throw "Could not retrieve certificate asset: $CertificateAssetName. Assure that this asset exists in the Automation account."
}
Write-Verbose "Authenticating to Azure with certificate." -Verbose
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName - SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID
$job = (Get-AzureAutomationJob –AutomationAccountName "THE NAME OF THE AUTOMATION ACCOUNT AS IT APPEARS IN THE PORTAL" –Name "JobStatusTest" | sort LastModifiedDate –desc)[0]
Well, you would need to use Get-AzureRMAutomation job for that. Let me elaborate on that, I think in march 2016 Microsoft removed Azure Automation from the OLD azure model and now it is present only in the new one. so you would need to add RM to your commandlets