How to retrieve storage account key using powershell function app? - azure

I'm using powershell function app to retrieve storage account key but i'm not able to access resources .Please help me .
$resourceGroup = "DemoResourceGroup"
$AccountName = "Demo"
$Key = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroup -Name $AccountName)
Write-Host "storage account key 1 = " $Key
I'm getting following error :
2020-05-14T14:00:05Z [Error] ERROR: Get-AzStorageAccountKey : 'this.Client.SubscriptionId' cannot be null.
At D:\home\site\wwwroot\TimerTrigger1\run.ps1:25 char:8
+ $key = Get-AzStorageAccountKey -ResourceGroupName "DocumentParser_FBI ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzStorageAccountKey], ValidationException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Management.Storage.GetAzureStorageAccountKeyCommand
Script stack trace:
at , D:\home\site\wwwroot\TimerTrigger1\run.ps1: line 25
Microsoft.Rest.ValidationException: 'this.Client.SubscriptionId' cannot be null.
at Microsoft.Azure.Management.Storage.StorageAccountsOperations.ListKeysWithHttpMessagesAsync(String resourceGroupName, String accountName, Nullable1 expand, Dictionary2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Azure.Management.Storage.StorageAccountsOperationsExtensions.ListKeysAsync(IStorageAccountsOperations operations, String resourceGroupName, String accountName, Nullable1 expand, CancellationToken cancellationToken)
at Microsoft.Azure.Management.Storage.StorageAccountsOperationsExtensions.ListKeys(IStorageAccountsOperations operations, String resourceGroupName, String accountName, Nullable1 expand)
at Microsoft.Azure.Commands.Management.Storage.GetAzureStorageAccountKeyCommand.ExecuteCmdlet()

According to the script you provide, you use Az module. So if you want to choose which Azure subscription you use, you need to use the command Select-AzSubscription. Besides, you also can add -Subscription "<subscription Id>" in Connect-AzAccoun to ensure when you login, you choose the right subscription.
For example
Create the service principal
Import-Module Az.Resources # Imports the PSADPasswordCredential object
$credentials = New-Object Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential -Property #{ StartDate=Get-Date; EndDate=Get-Date -Year 2024; Password=<Choose a strong password>}
$sp = New-AzAdServicePrincipal -DisplayName ServicePrincipalName -PasswordCredential $credentials
assign the role to the service principal. For example, assign Contributor role to the sp at the subscription level
New-AzRoleAssignment -ApplicationId <service principal application ID> -RoleDefinitionName "Contributor" `
-Scope "/subscriptions/<subscription id>"
Script
$appId = "your sp app id"
$password = "your sp password"
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($appId, $secpasswd)
Connect-AzAccount -ServicePrincipal -Credential $mycreds -Tenant <you sp tenant id>
Get-AzSubscription -SubscriptionName "CSP Azure" | Select-AzSubscription
$resourceGroup = "nora4test"
$AccountName = "qsstorageacc"
$Key = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroup -Name $AccountName)[0].Value
Write-Host "storage account key 1 = " $Key

Related

Creating Azure AD user from Azure Runbook

I'm trying to use an Azure Automation account + accompanying powershell runbook to automate the process of creating an Azure Active Directory user.
When I run the following command, I'm presented with the error, am I trying to achieve the impossible here or is there an easy fix to this problem:
System.Management.Automation.ParameterBindingException: A parameter cannot be found that matches parameter name 'Surname'.
at System.Management.Automation.CmdletParameterBinderController.VerifyArgumentsProcessed(ParameterBindingException originalBindingException)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 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)
My runbook has the following script:
Param
(
[parameter(Mandatory=$true)]
[string] $firstname,
[parameter(Mandatory=$true)]
[string] $lastname,
[parameter(Mandatory=$true)]
[string] $city,
[parameter(Mandatory=$true)]
[string] $phone,
[parameter(Mandatory=$true)]
[string] $pw,
[string]$method,
[string]$UAMI
)
$displayname = $firstname + " " + $lastname
$upn = "$firstname.$lastname" + "#aguafriawindowslive.onmicrosoft.com"
#Secret Password
$secureStrPassword = ConvertTo-SecureString -String $pw -AsPlainText -Force
$automationAccount = "automationaccount01"
# 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
}
#Create User
New-AzADUser -DisplayName $displayname -UserPrincipalName $upn -Surname $lastname -City $city -Password $secureStrPassword -MailNickname $firstname -ForceChangePasswordNextLogin
Insufficient privileges error occurs when you have missed giving role required to do operation on the resources.Ensure that your runbook account has permissions to access any resources used in your script.
Try this:
Go to Azure portal --> Azure AD --> roles and Administrator-->Directory Readers role --> assign this role to the your runbook account name.
or
Try to add the application permissions > Directory.Read.All in for the azure ad App of your automation run as account and also Directory.ReadWrite.All if required and grant admin consent to it.

Download parquet file from ADL Gen2 using Get-AzureStorageBlobContent

I am trying below powershell command to download parquet file from ADL Gen 2 to local system.
Below is the code snippet
#this appid has access to ADL
[string] $AppID = "bbb88818-aaaa-44fb-q2345678901y"
[string] $TenantId = "ttt88888-xxxx-yyyy-q2345678901y"
[string] $SubscriptionName = "Sub Sample"
[string] $LocalTargetFilePathName = "D:\MoveToModern"
Write-Host "AppID = " $AppID
Write-Host "TenantId = " $TenantId
Write-Host "SubscriptionName = " $SubscriptionName
Write-Host "AzureDataLakeAccountName = " AzureDataLakeAccountName
Write-Host "AzureDataLakeSrcFilePath = " $AzureDataLakeSrcFilePath
Write-Host "LocalTargetFilePathName = " $LocalTargetFilePathName
#this is the access key of the appid
$AccessKeyValue = "1234567=u-r.testabcdefaORYsw5AN5"
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Login-AzureRmAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId
Get-AzureRmSubscription
Get-AzureRmSubscription -SubscriptionName $SubscriptionName | Set-AzureRmContext
Get-AzureStorageBlobContent -Container "/Test/Partner/Account/" -Blob "Account.parquet" -Destination "D:\MoveToModern"
But I am getting below error
May be we have to set the storage context. Can you please let me know how to set the storage context with the service principal. (I have app id & app key of service principal. W.r.t ADL Gen2 source, I just have the path details. Source team has provided access to service principal)
If you want to download files from Azure Data Lake Gen2, I suggest you use PowerShell module Az.Storage. Meanwhile, regarding how to implement it with a service principal, you have two choices.
1. Use Azure RABC Role
If you use Azure RABC Role, you need to assign the special role(Storage Blob Data Reader) to the sp.
For example
$AppID = ""
$AccessKeyValue = ""
$TenantId=""
$SubscriptionName = ""
#1. Assign role at the storage account level
#please use owner account to login
Connect-AzAccount -Tenant $TenantId -Subscription $SubscriptionName
New-AzRoleAssignment -ApplicationId $AppID -RoleDefinitionName "Storage Blob Data Reader" `
-Scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>"
# download
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Connect-AzAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId -Subscription $SubscriptionName
$AzureDataLakeAccountName = "testadls05"
$ctx =New-AzStorageContext -StorageAccountName $AzureDataLakeAccountName -UseConnectedAccount
$LocalTargetFilePathName = "D:\test.parquet"
$filesystemName="test"
$path="2020/10/28/test.parquet"
Get-AzDataLakeGen2ItemContent -Context $ctx -FileSystem $filesystemName -Path $path -Destination $LocalTargetFilePathName
Use Access control lists
If you use the method, to grant a security principal read access to a file, you'll need to give the security principal Execute permissions to the container, and to each folder in the hierarchy of folders that lead to the file.
For example
$AppID = ""
$AccessKeyValue = ""
$TenantId=""
$azurePassword = ConvertTo-SecureString $AccessKeyValue -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($AppID, $azurePassword)
Connect-AzAccount -Credential $psCred -ServicePrincipal -Tenant $TenantId
$AzureDataLakeAccountName = "testadls05"
$ctx =New-AzStorageContext -StorageAccountName $AzureDataLakeAccountName -UseConnectedAccount
$filesystemName="test"
$path="2020/10/28/test.parquet"
$LocalTargetFilePathName = "D:\test1.parquet"
Get-AzDataLakeGen2ItemContent -Context $ctx -FileSystem $filesystemName -Path $path -Destination $LocalTargetFilePathName
For more details, please refer to
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control-model
https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-directory-file-acl-powershell

Enable automatic key rotation for keyvault

I've been working on a solution to implement automatic key rotation for a storage account using keyvault. The script I'm using is listed below. The object ID is not a service principal (its my ObjectID).
$resourcegroup = "resourcegroupname"
$saname = "storageaccountname"
$vaultname = "keyvaultname"
$storage = Get-AzureRmStorageAccount -ResourceGroupName $resourcegroup -
StorageAccountName $saname
$userPrincipalId = $(Get-AzureRmADUser -ObjectId "my-object-id").Id
New-AzureRmRoleAssignment -ObjectId $userPrincipalId -RoleDefinitionName
'Storage Account Key Operator Service Role' -Scope $storage.Id
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultname -ObjectId $userPrincipalId - -PermissionsToStorage all
$regenPeriod = [System.Timespan]::FromDays(1)
Add-AzureKeyVaultManagedStorageAccount -VaultName $vaultname -AccountName
$saname -AccountResourceId $storage.Id -ActiveKeyName key2 -RegenerationPeriod $regenPeriod
But then I get the following error
Add-AzureKeyVaultManagedStorageAccount : Key vault service doesn't have proper permissions to access the storage account
https://something.vault.azure.net/storage/something
At line:17 char:1
+ Add-AzureKeyVaultManagedStorageAccount -VaultName $vaultname -Account ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Add-AzureKeyVaultManagedStorageAccount], KeyVaultErrorException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.KeyVault.AddAzureKeyVaultManagedStorageAccount
You also need to assign Storage Account Key Operator Service Role to KeyVault's Service principal on the storage account.
Refer to the documentation here

Export SQL Azure db to blob - Start-AzureSqlDatabaseExport : Cannot convert AzureStorageContainer to AzureStorageContainer

I am using this code found on stack , and all connections are correct.
Import-Module Azure
Import-Module Azure.Storage
Get-AzureRmSubscription –SubscriptionName “Production” | Select-AzureRmSubscription
# Username for Azure SQL Database server
$ServerLogin = "username"
# Password for Azure SQL Database server
$serverPassword = ConvertTo-SecureString "abcd" -AsPlainText -Force
# Establish credentials for Azure SQL Database Server
$ServerCredential = new-object System.Management.Automation.PSCredential($ServerLogin, $serverPassword)
# Create connection context for Azure SQL Database server
$SqlContext = New-AzureSqlDatabaseServerContext -FullyQualifiedServerName “myspecialsqlserver.database.windows.net” -Credential $ServerCredential
$StorageContext = New-AzureStorageContext -StorageAccountName 'prodwad' -StorageAccountKey 'xxxxx'
$Container = Get-AzureStorageContainer -Name 'automateddbbackups' -Context $StorageContext
$exportRequest = Start-AzureSqlDatabaseExport -SqlConnectionContext $SqlContext -StorageContainer $Container -DatabaseName 'Users' -BlobName 'autobackupotest.bacpac' -Verbose -Debug
I am getting this error. I have spent hours on this.
Start-AzureSqlDatabaseExport : Cannot bind parameter 'StorageContainer'. Cannot convert the
"Microsoft.WindowsAzure.Commands.Common.Storage.ResourceModel.AzureStorageContainer" value of type
"Microsoft.WindowsAzure.Commands.Common.Storage.ResourceModel.AzureStorageContainer" to type
"Microsoft.WindowsAzure.Commands.Common.Storage.ResourceModel.AzureStorageContainer".
At line:31 char:99
+ ... SqlConnectionContext $SqlContext -StorageContainer $Container -Databa ...
+ ~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-AzureSqlDatabaseExport], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.WindowsAzure.Commands.SqlDatabase.Database.Cmdlet.StartAzureSqlDatabaseExport
I am using AzureRM 3.8.0
According to your description and codes, If you want to start a new sqldatabase export.I suggest you could try below codes. It will work well.
$subscriptionId = "YOUR AZURE SUBSCRIPTION ID"
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId $subscriptionId
# Database to export
$DatabaseName = "DATABASE-NAME"
$ResourceGroupName = "RESOURCE-GROUP-NAME"
$ServerName = "SERVER-NAME"
$serverAdmin = "ADMIN-NAME"
$serverPassword = "ADMIN-PASSWORD"
$securePassword = ConvertTo-SecureString -String $serverPassword -AsPlainText -Force
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $serverAdmin, $securePassword
# Generate a unique filename for the BACPAC
$bacpacFilename = $DatabaseName + (Get-Date).ToString("yyyyMMddHHmm") + ".bacpac"
# Storage account info for the BACPAC
$BaseStorageUri = "https://STORAGE-NAME.blob.core.windows.net/BLOB-CONTAINER-NAME/"
$BacpacUri = $BaseStorageUri + $bacpacFilename
$StorageKeytype = "StorageAccessKey"
$StorageKey = "YOUR STORAGE KEY"
$exportRequest = New-AzureRmSqlDatabaseExport -ResourceGroupName $ResourceGroupName -ServerName $ServerName `
-DatabaseName $DatabaseName -StorageKeytype $StorageKeytype -StorageKey $StorageKey -StorageUri $BacpacUri `
-AdministratorLogin $creds.UserName -AdministratorLoginPassword $creds.Password
$exportRequest
# Check status of the export
Get-AzureRmSqlDatabaseImportExportStatus -OperationStatusLink $exportRequest.OperationStatusLink
Then you could use Get-AzureRmSqlDatabaseImportExportStatus to see the details information, like below:
I got the same problem after updating some powershell packages which I do not remember exactly. After the update my scripts started to fail.
My solution is :
Install the latest AzureRM from nuget via powershell
Use the other overload of Start-AzureSqlDatabaseExport which utilizes the parameters
-StorageContainerName and -StorageContext rather than -StorageContainer
It looks like if you pass the parameters to the function it will create the container object internally without crashing.

Authenticated with "Login-AzureRmAccount -ServicePrincipal" but no subscription is set?

I've successfully created a self-signed certificate with application & service principle using the New-AzureRmADApplication and New-AzureRmADServicePrincipal cmdlets.
I can execute the login using this command after retrieving the certificate:
Login-AzureRmAccount -ServicePrincipal -CertificateThumbprint $cert.Thumbprint -TenantId $tenantID -ApplicationId $applicationID
However, the SubscriptionId/SubscriptionName attributes of this authentication display as blank:
Environment : AzureCloud
Account : ********************
TenantId : ********************
SubscriptionId :
SubscriptionName :
CurrentStorageAccount :
Subsquently, this command works!
$secret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $keyName
What is confusing to me is that I am able to retrieve a AzureKeyVaultSecret in my DEV subscription, but I do not understand how this cmdlet knows which of my subscriptions to use??? I intend to create the same vault in my PROD subscription, but first need to understand how this ServicePrincipal/Certificate authentication knows which subscription to pull from and/or how to manipulate it?
I can say that when I created the App/ServicePrincipal, I logged in specifying the "DEV" subscription like so:
$subscriptionName = "DEV"
$user = "user#company.com"
$password = "*****"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($user, $securePassword)
Login-AzureRmAccount -Credential $credential -SubscriptionName $subscriptionName

Resources