You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ex...@apache.org on 2021/03/02 04:35:47 UTC
[nifi] branch main updated: NIFI-8258: Add support for Service
Principal authentication in ADLS processors
This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 7876f41 NIFI-8258: Add support for Service Principal authentication in ADLS processors
7876f41 is described below
commit 7876f412fbf1785322c06f6bac32804f28d66512
Author: Peter Turcsanyi <tu...@apache.org>
AuthorDate: Thu Feb 25 09:04:07 2021 +0100
NIFI-8258: Add support for Service Principal authentication in ADLS processors
- Removed Expression Language support indicators from sensitive properties
This closes #4843
Signed-off-by: David Handermann <ex...@apache.org>
---
.../AbstractAzureDataLakeStorageProcessor.java | 51 +++--
.../storage/ADLSCredentialsControllerService.java | 155 +++++++++++----
.../TestADLSCredentialsControllerService.java | 217 ++++++++++++++++++++-
.../azure/storage/ADLSCredentialsDetails.java | 55 +++++-
4 files changed, 407 insertions(+), 71 deletions(-)
diff --git a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/processors/azure/AbstractAzureDataLakeStorageProcessor.java b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/processors/azure/AbstractAzureDataLakeStorageProcessor.java
index bb22c57..e6ca356 100644
--- a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/processors/azure/AbstractAzureDataLakeStorageProcessor.java
+++ b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/processors/azure/AbstractAzureDataLakeStorageProcessor.java
@@ -25,6 +25,8 @@ import java.util.Set;
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenCredential;
+import com.azure.identity.ClientSecretCredential;
+import com.azure.identity.ClientSecretCredentialBuilder;
import com.azure.identity.ManagedIdentityCredential;
import com.azure.identity.ManagedIdentityCredentialBuilder;
import com.azure.storage.common.StorageSharedKeyCredential;
@@ -53,12 +55,12 @@ import static org.apache.nifi.processors.azure.storage.utils.ADLSAttributes.ATTR
public abstract class AbstractAzureDataLakeStorageProcessor extends AbstractProcessor {
public static final PropertyDescriptor ADLS_CREDENTIALS_SERVICE = new PropertyDescriptor.Builder()
- .name("adls-credentials-service")
- .displayName("ADLS Credentials")
- .description("Controller Service used to obtain Azure Credentials.")
- .identifiesControllerService(ADLSCredentialsService.class)
- .required(true)
- .build();
+ .name("adls-credentials-service")
+ .displayName("ADLS Credentials")
+ .description("Controller Service used to obtain Azure Credentials.")
+ .identifiesControllerService(ADLSCredentialsService.class)
+ .required(true)
+ .build();
public static final PropertyDescriptor FILESYSTEM = new PropertyDescriptor.Builder()
.name("filesystem-name").displayName("Filesystem Name")
@@ -120,7 +122,7 @@ public abstract class AbstractAzureDataLakeStorageProcessor extends AbstractProc
final ADLSCredentialsService credentialsService = context.getProperty(ADLS_CREDENTIALS_SERVICE).asControllerService(ADLSCredentialsService.class);
- ADLSCredentialsDetails credentialsDetails = credentialsService.getCredentialsDetails(attributes);
+ final ADLSCredentialsDetails credentialsDetails = credentialsService.getCredentialsDetails(attributes);
final String accountName = credentialsDetails.getAccountName();
final String accountKey = credentialsDetails.getAccountKey();
@@ -128,9 +130,13 @@ public abstract class AbstractAzureDataLakeStorageProcessor extends AbstractProc
final AccessToken accessToken = credentialsDetails.getAccessToken();
final String endpointSuffix = credentialsDetails.getEndpointSuffix();
final boolean useManagedIdentity = credentialsDetails.getUseManagedIdentity();
+ final String servicePrincipalTenantId = credentialsDetails.getServicePrincipalTenantId();
+ final String servicePrincipalClientId = credentialsDetails.getServicePrincipalClientId();
+ final String servicePrincipalClientSecret = credentialsDetails.getServicePrincipalClientSecret();
final String endpoint = String.format("https://%s.%s", accountName,endpointSuffix);
- DataLakeServiceClient storageClient;
+
+ final DataLakeServiceClient storageClient;
if (StringUtils.isNotBlank(accountKey)) {
final StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName,
accountKey);
@@ -140,17 +146,28 @@ public abstract class AbstractAzureDataLakeStorageProcessor extends AbstractProc
storageClient = new DataLakeServiceClientBuilder().endpoint(endpoint).sasToken(sasToken)
.buildClient();
} else if (accessToken != null) {
- TokenCredential credential = tokenRequestContext -> Mono.just(accessToken);
+ final TokenCredential credential = tokenRequestContext -> Mono.just(accessToken);
storageClient = new DataLakeServiceClientBuilder().endpoint(endpoint).credential(credential)
- .buildClient();
- } else if(useManagedIdentity){
- final ManagedIdentityCredential misCrendential = new ManagedIdentityCredentialBuilder()
- .build();
- storageClient = new DataLakeServiceClientBuilder()
- .endpoint(endpoint)
- .credential(misCrendential)
- .buildClient();
+ .buildClient();
+ } else if (useManagedIdentity) {
+ final ManagedIdentityCredential misCredential = new ManagedIdentityCredentialBuilder()
+ .build();
+ storageClient = new DataLakeServiceClientBuilder()
+ .endpoint(endpoint)
+ .credential(misCredential)
+ .buildClient();
+ } else if (StringUtils.isNoneBlank(servicePrincipalTenantId, servicePrincipalClientId, servicePrincipalClientSecret)) {
+ final ClientSecretCredential credential = new ClientSecretCredentialBuilder()
+ .tenantId(servicePrincipalTenantId)
+ .clientId(servicePrincipalClientId)
+ .clientSecret(servicePrincipalClientSecret)
+ .build();
+
+ storageClient = new DataLakeServiceClientBuilder()
+ .endpoint(endpoint)
+ .credential(credential)
+ .buildClient();
} else {
throw new IllegalArgumentException("No valid credentials were provided");
}
diff --git a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsControllerService.java b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsControllerService.java
index ec86f9c..8ecb554 100644
--- a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsControllerService.java
+++ b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsControllerService.java
@@ -26,6 +26,7 @@ import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.processors.azure.storage.utils.AzureStorageUtils;
@@ -35,7 +36,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.StringJoiner;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -49,37 +49,81 @@ import java.util.function.Function;
public class ADLSCredentialsControllerService extends AbstractControllerService implements ADLSCredentialsService {
public static final PropertyDescriptor ACCOUNT_NAME = new PropertyDescriptor.Builder()
- .fromPropertyDescriptor(AzureStorageUtils.ACCOUNT_NAME)
- .description(AzureStorageUtils.ACCOUNT_NAME_BASE_DESCRIPTION)
- .required(true)
- .build();
+ .fromPropertyDescriptor(AzureStorageUtils.ACCOUNT_NAME)
+ .description(AzureStorageUtils.ACCOUNT_NAME_BASE_DESCRIPTION)
+ .required(true)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
public static final PropertyDescriptor ENDPOINT_SUFFIX = new PropertyDescriptor.Builder()
- .fromPropertyDescriptor(AzureStorageUtils.ENDPOINT_SUFFIX)
- .displayName("Endpoint Suffix")
- .description(
- "Storage accounts in public Azure always use a common FQDN suffix. " +
- "Override this endpoint suffix with a different suffix in certain circumstances (like Azure Stack or non-public Azure regions).")
- .required(true)
- .defaultValue("dfs.core.windows.net")
- .build();
+ .fromPropertyDescriptor(AzureStorageUtils.ENDPOINT_SUFFIX)
+ .displayName("Endpoint Suffix")
+ .description("Storage accounts in public Azure always use a common FQDN suffix. " +
+ "Override this endpoint suffix with a different suffix in certain circumstances (like Azure Stack or non-public Azure regions).")
+ .required(true)
+ .defaultValue("dfs.core.windows.net")
+ .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
+ .build();
+
+ public static final PropertyDescriptor ACCOUNT_KEY = new PropertyDescriptor.Builder()
+ .fromPropertyDescriptor(AzureStorageUtils.ACCOUNT_KEY)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
+
+ public static final PropertyDescriptor SAS_TOKEN = new PropertyDescriptor.Builder()
+ .fromPropertyDescriptor(AzureStorageUtils.PROP_SAS_TOKEN)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
public static final PropertyDescriptor USE_MANAGED_IDENTITY = new PropertyDescriptor.Builder()
- .name("storage-use-managed-identity")
- .displayName("Use Azure Managed Identity")
- .description("Choose whether or not to use the managed identity of Azure VM/VMSS ")
- .required(false)
- .defaultValue("false")
- .allowableValues("true", "false")
- .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
- .build();
+ .name("storage-use-managed-identity")
+ .displayName("Use Azure Managed Identity")
+ .description("Choose whether or not to use the managed identity of Azure VM/VMSS ")
+ .required(false)
+ .defaultValue("false")
+ .allowableValues("true", "false")
+ .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
+ .build();
+
+ public static final PropertyDescriptor SERVICE_PRINCIPAL_TENANT_ID = new PropertyDescriptor.Builder()
+ .name("service-principal-tenant-id")
+ .displayName("Service Principal Tenant ID")
+ .description("Tenant ID of the Azure Active Directory hosting the Service Principal. The property is required when Service Principal authentication is used.")
+ .sensitive(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
+
+ public static final PropertyDescriptor SERVICE_PRINCIPAL_CLIENT_ID = new PropertyDescriptor.Builder()
+ .name("service-principal-client-id")
+ .displayName("Service Principal Client ID")
+ .description("Client ID (or Application ID) of the Client/Application having the Service Principal. The property is required when Service Principal authentication is used.")
+ .sensitive(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
+
+ public static final PropertyDescriptor SERVICE_PRINCIPAL_CLIENT_SECRET = new PropertyDescriptor.Builder()
+ .name("service-principal-client-secret")
+ .displayName("Service Principal Client Secret")
+ .description("Password of the Client/Application. The property is required when Service Principal authentication is used.")
+ .sensitive(true)
+ .required(false)
+ .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
+ .expressionLanguageSupported(ExpressionLanguageScope.NONE)
+ .build();
private static final List<PropertyDescriptor> PROPERTIES = Collections.unmodifiableList(Arrays.asList(
- ACCOUNT_NAME,
- ENDPOINT_SUFFIX,
- AzureStorageUtils.ACCOUNT_KEY,
- AzureStorageUtils.PROP_SAS_TOKEN,
- USE_MANAGED_IDENTITY
+ ACCOUNT_NAME,
+ ENDPOINT_SUFFIX,
+ ACCOUNT_KEY,
+ SAS_TOKEN,
+ USE_MANAGED_IDENTITY,
+ SERVICE_PRINCIPAL_TENANT_ID,
+ SERVICE_PRINCIPAL_CLIENT_ID,
+ SERVICE_PRINCIPAL_CLIENT_SECRET
));
private ConfigurationContext context;
@@ -93,20 +137,41 @@ public class ADLSCredentialsControllerService extends AbstractControllerService
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
final List<ValidationResult> results = new ArrayList<>();
- boolean accountKeySet = StringUtils.isNotBlank(validationContext.getProperty(AzureStorageUtils.ACCOUNT_KEY).getValue());
- boolean sasTokenSet = StringUtils.isNotBlank(validationContext.getProperty(AzureStorageUtils.PROP_SAS_TOKEN).getValue());
+ boolean accountKeySet = StringUtils.isNotBlank(validationContext.getProperty(ACCOUNT_KEY).getValue());
+ boolean sasTokenSet = StringUtils.isNotBlank(validationContext.getProperty(SAS_TOKEN).getValue());
boolean useManagedIdentitySet = validationContext.getProperty(USE_MANAGED_IDENTITY).asBoolean();
- if (!onlyOneSet(accountKeySet, sasTokenSet, useManagedIdentitySet)) {
- StringJoiner options = new StringJoiner(", ")
- .add(AzureStorageUtils.ACCOUNT_KEY.getDisplayName())
- .add(AzureStorageUtils.PROP_SAS_TOKEN.getDisplayName())
- .add(USE_MANAGED_IDENTITY.getDisplayName());
+ boolean servicePrincipalTenantIdSet = StringUtils.isNotBlank(validationContext.getProperty(SERVICE_PRINCIPAL_TENANT_ID).getValue());
+ boolean servicePrincipalClientIdSet = StringUtils.isNotBlank(validationContext.getProperty(SERVICE_PRINCIPAL_CLIENT_ID).getValue());
+ boolean servicePrincipalClientSecretSet = StringUtils.isNotBlank(validationContext.getProperty(SERVICE_PRINCIPAL_CLIENT_SECRET).getValue());
+ boolean servicePrincipalSet = servicePrincipalTenantIdSet || servicePrincipalClientIdSet || servicePrincipalClientSecretSet;
+
+ if (!onlyOneSet(accountKeySet, sasTokenSet, useManagedIdentitySet, servicePrincipalSet)) {
results.add(new ValidationResult.Builder().subject(this.getClass().getSimpleName())
.valid(false)
- .explanation("one and only one of [" + options + "] should be set")
+ .explanation("one and only one authentication method of [Account Key, SAS Token, Managed Identity, Service Principal] should be used")
.build());
+ } else if (servicePrincipalSet) {
+ String template = "'%s' must be set when Service Principal authentication is being configured";
+ if (!servicePrincipalTenantIdSet) {
+ results.add(new ValidationResult.Builder().subject(this.getClass().getSimpleName())
+ .valid(false)
+ .explanation(String.format(template, SERVICE_PRINCIPAL_TENANT_ID.getDisplayName()))
+ .build());
+ }
+ if (!servicePrincipalClientIdSet) {
+ results.add(new ValidationResult.Builder().subject(this.getClass().getSimpleName())
+ .valid(false)
+ .explanation(String.format(template, SERVICE_PRINCIPAL_CLIENT_ID.getDisplayName()))
+ .build());
+ }
+ if (!servicePrincipalClientSecretSet) {
+ results.add(new ValidationResult.Builder().subject(this.getClass().getSimpleName())
+ .valid(false)
+ .explanation(String.format(template, SERVICE_PRINCIPAL_CLIENT_SECRET.getDisplayName()))
+ .build());
+ }
}
return results;
@@ -129,23 +194,29 @@ public class ADLSCredentialsControllerService extends AbstractControllerService
public ADLSCredentialsDetails getCredentialsDetails(Map<String, String> attributes) {
ADLSCredentialsDetails.Builder credentialsBuilder = ADLSCredentialsDetails.Builder.newBuilder();
- setValue(credentialsBuilder, ACCOUNT_NAME, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setAccountName);
- setValue(credentialsBuilder, AzureStorageUtils.ACCOUNT_KEY, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setAccountKey);
- setValue(credentialsBuilder, AzureStorageUtils.PROP_SAS_TOKEN, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setSasToken);
- setValue(credentialsBuilder, ENDPOINT_SUFFIX, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setEndpointSuffix);
- setValue(credentialsBuilder, USE_MANAGED_IDENTITY, PropertyValue::asBoolean, ADLSCredentialsDetails.Builder::setUseManagedIdentity);
+ setValue(credentialsBuilder, ACCOUNT_NAME, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setAccountName, attributes);
+ setValue(credentialsBuilder, ACCOUNT_KEY, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setAccountKey, attributes);
+ setValue(credentialsBuilder, SAS_TOKEN, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setSasToken, attributes);
+ setValue(credentialsBuilder, ENDPOINT_SUFFIX, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setEndpointSuffix, attributes);
+ setValue(credentialsBuilder, USE_MANAGED_IDENTITY, PropertyValue::asBoolean, ADLSCredentialsDetails.Builder::setUseManagedIdentity, attributes);
+ setValue(credentialsBuilder, SERVICE_PRINCIPAL_TENANT_ID, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setServicePrincipalTenantId, attributes);
+ setValue(credentialsBuilder, SERVICE_PRINCIPAL_CLIENT_ID, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setServicePrincipalClientId, attributes);
+ setValue(credentialsBuilder, SERVICE_PRINCIPAL_CLIENT_SECRET, PropertyValue::getValue, ADLSCredentialsDetails.Builder::setServicePrincipalClientSecret, attributes);
return credentialsBuilder.build();
}
private <T> void setValue(
- ADLSCredentialsDetails.Builder credentialsBuilder,
- PropertyDescriptor propertyDescriptor, Function<PropertyValue, T> getPropertyValue,
- BiConsumer<ADLSCredentialsDetails.Builder, T> setBuilderValue
+ ADLSCredentialsDetails.Builder credentialsBuilder,
+ PropertyDescriptor propertyDescriptor, Function<PropertyValue, T> getPropertyValue,
+ BiConsumer<ADLSCredentialsDetails.Builder, T> setBuilderValue, Map<String, String> attributes
) {
PropertyValue property = context.getProperty(propertyDescriptor);
if (property.isSet()) {
+ if (propertyDescriptor.isExpressionLanguageSupported()) {
+ property = property.evaluateAttributeExpressions(attributes);
+ }
T value = getPropertyValue.apply(property);
setBuilderValue.accept(credentialsBuilder, value);
}
diff --git a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/test/java/org/apache/nifi/services/azure/storage/TestADLSCredentialsControllerService.java b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/test/java/org/apache/nifi/services/azure/storage/TestADLSCredentialsControllerService.java
index aa51c4c..6837c9e 100644
--- a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/test/java/org/apache/nifi/services/azure/storage/TestADLSCredentialsControllerService.java
+++ b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/test/java/org/apache/nifi/services/azure/storage/TestADLSCredentialsControllerService.java
@@ -16,7 +16,7 @@
*/
package org.apache.nifi.services.azure.storage;
-import org.apache.nifi.processors.azure.storage.utils.AzureStorageUtils;
+import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.util.NoOpProcessor;
import org.apache.nifi.util.TestRunner;
@@ -39,7 +39,10 @@ public class TestADLSCredentialsControllerService {
private static final String ACCOUNT_NAME_VALUE = "AccountName";
private static final String ACCOUNT_KEY_VALUE = "AccountKey";
private static final String SAS_TOKEN_VALUE = "SasToken";
- public static final String END_POINT_SUFFIX_VALUE = "end.point.suffix";
+ private static final String END_POINT_SUFFIX_VALUE = "end.point.suffix";
+ private static final String SERVICE_PRINCIPAL_TENANT_ID_VALUE = "ServicePrincipalTenantID";
+ private static final String SERVICE_PRINCIPAL_CLIENT_ID_VALUE = "ServicePrincipalClientID";
+ private static final String SERVICE_PRINCIPAL_CLIENT_SECRET_VALUE = "ServicePrincipalClientSecret";
private TestRunner runner;
private ADLSCredentialsControllerService credentialsService;
@@ -86,6 +89,36 @@ public class TestADLSCredentialsControllerService {
}
@Test
+ public void testNotValidBecauseBothAccountKeyAndServicePrincipalTenantIdSpecified() {
+ configureAccountName();
+
+ configureAccountKey();
+ configureServicePrincipalTenantId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothAccountKeyAndServicePrincipalClientIdSpecified() {
+ configureAccountName();
+
+ configureAccountKey();
+ configureServicePrincipalClientId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothAccountKeyAndServicePrincipalClientSecretSpecified() {
+ configureAccountName();
+
+ configureAccountKey();
+ configureServicePrincipalClientSecret();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
public void testNotValidBecauseBothSasTokenAndUseManagedIdentitySpecified() {
configureAccountName();
@@ -96,12 +129,75 @@ public class TestADLSCredentialsControllerService {
}
@Test
- public void testNotValidBecauseAllCredentialsSpecified() {
+ public void testNotValidBecauseBothSasTokenAndServicePrincipalTenantIdSpecified() {
+ configureAccountName();
+
+ configureSasToken();
+ configureServicePrincipalTenantId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothSasTokenAndServicePrincipalClientIdSpecified() {
+ configureAccountName();
+
+ configureSasToken();
+ configureServicePrincipalClientId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothSasTokenAndServicePrincipalClientSecretSpecified() {
+ configureAccountName();
+
+ configureSasToken();
+ configureServicePrincipalClientSecret();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothUseManagedIdentityAndServicePrincipalTenantIdSpecified() {
+ configureAccountName();
+
+ configureUseManagedIdentity();
+ configureServicePrincipalTenantId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothUseManagedIdentityAndServicePrincipalClientIdSpecified() {
+ configureAccountName();
+
+ configureUseManagedIdentity();
+ configureServicePrincipalClientId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseBothUseManagedIdentityAndServicePrincipalClientSecretSpecified() {
+ configureAccountName();
+
+ configureUseManagedIdentity();
+ configureServicePrincipalClientSecret();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseAllCredentialsSpecified() throws Exception {
configureAccountName();
configureAccountKey();
configureSasToken();
configureUseManagedIdentity();
+ configureServicePrincipalTenantId();
+ configureServicePrincipalClientId();
+ configureServicePrincipalClientSecret();
runner.assertNotValid(credentialsService);
}
@@ -148,6 +244,46 @@ public class TestADLSCredentialsControllerService {
}
@Test
+ public void testValidWithAccountNameAndServicePrincipalWithClientSecret() {
+ configureAccountName();
+ configureServicePrincipalTenantId();
+ configureServicePrincipalClientId();
+ configureServicePrincipalClientSecret();
+
+ runner.assertValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseNoTenantIdSpecifiedForServicePrincipal() {
+ configureAccountName();
+
+ configureServicePrincipalClientId();
+ configureServicePrincipalClientSecret();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseNoClientIdSpecifiedForServicePrincipal() {
+ configureAccountName();
+
+ configureServicePrincipalTenantId();
+ configureServicePrincipalClientSecret();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
+ public void testNotValidBecauseNoClientSecretSpecifiedForServicePrincipal() {
+ configureAccountName();
+
+ configureServicePrincipalTenantId();
+ configureServicePrincipalClientId();
+
+ runner.assertNotValid(credentialsService);
+ }
+
+ @Test
public void testGetCredentialsDetailsWithAccountKey() throws Exception {
// GIVEN
configureAccountName();
@@ -164,6 +300,9 @@ public class TestADLSCredentialsControllerService {
assertNull(actual.getSasToken());
assertFalse(actual.getUseManagedIdentity());
assertNotNull(actual.getEndpointSuffix());
+ assertNull(actual.getServicePrincipalTenantId());
+ assertNull(actual.getServicePrincipalClientId());
+ assertNull(actual.getServicePrincipalClientSecret());
}
@Test
@@ -183,6 +322,9 @@ public class TestADLSCredentialsControllerService {
assertNull(actual.getAccountKey());
assertFalse(actual.getUseManagedIdentity());
assertNotNull(actual.getEndpointSuffix());
+ assertNull(actual.getServicePrincipalTenantId());
+ assertNull(actual.getServicePrincipalClientId());
+ assertNull(actual.getServicePrincipalClientSecret());
}
@Test
@@ -202,6 +344,33 @@ public class TestADLSCredentialsControllerService {
assertNull(actual.getAccountKey());
assertNull(actual.getSasToken());
assertNotNull(actual.getEndpointSuffix());
+ assertNull(actual.getServicePrincipalTenantId());
+ assertNull(actual.getServicePrincipalClientId());
+ assertNull(actual.getServicePrincipalClientSecret());
+ }
+
+ @Test
+ public void testGetCredentialsDetailsWithServicePrincipalWithClientSecret() throws Exception {
+ // GIVEN
+ configureAccountName();
+ configureServicePrincipalTenantId();
+ configureServicePrincipalClientId();
+ configureServicePrincipalClientSecret();
+
+ runner.enableControllerService(credentialsService);
+
+ // WHEN
+ ADLSCredentialsDetails actual = credentialsService.getCredentialsDetails(new HashMap<>());
+
+ // THEN
+ assertEquals(ACCOUNT_NAME_VALUE, actual.getAccountName());
+ assertNull(actual.getAccountKey());
+ assertNull(actual.getSasToken());
+ assertFalse(actual.getUseManagedIdentity());
+ assertNotNull(actual.getEndpointSuffix());
+ assertEquals(SERVICE_PRINCIPAL_TENANT_ID_VALUE, actual.getServicePrincipalTenantId());
+ assertEquals(SERVICE_PRINCIPAL_CLIENT_ID_VALUE, actual.getServicePrincipalClientId());
+ assertEquals(SERVICE_PRINCIPAL_CLIENT_SECRET_VALUE, actual.getServicePrincipalClientSecret());
}
@Test
@@ -220,16 +389,32 @@ public class TestADLSCredentialsControllerService {
assertEquals(END_POINT_SUFFIX_VALUE, actual.getEndpointSuffix());
}
+ @Test
+ public void testGetCredentialsDetailsWithSetEndpointSuffixUsingEL() throws Exception {
+ // GIVEN
+ configureAccountName();
+ configureAccountKey();
+ configureEndpointSuffixUsingEL();
+
+ runner.enableControllerService(credentialsService);
+
+ // WHEN
+ ADLSCredentialsDetails actual = credentialsService.getCredentialsDetails(new HashMap<>());
+
+ // THEN
+ assertEquals(END_POINT_SUFFIX_VALUE, actual.getEndpointSuffix());
+ }
+
private void configureAccountName() {
runner.setProperty(credentialsService, ADLSCredentialsControllerService.ACCOUNT_NAME, ACCOUNT_NAME_VALUE);
}
private void configureAccountKey() {
- runner.setProperty(credentialsService, AzureStorageUtils.ACCOUNT_KEY, ACCOUNT_KEY_VALUE);
+ runner.setProperty(credentialsService, ADLSCredentialsControllerService.ACCOUNT_KEY, ACCOUNT_KEY_VALUE);
}
private void configureSasToken() {
- runner.setProperty(credentialsService, AzureStorageUtils.PROP_SAS_TOKEN, SAS_TOKEN_VALUE);
+ runner.setProperty(credentialsService, ADLSCredentialsControllerService.SAS_TOKEN, SAS_TOKEN_VALUE);
}
private void configureUseManagedIdentity() {
@@ -239,4 +424,26 @@ public class TestADLSCredentialsControllerService {
private void configureEndpointSuffix() {
runner.setProperty(credentialsService, ADLSCredentialsControllerService.ENDPOINT_SUFFIX, END_POINT_SUFFIX_VALUE);
}
+
+ private void configureEndpointSuffixUsingEL() {
+ String variableName = "endpoint.suffix";
+ configurePropertyUsingEL(ADLSCredentialsControllerService.ENDPOINT_SUFFIX, variableName, END_POINT_SUFFIX_VALUE);
+ }
+
+ private void configureServicePrincipalTenantId() {
+ runner.setProperty(credentialsService, ADLSCredentialsControllerService.SERVICE_PRINCIPAL_TENANT_ID, SERVICE_PRINCIPAL_TENANT_ID_VALUE);
+ }
+
+ private void configureServicePrincipalClientId() {
+ runner.setProperty(credentialsService, ADLSCredentialsControllerService.SERVICE_PRINCIPAL_CLIENT_ID, SERVICE_PRINCIPAL_CLIENT_ID_VALUE);
+ }
+
+ private void configureServicePrincipalClientSecret() {
+ runner.setProperty(credentialsService, ADLSCredentialsControllerService.SERVICE_PRINCIPAL_CLIENT_SECRET, SERVICE_PRINCIPAL_CLIENT_SECRET_VALUE);
+ }
+
+ private void configurePropertyUsingEL(PropertyDescriptor propertyDescriptor, String variableName, String variableValue) {
+ runner.setProperty(credentialsService, propertyDescriptor, String.format("${%s}", variableName));
+ runner.setVariable(variableName, variableValue);
+ }
}
diff --git a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-services-api/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsDetails.java b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-services-api/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsDetails.java
index cd1111e..03143ed 100644
--- a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-services-api/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsDetails.java
+++ b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-services-api/src/main/java/org/apache/nifi/services/azure/storage/ADLSCredentialsDetails.java
@@ -29,13 +29,20 @@ public class ADLSCredentialsDetails {
private final boolean useManagedIdentity;
+ private final String servicePrincipalTenantId;
+ private final String servicePrincipalClientId;
+ private final String servicePrincipalClientSecret;
+
public ADLSCredentialsDetails(
- String accountName,
- String accountKey,
- String sasToken,
- String endpointSuffix,
- AccessToken accessToken,
- boolean useManagedIdentity
+ String accountName,
+ String accountKey,
+ String sasToken,
+ String endpointSuffix,
+ AccessToken accessToken,
+ boolean useManagedIdentity,
+ String servicePrincipalTenantId,
+ String servicePrincipalClientId,
+ String servicePrincipalClientSecret
) {
this.accountName = accountName;
this.accountKey = accountKey;
@@ -43,6 +50,9 @@ public class ADLSCredentialsDetails {
this.endpointSuffix = endpointSuffix;
this.accessToken = accessToken;
this.useManagedIdentity = useManagedIdentity;
+ this.servicePrincipalTenantId = servicePrincipalTenantId;
+ this.servicePrincipalClientId = servicePrincipalClientId;
+ this.servicePrincipalClientSecret = servicePrincipalClientSecret;
}
public String getAccountName() {
@@ -69,6 +79,18 @@ public class ADLSCredentialsDetails {
return useManagedIdentity;
}
+ public String getServicePrincipalTenantId() {
+ return servicePrincipalTenantId;
+ }
+
+ public String getServicePrincipalClientId() {
+ return servicePrincipalClientId;
+ }
+
+ public String getServicePrincipalClientSecret() {
+ return servicePrincipalClientSecret;
+ }
+
public static class Builder {
private String accountName;
private String accountKey;
@@ -76,6 +98,9 @@ public class ADLSCredentialsDetails {
private String endpointSuffix;
private AccessToken accessToken;
private boolean useManagedIdentity;
+ private String servicePrincipalTenantId;
+ private String servicePrincipalClientId;
+ private String servicePrincipalClientSecret;
private Builder() {}
@@ -113,8 +138,24 @@ public class ADLSCredentialsDetails {
return this;
}
+ public Builder setServicePrincipalTenantId(String servicePrincipalTenantId) {
+ this.servicePrincipalTenantId = servicePrincipalTenantId;
+ return this;
+ }
+
+ public Builder setServicePrincipalClientId(String servicePrincipalClientId) {
+ this.servicePrincipalClientId = servicePrincipalClientId;
+ return this;
+ }
+
+ public Builder setServicePrincipalClientSecret(String servicePrincipalClientSecret) {
+ this.servicePrincipalClientSecret = servicePrincipalClientSecret;
+ return this;
+ }
+
public ADLSCredentialsDetails build() {
- return new ADLSCredentialsDetails(accountName, accountKey, sasToken, endpointSuffix, accessToken, useManagedIdentity);
+ return new ADLSCredentialsDetails(accountName, accountKey, sasToken, endpointSuffix, accessToken, useManagedIdentity,
+ servicePrincipalTenantId, servicePrincipalClientId, servicePrincipalClientSecret);
}
}
}