Skip to content

Commit

Permalink
apacheGH-41095: [C++][FS][Azure] Add support for CopyFile with hierar…
Browse files Browse the repository at this point in the history
…chical namespace support (apache#41276)

### Rationale for this change

We need to add SAS (Shared Access Signatures) token for source URL.

### What changes are included in this PR?

Generate SAS token for source URL.

### Are these changes tested?

Yes.

### Are there any user-facing changes?

Yes.
* GitHub Issue: apache#41095

Authored-by: Sutou Kouhei <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
  • Loading branch information
kou authored and tolleybot committed May 2, 2024
1 parent fb4ff14 commit 10ae8cb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 8 deletions.
44 changes: 36 additions & 8 deletions cpp/src/arrow/filesystem/azurefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ std::string BuildBaseUrl(const std::string& scheme, const std::string& authority
url += "/";
return url;
}

template <typename... PrefixArgs>
Status ExceptionToStatus(const Storage::StorageException& exception,
PrefixArgs&&... prefix_args) {
return Status::IOError(std::forward<PrefixArgs>(prefix_args)..., " Azure Error: [",
exception.ErrorCode, "] ", exception.what());
}
} // namespace

std::string AzureOptions::AccountBlobUrl(const std::string& account_name) const {
Expand Down Expand Up @@ -381,6 +388,22 @@ AzureOptions::MakeDataLakeServiceClient() const {
return Status::Invalid("AzureOptions doesn't contain a valid auth configuration");
}

Result<std::string> AzureOptions::GenerateSASToken(
Storage::Sas::BlobSasBuilder* builder, Blobs::BlobServiceClient* client) const {
if (storage_shared_key_credential_) {
return builder->GenerateSasToken(*storage_shared_key_credential_);
} else {
// GH-39344: This part isn't tested. This may not work.
try {
auto delegation_key_response = client->GetUserDelegationKey(builder->ExpiresOn);
return builder->GenerateSasToken(delegation_key_response.Value, account_name);
} catch (const Storage::StorageException& exception) {
return ExceptionToStatus(exception, "GetUserDelegationKey failed for '",
client->GetUrl(), "'.");
}
}
}

namespace {

// An AzureFileSystem represents an Azure storage account. An AzureLocation describes a
Expand Down Expand Up @@ -450,13 +473,6 @@ struct AzureLocation {
}
};

template <typename... PrefixArgs>
Status ExceptionToStatus(const Storage::StorageException& exception,
PrefixArgs&&... prefix_args) {
return Status::IOError(std::forward<PrefixArgs>(prefix_args)..., " Azure Error: [",
exception.ErrorCode, "] ", exception.what());
}

Status PathNotFound(const AzureLocation& location) {
return ::arrow::fs::internal::PathNotFound(location.all);
}
Expand Down Expand Up @@ -2868,8 +2884,20 @@ class AzureFileSystem::Impl {
if (src == dest) {
return Status::OK();
}
std::string sas_token;
{
Storage::Sas::BlobSasBuilder builder;
std::chrono::seconds available_period(60);
builder.ExpiresOn = std::chrono::system_clock::now() + available_period;
builder.BlobContainerName = src.container;
builder.BlobName = src.path;
builder.Resource = Storage::Sas::BlobSasResource::Blob;
builder.SetPermissions(Storage::Sas::BlobSasPermissions::Read);
ARROW_ASSIGN_OR_RAISE(
sas_token, options_.GenerateSASToken(&builder, blob_service_client_.get()));
}
auto src_url = GetBlobClient(src.container, src.path).GetUrl() + sas_token;
auto dest_blob_client = GetBlobClient(dest.container, dest.path);
auto src_url = GetBlobClient(src.container, src.path).GetUrl();
if (!dest.path.empty()) {
auto dest_parent = dest.parent();
if (!dest_parent.path.empty()) {
Expand Down
8 changes: 8 additions & 0 deletions cpp/src/arrow/filesystem/azurefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ namespace Azure::Storage::Blobs {
class BlobServiceClient;
}

namespace Azure::Storage::Sas {
struct BlobSasBuilder;
}

namespace Azure::Storage::Files::DataLake {
class DataLakeFileSystemClient;
class DataLakeServiceClient;
Expand Down Expand Up @@ -196,6 +200,10 @@ struct ARROW_EXPORT AzureOptions {

Result<std::unique_ptr<Azure::Storage::Files::DataLake::DataLakeServiceClient>>
MakeDataLakeServiceClient() const;

Result<std::string> GenerateSASToken(
Azure::Storage::Sas::BlobSasBuilder* builder,
Azure::Storage::Blobs::BlobServiceClient* client) const;
};

/// \brief FileSystem implementation backed by Azure Blob Storage (ABS) [1] and
Expand Down

0 comments on commit 10ae8cb

Please sign in to comment.