I would like to move a file within an Azure App Service from a script. I thought that Azure CLI with az webapp command could be used for that, but could not find a way to access the files.
I know that there is Kudu REST API for file access, but I want to run the script during an Azure Devops Pipeline, so authentication for the REST API seems like an issue - I don't want to store the credentials in the pipeline. The same holds for FTP access.
However, there is an Azure CLI task with authorization through configured Service connections, so I thought this might be the way.
So, the core question is - How to move a file within Azure App Service from a command line?
So, it turned out that I can use Azure CLI to get Publishing profile for a particular App service (or even slot) and then use the user name and password from it to access Kudu REST API.
I used this Powershell 6 script
function Get-PublishingProfile($resourceGroupName, $webAppName, $slotName) {
if ([string]::IsNullOrWhiteSpace($slotName)) {
$xml = Get-AzWebAppPublishingProfile -ResourceGroupName $resourceGroupName -Name $webAppName
}
else {
$xml = Get-AzWebAppSlotPublishingProfile -ResourceGroupName $resourceGroupName -Name $webAppName -Slot $slotName
}
return $xml |
Select-Xml -XPath "publishData/publishProfile[1]" |
Select-Object -ExpandProperty Node |
Select-Object -Property publishUrl, msdeploySite, userName, userPWD, destinationAppUrl
}
$profile = Get-PublishingProfile $resourceGroupName $webAppName $slotName
$securePassword = ConvertTo-SecureString -String $profile.userPWD -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($profile.userName, $securePassword)
$fileUri = "https://$($profile.publishUrl)/api/vfs/site/wwwroot/some_file.txt"
$headers = #{
"If-Match" = "*"
}
Invoke-RestMethod -Uri $fileUri -Method Get -Credential $credentials -Authentication Basic -Headers $headers
Related
I have a subscription I want to pause/resume with a PowerShell script (Azure Analysis Services). I use this exact same script to pause my Embedded Capacity and that works fine, but when I run my script for my new subscription it wont work. This is the script I use:
$userPassword = "myappsecret"
$userPassword2 = ConvertTo-SecureString -String $userPassword -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "appid", $userPassword2
Connect-AzAccount -ServicePrincipal -TenantId "tenantid" -Credential $Credential
Select-AzSubscription -SubscriptionId "subscriptionname here"
Get-AzPowerBIEmbeddedCapacity -ResourceGroupName "groupnamehere" -Name "namehere"
Suspend-AzPowerBIEmbeddedCapacity -Name "namehere" -ResourceGroupName "groupnamehere" -PassThru
To check why this won't work I tried to simply use Get-AzSubscription to see if something was wrong and it wont show any subscription.
If I try the same for my Embedded Capacity it works just fine.
What could be wrong?
To get the list of all Azure Ad subscriptions by using Get-AzSubscription, make sure that you have owner/admin role.
You can make use of the below command to get Azure Ad subscriptions for a specific tenant:
Make sure to connect-azaccount with Administrator details.
Get-AzSubscription -TenantId "your_tenant_id"
Get-AzContext command list the information of the Azure Subscription that is currently selected.
To use a specific subscription, you can make use of below command:
Get-AzSubscription -SubscriptionId "xxxx-xxxx-xxxx-xxxx" -TenantId "yyyy-yyyy-yyyy-yyyy" | Set-AzContext
Or please modify your code by adding the below snippet:
$subscriptionId = 'Your_Subscription_ID';
Select-AzSubscription -SubscriptionId $subscriptionId
You can check the Subscription Id via Azure Portal too.
Reference:
Get-AzSubscription (Az.Accounts) | Microsoft Docs
I've got an Automation Account in Azure that runs a Powershell runbook.
It runs perfectly fine when I trigger it via the portal, manually specifying the inputs
I've created a webhook with the same input settings. I call it from CURL like
curl -d '' https://800b2bec-b1ae-4fa1-ba30-8c7d32096828.webhook.ae.azure-automation.net/webhooks?[redactedtoken]
The webhook shows as triggered successfully in the portal, however the job fails with no visible error.
There is no output, even though the first line in my powershell function is Write-Output "Hello"
There are no exception messages, no logs at all.
Any idea how I might get more information as to what might be going wrong?
I've updated the Az modules and enabled verbose logging in the runbook.
Full source below, if it helps.
Param(
[string]$resourceGroup,
[string]$VMName,
[string]$method,
[string]$UAMI
)
Write-Output "Hello"
$automationAccount = "AlsAutomation"
# 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 and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
if ($method -eq "SA")
{
Write-Output "Using system-assigned managed identity"
}
elseif ($method -eq "UA")
{
Write-Output "Using user-assigned managed identity"
# Connects using the Managed Service Identity of the named user-assigned managed identity
$identity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroup `
-Name $UAMI -DefaultProfile $AzureContext
# validates assignment only, not perms
if ((Get-AzAutomationAccount -ResourceGroupName $resourceGroup `
-Name $automationAccount `
-DefaultProfile $AzureContext).Identity.UserAssignedIdentities.Values.PrincipalId.Contains($identity.PrincipalId))
{
$AzureContext = (Connect-AzAccount -Identity -AccountId $identity.ClientId).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
}
else {
Write-Output "Invalid or unassigned user-assigned managed identity"
exit
}
}
else {
Write-Output "Invalid method. Choose UA or SA."
exit
}
# Get current state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName `
-Status -DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Beginning VM status: $status `r`n"
# Start or stop VM based on current state
if($status -eq "Powerstate/deallocated")
{
Start-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext
}
elseif ($status -eq "Powerstate/running")
{
Stop-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext -Force
}
# Get new state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName -Status `
-DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Ending VM status: $status `r`n `r`n"
Write-Output "Account ID of current context: " $AzureContext.Account.Id
We have tested this in our local environment it is working fine, Below statements are based on the analysis.
In our local environment, We have created a Powershell runbook running with different PowerShell Versions 7.1 & Version 5.1.
Using the above share Script & webhook URI, when we are trying to invoke the runbook (PowerShell version 7.1) using the `Invoke-webRequest method it is continuously failing.
Alternatively, We have tried to invoke the runbook (PowerShell version 5.1) using the Invoke-webRequest method it is working fine.
We would suggest you to use Powershell Version 5.1 instead of 7.1 in your Runbook.
Here is the sample Output for reference:
I need help on this scenario. we have a cert in azure key vault which needs to be download to a windows VM for our .net application to run on iis. I am able to upload the cert to Azure keyvault with out issues. I am running a azure devops powershell tasks inline powershell script.
it will connect to azure using conenct-azaccount with appropriate login creds.enter code here
we run invoke-azvmssruncommand and specific the script path and variable which needs to be passed as parameters.
in the PowerShell script we have script to get the cert from azure keyvualt once its connected to azure vm
below is the error
error: an error occurred while sending request. need your thoughts on it.
Invoke-AzVmssVMRunCommand -VMScaleSetName dev-CTUS -ResourceGroupName RG -InstanceId $instanceid -CommandId 'RunPowerShellScript'-ScriptPath "path"\downloadcertfromkeyvault.ps1" -Parameter #{"vaultname"= "keyvault name";"certname"="app-DEV";"password"= "jdksjkdjalksd";"said"="";"sapuserid"; password"="password";"devSubscriptionId"="ZXXXXXXXXXX"} -Debug
this is the command which i used in azure devops powershell inline script .
inside powershell script
$SecurePassword = "$sapassword" | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $said, $SecurePassword
Connect-AzAccount -Credential $Credential -Tenant "XXXXXXXXXXXX-a68c-41e5-XXXXXXXX"
Write-log "setting subscription to retrive certs"
Set-AzContext $devSubscriptionId
$password = "$password"
$password = ConvertTo-SecureString -String "$password" -AsPlainText -Force
$cert = Get-AzKeyVaultCertificate -VaultName $vaultname -Name $certname
$secret = Get-AzKeyVaultSecret -VaultName $vaultname -Name $cert.Name
$pfxpath = [System.Environment]::GetFolderPath("Desktop")
$secretByte = [Convert]::FromBase64String($secret.SecretValueText)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $password)
# Write to a file
[System.IO.File]::WriteAllBytes("$pfxpath\$certname.pfx", $pfxFileByte)
$certificate= Get-ChildItem -path cert:\LocalMachine\My` `
Write-Log $certificate
I have a shell script inside Azure Linux vm. The Azure Linux VM has Sophos installed in it.The shell script can scan the files present in a directory by using savscan command. Challenge is , we are using azure data factory pipeline, which needs to call the azure function. The azure function should be able to ssh to linux vm, and execute the script. The function should pass the parameters like file path for the azure shared file storage where Sophos needs to perform the scan.
I understand thepipeline can call the http triggered azure function. But how can we ssh into a vm and run the scripts remotely from the azure function. Also the parameters for the file path will come from data factory.
inotifywait -mr -e close_write "/xyz/abc/" |
while read dir eve file; do
echo "new file '$path$file' detected - start scan"
savscan -eec $path$file
if [ $? -eq 0 ]
then
echo "1"
else
echo "0"
fi
done
Seems there is something wrong with your ScriptPath param . If you are using Azure Automation, we can't place static script files in it , but we can download our script first and place it in "c:/temp" folder of Azure automation.
I did some tests on my side , I placed my scripts in Azure storage account , before I need to run this script, I will download it to Azure automation temp folder so that I can specify a path to run it .
Try the PS below in Automation:
$appid = "<your Azure application ID>"
$passwd = "<your Azure application password>"
$tenant = "<tenant>"
$storageName = "<storage name>"
$containerName = "<container name>"
$scrtptName = "<script name>"
$storageResourceGroupName = "<storage group name>"
$vmName = "<vm name>"
$VMResourceGroupName = "<vm group name>"
$secpasswd = ConvertTo-SecureString -String $passwd -AsPlainText -Force
$cred = New-Object Management.Automation.PSCredential ($appid , $secpasswd)
login-AzAccount -Credential $cred -Tenant $tenant -ServicePrincipal
$storage = Get-AzStorageAccount -ResourceGroupName $storageResourceGroupName -Name $storageName
Get-AzStorageBlobContent -Container $containerName -Blob $scrtptName -Context $storage.Context -Destination "c:/temp"
$scriptPath = "c:/temp/$scrtptName"
$result = Invoke-AzVMRunCommand -VMname $vmName -ResourceGroupName $VMResourceGroupName -CommandId 'RunPowerShellScript' -ScriptPath $scriptPath
echo $result.Value
Remove-Item $scriptPath -Force
Modules I imported :
I place my script in my storage account, in this case , it is used for download something :
My test script content :
$url = "https://download.microsoft.com/download/1/E/7/1E7B1181-3974-4B29-9A47-CC857B271AA2/English/X64/msodbcsql.msi"
$outpath = "c:/odbc.msi"
Invoke-WebRequest -Uri $url -OutFile $outpath
Test on Azure automation and its result :
As you can see the file has been download successfully .
Btw, there is no need to use remote powershell here , you can use run command feature of Azure VMs to run your scripts on Azure VMs directly .
Nice work Stanley, I will test it too on an Ubuntu Machine. Hope it works :)
I have a script which spins up an Azure VM and specifies an admin username and password.
Is it possible to have the script setup a second admin? The reason for this is so that more than one user can be on the machine at the same time.
Do you have access to the vm with Invoke-Command?
If yes, might this helps: How to Manage Local Users and Groups using PowerShell
According to my research, two users can access Azure windows VM concurrently. A maximum of two concurrent connections are supported unless the server is configured as a Remote Desktop Services session host. Regarding how to add local user to Azure VM, you use the the VM Access extension in Azure PowerShell. For more details, please refer to the document
For example
Connect-AzAccount
$vm = Get-AzVM -ResourceGroupName jimtest -Name jimtest
$name = "jimtest1"
$password = "Pass***!"
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$mycred= New-Object System.Management.Automation.PSCredential ($name, $secpasswd)
Set-AzVMAccessExtension -Credential $mycred -ResourceGroupName $vm.ResourceGroupName -VMName $vm.Name -Location $vm.Location -Name VMAccessAgent -TypeHandlerVersion "2.0"
You can use this PowerShell command below to add an admin account to your VM :
$adminName = "testadmin"
$passstr = "password123!"
$Password = ConvertTo-SecureString -String $passstr -AsPlainText -Force
New-LocalUser $adminName -Password $Password -FullName $adminName -Description "test admin account"
Add-LocalGroupMember -Group "Administrators" -Member $adminName
And you can use the Powershell command below to run your custom Powershell command on your Azure VMs(get started with azure powershell see here):
Connect-AzAccount
$vm = Get-AzVM -Name "<your vm name>" -ResourceGroupName "<your vm resource group>"
Invoke-AzVMRunCommand -VM $vm -CommandId 'RunPowerShellScript' -ScriptPath "<path of adding admin account command>"
so just save the first part command as a .ps1 file , and copy the path as value of you can add an local admin account to your VM.
Result :