Set-AzureStorageBlobContent does not work in Azure Automation like it does in Azure Cloud Shell - Exact Same Code

Admin DL Shumate 16 Reputation points
2022-08-19T17:01:23.92+00:00

The code below works in Azure Cloud Shell, but does not work in Azure Automation powershell runbook. Same exact admin account is used and modules for all aspects of the code below have been installed as necessary for the runbook.

Connect-azaccount -identity
Get-AzContext -ListAvailable | Where{$_.Name -match <Name of Subscription>} | Set-AzContext

$acctKey = (Get-AzStorageAccountKey -Name <Name of Storage Account> -ResourceGroupName <Name of Resource Group>).Value[0]

$storageContext = New-AzureStorageContext -StorageAccountName <Storage Account Name> -StorageAccountKey $acctKey
$storageContext

$todaydate = Get-Date -Format MM-dd-yy
$LogFull = "AzureScan-$todaydate.log"
$LogItem = New-Item -ItemType File -Name $LogFull

"Test Text to Write" | Out-File -FilePath $LogFull -Append

Set-AzureStorageBlobContent -File $LogFull -Container <Name of Container> -BlobType "Block" -Context $storageContext -Verbose

Why are their differences in how the code performs? How can I get my runbook to run like the Azure Cloud Shell?

Azure Automation
Azure Automation
An Azure service that is used to automate, configure, and install updates across hybrid environments.
1,109 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Admin DL Shumate 16 Reputation points
    2022-08-19T17:08:04.817+00:00

    Error Details:

    Resource group <Name of Resource Group> could not be found.

    System.Management.Automation.RuntimeException: Cannot index into a null array.
    at CallSite.Target(Closure , CallSite , Object , Int32 )
    at System.Dynamic.UpdateDelegates.UpdateAndExecute2T0,T1,TRet
    at System.Management.Automation.Interpreter.DynamicInstruction3.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on parameter 'StorageAccountKey'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. ---> System.Management.Automation.ValidationMetadataException: The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. at System.Management.Automation.ValidateNotNullOrEmptyAttribute.Validate(Object arguments, EngineIntrinsics engineIntrinsics) at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags) --- End of inner exception stack trace --- at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags) at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags) at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags) at System.Management.Automation.CmdletParameterBinderController.BindParameters(UInt32 parameterSets, Collection1 arguments)
    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection1 arguments) at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection1 arguments)
    at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
    at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
    at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
    at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

    Because the Az modules have all the capabilities of AzureRM modules and more, we will retire the AzureRM modules on 29 February 2024. Learn more about the migration to Az: http://aka.ms/azpsmigrate.
    Could not get the storage context. Please pass in a storage context or set the current storage context.

    0 comments No comments

  2. AnuragSingh-MSFT 19,681 Reputation points
    2022-08-23T08:05:56.657+00:00

    Hi @Admin DL Shumate ,

    Thank you for reaching out to Microsoft Q&A for this question.

    I see that you are trying to implement a PS script (which works in Azure cloud shell) as an automation runbook and it is not working as expected. Based on the errors, the following suggestions should help you fix it.

    When you use Connect-azaccount -identity, the runbook uses managed identity of the Automation Account to authenticate with other Azure Services. In cloud shell, it will be your own user account.
    Based on the error Resource group <Name of Resource Group> could not be found., it looks like the managed identity of Automation Account does not have permission to read these details.

    To fix it,

    1. Assign Contributor role to the Azure Automation Account's managed identity on the Azure Automation Account. To do that -

    a. In Azure Portal, go to your Automation Account --> Access control (IAM) --> "+ Add" --> Add role assignment
    b. Select "Contributor" --> Next --> Select "Managed Identity" --> click "Select members" --> search for the Automation Account and select it --> click "Select" --> click "Review + assign"

    The steps above would ensure that managed identity has the permission to read context (Get-AzContext -ListAvailable) and set it correctly. To test that, you can assign the output of this statement to a variable and use write-output to print it out.

    2. I also see that you are using Get-AzStorageAccountKey to get the storage key of the specified storage account. For that to work, the Automation account's managed identity will require respective role assigned to it to be able to read this key. To check role details:

    a. In Azure portal, go to your storage account --> Access Control (IAM) --> "Roles" tab. You can search for the roles available with the description. For current script to work, the automation account's identity will need minimum of "Reader and Data Access" role on the storage account to be able to access keys

    233983-image.png

    Use the steps mentioned in the previous section to assign this role to the Azure Automation's Managed identity.

    Hope this helps!

    ---
    Please 'Accept as answer' and ‘Upvote’ if it helped so that it can help others in the community looking for help on similar topics.

    0 comments No comments