This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 659b2311bc GH-39262: [C++][Azure][FS] Add default credential auth
configuration (#39263)
659b2311bc is described below
commit 659b2311bc577eb4322c5772a5e90f919620bb95
Author: Thomas Newton <[email protected]>
AuthorDate: Tue Dec 19 07:32:00 2023 +0000
GH-39262: [C++][Azure][FS] Add default credential auth configuration
(#39263)
### Rationale for this change
Default credential is a useful auth option.
### What changes are included in this PR?
Implement `AzureOptions::ConfigureDefaultCredential` plus a little bit of
plumbing to go around it.
Created a simple test.
### Are these changes tested?
Added a simple unittest that everything initialises happily. This does not
actually test a successful authentication. I think to do a real authentication
with Azure we would need to run the test against real blob storage and we would
need to create various identities which are non-trivial to create. Personally I
think this is ok because all the complexity is abstracted away by the Azure SDK.
### Are there any user-facing changes?
* Closes: #39262
Lead-authored-by: Thomas Newton <[email protected]>
Co-authored-by: Sutou Kouhei <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
cpp/src/arrow/filesystem/azurefs.cc | 24 ++++++++++++++++++++++--
cpp/src/arrow/filesystem/azurefs.h | 7 +++++++
cpp/src/arrow/filesystem/azurefs_test.cc | 18 ++++++------------
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/cpp/src/arrow/filesystem/azurefs.cc
b/cpp/src/arrow/filesystem/azurefs.cc
index 2178853640..dd267aac36 100644
--- a/cpp/src/arrow/filesystem/azurefs.cc
+++ b/cpp/src/arrow/filesystem/azurefs.cc
@@ -18,6 +18,7 @@
#include "arrow/filesystem/azurefs.h"
#include "arrow/filesystem/azurefs_internal.h"
+#include <azure/identity.hpp>
#include <azure/storage/blobs.hpp>
#include <azure/storage/files/datalake.hpp>
@@ -61,6 +62,8 @@ bool AzureOptions::Equals(const AzureOptions& other) const {
switch (credential_kind_) {
case CredentialKind::kAnonymous:
return true;
+ case CredentialKind::kTokenCredential:
+ return token_credential_ == other.token_credential_;
case CredentialKind::kStorageSharedKeyCredential:
return storage_shared_key_credential_->AccountName ==
other.storage_shared_key_credential_->AccountName;
@@ -69,8 +72,7 @@ bool AzureOptions::Equals(const AzureOptions& other) const {
return false;
}
-Status AzureOptions::ConfigureAccountKeyCredential(const std::string&
account_name,
- const std::string&
account_key) {
+void AzureOptions::SetUrlsForAccountName(const std::string& account_name) {
if (this->backend == AzureBackend::kAzurite) {
account_blob_url_ = "http://127.0.0.1:10000/" + account_name + "/";
account_dfs_url_ = "http://127.0.0.1:10000/" + account_name + "/";
@@ -78,6 +80,18 @@ Status AzureOptions::ConfigureAccountKeyCredential(const
std::string& account_na
account_dfs_url_ = "https://" + account_name + ".dfs.core.windows.net/";
account_blob_url_ = "https://" + account_name + ".blob.core.windows.net/";
}
+}
+
+Status AzureOptions::ConfigureDefaultCredential(const std::string&
account_name) {
+ AzureOptions::SetUrlsForAccountName(account_name);
+ credential_kind_ = CredentialKind::kTokenCredential;
+ token_credential_ =
std::make_shared<Azure::Identity::DefaultAzureCredential>();
+ return Status::OK();
+}
+
+Status AzureOptions::ConfigureAccountKeyCredential(const std::string&
account_name,
+ const std::string&
account_key) {
+ AzureOptions::SetUrlsForAccountName(account_name);
credential_kind_ = CredentialKind::kStorageSharedKeyCredential;
storage_shared_key_credential_ =
std::make_shared<Storage::StorageSharedKeyCredential>(account_name,
account_key);
@@ -89,6 +103,9 @@ Result<std::unique_ptr<Blobs::BlobServiceClient>>
AzureOptions::MakeBlobServiceC
switch (credential_kind_) {
case CredentialKind::kAnonymous:
break;
+ case CredentialKind::kTokenCredential:
+ return std::make_unique<Blobs::BlobServiceClient>(account_blob_url_,
+ token_credential_);
case CredentialKind::kStorageSharedKeyCredential:
return std::make_unique<Blobs::BlobServiceClient>(account_blob_url_,
storage_shared_key_credential_);
@@ -101,6 +118,9 @@ AzureOptions::MakeDataLakeServiceClient() const {
switch (credential_kind_) {
case CredentialKind::kAnonymous:
break;
+ case CredentialKind::kTokenCredential:
+ return
std::make_unique<DataLake::DataLakeServiceClient>(account_dfs_url_,
+
token_credential_);
case CredentialKind::kStorageSharedKeyCredential:
return std::make_unique<DataLake::DataLakeServiceClient>(
account_dfs_url_, storage_shared_key_credential_);
diff --git a/cpp/src/arrow/filesystem/azurefs.h
b/cpp/src/arrow/filesystem/azurefs.h
index 1266aa2d02..b2c7010ff3 100644
--- a/cpp/src/arrow/filesystem/azurefs.h
+++ b/cpp/src/arrow/filesystem/azurefs.h
@@ -70,16 +70,23 @@ struct ARROW_EXPORT AzureOptions {
enum class CredentialKind {
kAnonymous,
+ kTokenCredential,
kStorageSharedKeyCredential,
} credential_kind_ = CredentialKind::kAnonymous;
std::shared_ptr<Azure::Storage::StorageSharedKeyCredential>
storage_shared_key_credential_;
+ std::shared_ptr<Azure::Core::Credentials::TokenCredential> token_credential_;
+
+ void SetUrlsForAccountName(const std::string& account_name);
+
public:
AzureOptions();
~AzureOptions();
+ Status ConfigureDefaultCredential(const std::string& account_name);
+
Status ConfigureAccountKeyCredential(const std::string& account_name,
const std::string& account_key);
diff --git a/cpp/src/arrow/filesystem/azurefs_test.cc
b/cpp/src/arrow/filesystem/azurefs_test.cc
index 463ff4e8da..799f3992a2 100644
--- a/cpp/src/arrow/filesystem/azurefs_test.cc
+++ b/cpp/src/arrow/filesystem/azurefs_test.cc
@@ -43,9 +43,6 @@
#include <gmock/gmock-matchers.h>
#include <gmock/gmock-more-matchers.h>
#include <gtest/gtest.h>
-#include <azure/identity/client_secret_credential.hpp>
-#include <azure/identity/default_azure_credential.hpp>
-#include <azure/identity/managed_identity_credential.hpp>
#include <azure/storage/blobs.hpp>
#include <azure/storage/common/storage_credential.hpp>
#include <azure/storage/files/datalake.hpp>
@@ -266,15 +263,12 @@ class AzureHierarchicalNSEnv : public
AzureEnvImpl<AzureHierarchicalNSEnv> {
bool WithHierarchicalNamespace() const final { return true; }
};
-// Placeholder tests
-// TODO: GH-18014 Remove once a proper test is added
-TEST(AzureFileSystem, InitializeCredentials) {
- auto default_credential =
std::make_shared<Azure::Identity::DefaultAzureCredential>();
- auto managed_identity_credential =
- std::make_shared<Azure::Identity::ManagedIdentityCredential>();
- auto service_principal_credential =
- std::make_shared<Azure::Identity::ClientSecretCredential>("tenant_id",
"client_id",
-
"client_secret");
+TEST(AzureFileSystem, InitializeFilesystemWithDefaultCredential) {
+ AzureOptions options;
+ options.backend = AzureBackend::kAzurite; // Irrelevant for this test
because it
+ // doesn't connect to the server.
+ ARROW_EXPECT_OK(options.ConfigureDefaultCredential("dummy-account-name"));
+ EXPECT_OK_AND_ASSIGN(auto default_credential_fs,
AzureFileSystem::Make(options));
}
TEST(AzureFileSystem, OptionsCompare) {