This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new ce5e2ef6a2 use managed identity to connect to Azure blob storage, 
fixes #6343 (#6344)
ce5e2ef6a2 is described below

commit ce5e2ef6a2d720592a110768ac969611d3874423
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Mon Jan 12 16:38:25 2026 +0100

    use managed identity to connect to Azure blob storage, fixes #6343 (#6344)
    
    Also fix listing of containers on root path
---
 assemblies/debug/pom.xml                           |   6 ++
 plugins/tech/azure/pom.xml                         |   4 +
 .../org/apache/hop/vfs/azure/AzureFileObject.java  | 111 ++++++++++++++++-----
 .../apache/hop/vfs/azure/AzureFileProvider.java    |  69 +++++++++----
 .../vfs/azure/metadatatype/AzureMetadataType.java  |   3 +-
 .../metadatatype/AzureMetadataTypeEditor.java      |  84 ++++++++++++----
 .../messages/messages_en_US.properties             |   1 +
 7 files changed, 214 insertions(+), 64 deletions(-)

diff --git a/assemblies/debug/pom.xml b/assemblies/debug/pom.xml
index 0a46803f67..7babad32a1 100644
--- a/assemblies/debug/pom.xml
+++ b/assemblies/debug/pom.xml
@@ -403,6 +403,12 @@
             <version>${project.version}</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.hop</groupId>
+            <artifactId>hop-tech-azure</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.hop</groupId>
             <artifactId>hop-tech-google</artifactId>
diff --git a/plugins/tech/azure/pom.xml b/plugins/tech/azure/pom.xml
index 31ff9de5ff..fce8f59630 100755
--- a/plugins/tech/azure/pom.xml
+++ b/plugins/tech/azure/pom.xml
@@ -60,6 +60,10 @@
     </dependencyManagement>
 
     <dependencies>
+        <dependency>
+            <groupId>com.azure</groupId>
+            <artifactId>azure-core-http-netty</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>com.azure</groupId>
diff --git 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileObject.java
 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileObject.java
index cd7736c483..7532546074 100644
--- 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileObject.java
+++ 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileObject.java
@@ -27,6 +27,7 @@ import com.azure.storage.file.datalake.DataLakeServiceClient;
 import com.azure.storage.file.datalake.models.ListFileSystemsOptions;
 import com.azure.storage.file.datalake.models.ListPathsOptions;
 import com.azure.storage.file.datalake.models.PathItem;
+import com.azure.storage.file.datalake.options.DataLakePathDeleteOptions;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -115,7 +116,6 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
     }
     containerName = ((AzureFileName) getName()).getContainer();
     String fullPath = ((AzureFileName) getName()).getPath();
-    DataLakeFileSystemClient fileSystemClient = 
service.getFileSystemClient(containerName);
     ListPathsOptions lpo = new ListPathsOptions();
     children = new ArrayList<>();
     if (isFileSystemRoot(fullPath)) {
@@ -124,7 +124,19 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
           .iterator()
           .forEachRemaining(
               item -> {
-                children.add(StringUtils.substringAfterLast(item.getName(), 
"/"));
+                String containerName = item.getName();
+                // Extract just the container name (remove any path after last 
/)
+                String cleanName = 
StringUtils.substringAfterLast(containerName, "/");
+                // If substringAfterLast returns empty, use the full name
+                if (StringUtils.isEmpty(cleanName)) {
+                  cleanName = containerName;
+                }
+                // Only add valid, non-empty container names
+                if (!StringUtils.isEmpty(cleanName)
+                    && !cleanName.equals(".")
+                    && !cleanName.equals("..")) {
+                  children.add(cleanName);
+                }
               });
 
       size = children.size();
@@ -132,10 +144,27 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
       type = FileType.FOLDER;
       dataLakeFileClient = null;
       currentFilePath = "";
-    } else if (isContainer(fullPath)) {
+      return; // Early return for root level - no need to get fileSystemClient
+    }
+
+    // Get the fileSystemClient for container and below
+    DataLakeFileSystemClient fileSystemClient = 
service.getFileSystemClient(containerName);
+
+    if (isContainer(fullPath)) {
       if (containerExists()) {
         type = FileType.FOLDER;
-        fileSystemClient.listPaths().forEach(pi -> children.add(pi.getName()));
+        ListPathsOptions rootLpo = new ListPathsOptions();
+        rootLpo.setRecursive(false);
+        fileSystemClient
+            .listPaths(rootLpo, null)
+            .forEach(
+                pi -> {
+                  String childName = pi.getName();
+                  // Only add non-empty, valid child names
+                  if (!childName.isEmpty() && !childName.equals(".") && 
!childName.equals("..")) {
+                    children.add(childName);
+                  }
+                });
       } else {
         type = FileType.IMAGINARY;
         throw new HopException("Container does not exist: " + fullPath);
@@ -145,7 +174,18 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
       currentFilePath = ((AzureFileName) getName()).getPathAfterContainer();
       if (StringUtils.isEmpty(currentFilePath)) {
         type = FileType.FOLDER;
-        fileSystemClient.listPaths().forEach(pi -> children.add(pi.getName()));
+        ListPathsOptions rootLpo = new ListPathsOptions();
+        rootLpo.setRecursive(false);
+        fileSystemClient
+            .listPaths(rootLpo, null)
+            .forEach(
+                pi -> {
+                  String childName = pi.getName();
+                  // Only add non-empty, valid child names
+                  if (!childName.isEmpty() && !childName.equals(".") && 
!childName.equals("..")) {
+                    children.add(childName);
+                  }
+                });
       } else {
         lpo.setPath(currentFilePath);
         DataLakeDirectoryClient directoryClient =
@@ -161,13 +201,38 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
         final Boolean isFile = !isDirectory;
         if (exists && isDirectory) {
           children = new ArrayList<>();
+          lpo.setRecursive(false); // Only get immediate children, not 
recursive
           PagedIterable<PathItem> pathItems = fileSystemClient.listPaths(lpo, 
null);
+
+          // Normalize the current path for comparison
+          final String normalizedCurrentPath;
+          String tempPath = StringUtils.removeStart(currentFilePath, "/");
+          if (!tempPath.isEmpty() && !tempPath.endsWith("/")) {
+            normalizedCurrentPath = tempPath + "/";
+          } else {
+            normalizedCurrentPath = tempPath;
+          }
+
           pathItems.forEach(
               item -> {
-                children.add(
-                    StringUtils.removeStart(
-                        
item.getName().replace(StringUtils.removeStart(currentFilePath, "/"), ""),
-                        "/"));
+                String itemName = item.getName();
+                String childName;
+
+                // Remove the current directory prefix to get the child name
+                if (!normalizedCurrentPath.isEmpty()
+                    && itemName.startsWith(normalizedCurrentPath)) {
+                  childName = 
itemName.substring(normalizedCurrentPath.length());
+                } else {
+                  childName = itemName;
+                }
+
+                // Remove any leading slashes
+                childName = StringUtils.removeStart(childName, "/");
+
+                // Only add non-empty, valid child names
+                if (!childName.isEmpty() && !childName.equals(".") && 
!childName.equals("..")) {
+                  children.add(childName);
+                }
               });
           size = children.size();
           type = FileType.FOLDER;
@@ -268,26 +333,22 @@ public class AzureFileObject extends 
AbstractFileObject<AzureFileSystem> {
       FileObject parent = getParent();
       boolean lastFile = ((AzureFileObject) parent).doListChildren().length == 
1;
       try {
+        // Create delete options with recursive=true to handle non-empty 
directories
+        DataLakePathDeleteOptions deleteOptions = new 
DataLakePathDeleteOptions();
+        deleteOptions.setIsRecursive(true);
+
         if (currentFilePath.equals("")) {
-          fileClient.delete();
+          fileClient.deleteIfExistsWithResponse(deleteOptions, null, null);
         } else {
           if (StringUtils.isNotEmpty(currentFilePath) && fileClient.exists()) {
-            fileClient.delete();
+            fileClient.deleteIfExistsWithResponse(deleteOptions, null, null);
           } else if (dirPathItem != null) {
-            ListPathsOptions lpo = new ListPathsOptions();
-            lpo.setPath(((AzureFileName) getName()).getPathAfterContainer());
-
-            fileSystemClient
-                .listPaths(lpo, null)
-                .forEach(
-                    pi -> {
-                      if (!pi.isDirectory()
-                          && 
getFilePath(pi.getName()).startsWith(getName().getPath())) {
-                        DataLakeFileClient dataLakeFileClient =
-                            fileSystemClient.getFileClient(pathItem.getName());
-                        dataLakeFileClient.delete();
-                      }
-                    });
+            // For directories, use the directory client with recursive delete
+            DataLakeDirectoryClient directoryClient =
+                fileSystemClient.getDirectoryClient(currentFilePath);
+            if (directoryClient.exists()) {
+              directoryClient.deleteIfExistsWithResponse(deleteOptions, null, 
null);
+            }
           } else {
             throw new UnsupportedOperationException();
           }
diff --git 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileProvider.java
 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileProvider.java
index 1a44ca5736..4a61d05fbd 100644
--- 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileProvider.java
+++ 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/AzureFileProvider.java
@@ -18,6 +18,8 @@
 
 package org.apache.hop.vfs.azure;
 
+import com.azure.identity.DefaultAzureCredential;
+import com.azure.identity.DefaultAzureCredentialBuilder;
 import com.azure.storage.common.StorageSharedKeyCredential;
 import com.azure.storage.file.datalake.DataLakeServiceClient;
 import com.azure.storage.file.datalake.DataLakeServiceClientBuilder;
@@ -111,6 +113,8 @@ public class AzureFileProvider extends 
AbstractOriginatingFileProvider {
       logger.info("Initialize Azure client");
 
       AzureFileName azureRootName = (AzureFileName) fileName;
+      DataLakeServiceClient serviceClient;
+
       if (azureMetadataType != null) {
 
         if (StringUtils.isEmpty(azureMetadataType.getStorageAccountName())) {
@@ -119,21 +123,52 @@ public class AzureFileProvider extends 
AbstractOriginatingFileProvider {
                   + azureMetadataType.getName()
                   + "\" is missing a storage account name");
         }
-        if (StringUtils.isEmpty(azureMetadataType.getStorageAccountKey())) {
-          throw new FileSystemException(
-              "Azure configuration \""
-                  + azureMetadataType.getName()
-                  + "\" is missing a storage account key");
-        }
 
         account = variables.resolve(azureMetadataType.getStorageAccountName());
-        key =
-            Encr.decryptPasswordOptionallyEncrypted(
-                variables.resolve(azureMetadataType.getStorageAccountKey()));
         endpoint =
             (!Utils.isEmpty(azureMetadataType.getStorageAccountEndpoint()))
                 ? 
variables.resolve(azureMetadataType.getStorageAccountEndpoint())
                 : String.format(Locale.ROOT, 
"https://%s.dfs.core.windows.net";, account);
+
+        // Determine authentication type (default to "Key" for backward 
compatibility)
+        String authType = azureMetadataType.getAuthenticationType();
+        if (StringUtils.isEmpty(authType)) {
+          authType = "Key";
+        }
+
+        DataLakeServiceClientBuilder clientBuilder =
+            new DataLakeServiceClientBuilder().endpoint(endpoint);
+
+        if ("Managed Identity".equals(authType)) {
+          // Use Managed Identity authentication (supports Azure CLI, Managed 
Identity, etc.)
+          try {
+            DefaultAzureCredential credential = new 
DefaultAzureCredentialBuilder().build();
+            serviceClient = clientBuilder.credential(credential).buildClient();
+          } catch (Exception e) {
+            throw new FileSystemException(
+                "Failed to authenticate using Managed Identity. Please ensure 
you have: "
+                    + "1) Azure CLI installed and logged in (az login), OR "
+                    + "2) Running on Azure with Managed Identity enabled, OR "
+                    + "3) Environment variables configured (AZURE_CLIENT_ID, 
AZURE_TENANT_ID, AZURE_CLIENT_SECRET). "
+                    + "Also ensure your identity has proper permissions (e.g., 
'Storage Blob Data Contributor' role) on the storage account.",
+                e);
+          }
+        } else {
+          // Use Key-based authentication
+          if (StringUtils.isEmpty(azureMetadataType.getStorageAccountKey())) {
+            throw new FileSystemException(
+                "Azure configuration \""
+                    + azureMetadataType.getName()
+                    + "\" is missing a storage account key");
+          }
+
+          key =
+              Encr.decryptPasswordOptionallyEncrypted(
+                  variables.resolve(azureMetadataType.getStorageAccountKey()));
+
+          StorageSharedKeyCredential storageCreds = new 
StorageSharedKeyCredential(account, key);
+          serviceClient = clientBuilder.credential(storageCreds).buildClient();
+        }
       } else {
         AzureConfig config = AzureConfigSingleton.getConfig();
 
@@ -153,16 +188,14 @@ public class AzureFileProvider extends 
AbstractOriginatingFileProvider {
             (!Utils.isEmpty(config.getEmulatorUrl()))
                 ? newVariables.resolve(config.getEmulatorUrl())
                 : String.format(Locale.ROOT, 
"https://%s.dfs.core.windows.net";, account);
-      }
-
-      StorageSharedKeyCredential storageCreds = new 
StorageSharedKeyCredential(account, key);
 
-      DataLakeServiceClient serviceClient =
-          new DataLakeServiceClientBuilder()
-              .endpoint(endpoint)
-              .credential(storageCreds)
-              // .httpClient((HttpClient) client)
-              .buildClient();
+        StorageSharedKeyCredential storageCreds = new 
StorageSharedKeyCredential(account, key);
+        serviceClient =
+            new DataLakeServiceClientBuilder()
+                .endpoint(endpoint)
+                .credential(storageCreds)
+                .buildClient();
+      }
 
       azureFileSystem =
           new AzureFileSystem(
diff --git 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataType.java
 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataType.java
index b89264ab6a..e430001029 100644
--- 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataType.java
+++ 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataType.java
@@ -39,6 +39,7 @@ public class AzureMetadataType extends HopMetadataBase 
implements Serializable,
   private static final Class<?> PKG = AzureMetadataType.class;
   @HopMetadataProperty private String description;
   @HopMetadataProperty private String storageAccountName;
+  @HopMetadataProperty private String authenticationType;
 
   @HopMetadataProperty(password = true)
   private String storageAccountKey;
@@ -46,6 +47,6 @@ public class AzureMetadataType extends HopMetadataBase 
implements Serializable,
   @HopMetadataProperty private String storageAccountEndpoint;
 
   public AzureMetadataType() {
-    // Do nothing
+    this.authenticationType = "Key"; // Default to Key authentication
   }
 }
diff --git 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataTypeEditor.java
 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataTypeEditor.java
index cbdbbb1980..bc571b6d7d 100644
--- 
a/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataTypeEditor.java
+++ 
b/plugins/tech/azure/src/main/java/org/apache/hop/vfs/azure/metadatatype/AzureMetadataTypeEditor.java
@@ -23,6 +23,7 @@ import org.apache.hop.i18n.BaseMessages;
 import org.apache.hop.ui.core.PropsUi;
 import org.apache.hop.ui.core.metadata.MetadataEditor;
 import org.apache.hop.ui.core.metadata.MetadataManager;
+import org.apache.hop.ui.core.widget.ComboVar;
 import org.apache.hop.ui.core.widget.PasswordTextVar;
 import org.apache.hop.ui.core.widget.TextVar;
 import org.apache.hop.ui.hopgui.HopGui;
@@ -43,6 +44,8 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
   private Text wName;
   private Text wDescription;
   private TextVar wStorageAccountName;
+  private ComboVar wAuthenticationType;
+  private Label wlStorageAccountKey;
   private PasswordTextVar wStorageAccountKey;
   private TextVar wStorageAccountEndpoint;
 
@@ -98,6 +101,27 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     wDescription.setLayoutData(fdDescription);
     lastControl = wDescription;
 
+    // The storage account endpoint
+    //
+    Label wlStorageAccountEndpoint = new Label(parent, SWT.RIGHT);
+    PropsUi.setLook(wlStorageAccountEndpoint);
+    wlStorageAccountEndpoint.setText(
+        BaseMessages.getString(PKG, 
"AzureMetadataTypeEditor.StorageAccountEndpoint.Label"));
+    FormData fdlStorageAccountEndpoint = new FormData();
+    fdlStorageAccountEndpoint.top = new FormAttachment(lastControl, margin);
+    fdlStorageAccountEndpoint.left = new FormAttachment(0, 0);
+    fdlStorageAccountEndpoint.right = new FormAttachment(middle, -margin);
+    wlStorageAccountEndpoint.setLayoutData(fdlStorageAccountEndpoint);
+    wStorageAccountEndpoint =
+        new TextVar(getVariables(), parent, SWT.SINGLE | SWT.LEFT | 
SWT.BORDER);
+    PropsUi.setLook(wStorageAccountEndpoint);
+    FormData fdStorageAccountEndpoint = new FormData();
+    fdStorageAccountEndpoint.top = new 
FormAttachment(wlStorageAccountEndpoint, 0, SWT.CENTER);
+    fdStorageAccountEndpoint.left = new FormAttachment(middle, 0);
+    fdStorageAccountEndpoint.right = new FormAttachment(95, 0);
+    wStorageAccountEndpoint.setLayoutData(fdStorageAccountEndpoint);
+    lastControl = wStorageAccountEndpoint;
+
     // The Storage account name
     //
     Label wlStorageAccountName = new Label(parent, SWT.RIGHT);
@@ -118,9 +142,30 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     wStorageAccountName.setLayoutData(fdStorageAccountName);
     lastControl = wStorageAccountName;
 
+    // The Authentication type
+    //
+    Label wlAuthenticationType = new Label(parent, SWT.RIGHT);
+    PropsUi.setLook(wlAuthenticationType);
+    wlAuthenticationType.setText(
+        BaseMessages.getString(PKG, 
"AzureMetadataTypeEditor.AuthenticationType.Label"));
+    FormData fdlAuthenticationType = new FormData();
+    fdlAuthenticationType.top = new FormAttachment(lastControl, margin);
+    fdlAuthenticationType.left = new FormAttachment(0, 0);
+    fdlAuthenticationType.right = new FormAttachment(middle, -margin);
+    wlAuthenticationType.setLayoutData(fdlAuthenticationType);
+    wAuthenticationType = new ComboVar(getVariables(), parent, SWT.SINGLE | 
SWT.LEFT | SWT.BORDER);
+    PropsUi.setLook(wAuthenticationType);
+    wAuthenticationType.setItems(new String[] {"Key", "Managed Identity"});
+    FormData fdAuthenticationType = new FormData();
+    fdAuthenticationType.top = new FormAttachment(wlAuthenticationType, 0, 
SWT.CENTER);
+    fdAuthenticationType.left = new FormAttachment(middle, 0);
+    fdAuthenticationType.right = new FormAttachment(95, 0);
+    wAuthenticationType.setLayoutData(fdAuthenticationType);
+    lastControl = wAuthenticationType;
+
     // The Storage account key
     //
-    Label wlStorageAccountKey = new Label(parent, SWT.RIGHT);
+    wlStorageAccountKey = new Label(parent, SWT.RIGHT);
     PropsUi.setLook(wlStorageAccountKey);
     wlStorageAccountKey.setText(
         BaseMessages.getString(PKG, 
"AzureMetadataTypeEditor.StorageAccountKey.Label"));
@@ -139,25 +184,15 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     wStorageAccountKey.setLayoutData(fdStorageAccountKey);
     lastControl = wStorageAccountKey;
 
-    // The storage account endpoint
-    //
-    Label wlStorageAccountEndpoint = new Label(parent, SWT.RIGHT);
-    PropsUi.setLook(wlStorageAccountEndpoint);
-    wlStorageAccountEndpoint.setText(
-        BaseMessages.getString(PKG, 
"AzureMetadataTypeEditor.StorageAccountEndpoint.Label"));
-    FormData fdlStorageAccountEndpoint = new FormData();
-    fdlStorageAccountEndpoint.top = new FormAttachment(lastControl, margin);
-    fdlStorageAccountEndpoint.left = new FormAttachment(0, 0);
-    fdlStorageAccountEndpoint.right = new FormAttachment(middle, -margin);
-    wlStorageAccountEndpoint.setLayoutData(fdlStorageAccountEndpoint);
-    wStorageAccountEndpoint =
-        new TextVar(getVariables(), parent, SWT.SINGLE | SWT.LEFT | 
SWT.BORDER);
-    PropsUi.setLook(wStorageAccountEndpoint);
-    FormData fdStorageAccountEndpoint = new FormData();
-    fdStorageAccountEndpoint.top = new 
FormAttachment(wlStorageAccountEndpoint, 0, SWT.CENTER);
-    fdStorageAccountEndpoint.left = new FormAttachment(middle, 0);
-    fdStorageAccountEndpoint.right = new FormAttachment(95, 0);
-    wStorageAccountEndpoint.setLayoutData(fdStorageAccountEndpoint);
+    // Add listener to authentication type to show/hide storage account key
+    wAuthenticationType.addModifyListener(
+        e -> {
+          String authType = wAuthenticationType.getText();
+          boolean showKey = "Key".equals(authType);
+          wlStorageAccountKey.setVisible(showKey);
+          wStorageAccountKey.setVisible(showKey);
+          parent.layout(true, true);
+        });
 
     setWidgetsContent();
 
@@ -165,6 +200,7 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     wName.addModifyListener(e -> setChanged());
     wDescription.addModifyListener(e -> setChanged());
     wStorageAccountName.addModifyListener(e -> setChanged());
+    wAuthenticationType.addModifyListener(e -> setChanged());
     wStorageAccountKey.addModifyListener(e -> setChanged());
     wStorageAccountEndpoint.addModifyListener(e -> setChanged());
   }
@@ -175,8 +211,15 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     wName.setText(Const.NVL(azureMetadataType.getName(), ""));
     wDescription.setText(Const.NVL(azureMetadataType.getDescription(), ""));
     
wStorageAccountName.setText(Const.NVL(azureMetadataType.getStorageAccountName(),
 ""));
+    
wAuthenticationType.setText(Const.NVL(azureMetadataType.getAuthenticationType(),
 "Key"));
     
wStorageAccountKey.setText(Const.NVL(azureMetadataType.getStorageAccountKey(), 
""));
     
wStorageAccountEndpoint.setText(Const.NVL(azureMetadataType.getStorageAccountEndpoint(),
 ""));
+
+    // Show/hide storage account key based on authentication type
+    String authType = wAuthenticationType.getText();
+    boolean showKey = "Key".equals(authType);
+    wlStorageAccountKey.setVisible(showKey);
+    wStorageAccountKey.setVisible(showKey);
   }
 
   @Override
@@ -184,6 +227,7 @@ public class AzureMetadataTypeEditor extends 
MetadataEditor<AzureMetadataType> {
     azureMetadataType.setName(wName.getText());
     azureMetadataType.setDescription(wDescription.getText());
     azureMetadataType.setStorageAccountName(wStorageAccountName.getText());
+    azureMetadataType.setAuthenticationType(wAuthenticationType.getText());
     azureMetadataType.setStorageAccountKey(wStorageAccountKey.getText());
     
azureMetadataType.setStorageAccountEndpoint(wStorageAccountEndpoint.getText());
   }
diff --git 
a/plugins/tech/azure/src/main/resources/org/apache/hop/vfs/azure/metadatatype/messages/messages_en_US.properties
 
b/plugins/tech/azure/src/main/resources/org/apache/hop/vfs/azure/metadatatype/messages/messages_en_US.properties
index d45868a097..5c8c686451 100644
--- 
a/plugins/tech/azure/src/main/resources/org/apache/hop/vfs/azure/metadatatype/messages/messages_en_US.properties
+++ 
b/plugins/tech/azure/src/main/resources/org/apache/hop/vfs/azure/metadatatype/messages/messages_en_US.properties
@@ -22,5 +22,6 @@ AzureMetadataType.Description=
 AzureMetadataTypeEditor.Name.Label=Name
 AzureMetadataTypeEditor.Description.Label=Description
 AzureMetadataTypeEditor.StorageAccountName.Label=Storage Account Name
+AzureMetadataTypeEditor.AuthenticationType.Label=Authentication Type
 AzureMetadataTypeEditor.StorageAccountKey.Label=Storage Account Key
 AzureMetadataTypeEditor.StorageAccountEndpoint.Label=Storage Endpoint
\ No newline at end of file

Reply via email to