How to make an Azure app registration with platform SPA via Powershell - azure

We use PowerShell to set up an Azure deployment, which, among other Azure resources, creates an app registration.
The simplified code is as follows:
$appRegistration = New-AzADApplication `
-DisplayName $applicationName `
-HomePage "$webAppUrl" `
-IdentifierUris "api://$webAppName";
To it, we add redirect uris, like this:
if ($redirectUris -notcontains "$webAppUrl") {
$redirectUris.Add("$webAppUrl");
Write-Host "Adding $webAppUrl to redirect URIs";
}
if ($redirectUris -notcontains "$webAppUrl/aad-auth") {
$redirectUris.Add("$webAppUrl/aad-auth");
Write-Host "Adding $webAppUrl/aad-auth to redirect URIs";
}
Update-AzADApplication `
-ApplicationId $applicationId `
-IdentifierUris "api://$applicationId" `
-ReplyUrl $redirectUris | Out-Null
This works great, and an app registration with the "web" platform is created. It looks like this:
My question is how can we get these redirect uris to be under the "SPA" platform, using PowerShell? Like in the image below, which was done manually on the Portal.

Looks there is no feature in the built-in command to do that, you could call the MS Graph - Update application in the powershell directly.
You could refer to the sample below work for me, make sure your service principal/user acount logged in Az via Connect-AzAccount has the permission to call the API.
$objectId = "xxxxxxxxxxxxxxxx"
$redirectUris = #()
$webAppUrl = "https://joyweb.azurewebsites.net"
if ($redirectUris -notcontains "$webAppUrl") {
$redirectUris += "$webAppUrl"
Write-Host "Adding $webAppUrl to redirect URIs";
}
if ($redirectUris -notcontains "$webAppUrl/aad-auth") {
$redirectUris += "$webAppUrl/aad-auth"
Write-Host "Adding $webAppUrl/aad-auth to redirect URIs";
}
$accesstoken = (Get-AzAccessToken -Resource "https://graph.microsoft.com/").Token
$header = #{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer ' + $accesstoken
}
$body = #{
'spa' = #{
'redirectUris' = $redirectUris
}
} | ConvertTo-Json
Invoke-RestMethod -Method Patch -Uri "https://graph.microsoft.com/v1.0/applications/$objectId" -Headers $header -Body $body
Check the result in the portal:

There was a similar thread where someone was trying to programmatically add the redirect URIs for SPA and could not do it because it defaults under the Web section.
He was able to resolve this by posting with Azure CLI to the Graph API:
az rest `
--method PATCH `
--uri 'https://graph.microsoft.com/v1.0/applications/{id}' `
--headers 'Content-Type=application/json' `
--body "{spa:{redirectUris:['http://localhost:3000']}}"

Related

In azure can we update the profile.ps1 file function app?

We have a function in azure portal. When we create function app, we can see the profile.ps1 in App Files section of a function App. Can we edit this profile.ps1 file using PowerShell or CLI commands. If Yes, please help me out.
Any help can be appriciated...!
In this case, your option is to use Kudu API via powershell to update the profile.ps1, in my sample, I store the new profile.ps1 with the path C:\Users\Administrator\Desktop\profile.ps1 in local, it works fine on my side.
Sample:
$appsvWebAppName = "<functionapp-name>"
$resourceGroupName = "<group-name>"
$resource = Invoke-AzResourceAction -ResourceGroupName $resourceGroupName -ResourceType Microsoft.Web/sites/config -ResourceName "$appsvWebAppName/publishingcredentials" -Action list -ApiVersion 2018-02-01 -Force
$username = $resource.Properties.publishingUserName
$password = $resource.Properties.publishingPassword
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
$userAgent = "powershell/1.0"
$apiUrl = "https://$appsvWebAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/profile.ps1"
$filePath = "C:\Users\Administrator\Desktop\profile.ps1"
$headers = #{
'Authorization' = 'Basic ' + $base64AuthInfo
'If-Match' = '*'
}
Invoke-RestMethod -Uri $apiUrl -Headers $headers -UserAgent $userAgent -Method PUT -InFile $filePath -ContentType "multipart/form-data"
Check in the portal:

Disable AFD Backend Pool's Backend Host with Azure Cli or Azure REST API

Im trying to update an existing backend host of a AFD backend pool to have its status from Enabled to Disabled.
Is there a way to update existing backend host of Front Door backend pools?
currently, i can only see add, list and remove in the following azure front door cli docs:
az network front-door backend-pool backend add
az network front-door backend-pool backend list
az network front-door backend-pool backend remove
Is there one for update?
I've also looked into the Azure REST API docs and have not found an endpoint to update a backend host of AFD backend pools.
I am able to achieve your ask using PowerShell.
Here is the script:
$resourceGroup1 = "frontdoor"
$frontDoor1 = "msrini"
$afd = Get-AzFrontDoor -ResourceGroupName $resourceGroup1 -name $frontDoor1
$loadBalancingSetting1=$afd.LoadBalancingSettings
$afd.BackendPools.backends[0].EnabledState = "Disabled"
$backendpool1=$afd.BackendPools
$frontendEndpoint1 = $afd.FrontendEndpoints
$healthProbeSetting1= $afd.HealthProbeSettings
$routingrule1 = $afd.RoutingRules
$backendpoolsettings1 = $afd.BackendPoolsSetting
Set-AzFrontDoor -Name $frontDoor1 -ResourceGroupName $resourceGroup1 -RoutingRule $routingrule1 -BackendPool $backendpool1 -FrontendEndpoint $frontendEndpoint1 -LoadBalancingSetting $loadBalancingSetting1 -HealthProbeSetting $healthProbeSetting1 -BackendPoolsSetting $backendpoolsettings1
I was able to resolve my issue, the below script requires using azure cli with a logged in service principle.
Param(
[string]$desiredState, #"Enabled" or "Disabled"
[string]$frontDoorName,
[string]$resourceGroupName,
[string]$targetBackendPool,
[string]$targetBackendHost
)
# Get Access Token
$token = az account get-access-token | ConvertFrom-Json
$accessToken = $token.accessToken
$subscriptionId = $token.subscription
$tenantId = $token.tenant
$uri = "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.Network/frontDoors/$($frontDoorName)?api-version=2019-05-01"
$headers = #{ "Authorization" = "Bearer $accessToken" }
$contentType = "application/json"
# Get AFD Configuration.
Write-Host "Invoking Azure REST API to get AFD configuration"
$afdConfig = Invoke-WebRequest -method get -uri $uri -headers $headers | ConvertFrom-Json
# Edit AFD Configuration to toggle backend host state
Write-Host "Checking BackendHost: $targetBackendHost In Backend Pool: $targetBackendPool"
foreach ($backendPool in $afdConfig.properties.backendPools) {
if ($backendPool.name -eq $targetBackendPool) {
foreach ($backends in $backendPool.properties.backends) {
if ($backends.address -eq $targetBackendHost) {
$currentState = $backends.enabledState
Write-Host "Current State of $targetBackendHost is $currentState"
if ($currentState -eq $desiredState) {
Write-Host "$targetBackendHost is already in the desired state of $desiredState"
exit
}
$backends.enabledState = $desiredState
Write-Host "$targetBackendHost Updated to $desiredState."
}
}
}
}
$updateRequest = $afdConfig | ConvertTo-Json -Depth 100
# Update AFD Configuration.
Write-Host "Invoking Azure REST API to update AFD configuration"
Invoke-WebRequest -method put -uri $uri -headers $headers -ContentType $contentType -body $updateRequest
# Poll current state until the change has been fully propogated in azure
Write-Host "Polling AFD until update is complete."
do {
$afdConfig = Invoke-WebRequest -method get -uri $uri -headers $headers | ConvertFrom-Json
foreach ($backendPool in $afdConfig.properties.backendPools) {
if ($backendPool.name -eq $targetBackendPool) {
foreach ($backends in $backendPool.properties.backends) {
if ($backends.address -eq $targetBackendHost) {
$currentState = $backends.enabledState
}
}
}
}
Write-Host "$targetBackendHost is currently in $currentState"
Start-Sleep -Seconds 1
} until ($currentState -eq $desiredState)
Write-Host "$targetBackendHost has successfully been updated to $desiredState"
I did it using Powershell
$FrontDoor = Get-AzFrontDoor -ResourceGroupName "FrontDoorResourceGroupName" -Name "FrontDoorName"
$FrontDoor.BackendPools.Backends[0].EnabledState = "Disabled"
Set-AzFrontDoor -InputObject $FrontDoor

Create azure application through Az module and assign API permissions using powershell

I have written a script which creates azure application using Az module, creates secret key, assigns owner. But assigning API permission gives insufficient permission error. The user is an admin user. Still unable to assign API permission. What wrong am I doing?
$ErrorActionPreference = 'Stop'
Connect-AzAccount
Import-Module Az.Resources
$tenant = Get-AzTenant
Set-AzContext -TenantId $tenant.Id
$AppName = Read-Host -Prompt 'Enter Application name '
$myApp = New-AzADApplication -DisplayName $AppName -IdentifierUris "http://$AppName.com"
Write-Host "App registered.."
$sp = New-AzADServicePrincipal -ApplicationId $myApp.ApplicationId -Role Owner
Write-Host "Service principal registered.."
$startDate = Get-Date
$endDate = $startDate.AddYears(100)
$secret = Read-Host -Prompt 'Enter App Secret Key ' -AsSecureString
$secPassword = ConvertTo-SecureString -AsPlainText -Force -String $secret
New-AzADAppCredential -ObjectId $myApp.ObjectId -StartDate $startDate -EndDate $endDate -Password $secPassword
$ResourceAppIdURI = "https://graph.windows.net/"
# $authority = "https://login.microsoftonline.com/$tenant/oauth2/v2.0/token"
$authority = "https://login.windows.net/$tenant/oauth2/token"
$ClientCred = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList $myApp.ApplicationId, $secret
$AuthContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority,$false
$AuthContext.TokenCache.Clear()
Start-Sleep -Seconds 10
$Token = $Authcontext.AcquireTokenAsync($ResourceAppIdURI, $ClientCred)
$AuthHeader = #{"Authorization" = $Token.Result.CreateAuthorizationHeader();"Content-Type"="application/json"}
$url = "https://graph.windows.net/$tenant/applications/$($myApp.ObjectID)?api-version=1.6"
Write-Host "URL: " $url
$postData = "{`"requiredResourceAccess`":[{`"resourceAppId`":`"00000003-0000-0000-c000-000000000000`",
`"resourceAccess`":[{`"id`":`"e1fe6dd8-ba31-4d61-89e7-88639da4683d`",`"type`":`"Scope`"}]}]}";
$result = Invoke-RestMethod -Uri $url -Method "PATCH" -Headers $AuthHeader -Body $postData
Write-Host "Result of App API permission: " $result
In my case, the easiest way to do this without messing around with http requests, was to combine the Azure-powershell module and the Az cli module
So, once I have created my new app:
$myApp = New-AzADApplication -DisplayName $AppName -IdentifierUris "http://$AppName.com"
Then I would login into azure using the Az Cli, and, for instance:
Add some api permissions
Grant these permissions directory admin consent ( if needed )
. { $azcliLogin = az login }
. { az account set --subscription $config.subscriptionId }
. { az ad app permission add --id $myApp.appid --api 00000002-0000-0000-c000-000000000000 --api-permissions 78c8a3c8-a07e-4b9e-af1b-b5ccab50a175=Role }
. { $appApiGrant = az ad app permission grant --id $config.azureAccess.appid --api 00000002-0000-0000-c000-000000000000 }
. { az ad app permission admin-consent --id $myApp.appid }
Where:
--api 00000002-0000-0000-c000-000000000000 Refers to Microsoft Graph API
--api-permissions 78c8a3c8-a07e-4b9e-af1b-b5ccab50a175=Role Refers to some role on this api, as Directory.ReadWrite.All
You can get the required API and API-PERMISSIONS guids from the App manifiest in Azure
This way you create the app with the required granted api permissions, in a single powershell script.
If you want to call Azure AAD graph API to assign permissions with OAuth 2.0 client credentials flow, we need to provide enough permissions(Azure AD Graph -> Aapplication permissions -> Application.ReadWrite.All)
Besides, regarding how to assign permissions to AD application with PowerShell, we also can use PowerShell module AzureAD.
For example
Connect-AzureAD
$AppAccess = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]#{
ResourceAppId = "00000003-0000-0000-c000-000000000000";
ResourceAccess =
[Microsoft.Open.AzureAD.Model.ResourceAccess]#{
Id = "";
Type = ""},
[Microsoft.Open.AzureAD.Model.ResourceAccess]#{
Id = "";
Type = ""}
}
Set-AzureADApplication -ObjectId <the app object id> -RequiredResourceAccess $AppAccess
Update
According to my test, when we use Az module, we can use the following method to get access token and call AAD graph rest API. But please note that when you use the method, the account you use to run Connect-AzAccount should be Azure AD Global Admin
Connect-AzAccount
$context =Get-AzContext
$dexResourceUrl='https://graph.windows.net/'
$token = [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, $dexResourceUrl).AccessToken
# assign permissions
$headers =#{}
$headers.Add("Content-Type", "application/json")
$headers.Add("Accept", "application/json")
$headers.Add("Authorization", "Bearer $($token)")
$body = "{
`n `"requiredResourceAccess`": [{
`n `"resourceAppId`": `"00000003-0000-0000-c000-000000000000`",
`n `"resourceAccess`": [
`n {
`n `"id`": `"405a51b5-8d8d-430b-9842-8be4b0e9f324`",
`n `"type`": `"Role`"
`n },
`n {
`n `"id`": `"09850681-111b-4a89-9bed-3f2cae46d706`",
`n `"type`": `"Role`"
`n }
`n ]
`n }
`n ]
`n}
`n"
$url ='https://graph.windows.net/hanxia.onmicrosoft.com/applications/d4975420-841f-47d5-a3d2-0870901f13cd?api-version=1.6'
Invoke-RestMethod $url -Method 'PATCH' -Headers $headers -Body $body
#check if adding the permissions you need
$headers =#{}
$headers.Add("Accept", "application/json")
$headers.Add("Authorization", "Bearer $($token)")
$url ='https://graph.windows.net/hanxia.onmicrosoft.com/applications/<aad application object id>?api-version=1.6'
$response=Invoke-RestMethod $url -Method 'GET' -Headers $headers
$response.requiredResourceAccess | ConvertTo-Json

Can you download an Azure Blob using Virtual Machine Identity Access Token through PowerShell without using Access Keys

I'm setting up a VM to do some bootstrapping on creation.
Part of this is to download a blob from an azure storage account to the VM.
These are all in the same subscription, resource group, etc.
I can do it this way fine:
function Get-BlobUsingVMIdentity
{
param(
[Parameter(Mandatory = $true)] $containerName,
[Parameter(Mandatory = $true)] $blobName,
[Parameter(Mandatory = $true)] $outputFolder
)
write-host "Defining package information"
mkdir $outputFolder -force
write-host "Getting Instance meta data"
$instanceInfo = Invoke-WebRequest -UseBasicParsing -Uri 'http://169.254.169.254/metadata/instance/?api-version=2018-02-01' `
-Headers #{Metadata="true"} `
| select -expand content `
| convertfrom-json `
| select -expand compute
$storageAccountName = "$($instanceInfo.resourceGroupName.replace('-rg',''))sa" # This is custom since we know our naming schema
$resourceGroupName = $($instanceInfo.resourceGroupName)
$subscriptionId = $($instanceInfo.subscriptionId)
write-host "Got storageAccountName [$storageAccountName], resourceGroupName [$resourceGroupName], subscriptionId [$subscriptionId]"
write-host "Getting VM Instance Access Token"
$response = Invoke-WebRequest -UseBasicParsing -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' `
-Headers #{Metadata = "true" }
$content = $response.Content | ConvertFrom-Json
$access_token = $content.access_token
write-host "Getting SAS Token From Storage Account"
$params = #{canonicalizedResource = "/blob/$($storageAccountName)/$($containerName)"; signedResource = "c"; signedPermission = "rcw"; signedProtocol = "https"; signedExpiry = "2031-09-23T00:00:00Z" }
$jsonParams = $params | ConvertTo-Json
$sasResponse = Invoke-WebRequest -UseBasicParsing -Uri "https://management.azure.com/subscriptions/$($subscriptionId)/resourceGroups/$($resourceGroupName)/providers/Microsoft.Storage/storageAccounts/$($storageAccountName)/listServiceSas/?api-version=2017-06-01" `
-Method POST `
-Body $jsonParams `
-Headers #{Authorization="Bearer $access_token"}
$sasContent = $sasResponse.Content | ConvertFrom-Json
$sasCred = $sasContent.serviceSasToken
write-host "Manually download blob"
$params = #{signedResource = "c"; signedPermission = "rcw"; signedProtocol = "https"; signedExpiry = "2031-09-23T00:00:00Z" }
$jsonParams = $params | ConvertTo-Json
$sasResponse = Invoke-WebRequest -UseBasicParsing -Uri "https://$($storageAccountName).blob.core.windows.net/$($containerName)/$($blobName)?api-version=2017-06-01" `
-Method POST `
-Body $jsonParams `
-Headers #{Authorization="Bearer $access_token"}
$sasContent = $sasResponse.Content | ConvertFrom-Json
$sasCred = $sasContent.serviceSasToken
write-host "Setting up storage context"
$ctx = New-AzStorageContext -StorageAccountName $storageAccountName -SasToken $sasCred
write-host "Downloading package"
Get-AzStorageBlobContent `
-Blob $blobName `
-Container $containerName `
-Destination $outputFolder `
-Context $ctx `
-Force
}
This works fine, except I have to grant full/write access to the identity in order for it to use the access key.
Is there a similar approach that would allow read only access to the blob?
My goals are:
1. No credentials stored anywhere
2. Download blob to VM from azure storage
3. No statically defined variables (ex: subscriptionid)
4. Read only access to the blob/storage account.
Appreciate any help!
According to my understanding, you want to use Azure VM MSI to access Azure storage. If so, please refer to the following steps:
Enable a system-assigned managed identity on a VM
Connect-AzAccount
$vm = Get-AzVM -ResourceGroupName myResourceGroup -Name myVM
Update-AzVM -ResourceGroupName myResourceGroup -VM $vm -AssignIdentity:$SystemAssigned
Grant your VM access to an Azure Storage container
Connect-AzAccount
$spID = (Get-AzVM -ResourceGroupName myRG -Name myVM).identity.principalid
New-AzRoleAssignment -ObjectId $spID -RoleDefinitionName "Storage Blob Data Reader" -Scope "/subscriptions/<mySubscriptionID>/resourceGroups/<myResourceGroup>/providers/Microsoft.Storage/storageAccounts/<myStorageAcct>/blobServices/default/containers/<container-name>"
access blob
# get AD access token
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' `
-Headers #{Metadata="true"}
$content =$response.Content | ConvertFrom-Json
$access_token = $content.access_token
# call Azure blob rest api
$url="https://<myaccount>.blob.core.windows.net/<mycontainer>/<myblob>"
$RequestHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$RequestHeader.Add("Authorization", "Bearer $access_token")
$RequestHeader.Add("x-ms-version", "2019-02-02")
$result = Invoke-WebRequest -Uri $url -Headers $RequestHeader
$result.content
Update
According to my test, when we get token to access Azure blob, we need to change resouce as https://storage.azure.com/
# get AD access token
$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://storage.azure.com/' `
-Headers #{Metadata="true"}
$content =$response.Content | ConvertFrom-Json
$access_token = $content.access_token
# call Azure blob rest api
$url="https://<myaccount>.blob.core.windows.net/<mycontainer>/<myblob>"
$RequestHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$RequestHeader.Add("Authorization", "Bearer $access_token")
$RequestHeader.Add("x-ms-version", "2019-02-02")
$result = Invoke-WebRequest -Uri $url -Headers $RequestHeader
$result.content
Update
Found a much easier way to do it!
The key was to use:
Connect-AzAccount -identity
This auto logs in a the identity and allows you to interact through AZ module instead of trying to hack API calls together.
You only need [Storage Blob Data Reader] assigned to the container to pull this off.
Working example looks like this:
function Get-BlobUsingVMIdentity
{
param(
[Parameter(Mandatory = $true)] $containerName,
[Parameter(Mandatory = $true)] $blobName,
[Parameter(Mandatory = $true)] $outputFolder
)
write-host "Get instance info"
$instanceInfo = Invoke-WebRequest -UseBasicParsing -Uri 'http://169.254.169.254/metadata/instance/?api-version=2018-02-01' `
-Headers #{Metadata="true"} `
| select -expand content `
| convertfrom-json `
| select -expand compute
$storageAccountName = "$($instanceInfo.resourceGroupName.replace('-rg',''))sa" # This is custom since we know our naming schema
write-host "Clear existing identies to keep cache fresh"
Clear-AzContext -force
write-host "Authenticate using identity"
$account = Connect-AzAccount -identity
if(-not $account.Context.Subscription.Id)
{
write-error "Failed to authenticate with identity. Ensure VM has identity enabled and is assigned the correct IAM roles"
return
}
write-host "Get storage context"
$ctx = New-AZStorageContext -StorageAccountName $storageAccountName
write-host "Getting blob"
Get-AzStorageBlobContent `
-Blob $blobName `
-Container $containerName `
-Destination $outputFolder `
-Context $ctx `
-Force
}
Get-BlobUsingVMIdentity `
-containerName "deploy" `
-blobName "deploy.zip" `
-outputFolder "c:\deploy\"

Forced Conversion from AzureRM to AZ powershell

We have found that our AzureRM scripts have started to fail with Request to a Error downlevel service failed. This has forced us to change our scripts to start using the AZ powershell module, https://learn.microsoft.com/en-us/powershell/azure/new-azureps-module-az?view=azps-1.6.0. The conversion has worked really well except I haven't found the replacement for New-AzureWebsiteJob. Has anyone else run into this?
For New-AzureWebsiteJob cmdlet, there is no direct equivalent in the Az or ARM PowerShell Cmdlets.
You can follow this blog to achieve your purpose, and note that if you are using Az powershell module, please modify ARM Powershell to Az powershell respectively.
Sample code for Az powershell like below:
#Resource details :
$resourceGroupName = "<Resourcegroup name>";
$webAppName = "<WebApp name>";
$Apiversion = 2015-08-01
#Function to get Publishing credentials for the WebApp :
function Get-PublishingProfileCredentials($resourceGroupName, $webAppName){
$resourceType = "Microsoft.Web/sites/config"
$resourceName = "$webAppName/publishingcredentials"
$publishingCredentials = Invoke-AzResourceAction -ResourceGroupName $resourceGroupName -ResourceType
$resourceType -ResourceName $resourceName -Action list -ApiVersion $Apiversion -Force
return $publishingCredentials
}
#Pulling authorization access token :
function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName){
$publishingCredentials = Get-PublishingProfileCredentials $resourceGroupName $webAppName
return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f
$publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
}
$accessToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppname
#Generating header to create and publish the Webjob :
$Header = #{
'Content-Disposition'='attachment; attachment; filename=Copy.zip'
'Authorization'=$accessToken
}
$apiUrl = "https://$webAppName.scm.azurewebsites.net/api/<Webjob-type>/<Webjob-name>"
$result = Invoke-RestMethod -Uri $apiUrl -Headers $Header -Method put -InFile "<Complete path of the file>\
<filename>.zip" -ContentType 'application/zip'

Resources