Update ElasticsearchClientService property descriptor dependencies

This commit is contained in:
Chris Sampson 2025-01-23 20:57:25 +00:00
parent 90cada2204
commit 39b16c3617
No known key found for this signature in database
GPG Key ID: 546AEB0826587237
3 changed files with 24 additions and 84 deletions

View File

@ -69,11 +69,21 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
.displayName("OAuth2 Access Token Provider") .displayName("OAuth2 Access Token Provider")
.description("The OAuth2 Access Token Provider used to provide JWTs for Bearer Token Authorization with Elasticsearch.") .description("The OAuth2 Access Token Provider used to provide JWTs for Bearer Token Authorization with Elasticsearch.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.JWT) .dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.JWT)
.required(false) .required(true)
.identifiesControllerService(OAuth2AccessTokenProvider.class) .identifiesControllerService(OAuth2AccessTokenProvider.class)
.addValidator(Validator.VALID) .addValidator(Validator.VALID)
.build(); .build();
PropertyDescriptor JWT_SHARED_SECRET = new PropertyDescriptor.Builder()
.name("jwt-shared-secret")
.displayName("JWT Shared Secret")
.description("JWT realm Shared Secret.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.JWT)
.required(true)
.sensitive(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
PropertyDescriptor RUN_AS_USER = new PropertyDescriptor.Builder() PropertyDescriptor RUN_AS_USER = new PropertyDescriptor.Builder()
.name("el-cs-run-as-user") .name("el-cs-run-as-user")
.displayName("Run As User") .displayName("Run As User")
@ -88,7 +98,7 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
.displayName("Username") .displayName("Username")
.description("The username to use with XPack security.") .description("The username to use with XPack security.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.BASIC) .dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.BASIC)
.required(false) .required(true)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT) .expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build(); .build();
@ -98,7 +108,7 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
.displayName("Password") .displayName("Password")
.description("The password to use with XPack security.") .description("The password to use with XPack security.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.BASIC) .dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.BASIC)
.required(false) .required(true)
.sensitive(true) .sensitive(true)
.expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT) .expressionLanguageSupported(ExpressionLanguageScope.ENVIRONMENT)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
@ -109,7 +119,7 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
.displayName("API Key ID") .displayName("API Key ID")
.description("Unique identifier of the API key.") .description("Unique identifier of the API key.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.API_KEY) .dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.API_KEY)
.required(false) .required(true)
.sensitive(false) .sensitive(false)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build(); .build();
@ -119,17 +129,7 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
.displayName("API Key") .displayName("API Key")
.description("Encoded API key.") .description("Encoded API key.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.API_KEY) .dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.API_KEY)
.required(false) .required(true)
.sensitive(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
PropertyDescriptor JWT_SHARED_SECRET = new PropertyDescriptor.Builder()
.name("jwt-shared-secret")
.displayName("JWT Shared Secret")
.description("JWT realm Shared Secret.")
.dependsOn(AUTHORIZATION_SCHEME, AuthorizationScheme.JWT)
.required(false)
.sensitive(true) .sensitive(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build(); .build();

View File

@ -164,17 +164,8 @@ public class ElasticSearchClientServiceImpl extends AbstractControllerService im
final AuthorizationScheme authorizationScheme = validationContext.getProperty(AUTHORIZATION_SCHEME).asAllowableValue(AuthorizationScheme.class); final AuthorizationScheme authorizationScheme = validationContext.getProperty(AUTHORIZATION_SCHEME).asAllowableValue(AuthorizationScheme.class);
final boolean usernameSet = validationContext.getProperty(USERNAME).isSet();
final boolean passwordSet = validationContext.getProperty(PASSWORD).isSet();
final boolean apiKeyIdSet = validationContext.getProperty(API_KEY_ID).isSet();
final boolean apiKeySet = validationContext.getProperty(API_KEY).isSet();
final SSLContextProvider sslContextProvider = validationContext.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class); final SSLContextProvider sslContextProvider = validationContext.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
final boolean jwtSharedSecretSet = validationContext.getProperty(JWT_SHARED_SECRET).isSet();
final OAuth2AccessTokenProvider oAuth2Provider = validationContext.getProperty(OAUTH2_ACCESS_TOKEN_PROVIDER).asControllerService(OAuth2AccessTokenProvider.class);
if (authorizationScheme == AuthorizationScheme.PKI && (sslContextProvider == null)) { if (authorizationScheme == AuthorizationScheme.PKI && (sslContextProvider == null)) {
results.add(new ValidationResult.Builder().subject(PROP_SSL_CONTEXT_SERVICE.getName()).valid(false) results.add(new ValidationResult.Builder().subject(PROP_SSL_CONTEXT_SERVICE.getName()).valid(false)
.explanation(String.format("if '%s' is '%s' then '%s' must be set and specify a Keystore for mutual TLS encryption.", .explanation(String.format("if '%s' is '%s' then '%s' must be set and specify a Keystore for mutual TLS encryption.",
@ -183,35 +174,6 @@ public class ElasticSearchClientServiceImpl extends AbstractControllerService im
); );
} }
if (authorizationScheme == AuthorizationScheme.JWT) {
if (oAuth2Provider == null) {
results.add(new ValidationResult.Builder().subject(OAUTH2_ACCESS_TOKEN_PROVIDER.getName()).valid(false)
.explanation(String.format("if '%s' is '%s' then '%s' must be set.",
AUTHORIZATION_SCHEME.getDisplayName(), authorizationScheme.getDisplayName(), OAUTH2_ACCESS_TOKEN_PROVIDER.getDisplayName())
).build()
);
}
if (!jwtSharedSecretSet) {
results.add(new ValidationResult.Builder().subject(JWT_SHARED_SECRET.getName()).valid(false)
.explanation(String.format("if '%s' is '%s' then '%s' must be set.",
AUTHORIZATION_SCHEME.getDisplayName(), authorizationScheme.getDisplayName(), JWT_SHARED_SECRET.getDisplayName())
).build()
);
}
}
if (usernameSet && !passwordSet) {
addAuthorizationPropertiesValidationIssue(results, USERNAME, PASSWORD);
} else if (passwordSet && !usernameSet) {
addAuthorizationPropertiesValidationIssue(results, PASSWORD, USERNAME);
}
if (apiKeyIdSet && !apiKeySet) {
addAuthorizationPropertiesValidationIssue(results, API_KEY_ID, API_KEY);
} else if (apiKeySet && !apiKeyIdSet) {
addAuthorizationPropertiesValidationIssue(results, API_KEY, API_KEY_ID);
}
final boolean sniffClusterNodes = validationContext.getProperty(SNIFF_CLUSTER_NODES).asBoolean(); final boolean sniffClusterNodes = validationContext.getProperty(SNIFF_CLUSTER_NODES).asBoolean();
final boolean sniffOnFailure = validationContext.getProperty(SNIFF_ON_FAILURE).asBoolean(); final boolean sniffOnFailure = validationContext.getProperty(SNIFF_ON_FAILURE).asBoolean();
if (sniffOnFailure && !sniffClusterNodes) { if (sniffOnFailure && !sniffClusterNodes) {
@ -222,13 +184,6 @@ public class ElasticSearchClientServiceImpl extends AbstractControllerService im
return results; return results;
} }
private void addAuthorizationPropertiesValidationIssue(final List<ValidationResult> results, final PropertyDescriptor presentProperty, final PropertyDescriptor missingProperty) {
results.add(new ValidationResult.Builder().subject(missingProperty.getName()).valid(false)
.explanation(String.format("if '%s' is set, then '%s' must be set.", presentProperty.getDisplayName(), missingProperty.getDisplayName()))
.build()
);
}
@OnEnabled @OnEnabled
public void onEnabled(final ConfigurationContext context) throws InitializationException { public void onEnabled(final ConfigurationContext context) throws InitializationException {
try { try {

View File

@ -73,14 +73,11 @@ class ElasticSearchClientServiceImplTest {
runner.assertValid(service); runner.assertValid(service);
runner.removeProperty(service, ElasticSearchClientService.PASSWORD); runner.removeProperty(service, ElasticSearchClientService.PASSWORD);
assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.USERNAME, ElasticSearchClientService.PASSWORD); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.PASSWORD);
runner.removeProperty(service, ElasticSearchClientService.USERNAME);
runner.assertValid(service);
runner.setProperty(service, ElasticSearchClientService.PASSWORD, "password"); runner.setProperty(service, ElasticSearchClientService.PASSWORD, "password");
runner.removeProperty(service, ElasticSearchClientService.USERNAME); runner.removeProperty(service, ElasticSearchClientService.USERNAME);
assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.PASSWORD, ElasticSearchClientService.USERNAME); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.USERNAME);
} }
@Test @Test
@ -91,14 +88,11 @@ class ElasticSearchClientServiceImplTest {
runner.assertValid(service); runner.assertValid(service);
runner.removeProperty(service, ElasticSearchClientService.API_KEY_ID); runner.removeProperty(service, ElasticSearchClientService.API_KEY_ID);
assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.API_KEY, ElasticSearchClientService.API_KEY_ID); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.API_KEY_ID);
runner.removeProperty(service, ElasticSearchClientService.API_KEY);
runner.assertValid(service);
runner.setProperty(service, ElasticSearchClientService.API_KEY_ID, "api-key-id"); runner.setProperty(service, ElasticSearchClientService.API_KEY_ID, "api-key-id");
runner.removeProperty(service, ElasticSearchClientService.API_KEY); runner.removeProperty(service, ElasticSearchClientService.API_KEY);
assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.API_KEY_ID, ElasticSearchClientService.API_KEY); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.API_KEY);
} }
@Test @Test
@ -119,7 +113,7 @@ class ElasticSearchClientServiceImplTest {
void testValidateJwtAuth() throws InitializationException { void testValidateJwtAuth() throws InitializationException {
runner.setProperty(service, ElasticSearchClientService.AUTHORIZATION_SCHEME, AuthorizationScheme.JWT); runner.setProperty(service, ElasticSearchClientService.AUTHORIZATION_SCHEME, AuthorizationScheme.JWT);
runner.setProperty(service, ElasticSearchClientService.JWT_SHARED_SECRET, "jwt-shared-secret"); runner.setProperty(service, ElasticSearchClientService.JWT_SHARED_SECRET, "jwt-shared-secret");
assertJWTAuthorizationValidationErrorMessage(ElasticSearchClientService.OAUTH2_ACCESS_TOKEN_PROVIDER); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.OAUTH2_ACCESS_TOKEN_PROVIDER);
final OAuth2AccessTokenProvider oAuth2AccessTokenProvider = mock(OAuth2AccessTokenProvider.class); final OAuth2AccessTokenProvider oAuth2AccessTokenProvider = mock(OAuth2AccessTokenProvider.class);
when(oAuth2AccessTokenProvider.getIdentifier()).thenReturn("oauth2-access-token-provider"); when(oAuth2AccessTokenProvider.getIdentifier()).thenReturn("oauth2-access-token-provider");
@ -128,12 +122,13 @@ class ElasticSearchClientServiceImplTest {
runner.assertValid(service); runner.assertValid(service);
runner.removeProperty(service, ElasticSearchClientService.JWT_SHARED_SECRET); runner.removeProperty(service, ElasticSearchClientService.JWT_SHARED_SECRET);
assertJWTAuthorizationValidationErrorMessage(ElasticSearchClientService.JWT_SHARED_SECRET); assertAuthorizationPropertyValidationErrorMessage(ElasticSearchClientService.JWT_SHARED_SECRET);
} }
private void assertAuthorizationPropertyValidationErrorMessage(final PropertyDescriptor presentProperty, final PropertyDescriptor missingProperty) { private void assertAuthorizationPropertyValidationErrorMessage(final PropertyDescriptor missingProperty) {
final AssertionFailedError afe = assertThrows(AssertionFailedError.class, () -> runner.assertValid(service)); final AssertionFailedError afe = assertThrows(AssertionFailedError.class, () -> runner.assertValid(service));
assertTrue(afe.getMessage().contains(String.format("if '%s' is set, then '%s' must be set.", presentProperty.getDisplayName(), missingProperty.getDisplayName()))); final String expectedMessage = String.format("%s is required", missingProperty.getDisplayName());
assertTrue(afe.getMessage().contains(expectedMessage), String.format("Validation error message \"%s\" does not contain \"%s\"", afe.getMessage(), expectedMessage));
} }
private void assertPKIAuthorizationValidationErrorMessage() { private void assertPKIAuthorizationValidationErrorMessage() {
@ -145,14 +140,4 @@ class ElasticSearchClientServiceImplTest {
ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE.getDisplayName() ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE.getDisplayName()
))); )));
} }
private void assertJWTAuthorizationValidationErrorMessage(final PropertyDescriptor expectedMissingProperty) {
final AssertionFailedError afe = assertThrows(AssertionFailedError.class, () -> runner.assertValid(service));
assertTrue(afe.getMessage().contains(String.format(
"if '%s' is '%s' then '%s' must be set.",
ElasticSearchClientService.AUTHORIZATION_SCHEME.getDisplayName(),
AuthorizationScheme.JWT.getDisplayName(),
expectedMissingProperty.getDisplayName()
)));
}
} }