Argument not serializable PowerShell - azure

I have a strange error, I'm running a PowerShell script in DevOps and at the end I want the contents sent to a storage account, I use the snippet below, which works in PowerShell ISE
$strgrg = "storage-rg"
$StorageAccountName = "storageaccount2021"
$ContainerName = "container1"
$Filename = "nsg.txt"
$endtime = (get-date).AddHours("2")
$ctx = (Get-AzStorageAccount -ResourceGroupName $strgrg -Name $StorageAccountName).context
$StorageAccountKey = New-AzStorageContainerSASToken -Context $ctx -Name $ContainerName -Permission racwdl -ExpiryTime $endtime
Set-AzStorageBlobContent -file ./$Filename -Container $ContainerName -Blob $Filename -Context $ctx -force
The error I get is:
WARNING: System.ArgumentException: Argument passed in is not serializable.
Parameter name: value at System.Collections.ListDictionaryInternal.set_Item(Object key, Object value)
at Microsoft.WindowsAzure.Commands.Common.MetricHelper.PopulatePropertiesFromQos(AzurePSQoSEvent qos, IDictionary`2 eventProperties, Boolean populateException)
at Microsoft.WindowsAzure.Commands.Common.MetricHelper.LogUsageEvent(AzurePSQoSEvent qos)
I put some debugging in and it looks like the error occurs after $endtime = (get-date).AddHours("2") when it's running the following line, but that seems fine $ctx = (Get-AzStorageAccount -ResourceGroupName $strgrg -Name $StorageAccountName).context
Can anyone see where I've gone wrong?
Thanks in advance :)

Related

How to convert JSON file content into Powershell object in Powershell runbook?

I'm trying to convert JSON file which is present in storage account data into Powershell object. But I'm not getting the proper output. Output does not contain proper values.
My code:
$storageAccountKey = "xxxx"
$Context = New-AzStorageContext -StorageAccountName 'xxxx' -StorageAccountKey $storageAccountKey
$b='C:\Temp\Scheduled.json'
Get-AzureStorageFileContent -Path $b -ShareName "file-share-name"
$newScheduledRules = Get-Content -Raw $b | ConvertFrom-Json
Write-Output ("########newScheduledRules::###########" + $newScheduledRules)
Output:
Could not get the storage context. Please pass in a storage context or set the current storage context.
########newScheduledRules::############{Scheduled=System.Object[]; Fusion=System.Object[]; MLBehaviorAnalytics=System.Object[]; MicrosoftSecurityIncidentCreation=System.Object[]}
I have reproduced in my environment and got expected results as below and followed below process and followed Microsoft-Document:
Scheduled.json:
{
"Rithwik":"Hello",
"Chotu":"Bojja"
}
Firstly, I have created Storage account and then added a Scheduled.json in file share as below:
Now i have created a runbook and excuted below script in runbook as below:
$storageAccountKey = "PFHxFbVmAEvwBM6/9kW4nORJYA+AStA2QQ1A=="
$Context = New-AzStorageContext -StorageAccountName 'rithwik' -StorageAccountKey $storageAccountKey
$out = "$($env:TEMP)\$([guid]::NewGuid())"
New-Item -Path $out -ItemType Directory -Force
Get-AzStorageFileContent -ShareName "rithwik" -Context $Context -Path 'Scheduled.json' -Destination $out -Force
$newScheduledRules = Get-Content -Path "$out\Scheduled.json" -Raw | ConvertFrom-Json
Write-Output ("########newScheduledRules::###########" + $newScheduledRules)
Output:
Here $out is the Destination Variable.
-Path should be Only the file name Scheduled.json in
Get-AzStorageFileContent command.
It seems the Get-AzureStorageFileContent is missing -Context parameter. It should be something like this
$OutPath = "$($env:TEMP)\$([guid]::NewGuid())"
New-Item -Path $OutPath -ItemType Directory -Force
$storageContext = (Get-AzStorageAccount -ResourceGroupName xxxx -Name xxxx).Context
Get-AzStorageFileContent -ShareName "file-share-name" -Context $storageContext -Path 'Scheduled.json' -Destination $OutPath -Force
$newScheduledRules = Get-Content -Path "$OutPath\Scheduled.json" -Raw | ConvertFrom-Json
Write-Output ("########newScheduledRules::###########" + $newScheduledRules)

Convert output of a command or script in a custom single line

Above hyperlink is the output image.
Hi All,
I want to convert the whole output in a single line result in powershell.Below is my code,
$containername = "testoutput"
$storageAccKey = (Get-AzStorageAccountKey -ResourceGroupName
$rgname -AccountName $storageAccountName)[0].value
$storagecontext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccKey
New-AzStorageContainer -Name $containername -Context $storagecontext -Permission Off
Write-Output "Container $($containername) created"
Assuming that this is what you're looking for:
$containername = "testoutput"
$storageAccountName = "teststorage001"
$storageAccKey = (Get-AzStorageAccountKey -ResourceGroupName $rgname -AccountName $storageAccountName)[0].value
$storagecontext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccKey
$result = New-AzStorageContainer -Name $containername -Context $storagecontext -Permission Off
Write-Host "Container $($containername) created in Storage Account-"$($result.Name)",PublicAccess-"$($result.PublicAccess)",LastModified-"$($result.LastModified)""
Either Write-Host or Write-Output can be used. The multiple lines you're seeing is the result of New-AzStorageContainer. Now, I have assigned it to a variable called $result and used in Write-Output.
One way to achieve your requirement is to use if-else condition and check New-AzStorageContainer -Name $containername -Context $storagecontext -Permission Off doesn't result null. Below is the complete code that worked for me.
$rgname = "<YOUR_RESOURCE_GROUP>"
$containername = "<YOUR_CONTAINER_NAME>"
$storageAccountName = "<YOUR_STORAGE_ACCOUNT>"
$storageAccKey = (Get-AzStorageAccountKey -ResourceGroupName $rgname -AccountName $storageAccountName)[0].value
$storagecontext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccKey
if((New-AzStorageContainer -Name $containername -Context $storagecontext -Permission Off) -ne $null){
Write-Output "Container $($containername) created"
}else{
Write-Output "Container $($containername) Not created"
}
RESULTS:

Encrypt Azure Storage account key in powershell script

I'm developing a new powershell script in order to download any blobs from a specific container and the problem is due to security reasons because I do not want to paste in text plain the azure account key.
So I have implemented a solution using 'ConvertTo-SecureString' command but the problem still exists because when I create a connection string to the blob, there appears a message who said: "Server Failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. HTTP Status Code 403 - HTTP Error".
With the key in plain text I'm able to create the connection string properly and then list and download all blobs from the container.
I tried other solutions for example ' $Credential= New-Object System.Management.Automation.PSCredential ('$ShareUser, $SharePassword)'
but there is other problem related with the input is not valid base64 string.
Do you know how to avoid this issues and create a secure connection string with an Azure Storage Account?
Best regards and thanks in advance
Here a part of my powershell script
$SecurePassword= Read-Host -AsSecureString | ConvertFrom-SecureString
$SecurePassword | Out-File -FilePath C:\test_blob\pass_file.xml
$ConfigFile= 'C:\Users\\config_file.xml'
IF (Test-Path) {
[xml]$Config= Get-Content $ConfigFile
[string] $Server = $Config.Config.Server;
[string] $SharePassword = $Config.Config.SharePassword;
} ELSE
{
write-host "File do not exists: $ConfigFile"
}
#BlobStorageInformation
$StorageAccountName='test_acc'
$Container='test'
$DestinationFolder= 'C:\Users\user1\Blobs'
$Context = New-AzStorageConext -StorageAccountName $StorageAccountName -StorageAccountKey $SharePassword
#List of Blobs
$ListBlob=#()
$ListBlob+= Get-AzStorageBlob -context $Context -container $Container | Where-Object {$_.LastModified -lt (Get-Date).AddDAys(-1)}
Why would you maintain the password files or enter storage key manually when you have az powershell. Just login using az powershell, set the subscription and enjoy !
$ResourceGroupName = "YOURRESOURCEGROUPNAME"
$StorageAccountName = "YOURSTORAGEACCOUNTNAME"
$ContainerName = "YOURCONTAINERNAME"
$LocalPath = "D:\Temp"
Write-Output 'Downloading Content from Azure blob to local...'
$storageKey = (Get-AzStorageAccountKey -ResourceGroupName $ResourceGroupName -AccountName $StorageAccountName).value[0]
$storageContext = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $storageKey
$blobs = Get-AzStorageBlob -Container $ContainerName -Context $storageContext
foreach($blob in $blobs)
{
Get-AzStorageBlobContent -Container $ContainerName -Context $storageContext -Force -Destination $LocalPath -Blob $blob.Name
}
Write-Output 'Content Downloaded Successfully !!!'

Showing all the blobs from multiple storage containers in Azure using powershell

I am trying to list all the blobs from various containers that i have in an Azure storage account using powershell
So i run the below commands :
$storageAccountName = "contoso"
$resourceGroup = "Contoso-Rg"
$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroup -Name $storageAccountName).Value[0]
$context=New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountkey
$containerName = Get-AzStorageContainer -Context $context
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName
$ctx = $storageAccount.Context
$containerName | ForEach-Object { Get-AzStorageBlob -Container $_ -Context $ctx }
When i run the last command it throws me the error as shown in the screenshot. Any idea what i am doing wrong and how to fix this
Instead of passing $_ to '-contianer' flag you need to pass $_.Name to container parameter in foreach-object.
Posting making the above changes to the shared script we are able to pull all the bolbs inside the container.
Here is the modified script :
$storageAccountName = "<strgAccountName>"
$resourceGroup = "<rgName>"
$storageAccountKey = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroup -Name $storageAccountName).Value[0]
$context=New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountkey
$containerName = Get-AzStorageContainer -Context $context
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName
$containerName | ForEach-Object { Get-AzStorageBlob -Container $_.Name -Context $context }
Here is the sample output for reference:

Azure PowerShell Download blob contents from container

I'm trying to download sme blob files from an azure storage account.
There are a mix of other containers and blockblobs in the parent container, I need to download just the blockblobs and not the other containers, I can't find a way of seperating them out, also I need to download some blobs from a conatiner within a container.
My code will download all the contents in the parent blob, including all sub containers.
$sub = "MySub"
$staccname = "straccname1234"
$key = "sdcsecurekeythinghere"
$ctx = New-AzureStorageContext -StorageAccountName $staccname `
-StorageAccountKey $key
$cont = "data\download\files.001" ##the container includes other cntainers and subcontainers
$dest = "C:\blb-Downloads"
Select-AzureSubscription -SubscriptionName $sub –Default
Set-AzureSubscription -Currentstaccname $staccname -SubscriptionName $sub
Get-AzureStorageBlob -Container $cont -Context $ctx
$blobs = Get-AzureStorageBlob -Container $cont -Context $ctx
$blobs | Get-AzureStorageBlobContent –Destination $dest -Context $ctx
There are approx 75 files in the parent blob and 123 files in data\downloads.
Using the newer Azure PowerShell Az module, you can use Get-AzStorageBlob to list all the block blobs from the container, then use Get-AzStorageBlobContent to download the blobs.
As already shown by #George Wallace, we can use Where-Object or its alias ? to filter block blob types.
Demo:
$resourceGroup = "myResourceGroup"
$storageAccount = "myStorageAccount"
$container = "myContainerName"
$destination = "./blobs"
# Create destination directory if it doesn't exist
if (-not (Test-Path -Path $destination -PathType Container)) {
New-Item -Path $destination -ItemType Directory
}
# Get storage account with container we want to download blobs from
$storageAccount = Get-AzStorageAccount -Name $storageAccount -ResourceGroupName $resourceGroup
# Get all BlockBlobs from container
$blockBlobs = Get-AzStorageBlob -Container $container -Context $storageAccount.Context
| Where-Object {$_.BlobType -eq "BlockBlob"}
# Download each blob from container into destination directory
$blockBlobs | Get-AzStorageBlobContent -Destination $destination -Force
Can you not just run the following and limit it to BlockBlobs only?
Get-AzureStorageBlob -Container $cont -Context $ctx | ? {$_.BlobType -eq "BlockBlob"}
This works for me
$storageaccountname = "jawadtestsaacc"
$sastoken = ""
$ContainerName = "access"
$Ctx = New-AzStorageContext -StorageAccountName $storageaccountname -SasToken $sastoken
Get-AzStorageBlob -Container "$ContainerName" -Blob "Az.json" -Context $Ctx | Get-AzStorageBlobContent
or
Get-AzStorageBlobContent -Container "$ContainerName" -Blob "Az.json" -Context $Ctx

Resources