Skip to content

Commit 659b231

Browse files
Tom-Newtonkou
andauthored
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 <thomas.w.newton@gmail.com> Co-authored-by: Sutou Kouhei <kou@cozmixng.org> Signed-off-by: Sutou Kouhei <kou@clear-code.com>
1 parent 0552217 commit 659b231

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

cpp/src/arrow/filesystem/azurefs.cc

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "arrow/filesystem/azurefs.h"
1919
#include "arrow/filesystem/azurefs_internal.h"
2020

21+
#include <azure/identity.hpp>
2122
#include <azure/storage/blobs.hpp>
2223
#include <azure/storage/files/datalake.hpp>
2324

@@ -61,6 +62,8 @@ bool AzureOptions::Equals(const AzureOptions& other) const {
6162
switch (credential_kind_) {
6263
case CredentialKind::kAnonymous:
6364
return true;
65+
case CredentialKind::kTokenCredential:
66+
return token_credential_ == other.token_credential_;
6467
case CredentialKind::kStorageSharedKeyCredential:
6568
return storage_shared_key_credential_->AccountName ==
6669
other.storage_shared_key_credential_->AccountName;
@@ -69,15 +72,26 @@ bool AzureOptions::Equals(const AzureOptions& other) const {
6972
return false;
7073
}
7174

72-
Status AzureOptions::ConfigureAccountKeyCredential(const std::string& account_name,
73-
const std::string& account_key) {
75+
void AzureOptions::SetUrlsForAccountName(const std::string& account_name) {
7476
if (this->backend == AzureBackend::kAzurite) {
7577
account_blob_url_ = "http://127.0.0.1:10000/" + account_name + "/";
7678
account_dfs_url_ = "http://127.0.0.1:10000/" + account_name + "/";
7779
} else {
7880
account_dfs_url_ = "https://" + account_name + ".dfs.core.windows.net/";
7981
account_blob_url_ = "https://" + account_name + ".blob.core.windows.net/";
8082
}
83+
}
84+
85+
Status AzureOptions::ConfigureDefaultCredential(const std::string& account_name) {
86+
AzureOptions::SetUrlsForAccountName(account_name);
87+
credential_kind_ = CredentialKind::kTokenCredential;
88+
token_credential_ = std::make_shared<Azure::Identity::DefaultAzureCredential>();
89+
return Status::OK();
90+
}
91+
92+
Status AzureOptions::ConfigureAccountKeyCredential(const std::string& account_name,
93+
const std::string& account_key) {
94+
AzureOptions::SetUrlsForAccountName(account_name);
8195
credential_kind_ = CredentialKind::kStorageSharedKeyCredential;
8296
storage_shared_key_credential_ =
8397
std::make_shared<Storage::StorageSharedKeyCredential>(account_name, account_key);
@@ -89,6 +103,9 @@ Result<std::unique_ptr<Blobs::BlobServiceClient>> AzureOptions::MakeBlobServiceC
89103
switch (credential_kind_) {
90104
case CredentialKind::kAnonymous:
91105
break;
106+
case CredentialKind::kTokenCredential:
107+
return std::make_unique<Blobs::BlobServiceClient>(account_blob_url_,
108+
token_credential_);
92109
case CredentialKind::kStorageSharedKeyCredential:
93110
return std::make_unique<Blobs::BlobServiceClient>(account_blob_url_,
94111
storage_shared_key_credential_);
@@ -101,6 +118,9 @@ AzureOptions::MakeDataLakeServiceClient() const {
101118
switch (credential_kind_) {
102119
case CredentialKind::kAnonymous:
103120
break;
121+
case CredentialKind::kTokenCredential:
122+
return std::make_unique<DataLake::DataLakeServiceClient>(account_dfs_url_,
123+
token_credential_);
104124
case CredentialKind::kStorageSharedKeyCredential:
105125
return std::make_unique<DataLake::DataLakeServiceClient>(
106126
account_dfs_url_, storage_shared_key_credential_);

cpp/src/arrow/filesystem/azurefs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,23 @@ struct ARROW_EXPORT AzureOptions {
7070

7171
enum class CredentialKind {
7272
kAnonymous,
73+
kTokenCredential,
7374
kStorageSharedKeyCredential,
7475
} credential_kind_ = CredentialKind::kAnonymous;
7576

7677
std::shared_ptr<Azure::Storage::StorageSharedKeyCredential>
7778
storage_shared_key_credential_;
7879

80+
std::shared_ptr<Azure::Core::Credentials::TokenCredential> token_credential_;
81+
82+
void SetUrlsForAccountName(const std::string& account_name);
83+
7984
public:
8085
AzureOptions();
8186
~AzureOptions();
8287

88+
Status ConfigureDefaultCredential(const std::string& account_name);
89+
8390
Status ConfigureAccountKeyCredential(const std::string& account_name,
8491
const std::string& account_key);
8592

cpp/src/arrow/filesystem/azurefs_test.cc

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@
4343
#include <gmock/gmock-matchers.h>
4444
#include <gmock/gmock-more-matchers.h>
4545
#include <gtest/gtest.h>
46-
#include <azure/identity/client_secret_credential.hpp>
47-
#include <azure/identity/default_azure_credential.hpp>
48-
#include <azure/identity/managed_identity_credential.hpp>
4946
#include <azure/storage/blobs.hpp>
5047
#include <azure/storage/common/storage_credential.hpp>
5148
#include <azure/storage/files/datalake.hpp>
@@ -266,15 +263,12 @@ class AzureHierarchicalNSEnv : public AzureEnvImpl<AzureHierarchicalNSEnv> {
266263
bool WithHierarchicalNamespace() const final { return true; }
267264
};
268265

269-
// Placeholder tests
270-
// TODO: GH-18014 Remove once a proper test is added
271-
TEST(AzureFileSystem, InitializeCredentials) {
272-
auto default_credential = std::make_shared<Azure::Identity::DefaultAzureCredential>();
273-
auto managed_identity_credential =
274-
std::make_shared<Azure::Identity::ManagedIdentityCredential>();
275-
auto service_principal_credential =
276-
std::make_shared<Azure::Identity::ClientSecretCredential>("tenant_id", "client_id",
277-
"client_secret");
266+
TEST(AzureFileSystem, InitializeFilesystemWithDefaultCredential) {
267+
AzureOptions options;
268+
options.backend = AzureBackend::kAzurite; // Irrelevant for this test because it
269+
// doesn't connect to the server.
270+
ARROW_EXPECT_OK(options.ConfigureDefaultCredential("dummy-account-name"));
271+
EXPECT_OK_AND_ASSIGN(auto default_credential_fs, AzureFileSystem::Make(options));
278272
}
279273

280274
TEST(AzureFileSystem, OptionsCompare) {

0 commit comments

Comments
 (0)