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