Fix TOCTOU while checking for container existence in azure_blob_storage

This is a simple time-of-check vs time-of-use, since between checking
does such container exist and creating one, there is a time window.

Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2023-02-07 12:04:16 +01:00
parent 38c001ca42
commit fe832c4418

View File

@ -2,6 +2,7 @@
#if USE_AZURE_BLOB_STORAGE #if USE_AZURE_BLOB_STORAGE
#include <Common/Exception.h>
#include <optional> #include <optional>
#include <re2/re2.h> #include <re2/re2.h>
#include <azure/identity/managed_identity_credential.hpp> #include <azure/identity/managed_identity_credential.hpp>
@ -125,22 +126,23 @@ std::unique_ptr<BlobContainerClient> getAzureBlobContainerClient(
auto blob_service_client = getAzureBlobStorageClientWithAuth<BlobServiceClient>(endpoint.storage_account_url, container_name, config, config_prefix); auto blob_service_client = getAzureBlobStorageClientWithAuth<BlobServiceClient>(endpoint.storage_account_url, container_name, config, config_prefix);
if (!endpoint.container_already_exists.has_value()) try
{ {
ListBlobContainersOptions blob_containers_list_options;
blob_containers_list_options.Prefix = container_name;
blob_containers_list_options.PageSizeHint = 1;
auto blob_containers = blob_service_client->ListBlobContainers().BlobContainers;
for (const auto & blob_container : blob_containers)
{
if (blob_container.Name == endpoint.container_name)
return getAzureBlobStorageClientWithAuth<BlobContainerClient>(final_url, container_name, config, config_prefix);
}
}
return std::make_unique<BlobContainerClient>( return std::make_unique<BlobContainerClient>(
blob_service_client->CreateBlobContainer(container_name).Value); blob_service_client->CreateBlobContainer(container_name).Value);
} }
catch (const Azure::Storage::StorageException & e)
{
/// If container_already_exists is not set (in config), ignore already exists error.
/// (Conflict - The specified container already exists)
if (!endpoint.container_already_exists.has_value() && e.StatusCode == Azure::Core::Http::HttpStatusCode::Conflict)
{
tryLogCurrentException("Container already exist, return existing container");
return getAzureBlobStorageClientWithAuth<BlobContainerClient>(final_url, container_name, config, config_prefix);
}
throw;
}
}
std::unique_ptr<AzureObjectStorageSettings> getAzureBlobStorageSettings(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, ContextPtr /*context*/) std::unique_ptr<AzureObjectStorageSettings> getAzureBlobStorageSettings(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, ContextPtr /*context*/)
{ {