I created new GitHub private repository, in that I added ARM templates for Azure key vault. After that I am trying to deploy ARM template from my local machine using PowerShell tool.
This is PowerShell script I used for deploying ARM template into azure.
#Login-AzureRmAccount
#region Parameters
$resourceGroupName='KZEU-ARMTMP-SB-DEV-RGP-01'
$location='eastus'
$parametersUri='E:\Kishore\Kishore GitHub\ARMTemplates\Parameters\StorageAccount.parameters.json'
$templateUri='https://raw.githubusercontent.com/xxxxxxx/ARMTemplates/master/Templates/StorageAccount.json?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$clientID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx="
#endregion
#region Login into Azure
$SecurePassword = $key | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $clientID, $SecurePassword
Add-AzureRmAccount -Credential $cred -Tenant "xxxxxxxxxxxxxxxxxxxxxx" - ServicePrincipal
Set-AzureRmContext -SubscriptionID 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
#endregion
#region Check or Create Resource Group
Get-AzureRmResourceGroup -Name $resourceGroupName -ev notPresent -ea 0
if($notPresent){
Write-Host "Failover RG '$resourceGroupName' doesn't exist. Creating a new in $location...." -ForegroundColor Yellow
New-AzureRmResourceGroup -Name $resourceGroupName -Location $location
}else{
Write-Host "Using existing resource group '$resourceGroupName'" -ForegroundColor Yellow;
}
#endregion
#region Validate & Deploy ARM Templates
try{
$templateValidationResult= Test-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateUri -TemplateParameterFile $parametersUri -Verbose
if($templateValidationResult[0].Code-eq"InvalidTemplateDeployment"){
Write-Host "Failed to validate ARM template"
exit 1
}else{
Write-Host "Successfully completed to validate ARM template"
$deploymentResult= New-AzureRmResourceGroupDeployment -Name StorageAccount-Deployment -ResourceGroupName $resourceGroupName -TemplateFile $templateUri -TemplateParameterFile $parametersUri -Verbose
if($deploymentResult.ProvisioningState-eq"Succeeded"){
Write-Host "Successfully completed to deploy ARM template"
}else{
Write-Host "Failed to deploy ARM template"
exit 1
}
}
}
catch{
$ex = $_.Exception | Format-List -Force
Write-Host $ex
}
#endregion
When I run the above PowerShell script, then I am getting the error like
Unable to download deployment content from "https://raw.githubusercontent.com/xxxx/demo-in/master/xxxx/keyVault.json"
So, can anyone suggest me how to resolve the above issue?
Your issue is that you can't deploy from a private repo (see doc). What you are trying to do is pass a template URI for Azure to read and it doesn't have permission to read from your private repo. You have a couple options:
Do like the docs say and save the deploy.json to Azure Storage
and protect it with a SAS token.
You can clone your repo locally and
deploy from the local file.
Related
I am trying to make a code using PowerShell so that secrets are not hardcoded on my runbook so that it will not be exposed in the script. I created encrypted variables in my automation account. These variables are AppID, AppSecret and TenantID.
This is the part of the script to login automatically to Azure. I didn't use managed identity for some compatibility reasons with the script.
My script is running fine when secrets and IDs are hardcoded but when I created variables it is not working. Error message is "Run Connect-AzAccount". Below is my code. Need help on how to correct this. Thank you in advance.
$AzVariableApplicationID = 'AppID'
$AzVariableAppSecret = 'AppSecret'
$AzVariableTenantID = 'TenantID'
$AppID = Get-AzAutomationVariable -Name $AzVariableApplicationID
$AppSecret = Get-AzAutomationVariable -Name $AzVariableAppSecret
$TenantID = Get-AzAutomationVariable -Name $AzVariableTenantID
$SecureSecret = $AppSecret | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $AppID, $SecureSecret
Connect-AzAccount -ServicePrincipal -Credential $Credential -Tenant $TenantID
As described in PsCustom Object - Hitchikers GUID(e) to Automation
, It is not possible to retrieve values for encrypted variables as they’re available within the runbook at runtime via the Get-AutomationVariable cmdlet
I found an alternative approach to "Connect Azure" by using "Certificate-based authentication" inside PowerShell runbook without hardcoding the values:
Created a new Service principal and provided the "Owner" role access to avoid any restrictions.
To authenticate via service principal, I create a new self-signed certificate with the command:
$cert=New-SelfSignedCertificate -Subject "CN=xxxxxCert" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature
Upload a certificate under Certifications & Secrets:
Click windows + R to open the run box and give certmgr.msc as shown here.
Export a certificate without private key.
Upload a certificate in the below path:
AzureAD -> App registrations -> Serviceprincipal
Now, I have exported the same certificate with key and uploaded inside my automation account to authenticate Service principal connection:
Added an "Azure Service Principal" connection inside automation accounts by providing "ApplicationID, TenantID, Certificate Thumbprint" of my Service principal as shown:
Inside PowerShell runbook, I ran the below script that works for me:
$connectionName = "serviceprincipalname"
try
{
$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
}
}
Logged in to Azure:
Register an App in App registrations and create a service principal in AzureAD
I am finding difficulties in finding the best and secure way to use connect-azaccount with azure devops pipeline. I have in the pipeline the following this simple powershell script which is used to create azure resources. Just to simplify things I only used the creation of a resource group:
$Location = "Location Name"
$resourceGroupName = "Resource Group Name"
try {
#Creation of Resource Group
$resourceGroup = Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if($null -eq $resourceGroup)
{
New-AzResourceGroup -Name $resourceGroupName -Location $Location
}
else
{
Write-Host "The ResourceGroup with the name: $resourceGroupName already exists."
}
}
catch
{
Write-Host "Error occurred: $_"
}
The problem here is when the pipeline is being run and it reaches the Powershell task, it gives me an error, Error occurred: Run Connect-AzAccount to login.
My issue here is that I honestly don't know which way is the most secure way to connect without typing any user credentials. It should directly connect and create the resources. Note that I am using Multi-Factor Authentication. In order to achieve that I found several solutions but I need help in choosing the best way. I found several solutions by adding a powershell task in the Yaml file. Here is the Yaml showing the powershell task to run the script:
- task: PowerShell#2
inputs:
filePath: '$(Pipeline.Workspace)/Deploy/functionapp.ps1'
Option 1:
Connect-AzAccount -Tenant 'xxxx-xxxx-xxxx-xxxx' -SubscriptionId 'yyyy-yyyy-yyyy-yyyy'
Now the problem here is that the Tenant ID and Subscription are going to be visible in the code and that is a very bad practice
Option 2 is to use the following script:
$User = "xxx#xxxx.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "<Password>" -AsPlainText -Force
$tenant = "<tenant id>"
$subscription = "<subscription id>"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
Connect-AzAccount -Credential $Credential -Tenant $tenant -Subscription $subscription
This is very similar to the first, but if I am not mistaken it is limited to a specific user.
Option 3 is to use a service principal:
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
I don't know if creating a service principal will incur any costs and what steps should I do to make it work.
I am honestly new to all this, can someone please provide me what are the exact steps to achieve this. Thank you for your answers :)
The most secure way is to create an Azure Resource Manager service connection and use it in your pipeline. You can create it using automated way, or manually using previously created service principal.
I have a powershell task that is used to run a script which involves creating azure resources (Example: Resource group, Azure Key Vault, Function App...). When the pipeline is being run and it arrives to the powershell task in the deploy stage, it shows the following message:
The problem here, it says Finishing:Powershell but it didn't execute the script and did not create any azure resource.
Here is a sample of the powershell script:
$vaultName = "key vault name"
$blobstorageName = "blob storage name"
$Location = "Location Name"
$resourceGroupName = "Resource Group Name"
try {
#Creation of Resource Group
$resourceGroup = Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if($null -eq $resourceGroup)
{
New-AzResourceGroup -Name $resourceGroupName -Location $Location
}
else
{
Write-Host "The ResourceGroup with the name: $resourceGroupName already exists."
}
# Creation of Storage Account
$checkBlobStorage = (Get-AzStorageAccountNameAvailability -Name $blobstorageName) | Select-Object NameAvailable
if ($checkBlobStorage.NameAvailable)
{
New-AzStorageAccount -ResourceGroupName $resourceGroupName -AccountName $blobstorageName -Location $Location -SkuName Standard_LRS -Kind StorageV2 -AccessTier Hot
}
else
{
Write-Host "The name $blobStorageName is not available. Suggest a new globally unique name!"
}
catch
{
}
Does anyone have a clue what is wrong ? Am I missing something in the powershell script (Maybe I don't have direct access to the azure portal from azure devops) or maybe something is missing in
the Yaml file ?
Two major issues:
you seem to be using the Powershell Task, which is not designed for communication with Azure. You should use the Azure Powershell task for this kind of script, because it already has the right modules loaded and the authentication prepared.
your script is swallowing the error so it is hiding what went wrong. It's usually more useful not to catch exceptions; if your script is erroring then let it error, and let the pipeline show you in its log what has happened.
we have a problem with a Microsoft bot hosted in Azure.
As long as we haven't resolved it, we want to periodically restart it.
We found 3 sets of powershell commands and spent the full day on it without making it work.
Solution 1:
we found the cmdlets : Get-AzCloudService Restart-AzCloudService.
We didn't understand from the documentation what module to install.
It returns : The term 'Restart-AzCloudService' is not recognized as the name of a cmdlet.
They talk about an obscure "extended support" to have access to it.
Solution 2:
We are able to list the cloud service using:
Connect-AzAccount
get-azresource -name $serviceName -resourcetype
"Microsoft.BotService/botServices"
But we do not find the cmdlet to restart the resource.
Solution 3:
Reset-AzureRoleInstance -serviceName $serviceName -Slot "production" -InstanceName $serviceName
Error : No default subscription has been designated. Use Select-AzureSubscription -Default
We are using MFA. Login-AzureRmAccount systematically fails , evenly saying that our account is disabled.
We did no manager to run the sequence:
Login-AzureRmAccount
Select-AzureSubscription -Default
Reset-AzureRoleInstance -serviceName $serviceName -Slot "production" -InstanceName $serviceName
The idea is to run this script twice a day, either from a VM or from an Azure Runbook.
We managed to run this code using an automation Account but we are still missing the last command that would restart the bot (that we consider a cloud service).
Param()
$automationAccount = "xxx"
$resourceGroup = "xxx"
$serviceName = "xxx"
$subscriptionname ="xxx"
$subscriptionid ="xxx"
# 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-AzureSubscription -SubscriptionId $subscriptionid
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
get-azresource -name $serviceName -resourcetype "Microsoft.BotService/botServices"
I want to deploy app services from Powershell.
I would like to use only publish profile (no password for azure account).
I tried FTP service, but sometimes files are blocked by running users.
I think I have to stop app service.
There is powershell command like:
Publish-AzWebApp
However first I need login with:
Connect-AzAccount
and pass credentials what I want to avoid.
There is any way to call Publish-AzWebApp based on only publish profile (no login by account)?
Connect-AzAccount has other options to login (token or certificate).
Unfortunately I don't know how to generate it.
BTW There was a topic about it:
How do I deploy to Azure App Service with PowerShell?
But it is old and now module "az" is recommended.
There is any way to call Publish-AzWebApp based on only publish profile (no login by account)?
No, you can't. If you want to use the Publish-AzWebApp , you always need to login with Connect-AzAccount, whatever the parameters you use, examples here.
If you want to use powershell to deploy the web app based on only publish profile, the workaround is to use Kudu API via powershell.
$username = "`$webappname"
$password = "xxxxxxx"
# Note that the $username here should look like `SomeUserName`, and **not** `SomeSite\SomeUserName`
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
$userAgent = "powershell/1.0"
$apiUrl = "https://joywebapp.scm.azurewebsites.net/api/zipdeploy"
$filePath = "C:\Users\joyw\Desktop\testdep.zip"
Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST -InFile $filePath -ContentType "multipart/form-data"
You may refer to this tutorial: https://learn.microsoft.com/en-us/powershell/azure/authenticate-azureps?view=azps-2.5.0#sign-in-with-a-service-principal-
Here is the step by step process of deploying and publishing an Azure app service with PowerShell (PS) using newly recommended Az module. You'll have to install Azure CLI before running the scripts:
$subscription = 'Visual Studio Enterprise – MPN' #Change it as per your Azure subscription
$location = 'Central US' #Change it according to the location where you want to host your web app
$resourceGroup = 'MyWebAppResourceGroup'
$ErrorActionPreference = "Stop" #this ensures that script stops executing at first error in the script.
Write-host "Installing nuget package provider"
Install-PackageProvider -Name NuGet -Scope CurrentUser -MinimumVersion 2.8.5.201 -Force
Write-Host "Setting Power Shell gallery"
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
Write-Host "Installing missing PowerShell modules required for running this script.."
if ((Get-InstalledModule -Name "Az.Accounts" -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "Az.Accounts module missing. Now installing..."
Install-Module -Name Az.Accounts -Scope CurrentUser
}
if ((Get-InstalledModule -Name "Az.Websites" -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "Az.Websites module missing. Now installing .."
Install-Module -Name Az.Websites -Scope CurrentUser
}
Write-Host "Installing PowerShell modules completed."
Write-Host "Staring to import PowerShell modules in current session...."
Import-Module Az.websites
Write-Host "Importing PowerShell modules completed."
#This is required due to an issue due to which PowerShell fails to connect with online resources. This issue is machine specific. So you can comment it if not required.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Write-Host "Connecting to Azure account..."
Connect-AzAccount
Write-Host "Setting subscription for current session..."
az account set --subscription $subscription
Write-Host "Creating resource group..."
az group create --name $resourceGroup --location $location
$webAppName="WelcomeCloudApp"
$appServicePlan="WelcomeCloudAppServicePlan"
Write-Host "Creating WebApp Service plan..."
New-AzAppServicePlan -Name $appServicePlan -ResourceGroupName $resourceGroup -Location $location -Tier 'Free' #-Debug
Write-Host "Creating WebApp..."
New-AzWebApp -Name $webAppName -Location $location -AppServicePlan $appServicePlan -ResourceGroupName $resourceGroup
Write-Host "Publishing WebApp..."
Publish-AzWebApp -ResourceGroupName $resourceGroup -Name $webAppName -ArchivePath WelcomeCloudAppService.zip
Write-Host "Finished installing your web app. Bye!"