Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SAS URL in Read-DbaBackupHeader and Get-DbaBackupInformation #9289

Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions public/Get-DbaBackupInformation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ function Get-DbaBackupInformation {
} else {
ForEach ($f in $path) {
Write-Message -Level VeryVerbose -Message "Not using sql for $f"

if ($f -is [System.IO.FileSystemInfo]) {
if ($f.PsIsContainer -eq $true -and $true -ne $MaintenanceSolution) {
Write-Message -Level VeryVerbose -Message "folder $($f.FullName)"
Expand All @@ -273,6 +274,24 @@ function Get-DbaBackupInformation {
Write-Message -Level VeryVerbose -Message "File"
$Files += $f.FullName
}
} elseif ($f -match "^http") {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can foresee a nice WTF if you call this method with a SAS URL for a container, and you have NOT created the SAS credential in MSSQL, because this method will properly enumerate the individual blobs, but when calling Read-DbaBackupHeader, they are going to get a permission denied issue (I could enumerate, but I could not read them...)

$uri = [System.Uri]$f;
$storageAccountName = $uri.Host.Split('.')[0];
$pathSegments = $uri.AbsolutePath.Trim('/').Split('/');
$containerName = $pathSegments[0];
$prefix = if ($pathSegments.Length -gt 1) { $pathSegments[1] } else { "" }
$sasToken = $uri.Query.TrimStart('?')
$ctx = New-AzStorageContext -StorageAccountName $storageAccountName -SasToken "$sasToken";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the only way I could find to obtain the blobs in a container through powershell, I really don't like the approach but it's the only way I could come up with.

# Get blobs avoiding Archive tier (which needs rehydration before download)
# we could easily filter here by folder, extension, etc. the blob Name contains
# the full path
$baseUrl = "$($uri.Scheme)://$($uri.Host)/$containerName/"
$blobs = Get-AzStorageBlob -Container $containerName -Context $ctx -Prefix $prefix |
Where-Object { ($_.AccessTier -ne 'Archive') -and ($_.Length -gt 0) };
foreach ($blob in $blobs) {
$blobUrl = $baseUrl + $blob.Name + "?" + $sasToken
$Files += $blobUrl;
}
} else {
if ($true -eq $MaintenanceSolution) {
$Files += Get-XpDirTreeRestoreFile -Path $f\FULL -SqlInstance $server -NoRecurse
Expand Down
10 changes: 9 additions & 1 deletion public/Read-DbaBackupHeader.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,15 @@ function Read-DbaBackupHeader {
$restore = New-Object Microsoft.SqlServer.Management.Smo.Restore

if ($DeviceType -eq 'URL') {
$restore.CredentialName = $AzureCredential
if (-not [String]::IsNullOrWhiteSpace($AzureCredential)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deal here is... Read-DbaBackupHeader is actually working right now. If you want to use a SAS URL, you need to remove the SAS from the URL and add the SAS credential in MSSQL. This is here for convenience, you either use an explicit credential or a SAS URL, and if it is a SAS url, MSSQL wants it without the SAS token.

$restore.CredentialName = $AzureCredential
} else {
# If we are restoring with an SAS (Shared Access Signature) the only way to get MSSQL
# to read the headers is to REMOVE the SAS from the URL and register the SHARED ACCESS SIGNATURE credential in MSSQL
# but we cannot rely on this command doing so, so just get rid of the Query String.
# If the SAS crendential is no there the error we get is " Operating system error 86(The specified network password is not correct.)."
$Path = $Path -replace '\?.*'
}
}

$device = New-Object Microsoft.SqlServer.Management.Smo.BackupDeviceItem $Path, $DeviceType
Expand Down
Loading