This is an automated email from the ASF dual-hosted git repository.
laskoviymishka pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new e303dfde feat(io): add ManagedIdentityCredential support for Azure
(#1062)
e303dfde is described below
commit e303dfdeb8fc51834573cc7f6ccff1c454478744
Author: Alessandro Nori <[email protected]>
AuthorDate: Tue May 26 14:29:42 2026 +0200
feat(io): add ManagedIdentityCredential support for Azure (#1062)
## Changes
- Add `ADLSManagedIdentityEnabled`
(`adls.auth.managed-identity.enabled`) property to opt into
`ManagedIdentityCredential` instead of `DefaultAzureCredential`
- Add `ADLSManagedIdentityClientID`
(`adls.auth.managed-identity.client-id`) property for user-assigned
managed identities
## Motivation
`DefaultAzureCredential` sets a short timeout on its first managed
identity attempt. In production, this causes frequent "managed identity
timed out" errors when the app requests a token. Using
`ManagedIdentityCredential` directly avoids this timeout.
Reference:
https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/TROUBLESHOOTING.md#troubleshoot-defaultazurecredential-authentication-issues
---
io/config.go | 2 ++
io/gocloud/azure.go | 22 ++++++++++++++++++++++
io/gocloud/azure_test.go | 20 ++++++++++++++++++++
3 files changed, 44 insertions(+)
diff --git a/io/config.go b/io/config.go
index 712c8d0d..c66b0c3d 100644
--- a/io/config.go
+++ b/io/config.go
@@ -47,8 +47,10 @@ const (
ADLSConnectionStringPrefix = "adls.connection-string."
ADLSSharedKeyAccountName = "adls.auth.shared-key.account.name"
ADLSSharedKeyAccountKey = "adls.auth.shared-key.account.key"
+ ADLSClientID = "adls.client-id"
ADLSEndpoint = "adls.endpoint"
ADLSProtocol = "adls.protocol"
+ ADLSManagedIdentityEnabled = "adls.auth.managed-identity.enabled"
// Not in use yet
// ADLSReadBlockSize = "adls.read.block-size-bytes"
diff --git a/io/gocloud/azure.go b/io/gocloud/azure.go
index 06da2e2c..64177f14 100644
--- a/io/gocloud/azure.go
+++ b/io/gocloud/azure.go
@@ -159,6 +159,28 @@ func createAzureBucket(ctx context.Context, parsed
*url.URL, props map[string]st
if err != nil {
return nil, fmt.Errorf("failed
container.NewClientFromConnectionString: %w", err)
}
+ } else if props[io.ADLSManagedIdentityEnabled] == "true" {
+ containerURL, err := createContainerURL(location.accountName,
protocol, endpoint, "", location.containerName)
+ if err != nil {
+ return nil, err
+ }
+
+ var miOpts *azidentity.ManagedIdentityCredentialOptions
+ if clientID := props[io.ADLSClientID]; clientID != "" {
+ miOpts = &azidentity.ManagedIdentityCredentialOptions{
+ ID: azidentity.ClientID(clientID),
+ }
+ }
+
+ cred, err := azidentity.NewManagedIdentityCredential(miOpts)
+ if err != nil {
+ return nil, fmt.Errorf("failed
azidentity.NewManagedIdentityCredential: %w", err)
+ }
+
+ client, err = container.NewClient(containerURL, cred, nil)
+ if err != nil {
+ return nil, fmt.Errorf("failed container.NewClient:
%w", err)
+ }
} else {
containerURL, err := createContainerURL(location.accountName,
protocol, endpoint, "", location.containerName)
if err != nil {
diff --git a/io/gocloud/azure_test.go b/io/gocloud/azure_test.go
index cb1404e0..d5ef7e40 100644
--- a/io/gocloud/azure_test.go
+++ b/io/gocloud/azure_test.go
@@ -70,6 +70,26 @@ func TestCreateAzureBucketDefaultCredentialEmptyBucketName(t
*testing.T) {
"Expected container name error but got: %v", err)
}
+func TestCreateAzureBucketManagedIdentityCredentialCalled(t *testing.T) {
+ ctx := context.Background()
+
+ parsedURL, err :=
url.Parse("abfs://[email protected]/path")
+ assert.NoError(t, err)
+
+ // NewManagedIdentityCredential never fails at construction, so bucket
creation always succeeds.
+ bucket, err := createAzureBucket(ctx, parsedURL, map[string]string{
+ "adls.auth.managed-identity.enabled": "true",
+ })
+ assert.NoError(t, err)
+ assert.NotNil(t, bucket)
+
+ iter := bucket.List(nil)
+ _, err = iter.Next(ctx)
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "ManagedIdentityCredential",
+ "Expected ManagedIdentityCredential error but got: %v", err)
+}
+
func TestCreateAzureBucketSharedKeyMissingAccountKey(t *testing.T) {
ctx := context.Background()