Output Azure Function powershell value to azure storage account - powershell

I have a powershell script running in an azure function app that grabs a json list of IPs, parses it and just returns a list of IPs with 1 per line. I need to take this output and save it to a specific azure storage account. I'm attempting to use the static website in the storage account to create an HTTP endpoint for others to retrieve the list of IPs.
Here's the script
# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
#-------------------------------------------------------------------------------------------
$url = "https://ip-ranges.atlassian.com/"
Invoke-RestMethod $url
$iplist = Invoke-RestMethod $url
$iplist.items | select-object -ExpandProperty cidr
out-file $outputBlob
I've tested the function in azure and it runs there just fine. I can't seem to get the integration outputs section of the function app to work. The settings for the outputs is
Binding type - azure blob storage
blob paramter name - outputBlob
Path - test/list.txt
storage account connection - searched and selected the storage account
I am not finding much documentation on how to make my powershell script output to this storage account. The out-file clearly doesn't work.
----------- updated code ----------
Here is the code that now successfully saves the file to a container, but I still cant save to the $web container for the static website. The $ is not something I can use in the output binding
# Input bindings are passed in via param block.
param($Timer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($Timer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function ran! TIME: $currentUTCtime"
#------------------------
$url = "https://ip-ranges.atlassian.com/"
Invoke-RestMethod $url
$call = Invoke-RestMethod $url
$iplist = $call.items | select-object -ExpandProperty cidr
$output = out-string -InputObject $iplist
Push-OutputBinding -Name outputBlob -Value $output
the outputBlob binding is configured under integration > outputs > and the Path which is in the format of container/file. I cannot specify $web/file.txt...but if I do web/file.txt it will create a web container and put the output as file.txt within it. I need to do this, but it must go in the $web container.

This is something that I've been meaning to try for a little while but not actually got around to. Decided to give it a shot today when I seen your question.
So it is possible to push content using the blob output binding but the functionality is limited.
run.ps1
using namespace System.Net
# Input bindings are passed in via param block.
param (
$Request,
$TriggerMetadata
)
# Call the atlassian API to get the address ranges
$atlassianUri = "https://ip-ranges.atlassian.com/"
$iplist = Invoke-RestMethod $atlassianUri -ErrorAction Stop
$cidrList = $iplist.items | select-object -ExpandProperty cidr
# Push the contents to blob storage using the outputBinding
Push-OutputBinding -Name myOutputBlob -Value $cidrList
# Return a simple response so I know it worked
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = 'Successfully Updated Blob Storage'
})
function.json
You would have to include an timer Input Binding in your function but I used HTTP so that I could trigger it on-demand to test that it would work.
I have provided a static path to the blob output binding. The Path property can not be dynamically assigned from within the function yet according to this open GitHub issue.
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "Response"
},
{
"name": "myOutputBlob",
"type": "blob",
"path": "functioncopy/ipRanges.txt",
"connection": "MyStorageConnectionAppSetting",
"direction": "out"
}
]
}
The above code works however when sending the data to the blob file in the storage account Push-OutputBinding serialises the content to a JSON array e.g.
This may or may not work for you in it's current guise but I don't think there is a way using the output binding to just have a raw list.
You could however use the Az.Storage module within your function, create the file within your function execution and upload it that way instead
run.ps1
# Variables required - Fill these out
$storageAccountName = '<Insert Storage Account Here'
$containerName = '<Insert StorageContainer Name Here>'
$resourceGroupName = '<Insert resourceGroup Name Here>'
$subscriptionId = '<Insert subscriptionId Here>'
# Call the atlassian API to get the address ranges
$atlassianUri = "https://ip-ranges.atlassian.com/"
$iplist = Invoke-RestMethod $atlassianUri -ErrorAction Stop
$cidrList = $iplist.items | select-object -ExpandProperty cidr
# New-TemporaryFile uses [System.IO.Path]::GetTempPath() location
$tempFile = New-TemporaryFile
# Set the context to the subscription you want to use
# If your functionApp has access to more than one subscription it will load the first subscription by default.
# Possibly a good habit to be explicit about context.
Set-AzContext -Subscription $subscriptionId
# Get the Storage Account Key to authenticate
$storAccKeys = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
$primaryKey = $storAccKeys | Where-Object keyname -eq 'key1' | Select-Object -ExpandProperty value
# Write the CIDR list to the temp file created earlier
$cidrList | Out-File $tempFile
# Create a Storage Context which will be used in the subsequent commands
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $primaryKey
# Upload the temp file to blob storage
$setAzStorageBlobContentSplat = #{
Container = $containerName
File = $tempFile.FullName
Blob = 'ipranges.txt'
Context = $storageContext
Properties = #{
ContentType = 'text/plain'
}
}
Set-AzStorageBlobContent #setAzStorageBlobContentSplat
# Return a simple response so I know it worked
Push-OutputBinding -Name Response -Value (
[HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = 'Successfully Updated Blob Storage'
}
)
You can see the documentation on Set-AzStorageBlobContent for examples on that here:
https://learn.microsoft.com/en-us/powershell/module/az.storage/set-azstorageblobcontent?view=azps-6.2.1#examples

Related

Azure Function app won't load dependencies

I have checked the requirements.psd1 several times and it all appears right, but the function returns this error when running.
[Warning] The Function app may be missing a module containing the 'Set-AzStorageBlobContent' command definition. If this command belongs to a module available on the PowerShell Gallery, add a reference to this module to requirements.psd1. Make sure this module is compatible with PowerShell 7. For more details, see https://aka.ms/functions-powershell-managed-dependency. If the module is installed but you are still getting this error, try to import the module explicitly by invoking Import-Module just before the command that produces the error: this will not fix the issue but will expose the root cause.
2022-09-13T22:12:00.401 [Error] ERROR: The term 'Set-AzStorageBlobContent' is not recognized as the name of a cmdlet, function, script file, or operable program.Check the spelling of the name, or if a path was included, verify that the path is correct and try again.Exception :Type : System.Management.Automation.CommandNotFoundExceptionErrorRecord :Exception :Type : System.Management.Automation.ParentContainsErrorRecordExceptionMessage : The term 'Set-AzStorageBlobContent' is not recognized as the name of a cmdlet, function, script file, or operable program.Check the spelling of the name, or if a path was included, verify that the path is correct and try again.HResult : -2146233087TargetObject : Set-AzStorageBlobContentCategoryInfo : ObjectNotFound: (Set-AzStorageBlobContent:String)
I am not sure what i'm missing. I've read through other fixes i've found and believe I have it configured correctly. It feels "buggy". Here's my config below:
function.json
{
"bindings": [
{
"name": "Timer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 * * * * *"
}
]
}
host.json
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
}
}
profile.ps1
#if ($env:MSI_SECRET) {
# Disable-AzContextAutosave -Scope Process | Out-Null
# Connect-AzAccount -Identity
#}
requirements.psd1
# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
#{
# For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
# To use the Az module in your function app, please uncomment the line below.
'Az' = '7.*'
'Az.KeyVault' = '4.*'
'Az.Storage' = '4.*'
}
and the script that's running
#---------------------------------------------------------[Variables]------------------------------------------------------------
$storageAccountName = 'storageaccount'
$containerName = '$web'
$logContainerName = 'logfiles'
$subscription = 'Subscription'
$resourceGroupName = 'resourcegroup'
$blob = 'info.txt'
$logBlob = 'info.log'
$uri = "https://api.binaryedge.io/v1/minions"
#----------------------------------------------------------[Execution]-------------------------------------------------------------
# Call the API to get the IP addresses
Try {
$call = Invoke-RestMethod $uri -ErrorAction Stop
$list = $call.scanners
# New-TemporaryFile uses [System.IO.Path]::GetTempPath() location
$tempFile = New-TemporaryFile
# Set the context to the subscription you want to use
# If your functionApp has access to more than one subscription it will load the first subscription by default.
Set-AzContext -Subscription $subscription
# Get the Storage Account Key to authenticate
$storAccKeys = Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
$primaryKey = $storAccKeys | Where-Object keyname -eq 'key1' | Select-Object -ExpandProperty value
# Write the CIDR list to the temp file created earlier
$list | Out-File $tempFile
# Create a Storage Context which will be used in the subsequent commands
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $primaryKey
# Upload the temp file to blob storage
$setAzStorageBlobContentSplat = #{
Container = $containerName
File = $tempFile.FullName
Blob = $blob
Context = $storageContext
Properties = #{
ContentType = 'text/plain'
}
}
Set-AzStorageBlobContent #setAzStorageBlobContentSplat -Force
Write-Host Success!
}
Catch {
Out-Host $_.exception.message
}
Finally {
$time = Get-Date
$tempFile = New-TemporaryFile
"Script last completed at $time" | Out-File $tempFile -Append
$setAzStorageBlobContentSplat = #{
Container = $logContainerName
File = $tempFile.FullName
Blob = $logBlob
Context = $storageContext
Properties = #{
ContentType = 'text/plain'
}
}
Set-AzStorageBlobContent #setAzStorageBlobContentSplat -Force
}
Figured it out. For whatever reason, Connect-AzAccount is now required. Since I used a managed identity, the command to allow the script to run is Connect-AzAccount -Identity. You also need to add Az.Accounts to the requirements.psd1. This was the fix.
In the profile.ps1 file, I also had to uncomment the lines. This is the default, but I did it to get rid of one of the errors.
I will state for the record...several months ago this was NOT a requirement to make a script run. It also wasn't working in the profiles.ps1 file prior to commenting it out either.
I would recommend following the suggestion in the warning message and invoking Import-Module Az.Storage just before Set-AzStorageBlobContent. This will probably not fix the issue, but Import-Module will tell you why it cannot load the module.

Renaming devices in intune via Powershell

I am trying to write a PowerShell script that allows me to update all the names of our devices in Intune [430ish devices] to reflect our asset tags. When they were imported into our tenant, they were given the serialNumber of the device as their deviceName. All permissions for the API have been applied:
API Permissions:
Device Read
Device Read all
DeviceManagementApps.ReadAll
DeviceManagementApps.ReadWriteAll
DeviceManagementConfiguration.ReadAll
DeviceManagementConfiguration.ReadWriteAll
DeviceManagementManagedDevices.PrivilegedOperations.All
DeviceManagementManagedDevices.ReadAll
DeviceManagementManagedDevices.ReadWriteAll
DeviceManagementRBAC.ReadAll
DeviceManagementRBAC.ReadWriteALL
DeviceManagementServiceConfig.ReadAll
DeviceManagementServiceConfig.ReadWriteAll
User Read
This is the code as far as I can get it, but I am still getting the following error [I apologise for ugly or poorly formatted code, I have had no formal training, all learnt using google-fu!]:
# Setting variables for connecting to the MS API
$ApplicationID = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
$TenantDomainName = "contoso.com"
$AccessSecret = Read-Host "Enter Secret"
# Connect to MSGraph command to run
Connect-MSGraph
# Setting the body of the json
$Body = #{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $ApplicationID
Client_Secret = $AccessSecret
}
# Authenticating the connection to MSGraph
$ConnectGraph = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantDomainName/oauth2/v2.0/token" `
-Method POST -Body $Body
$token = $ConnectGraph.access_token
# Importing the CSV of device information
$csvfile = "C:\<Path to file>"
Import-Csv $csvfile | ForEach-Object {
$serialNumber = $_.serialNumber;
$tag = $_.tag;
$deviceId = $serialNumber
Write-Host "Renaming machine from: $deviceID to: $tag" -ForegroundColor Cyan
# Getting the Device from the CSV and then putting it into MSGraph compatible Json
$DeviceToRename = Get-IntuneManagedDevice -Filter ("serialNumber eq '$serialNumber'")
Foreach ($Device in $DeviceToRename) {
$Resource = "deviceManagement/managedDevices('$DeviceId')/setDeviceName"
$graphApiVersion = "Beta"
$uri = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/executeAction"
#This JSON format doesnt work
# $JSONPayload = #"
# { <NEW>
# "body": <NEW>
# {
# action: "setDeviceName",
# actionName: "setDeviceName",
# deviceName: "$tag",
# realaction: "setDeviceName",
# restartNow: false
# }
# } <NEW>
#"#
#Don't know if this works properly either?
$JSONPayload = #"
{
"#odata.type": "#microsoft.graph.managedDevice",
"actionName": "setDeviceName",
"deviceName": "$tag"
}
"#
# Writing out to check if this is working correctly
Write-Host $JSONPayload
# Converting $JSONPayload to an actual workable JSON
$convertedJSON = ConvertTo-Json $JSONPayload
try {
Invoke-MSGraphRequest -Url $uri -HttpMethod PATCH -Body $JSONPayload -ContentType "application/Json" -Verbose
} catch {
# Dig into the exception to get the Response details.
Write-Host "StatusCode:" "$_.Exception.Response.StatusCode.value__"
Write-Host "StatusDescription:" "$_.Exception.Response.StatusDescription"
Write-Host "StatusCode2:" "$_.ErrorDetails.Message"
}
}
}
Error response:
StatusCode: A parameter cannot be found that matches parameter name 'Body'..Exception.Response.StatusCode.value__
StatusDescription: A parameter cannot be found that matches parameter name 'Body'..Exception.Response.StatusDescription
StatusCode2: A parameter cannot be found that matches parameter name 'Body'..ErrorDetails.Message
Thanks
Tom
I had similar problems some months ago manipulating intune devices from an powershell runbook over graph. In my case the json body was the problem. I had to define the body first as hashtable and then convert it to json. Try something like this:
# JSONPayload as hashtable instead of string
$JSONPayload = #{
"#odata.type" = "#microsoft.graph.managedDevice"
"actionName" = "setDeviceName"
"deviceName" = "$tag"
}
# Writing out to check if this is working correctly
$JSONPayload
# Converting $JSONPayload to an actual workable JSON
$convertedJSON = $JSONPayload | ConvertTo-Json
And then pass the $convertedJSON to your graph call as body:
Invoke-MSGraphRequest -Url $uri -HttpMethod POST -Content $convertedJSON -Verbose
EDIT:
You are calling the endpoint /deviceManagement/managedDevices/executeAction with the http method PATCH. According to this ms docs article you have to call the endpoint with the http method POST.

Loop through REST endpoint to read document and write to Azure Blob storage

Using below PowerShell code to read the endpoint and write the result to blob storage. However, if the endpoint has more than one documents. How can we loop through each document and write the result as separate file (file1, file2....) in blob storage. If separate file no possible I am looking to store all document in one JSON file (FILE.JSON).
For example:
endpoint-------------blob storage
doc1-----------------file1.json
doc2-----------------file2.json
and so on
OR above approach not possible then:
doc1, doc2...ALL DOCS========> goes to file.json
#$Credential = Get-Credential
$Params = #{
"URI" = 'https://e832702c-faad-46e5-a585-885b8613c2ce-bluemix.cloudant.com/testdb/_all_docs?include_docs=true'
#"Authentication" = 'Basic'
#"Credential" = $Credential
}
$Result = (Invoke-RestMethod #Params).rows.doc | ConvertTo-Json -Depth 100
Write-Host "the result is :" $Result
$context=New-AzStorageContext -StorageAccountName "genstorage999" -StorageAccountKey "<your key>"
$container=Get-AzStorageContainer -Name "blobcontainer" -Context $context
$content = [system.Text.Encoding]::UTF8.GetBytes($Result)
$container.CloudBlobContainer.GetBlockBlobReference("testapp2.json").UploadFromByteArray($content,0,$content.Length)
Code Reference: Filter JSON ducument using PowerShell
Based on your previous question and your description, there will be some rows in the result data and each row will have a doc. You want to write doc content to separate .json files in storage if there will be multiple rows in the request response. I assume your result data get from this link(a mock API just for demo): https://stantest1016.blob.core.windows.net/static/result.json, and its result contains 2 rows:
You can just try the code below to meet your requirement:
$storageAccountKey= '<your key>'
$context = New-AzStorageContext -StorageAccountName '<account name>' -StorageAccountKey $storageAccountKey
$container = Get-AzStorageContainer -Name 'testc' -Context $context
$result = Invoke-RestMethod -Uri 'https://stantest1016.blob.core.windows.net/static/result.json'
foreach($row in $result.rows){
$destBlobName ="doc_" + $row.doc._id + ".json"
$contentText = $row.doc | ConvertTo-Json -Compress
$container.CloudBlobContainer.GetBlockBlobReference($destBlobName).UploadTextAsync($contentText)
}
Result :
Let me know if you have any other questions.

Create azure dynamic group from azure functions powershell

I am trying to create an azure function that has to create azure dynamic group when i execute the function from MS flow. I am using below code for this purpose.
$groupName = $Request.Query.Name
$groupDesc = $Request.Query.Desc
$domainnames = $Request.Query.DomainName
$dynamicrule = ""
Foreach($domainname in $domainnames.Split(";"))
{
$dynamicrule = $dynamicrule + "(user.userPrincipalName -contains ""_$domainname"") or";
}
$dynamicrule = $dynamicrule -replace ".{2}$"
$dynamicrule = $dynamicrule + "and (user.objectId -ne null)";
New-AzureADMSGroup -DisplayName $groupName -Description $groupDesc -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule $dynamicrule -MembershipRuleProcessingState "On"
When i execute the above command, i am getting below error messgae.
ERROR: The term 'New-AzureADMSGroup' is not recognized as the name of a cmdlet, function, script file, or operable program.Check the spelling of the name, or if a path was included, verify that the path is correct and try again.Exception :Type : System.Management.Automation.CommandNotFoundExceptionErrorRecord
Can sombody please help me on how can i create dynamic groups using azure function app.
Thanks,
Venu
From the error message, you did not install AzureAD powershell module in your function app. And if you want to create a dynamic group, you need to use the -MembershipRule parameter, it is just available in the preview version i.e. AzureADPreview module. Though the doc looks like the parameter is available in AzureAD, but per my test, it is not available.
Actually it is easy to solve the issue, but if you want to create a dynamic group with New-AzureADMSGroup, there will be a few follow-up issues, you could follow the steps below.
1.Navigate to the function app in the portal -> Identity -> enable the system-assigned identity(MSI) for your app.
2.Navigate to App files -> host.json -> make sure the managedDependency is Enabled.
{
"version": "2.0",
"managedDependency": {
"Enabled": true
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
In the requirements.psd1, add the AzureADPreview like below, then it will install the AzureADPreview module for you automatically.
#{
'Az' = '5.*'
'AzureADPreview' = '2.0.2.129'
}
In the profile.ps1, remove all the things and add the lines below, this is used to solve the issue related to AzureAD powershell in function, without it, you will get an error, details here.
$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
3.If you want to use New-AzureADMSGroup to create group in Azure AD, you need the permission in Microsoft Graph, in this case, we use MSI to auth, so use the commands below to give the permission to your MSI.
Run the commands below in local with the Global admin user account, replace <functionapp-name>:
Connect-AzureAD
$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '<functionapp-name>'")
$MSGraphAppId = "00000003-0000-0000-c000-000000000000"
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$MSGraphAppId'"
$PermissionName = "Group.ReadWrite.All"
$AppRole = $GraphServicePrincipal.AppRoles | Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}
New-AzureADServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id
4.After step 2, navigate to the kudu(in the Advanced Tools blade of the function app) -> data -> ManagedDependencies -> click the file with the format like 201208083153165.r(choose the newest one via the Modified time) -> check if the AzureADPreview module was installed successfully like below.
5.After the module was installed, in your function code, use the lines below, in my sample, I use this sample to test directly, you could change the code depends on your requirements, remember to replace 201208083153165.r with yours in step 4, it works fine on my side.
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.Name
if (-not $name) {
$name = $Request.Body.Name
}
$body = "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
if ($name) {
$body = "Hello, $name. This HTTP triggered function executed successfully."
}
$script = {
if ($env:MSI_SECRET) {
Disable-AzContextAutosave -Scope Process | Out-Null
Connect-AzAccount -Identity
}
$context = Get-AzContext
$graphtoken = (Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com").Token
$aadtoken = (Get-AzAccessToken -ResourceUrl "https://graph.windows.net").Token
Import-Module D:\home\data\ManagedDependencies\201208083153165.r\AzureADPreview
Connect-AzureAD -AccountId $context.Account -TenantId $context.Tenant -MsAccessToken $graphtoken -AadAccessToken $aadtoken
New-AzureADMSGroup -DisplayName "joyd1" -Description "Dynamic group created from PS" -MailEnabled $False -MailNickName "group" -SecurityEnabled $True -GroupTypes "DynamicMembership" -MembershipRule "(user.department -contains ""Marketing"")" -MembershipRuleProcessingState "On"
}
&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
Check the group in the portal:

Dynamic user credential generation with Powershell for Basic Auth Implementation

Requirement: Would like to have basic auth setup using custom php script.
Would like to :
Create user credentials dynamically
Create the cred php file with these credentials updated
Update the username & password to respective for Azure WebApp settings.
[ Note: FTPing the cred and auth files automatically if missing would be in upcoming post ]
Tools & Pre-requisites :
Azure Powershell 4.0+
Windows Powershell ISE
Knowledge of Storage Account ( Name, RG's )
Knowledge of WebApp for which backup is desired ( WebApp Name and RG )
Valid & Active Azure portal / AD login credentials
RESULT : On Azure Portal, The webapp in focus would have 'global_cred' variable key set with credentials generated stored as its value in application settings section as [username:password] format.
#######################
# Function to Generate dynamic 22char random string for password use
# Call custom function to write php constants for basic auth
Function writeFocusDomainCredFile{
param( $configObject, $hash, $farmprojectname )
#setting auth username:password
$configObject.authPasswordKey = (Get-RandomAlphanumericString -length 22 | Tee-Object -variable teeTime )
$hash['global_cred'] = [String]( $configObject.authUsernameKey + ':' + $configObject.authPasswordKey )
$prfilename = ( $configObject.ftpappdirectory + '\cred.php')
writeProjectBasicAuthCredOnNew -filename $prfilename -configObject $configObject
}
##########################
# Function to write the credentials to cred php file for basic auth use
# This file with other dependent files could be automatically ftp'd.
# Would share in another post
Function writeProjectBasicAuthCredOnNew{
param( $filename
,$configObject
)
writeDeployFileFiltersForDomain -ReportFileName $filename
Add-Content $filename ( "<?php" )
Add-Content $filename ("define('WPIZED_AUTH_USER', '" + $configObject.authUsernameKey + "');");
Add-Content $filename ("define('WPIZED_AUTH_PASS', '" + $configObject.authPasswordKey + "');");
}
###################################################################################################
# Configure Below as You prefer or desire #
$properties = #{
'ResourceName' = "AzureAppName";
'myResourceGroupName' = "{App Resource Group Name}";
'mySubscriptionName' = "{subscription name}";
'adminEmail' = "H.Bala#volunteering.com";
'ResourceGroupLocation' = "East US";
'authUsernameKey' = 'HBalaUsername'; #For this post, using fixed username as 'HBalaUsername'
'authPasswordKey' = '';
'PathFormatDate' = Get-Date -UFormat "%Y_%m_%d";
}
$configObject = New-Object –TypeName PSObject –Prop $properties
Write-Output $configObject
#Login cmdlet for active session
Login-AzureRmAccount
Get-AzureRmSubscription –SubscriptionName $configObject.mySubscriptionName | Select-AzureRmSubscription
(Get-AzureRmContext).Subscription
Select-AzureRMSubscription -SubscriptionName $configObject.mySubscriptionName
#Pull the Webapp details and configuration
$webApp = Get-AzureRMWebApp -ResourceGroupName $configObject.myResourceGroupName -Name $configObject.ResourceName
#Pull the Application Listing Environment / Configuration Variables
$appSettingList = $webApp.SiteConfig.AppSettings
$hash = #{}
ForEach ($kvp in $appSettingList) {
$hash[$kvp.Name] = $kvp.Value
}
writeFocusDomainCredFile -configObject $configObject -hash $hash
#[FTP Deploy Logic of this file and other basic auth or files shall cover in seperate topic ]
#[ Only setting the generated Credentials and saving to Application setting focused here ]
Set-AzureRMWebApp -ResourceGroupName $configObject.myResourceGroupName -Name $configObject.ResourceName -AppSettings $hash
Disclaimer: The intention is to share to another newbie who might find this helpful.