diff options
author | Serge <8523760+sergethedev17@users.noreply.github.com> | 2021-05-15 14:22:50 +0300 |
---|---|---|
committer | Serge <8523760+sergethedev17@users.noreply.github.com> | 2021-05-15 14:22:50 +0300 |
commit | 5b3d85fc2562f37204161a29723bfd2ab7e69c3e (patch) | |
tree | 4efa11a807299b971a7b92ca6c01dcbb0edbd66b /Duplicati/Library | |
parent | 5172119864da59e1e5986b0be33883c4194d82a1 (diff) |
Add authentication using Shared access signature token
Allow users to authenticate using a Shared access signature (SAS) token. SAS tokens are more secure because they:
* have a start and expiry date/time
* can be restricted to specified IP addresses
* can limit access scope to a single Storage blob container
Diffstat (limited to 'Duplicati/Library')
-rw-r--r-- | Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs | 26 | ||||
-rw-r--r-- | Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs | 20 | ||||
-rw-r--r-- | Duplicati/Library/Backend/AzureBlob/Strings.cs | 4 |
3 files changed, 35 insertions, 15 deletions
diff --git a/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs b/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs index 2e3bbf910..6ae9259c5 100644 --- a/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs +++ b/Duplicati/Library/Backend/AzureBlob/AzureBlobBackend.cs @@ -47,23 +47,26 @@ namespace Duplicati.Library.Backend.AzureBlob string storageAccountName = null; string accessKey = null; + string sasToken = null; string containerName = uri.Host.ToLowerInvariant(); if (options.ContainsKey("auth-username")) storageAccountName = options["auth-username"]; if (options.ContainsKey("auth-password")) - accessKey = options["auth-password"];
-
- if (options.ContainsKey("azure_account_name"))
- storageAccountName = options["azure_account_name"];
- else if (options.ContainsKey("azure-account-name"))
+ accessKey = options["auth-password"]; + + if (options.ContainsKey("azure_account_name")) + storageAccountName = options["azure_account_name"]; + else if (options.ContainsKey("azure-account-name")) storageAccountName = options["azure-account-name"]; if (options.ContainsKey("azure_access_key")) - accessKey = options["azure_access_key"];
+ accessKey = options["azure_access_key"]; else if (options.ContainsKey("azure-access-key")) accessKey = options["azure-access-key"]; + if (options.ContainsKey("azure-access-sas-token")) + sasToken = options["azure-access-sas-token"]; if (!string.IsNullOrEmpty(uri.Username)) storageAccountName = uri.Username; if (!string.IsNullOrEmpty(uri.Password)) @@ -73,12 +76,13 @@ namespace Duplicati.Library.Backend.AzureBlob { throw new UserInformationException(Strings.AzureBlobBackend.NoStorageAccountName, "AzureNoAccountName"); } - if (string.IsNullOrWhiteSpace(accessKey)) + if (string.IsNullOrWhiteSpace(accessKey) && string.IsNullOrWhiteSpace(sasToken)) { - throw new UserInformationException(Strings.AzureBlobBackend.NoAccessKey, "AzureNoAccessKey"); + throw new UserInformationException(Strings.AzureBlobBackend.NoAccessKeyOrSasToken, "AzureNoAccessKeyOrSasToken"); } - _azureBlob = new AzureBlobWrapper(storageAccountName, accessKey, containerName); + + _azureBlob = new AzureBlobWrapper(storageAccountName, accessKey, sasToken, containerName); } public string DisplayName @@ -158,6 +162,10 @@ namespace Duplicati.Library.Backend.AzureBlob CommandLineArgument.ArgumentType.Password, Strings.AzureBlobBackend.AccessKeyDescriptionShort, Strings.AzureBlobBackend.AccessKeyDescriptionLong), + new CommandLineArgument("azure-access-sas-token", + CommandLineArgument.ArgumentType.Password, + Strings.AzureBlobBackend.SasTokenDescriptionShort, + Strings.AzureBlobBackend.SasTokenDescriptionLong), new CommandLineArgument("azure-blob-container-name", CommandLineArgument.ArgumentType.String, Strings.AzureBlobBackend.ContainerNameDescriptionShort, diff --git a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs index b05465713..8602a4b41 100644 --- a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs +++ b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs @@ -62,7 +62,7 @@ namespace Duplicati.Library.Backend.AzureBlob } } - public AzureBlobWrapper(string accountName, string accessKey, string containerName) + public AzureBlobWrapper(string accountName, string accessKey, string sasToken, string containerName) { OperationContext.GlobalSendingRequest += (sender, args) => { @@ -73,8 +73,18 @@ namespace Duplicati.Library.Backend.AzureBlob ); }; - var connectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", - accountName, accessKey); + string connectionString; + if (sasToken != null)
+ {
+ connectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};SharedAccessSignature={1}", + accountName, sasToken);
+ } + else
+ {
+ connectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
+ accountName, accessKey);
+ } + var storageAccount = CloudStorageAccount.Parse(connectionString); var blobClient = storageAccount.CreateCloudBlobClient(); @@ -125,8 +135,8 @@ namespace Duplicati.Library.Backend.AzureBlob } } catch - { - // If the metadata fails to parse, return the basic entry + {
+ // If the metadata fails to parse, return the basic entry
} return new FileEntry(Uri.UrlDecode(blobName.Replace("+", "%2B"))); diff --git a/Duplicati/Library/Backend/AzureBlob/Strings.cs b/Duplicati/Library/Backend/AzureBlob/Strings.cs index d23603bfa..487805d36 100644 --- a/Duplicati/Library/Backend/AzureBlob/Strings.cs +++ b/Duplicati/Library/Backend/AzureBlob/Strings.cs @@ -9,7 +9,9 @@ namespace Duplicati.Library.Backend.AzureBlob.Strings { public static string StorageAccountNameDescriptionShort { get { return LC.L(@"The storage account name"); } } public static string AccessKeyDescriptionLong { get { return LC.L(@"The Azure access key which can be obtained by clicking the ""Manage Access Keys"" button on the storage account dashboard"); } } public static string AccessKeyDescriptionShort { get { return LC.L(@"The access key"); } } - public static string NoAccessKey { get { return LC.L(@"No Azure access key given"); } } + public static string SasTokenDescriptionLong { get { return LC.L(@"The Azure shared access signature (SAS) token which can be obtained by selecting the ""Shared access signature"" blade on the storage account dashboard, or inside a container blade"); } } + public static string SasTokenDescriptionShort { get { return LC.L(@"The SAS token"); } } + public static string NoAccessKeyOrSasToken { get { return LC.L(@"No Azure access key or SAS token given"); } } public static string AuthPasswordDescriptionLong { get { return LC.L(@"The password used to connect to the server. This may also be supplied as the environment variable ""AUTH_PASSWORD""."); } } public static string AuthPasswordDescriptionShort { get { return LC.L(@"Supplies the password used to connect to the server"); } } public static string AuthUsernameDescriptionLong { get { return LC.L(@"The username used to connect to the server. This may also be supplied as the environment variable ""AUTH_USERNAME""."); } } |