# HG changeset patch # User Alain Mazy # Date 1617348652 -7200 # Node ID 1691da4ae9c356c911b2b11d719e55a81ca7eb20 # Parent f10874e13d11726e7ead1e23cd6d0e4aab8a2d84# Parent 3b8fab63313d53cba42abb08a4eec63530a39bca merge patch-azure: 'create container if not exists' option diff -r f10874e13d11 -r 1691da4ae9c3 Aws/CMakeLists.txt diff -r f10874e13d11 -r 1691da4ae9c3 Azure/AzureBlobStoragePlugin.cpp --- a/Azure/AzureBlobStoragePlugin.cpp Fri Mar 19 17:40:12 2021 +0100 +++ b/Azure/AzureBlobStoragePlugin.cpp Fri Apr 02 09:30:52 2021 +0200 @@ -23,6 +23,7 @@ #include #include #include "cpprest/rawptrstream.h" +#include "cpprest/details/basic_types.h" // Create aliases to make the code easier to read. @@ -161,11 +162,32 @@ return "Azure Blob Storage"; } +bool isSasTokenAccountLevel(utility::string_t sasToken) +{ + // Use cpprestsdk's utility::string_t here since the expected argument is the return value of + // as::storage_credentials::sas_token(), which is type utility::string_t + size_t newIdx = 0; + size_t prevIdx = 0; + while ((newIdx = sasToken.find('&', prevIdx)) != utility::string_t::npos) + { + utility::string_t kvpair = sasToken.substr(prevIdx, newIdx-prevIdx); + prevIdx = newIdx + 1; // start next time from char after '&' + + size_t equalsIdx = kvpair.find('='); + utility::string_t key = kvpair.substr(0, equalsIdx); + if (key == "srt") // only account SAS has this parameter + return true; + } + + return false; +} + IStoragePlugin* AzureBlobStoragePluginFactory::CreateStoragePlugin(const OrthancPlugins::OrthancConfiguration& orthancConfig) { std::string connectionString; std::string containerName; bool enableLegacyStorageStructure; + bool createContainerIfNotExists; if (orthancConfig.IsSection(PLUGIN_SECTION)) { @@ -191,6 +213,8 @@ boost::trim(connectionString); // without that, if there's an EOL in the string, it fails with "provided uri is invalid" boost::trim(containerName); + + createContainerIfNotExists = pluginSection.GetBooleanValue("CreateContainerIfNotExists", true); } else if (orthancConfig.IsSection("BlobStorage")) // backward compatibility with the old plugin: { @@ -223,6 +247,8 @@ std::ostringstream connectionStringBuilder; connectionStringBuilder << "DefaultEndpointsProtocol=https;AccountName=" << accountName << ";AccountKey=" << accountKey; connectionString = connectionStringBuilder.str(); + + createContainerIfNotExists = pluginSection.GetBooleanValue("CreateContainerIfNotExists", true); } else { @@ -243,12 +269,21 @@ as::cloud_blob_container blobContainer = blobClient.get_container_reference(utility::conversions::to_string_t(containerName)); OrthancPlugins::LogInfo("Accessing blob container"); - // Return value is true if the container did not exist and was successfully created. - bool containerCreated = blobContainer.create_if_not_exists(); + // blobContainer.create_if_not_exists() throws an error if a service SAS (for a blob container) + // was used in the connectionString. + // Only allow the use of this function when using storage account-level credentials, whether + // through accountName/accountKey combo or account SAS. + if ((storageAccount.credentials().is_account_key() || + (storageAccount.credentials().is_sas() && isSasTokenAccountLevel(storageAccount.credentials().sas_token()))) + && createContainerIfNotExists) + { + // Return value is true if the container did not exist and was successfully created. + bool containerCreated = blobContainer.create_if_not_exists(); - if (containerCreated) - { - OrthancPlugins::LogWarning("Blob Storage Area container has been created. **** check in the Azure console that your container is private ****"); + if (containerCreated) + { + OrthancPlugins::LogWarning("Blob Storage Area container has been created. **** check in the Azure console that your container is private ****"); + } } OrthancPlugins::LogInfo("Blob storage initialized"); diff -r f10874e13d11 -r 1691da4ae9c3 Azure/CMakeLists.txt diff -r f10874e13d11 -r 1691da4ae9c3 Google/CMakeLists.txt