Download parquet file from ADL Gen2 using Get-AzureStorageBlobContent - azure

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

Related

How do I connect to Azure through PowerShell Modules, using the Service principal of a Registered App?

I need to create a powershell script that queries Azure Resources.
What I have is an App Registration.
App Registrations give us the following information:
# --- APP REGISTRATION OUTPUT
# appId = "***** APP ID *******"
# displayName = "**** APP Name **** "
# password = "***** SECRET *******"
# tenant = "**** TENANT ID *****"
I need to use these credentials to now access Azure via PowerShell script.
I have tried the following:
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPassword
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential
But I get an error:
… Account -ServicePrincipal -TenantId $TenantId -Credential $Credential
| ~~~~~~~~~~~
| Cannot bind argument to parameter 'Credential' because it is null.
I don't think what Im doing is abnormal. App Registrations give us the ability to allow Apps (PowerShell Apps!) to interact with a given tenant. Or am I mistaken?
I don't want the app to login every time using an account (i.e. To have a browser window open whenever the script runs).
What am I doing wrong?
You have missed converting your password into secure string. You could verify that in your $credential variable.
$ApplicationId = "0000-0000-0000-0000"
$Password = "000000000000000"
$TenantId = "0000-0000-000-000"
$subscriptionId = "0000-0000-0000-0000"
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecuredPassword
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential
$sub = Get-AzSubscription -SubscriptionId $subscriptionId
Set-AzContext -Subscription $sub
I have reproduced in my environment and below script worked for me :
$appId ="53f3ed85-70c1c2d4aeac"
$pswd="55z8Q~_N9SRajza8R"
$t = "72f988bf-cd011db47"
[ValidateNotNullOrEmpty()]$pswd="55z8BU4oik.kVrZWyaK8R" $sp = ConvertTo-SecureString -String $pswd -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $appId, $sp
Connect-AzAccount -ServicePrincipal -TenantId $t -Credential $Credential
Output:
You need to convert the secret value(password) into secured password like above, then it will work as mine worked.

PowerShell - How do I bulk upload Certificates to an Azure App Registration Certificate store?

As you can see from the code below I can upload on certificate at a time, but the problem is it wipes out all of the existing certificates when doing so.
$Tenant_ID = '00000000-0000-0000-0000-000000000000'
$Subscription_ID = '00000000-0000-0000-0000-000000000000'
$Azure_PassWord = (Get-StoredCredential -Target 'Domain' -Type Generic -AsCredentialObject).Password
$UserName = "$($env:USERNAME)#Google.com"
$EncryptedPassword = ConvertTo-SecureString $Azure_PassWord -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PsCredential($UserName,$EncryptedPassword)
$AzureConnection = (Connect-AzAccount -Credential $Credential -Tenant $Tenant_ID -Subscription $Subscription_ID -WarningAction 'Ignore').context
$AzureContext = (Set-AzContext -SubscriptionName $Subscription_ID -DefaultProfile $AzureConnection)
$Application_ID = '00000000-0000-0000-0000-000000000000'
$PFX_FileName = "Azure_Dev_V2"
$Cert_Password = "123456"
$Cert_Password = ConvertTo-SecureString -String $Cert_Password -Force -AsPlainText
$CurrentDate = Get-Date
$EndDate = $CurrentDate.AddYears(10)
$certificatePath = "C:\FilePath\Certificates\Certs\$($PFX_FileName).pfx" # OR Get-ChildItem -Path cert:\localmachine\my\$($Certificate_Thumbprint)
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2($certificatePath, $Cert_Password)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
$Azure_App_Registration = Get-AzADApplication -ApplicationId $Application_ID -DefaultProfile $AzureContext
New-AzADAppCredential -ApplicationObject $Azure_App_Registration -CertValue $keyValue -EndDate $EndDate -StartDate $CurrentDate
Connect-AzAccount -Subscription $Subscription_ID -ApplicationId $Azure_App_Registration.AppId -Tenant $Tenant_ID -CertificateThumbprint $cert.Thumbprint | Out-Null
Get-AzADAppCredential -ApplicationId $Azure_App_Registration.AppId | Where-Object {$_.DisplayName -match "CN=Azure_Dev_V2"}
In the Azure portal multiple certificates can be uploaded manually, and they will not delete the existing certificates.
EDIT: If bulk upload is not possible then how would I go about making sure the existing certificates that are in the Azure AD App Registration cert store do not get deleted ?
Thanks in Advance.

Download parquet file from ADL Gen2 using powershell

I am using below powershell command to download TSV file from ADL to local system and it works absolutely fine
#this appid has access to ADL
[string] $AppID = "bbb88818-aaaa-44fb-q2345678901y"
[string] $TenantId = "ttt88888-xxxx-yyyy-q2345678901y"
[string] $SubscriptionName = "Sub Sample"
[string] $AzureDataLakeAccountName = "sample.blob.core.windows.net"
[string] $AzureDataLakeSrcFilePath = "/accounts/sample/test.tsv"
[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
Export-AzureRmDataLakeStoreItem -AccountName $AzureDataLakeAccountName -Path $AzureDataLakeSrcFilePath -Destination $LocalTargetFilePathName -Force
But when I replace sourcefile path with value /accounts/sample/test-V4.parquet, I get below error:
ADLSException: Error in getting metadata for path /accounts/Partner/Non-PII/Account/Account-V4.parquet.
Operation: GETFILESTATUS failed with HttpStatus:Forbidden Error: Unexpected error in JSON parsing of the error stream. Content-Type of error response: application/xml.
ExceptionType: Newtonsoft.Json.JsonReaderException ExceptionMessage: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
AuthenticationFailedServer failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:de2e4b16-001e-002e-625f-c92785000000
Can you please let me know how can I download parquet file from ADL Gen2 using powershell.
According to the information you provide, you do not have enough permissions to do that. So you get Forbidden error. If you want to download a file from Azure data lake store with a service principal, we need to grant the security principal read access to the file and give the security principal Execute permissions to the container and each folder in the hierarchy of folders that lead to the file.
For example
Please check it and set the right ACL. Regarding how to do that, please refer to here
If you want to download files from Azure Data Lake Gen2, I suggest you use PowerShell module Az.Storage. For more details, please refer to here
For example
Configure ACL for the service principal.
If you want to download a file from Azure data lake Gen2 with a service principal, we need to grant the security principal read access to the file and give the security principal Execute permissions to the container and each folder in the hierarchy of folders that lead to the file. Regarding how to configure it, please refer to here.
Script
$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 = ""
$ctx =New-AzStorageContext -StorageAccountName $AzureDataLakeAccountName -UseConnectedAccount
$filesystemName="<your container name>"
$path="<your blob name>"
$LocalTargetFilePathName = ""
Get-AzDataLakeGen2ItemContent -Context $ctx -FileSystem $filesystemName -Path $path -Destination $LocalTargetFilePathName

where azure snapshots are stored with this script

I found this blog post
https://www.techmanyu.com/automate-disk-snapshots-azure/
And the author showes this script.
$clientID = "<client id>"
$key = "<client secret>"
$SecurePassword = $key | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $clientID, $SecurePassword
Add-AzureRmAccount -Credential $cred -Tenant "<Tenant ID>" -ServicePrincipal;
$disks=Get-AzureRmDisk | Select Name,Tags,Id,Location,ResourceGroupName ;
foreach($disk in $disks) { foreach($tag in $disk.Tags) { if($tag.Snapshot -eq 'True') {$snapshotconfig = New-AzureRmSnapshotConfig -SourceUri $disk.Id -CreateOption Copy -Location $disk.Location -AccountType PremiumLRS;$SnapshotName=$disk.Name+(Get-Date -Format "yyyy-MM-dd");New-AzureRmSnapshot -Snapshot $snapshotconfig -SnapshotName $SnapshotName -ResourceGroupName $disk.ResourceGroupName }}}
Trying to understand the script, I came up with the question, where are the snapshots stored? In the same managed disk as the VM disk?
After executing the script, it will create the snapshots that you can check them in the portal, they have the resource type of Microsoft.Compute/snapshots.
Essentially, they should be stored in the blob storage. Navigate to the snapshot in the portal -> Export, then you will find it generates a SAS token of the snapshot like https://md-nxxxqz.blob.core.windows.net/wxxxxxx0m/abcd?sv=2017-04-17&sr=b&si=31b3d91b-51be-4c1c-930e-996f382b8ad9&sig=xxxxxx. The md-nxxxqz is the storage account which stores the snapshots, it is managed by Azure.

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