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,21 +126,22 @@ 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; return std::make_unique<BlobContainerClient>(
blob_containers_list_options.Prefix = container_name; blob_service_client->CreateBlobContainer(container_name).Value);
blob_containers_list_options.PageSizeHint = 1; }
auto blob_containers = blob_service_client->ListBlobContainers().BlobContainers; catch (const Azure::Storage::StorageException & e)
for (const auto & blob_container : blob_containers) {
{ /// If container_already_exists is not set (in config), ignore already exists error.
if (blob_container.Name == endpoint.container_name) /// (Conflict - The specified container already exists)
return getAzureBlobStorageClientWithAuth<BlobContainerClient>(final_url, container_name, config, config_prefix); 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;
} }
return std::make_unique<BlobContainerClient>(
blob_service_client->CreateBlobContainer(container_name).Value);
} }
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*/)