Using Only a SAS Token To Upload in PowerShell - powershell

I have a SAS Token in the form:
https://name.blob.core.windows.net/container?sv=2015-04-05&sr=b&sig=abc123&se=2017-03-07T12%3A58%3A52Z&sp=rw
I am attempting to use an Az Provided Cmdlet in Powershell to upload content to this blob. I am unable to find an API that simply takes the above SAS token and a file to upload.
Reading this reddit post it seems like my options are:
Parse out the StorageAccountName (in the example name), Container (in the example container) and SASToken (in the example above sv=2015-04-05&sr=b&sig=abc123&se=2017-03-07T12%3A58%3A52Z&sp=rw) and then use New-AzStorageContext/Set-AzStorageBlobContent. This more or less is the answer in this StackOverflow Post (Connect to Azure Storage Account using only SAS token?)
Use Invoke-WebRequest or its kin to basically perform the REST call myself.
I would like to use as many Az provided cmdlets possible so starting with option 1, there doesn't seem to be an API to parse this, the closest I can find is this StackOverflow Post (Using SAS token to upload Blob content) talking about using CloudBlockBlob, however it is unclear if this class is available to me in PowerShell.
To these ends I've created a Regex that appears to work, but is most likely brittle, is there a better way to do this?
$SASUri = https://name.blob.core.windows.net/container?sv=2015-04-05&sr=b&sig=abc123&se=2017-03-07T12%3A58%3A52Z&sp=rw
$fileToUpload = 'Test.json'
$regex = [System.Text.RegularExpressions.Regex]::Match($SASUri, '(?i)\/+(?<StorageAccountName>.*?)\..*\/(?<Container>.*)\?(?<SASToken>.*)')
$storageAccountName = $regex.Groups['StorageAccountName'].Value
$container = $regex.Groups['Container'].Value
$sasToken = $regex.Groups['SASToken'].Value
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -SasToken $sasToken
Set-AzStorageBlobContent -File $fileToUpload -Container $container -Context $storageContext -Force
To Restate The Questions
Is there an Az Cmdlet that takes the SAS URI and SAS Token to allow upload?
(If not) Is there an API to parse the SAS URI + SAS Token?

Considering $SASUri is a URI, you can get a System.Uri object using something like:
$uri = [System.Uri] $SASUri
Once you have that, you can get the container name and the SAS token using something like:
$storageAccountName = $uri.DnsSafeHost.Split(".")[0]
$container = $uri.LocalPath.Substring(1)
$sasToken = $uri.Query
After that your code should work just fine:
$storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -SasToken $sasToken
Set-AzStorageBlobContent -File $fileToUpload -Container $container -Context $storageContext -Force

Related

Using SAS token to upload Blob content

I'm having difficulty in using a Blob SAS token to write a file to a Blob in Azure via Powershell.
The code I'm using to generate the SAS token is:
$storageContext = Get-AzureRmStorageAccount -ResourceGroupName $resourceGroup -Name $storageName
$token = New-AzureStorageBlobSASToken -Container $conName -Context $storageContext.Context -Blob $blobName -ExpiryTime $expiry -Permission rw -FullUri
This generates a token as expected: https://name.blob.core.windows.net/container/test.json?sv=2015-04-05&sr=b&sig=abc123&se=2017-03-07T12%3A58%3A52Z&sp=rw
If I use this in the browser it's working fine and downloading the file as expected. However, I can't use this to upload a file. Whenever I try I'm receiving a (403) Forbidden. The code I'm using to upload is:
$accountContext = New-AzureStorageContext -SasToken $sasToken
Get-AzureStorageContainer -Context $accountContext.Context | Set-AzureStorageBlobContent -File $blobFile
I've successfully been using a method similar to this to set Blob content after making a call to Add-AzureRmAccount to authenticate.
I've also tried to use a Container SAS token but I keep getting a 403 error with that.
The fact that the token works for a read leads me to believe that I'm missing something in my Powershell script - can anyone shed any light on what that is?
The fact that the token works for a read leads me to believe that I'm
missing something in my Powershell script - can anyone shed any light
on what that is?
I believe the problem is with the following line of code:
Get-AzureStorageContainer -Context $accountContext.Context
Two things here:
This cmdlet tries to list the blob containers in your storage account. In order to list blob containers using SAS, you would need an Account SAS where as the SAS you're using is a Container SAS.
Your SAS only has Read and Write permission. For listing containers, you would need List permission as well.
I would recommend simply using Set-AzureStorageBlobContent Cmdlet and provide necessary information to it instead of getting the container name through pipeline.
Set-AzureStorageBlobContent -File $blobFile -Container $conName -Context $accountContext.Context -Blob $blobName

Powershell List all tables on Azure Storage

I am trying to automate a query from tables on various Azure Storages.
The tables are automatically generated with a different name every week
I am looking for a way to automatically generate a list of the tables available on a given storage and then I can use the foreach() function to query each table.
I've seen a few bits of scripts here and there but cannot get something effective
for example:
$response = Invoke-WebRequest -Uri 'https://MyAccountName.table.core.windows.net/Tables/'
[xml]$tables = $response.Content
$tableNames = $tables.feed.entry.content.properties.TableName
To fetch the list of tables in your storage account you can use Azure PowerShell Cmdlets. There's absolutely no need to do it via consuming REST API. The Cmdlet you would want to use is Get-AzureStorageTable.
Here's a sample code:
$StorageAccountName = "your storage account name"
$StorageAccountKey = "your storage account key"
$ctx = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
Get-AzureStorageTable -Context $ctx

Azure Storage SAS URL Generation

I would like to have the SAS URL generated for temporary access to use during backup. How could I do this with powershell.
( Note : Posting this as I couldn't find a straight pointer on how to, since from PHP background and other pages talks about generating with console applications and using. )
The MSDN links https://msdn.microsoft.com/en-us/library/dn140255.aspx details the structure of a SAS Url and the same could be generated with cmdlet New-AzureStorageContainerSASToken
$SAStokenURL = New-AzureStorageContainerSASToken -Name $BackupContainerName -Context $context -Permission rwdl -StartTime $now.AddHours(-1) -ExpiryTime $now.AddMonths(1) -FullUri
write-host $SAStokenURL
Where,
$Context is the Storage context
and -FullUri returns the desired URL.
( I might not be complete or missing something and would glad to know further from experts here )
To generate a SAS token for providing temporary access to your Storage account containers/blobs through PowerShell, here are the commands that you can fire up to get things working.
$StartTime - Start time from when you want to the access to be given
$expiryTime - End time till when you want to the access to be given
$sasTokenFullURI = New-AzureStorageContainerSASToken -Name $StorageContainerName -Permission $Permission -StartTime $StartTime -ExpiryTime $expiryTime -Context $context -FullUri
Hope this helps!

How can I call New-AzureStorageContext using -SasToken instead of -StorageAccountKey

Using Azure Powershell v1.3, I'm trying to create a new storage context using an existing Shared Access Signature token which references an existing policy. When I call New-AzureStorageContext with -SasToken and -StorageAccountName I get an error:
PS C:\> $ctx = New-AzureStorageContext -SasToken '?sr=c&sv=2015-02-21&si=ReadOnly&sig=<signature omitted>=&api-version=2015-04-05' -StorageAccountName 'mystorageaccount'
New-AzureStorageContext : An item with the same key has already been added.
At line:1 char:8
I feel like I'm getting the format of the SAS token wrong, or am missing a step or parameter, but there are no examples on what it should look like, and this is the only SAS form I've been able to query from Azure.
Note I don't want to use New-AzureStorageAccountSASToken (which all examples use) because I already have a token, and just want to use it for read-only purposes, so I don't need to use the storage account keys. Creating a new one would require permissions I don't want this client to have.
What is the missing syntax / step?
I think you've discovered a bug in Storage Client Library. I traced the code from PowerShell to Storage Client Library and here's what I found. PowerShell Cmdlet code tries to create a StorageCredentials object by passing this SAS Token.
public StorageCredentials(string sasToken)
{
CommonUtility.AssertNotNullOrEmpty("sasToken", sasToken);
this.SASToken = sasToken;
this.UpdateQueryBuilder();
}
private void UpdateQueryBuilder()
{
SasQueryBuilder newQueryBuilder = new SasQueryBuilder(this.SASToken);
newQueryBuilder.Add(Constants.QueryConstants.ApiVersion, Constants.HeaderConstants.TargetStorageVersion);
this.queryBuilder = newQueryBuilder;
}
Now if you look at the code for UpdateQueryBuilder, it tries to add api-version again without checking if this is already there.
I created an issue on Github for this: https://github.com/Azure/azure-storage-net/issues/259.
It is an old one but now Storage Context is working with SAS:
$resourceGroup="YourResourceGroupName"
$storAccName = "YourStorageAccountName"
# get Storage Key
$storKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroup -Name $storAccName).Value[0]
# create main Storage Context
$storCont = New-AzureStorageContext -StorageAccountName $storAccName -StorageAccountKey $storKey
# create SAS token
$storSAS = New-AzureStorageAccountSASToken -Service Blob, Queue -ResourceType Service, Container, Object -Permission "rwdalucp" -Context $storCont
# create SAS-based Storage Context
$storContSAS = New-AzureStorageContext -StorageAccountName $storAccName -SasToken $storSAS

How to use "Set-AzureStorageFileContent" to upload file to HDInsight?

I think I have setup my powershell environment to connect to my Azure account. I want to upload a file to my HDInsight blob storage. I did:
Set-AzureStorageFileContent -ShareName "what is a share name?" -Source "c:\local.file" -Path "test/"
But I got
Set-AzureStorageFileContent : Can not find your azure storage credential.
Please set current storage account using
"Set-AzureSubscription" or set the "AZURE_STORAGE_CONNECTION_STRING" environment variable.
The help information for Set-AzureSubscription is so useless, I have no idea what it is talking about...
A few things here:
Set-AzureStorageFileContent uploads a file into File Service Share and not Blob Storage. To upload a file into blob storage, you would need to use Set-AzureStorageBlobContent Cmdlet.
I believe the error you're getting is because no storage account is specified. Set-AzureStorageBlobContent cmdlet has a parameter called Context and you would need to specify the context which can do by calling New-AzureStorageContext Cmdlet.
Sample code:
$storageContext = New-AzureStorageContext -StorageAccountName "accountname" -StorageAccountKey "accountkey"
Set-AzureStorageBlobContent -File "full file path" -Container "container name" -BlobType "Block" -Context $storageContext -Verbose
Please note that the container must exist in your storage account which you can create using New-AzureStorageContainer Cmdlet.