sashapolo commented on code in PR #1569:
URL: https://github.com/apache/ignite-3/pull/1569#discussion_r1123272084
##########
modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java:
##########
@@ -102,20 +107,24 @@ private void init(int port) throws IOException {
var logicalTopologyService = new
LogicalTopologyImpl(clusterStateStorage);
+ var distributedConfigurationUpdater = new
DistributedConfigurationUpdater();
+
distributedConfigurationUpdater.setClusterRestConfiguration(securityConfiguration);
+
this.clusterManager = new ClusterManagementGroupManager(
vaultManager,
clusterService,
raftManager,
clusterStateStorage,
logicalTopologyService,
- cmgConfiguration
- );
+ cmgConfiguration,
+ distributedConfigurationUpdater);
components.add(vaultManager);
components.add(clusterService);
components.add(raftManager);
components.add(clusterStateStorage);
components.add(clusterManager);
+ components.add(distributedConfigurationUpdater);
Review Comment:
This is a wrong component order, since `clusterManager` depends on
`distributedConfigurationUpdater`, `distributedConfigurationUpdater` should be
started earlier.
##########
modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItClusterManagementControllerTest.java:
##########
@@ -36,18 +38,28 @@
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import jakarta.inject.Inject;
import java.util.List;
+import org.apache.ignite.internal.configuration.AuthenticationConfiguration;
+import
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
+import
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
import org.apache.ignite.internal.rest.api.cluster.ClusterManagementApi;
import org.apache.ignite.internal.rest.api.cluster.ClusterStateDto;
+import org.apache.ignite.internal.rest.authentication.AuthProviderFactory;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
/**
* Cluster management REST test.
*/
+@Property(name = "micronaut.security.enabled", value = "false")
+@ExtendWith(ConfigurationExtension.class)
public class ItClusterManagementControllerTest extends RestTestBase {
@Inject
@Client("/management/v1/cluster")
private HttpClient client;
+ @InjectConfiguration
+ AuthenticationConfiguration authenticationConfiguration;
Review Comment:
can be private
##########
modules/rest/src/test/java/org/apache/ignite/internal/rest/authentication/DelegatingAuthenticationProviderTest.java:
##########
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.rest.authentication;
+
+import static
org.apache.ignite.internal.testframework.flow.TestFlowUtils.subscribeToValue;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willFailFast;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static reactor.adapter.JdkFlowAdapter.publisherToFlowPublisher;
+
+import io.micronaut.http.HttpMethod;
+import io.micronaut.http.simple.SimpleHttpRequest;
+import io.micronaut.security.authentication.AuthenticationException;
+import io.micronaut.security.authentication.AuthenticationResponse;
+import io.micronaut.security.authentication.UsernamePasswordCredentials;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import org.apache.ignite.internal.configuration.AuthenticationChange;
+import org.apache.ignite.internal.configuration.AuthenticationConfiguration;
+import org.apache.ignite.internal.configuration.AuthenticationView;
+import
org.apache.ignite.internal.configuration.BasicAuthenticationProviderChange;
+import
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
+import
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+
+@ExtendWith(ConfigurationExtension.class)
+class DelegatingAuthenticationProviderTest {
+
+ private final SimpleHttpRequest<Object> httpRequest = new
SimpleHttpRequest<>(HttpMethod.GET, "/", null);
+
+ private final DelegatingAuthenticationProvider provider = new
DelegatingAuthenticationProvider();
+
+ @InjectConfiguration
+ private AuthenticationConfiguration authenticationConfiguration;
+
+ @Test
+ public void enableAuth() {
+ // when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // unsuccessful authentication with invalid credentials
+ UsernamePasswordCredentials invalidCredentials = new
UsernamePasswordCredentials("admin", "wrong-password");
+ assertThat(authenticate(provider, invalidCredentials),
willFailFast(AuthenticationException.class));
+
+ }
+
+ @Test
+ public void leaveOldSettingWhenInvalidConfiguration() {
+ // when
+ AuthenticationView invalidAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeEnabled(true);
+ })
+ .value();
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
invalidAuthView)).join();
+
+ // then
+ // authentication is still disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void disableAuthEmptyProviders() {
+ //when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+
+ // just to be sure that authentication is enabled
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // disable authentication
+ AuthenticationView disabledAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.delete("basic"));
+ change.changeEnabled(false);
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView, disabledAuthView)).join();
+
+ // then
+ // authentication is disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void disableAuthNotEmptyProviders() {
+ //when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // disable authentication
+ AuthenticationView disabledAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeEnabled(false);
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView, disabledAuthView)).join();
+
+ // then
+ // authentication is disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void changedCredentials() {
+ // when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials adminAdminCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, adminAdminCredentials),
willCompleteSuccessfully());
+
+ // change authentication settings - change password
+ AuthenticationView adminNewPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.update("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("new-password")
+ .changeName("basic");
+ }));
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView,
adminNewPasswordAuthView)).join();
+
+ assertThat(authenticate(provider, adminAdminCredentials),
willFailFast(AuthenticationException.class));
+
+ // then
+ // successful authentication with the new password
+ UsernamePasswordCredentials adminPasswordCredentials = new
UsernamePasswordCredentials("admin", "new-password");
+ assertThat(authenticate(provider, adminPasswordCredentials),
willCompleteSuccessfully());
+ }
+
+ private CompletableFuture<AuthenticationResponse> authenticate(
+ DelegatingAuthenticationProvider provider,
+ UsernamePasswordCredentials credentials
+ ) {
+ return
subscribeToValue(publisherToFlowPublisher(provider.authenticate(httpRequest,
credentials)));
+ }
+
+ private static AuthenticationConfiguration
mutateConfiguration(AuthenticationConfiguration configuration,
+ Consumer<AuthenticationChange> consumer) {
+ CompletableFuture<AuthenticationConfiguration> future =
configuration.change(consumer)
+ .thenApply(unused -> configuration);
+ assertThat(future, willCompleteSuccessfully());
+ try {
+ return future.get();
Review Comment:
just a nitpick, but you can use `future.join` here
##########
modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ssl/ItRestSslTest.java:
##########
@@ -105,12 +106,49 @@ static void beforeAll(TestInfo testInfo) throws Exception
{
.sslContext(sslContextWithClientAuth())
.build();
- httpNode = new RestNode(workDir, testNodeName(testInfo, 3344), 3344,
10300, 10400, false, false, false);
- httpsNode = new RestNode(workDir, testNodeName(testInfo, 3345), 3345,
10301, 10401, true, false, false);
- dualProtocolNode = new RestNode(workDir, testNodeName(testInfo, 3346),
3346, 10302, 10402, true, false, true);
- httpsWithClientAuthNode = new RestNode(workDir, testNodeName(testInfo,
3347), 3347, 10303, 10403, true, true, false);
+ httpNode = RestNode.builder()
+ .workDir(workDir)
+ .name(testNodeName(testInfo, 3344))
+ .networkPort(3344)
+ .httpPort(10300)
+ .httpsPort(10400)
+ .sslEnabled(false)
+ .dualProtocol(false)
+ .build();
+
+ httpsNode = RestNode.builder()
+ .workDir(workDir)
+ .name(testNodeName(testInfo, 3345))
+ .networkPort(3345)
+ .httpPort(10301)
+ .httpsPort(10401)
+ .sslEnabled(true)
+ .dualProtocol(false)
+ .build();
+
+ dualProtocolNode = RestNode.builder()
+ .workDir(workDir)
+ .name(testNodeName(testInfo, 3346))
+ .networkPort(3346)
+ .httpPort(10302)
+ .httpsPort(10402)
+ .sslEnabled(true)
+ .dualProtocol(true)
+ .build();
+
+ httpsWithClientAuthNode = RestNode.builder()
+ .workDir(workDir)
+ .name(testNodeName(testInfo, 3347))
+ .networkPort(3347)
+ .httpPort(10303)
+ .httpsPort(10403)
+ .sslEnabled(true)
+ .sslClientAuthEnabled(true)
+ .dualProtocol(false)
+ .build();
- Stream.of(httpNode, httpsNode, dualProtocolNode,
httpsWithClientAuthNode).forEach(RestNode::start);
+ Stream.of(httpNode, httpsNode, dualProtocolNode,
httpsWithClientAuthNode)
Review Comment:
We can start these nodes in parallel, it will improve the test running time
##########
modules/security/src/test/java/org/apache/ignite/internal/configuration/AuthenticationConfigurationValidatorTest.java:
##########
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.configuration;
+
+import static
org.apache.ignite.internal.configuration.validation.TestValidationUtil.mockValidationContext;
+import static
org.apache.ignite.internal.configuration.validation.TestValidationUtil.validate;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import org.apache.ignite.configuration.validation.ValidationContext;
+import
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
+import
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+
+@ExtendWith(ConfigurationExtension.class)
+class AuthenticationConfigurationValidatorTest {
+
+ @InjectConfiguration
+ private AuthenticationConfiguration authenticationConfiguration;
+
+ @Test
+ public void nullAuth() {
+ // when
+ ValidationContext<AuthenticationView> ctx =
mockValidationContext(null, null);
+
+ // then
+ validate(AuthenticationConfigurationValidatorImpl.INSTANCE,
mock(AuthenticationConfigurationValidator.class), ctx,
+ "Auth config must not be null");
+ }
+
+ @Test
+ public void enableAuthEmptyProviders() {
+ // when
+ AuthenticationView newValue =
mutateConfiguration(authenticationConfiguration, change ->
change.changeEnabled(true)).value();
+ ValidationContext<AuthenticationView> ctx = mockValidationContext(
+ null,
+ newValue
+ );
+
+ // then
+ validate(AuthenticationConfigurationValidatorImpl.INSTANCE,
mock(AuthenticationConfigurationValidator.class), ctx,
+ "Providers must be present, if auth is enabled");
+ }
+
+ @Test
+ public void enableAuthNotEmptyProviders() {
+ // when
+ AuthenticationView newValue =
mutateConfiguration(authenticationConfiguration, change -> {
+ change.changeProviders(providers -> providers.create("basic",
provider -> {
+ provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("admin")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ }).value();
+
+ ValidationContext<AuthenticationView> ctx = mockValidationContext(
+ null,
+ newValue
+ );
+
+ // then
+ validate(AuthenticationConfigurationValidatorImpl.INSTANCE,
mock(AuthenticationConfigurationValidator.class), ctx, null);
+ }
+
+ @Test
+ public void disableAuthEmptyProviders() {
+ // when
+ AuthenticationView newValue =
mutateConfiguration(authenticationConfiguration, change ->
change.changeEnabled(false)).value();
+ ValidationContext<AuthenticationView> ctx = mockValidationContext(
+ null,
+ newValue
+ );
+
+ // then
+ validate(AuthenticationConfigurationValidatorImpl.INSTANCE,
mock(AuthenticationConfigurationValidator.class), ctx, null);
+ }
+
+ @Test
+ public void disableAuthNotEmptyProviders() {
+ // when
+ AuthenticationView newValue =
mutateConfiguration(authenticationConfiguration, change -> {
+ change.changeProviders(providers -> providers.create("basic",
provider -> {
+ provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("admin")
+ .changeName("basic");
+ }));
+ change.changeEnabled(false);
+ }).value();
+
+ ValidationContext<AuthenticationView> ctx = mockValidationContext(
+ null,
+ newValue
+ );
+ validate(AuthenticationConfigurationValidatorImpl.INSTANCE,
mock(AuthenticationConfigurationValidator.class), ctx, null);
+ }
+
+ private static AuthenticationConfiguration
mutateConfiguration(AuthenticationConfiguration configuration,
+ Consumer<AuthenticationChange> consumer) {
+ CompletableFuture<AuthenticationConfiguration> future =
configuration.change(consumer)
+ .thenApply(unused -> configuration);
+ assertThat(future, willCompleteSuccessfully());
+ try {
+ return future.get();
Review Comment:
Same minor comment about `future.join`
##########
modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java:
##########
@@ -640,7 +654,8 @@ public CompletableFuture<Ignite>
start(NodeBootstrapConfiguration cfg) {
indexManager,
qryEngine,
clientHandlerModule,
- (IgniteComponent) deploymentManager
+ (IgniteComponent) deploymentManager,
+ distributedConfigurationUpdater
Review Comment:
This is not correct: `distributedConfigurationUpdater` must be started
before `cmgMgr`
##########
modules/api/src/main/java/org/apache/ignite/InitParameters.java:
##########
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite;
+
+import java.util.Collection;
+import java.util.Objects;
+import org.apache.ignite.rest.AuthenticationConfig;
+
+/** Initialization parameters. */
+public class InitParameters {
+
+ /** Name of the node that the initialization request will be sent to. */
+ private final String nodeName;
+
+ /** Names of nodes that will host the Meta Storage <b>and</b> the CMG. */
+ private final Collection<String> metaStorageNodeNames;
+
+ /** Names of nodes that will host the CMG. */
+ private final Collection<String> cmgNodeNames;
+
+ /** Human-readable name of the cluster. */
+ private final String clusterName;
+
+ /** Authentication configuration, that will be applied after
initialization. */
+ private final AuthenticationConfig authenticationConfig;
+
+ /**
+ * Constructor.
+ *
+ * @param nodeName Name of the node that the initialization request will
be sent to.
+ * @param metaStorageNodeNames Names of nodes that will host the Meta
Storage <b>and</b> the CMG.
+ * @param clusterName Human-readable name of the cluster.
+ * @param authenticationConfig REST authentication configuration.
+ */
+ public InitParameters(String nodeName, Collection<String>
metaStorageNodeNames, Collection<String> cmgNodeNames, String clusterName,
+ AuthenticationConfig authenticationConfig) {
+
+ Objects.requireNonNull(nodeName);
+ Objects.requireNonNull(metaStorageNodeNames);
+ Objects.requireNonNull(cmgNodeNames);
+ Objects.requireNonNull(clusterName);
+ Objects.requireNonNull(authenticationConfig);
+
+ this.nodeName = nodeName;
+ this.metaStorageNodeNames = metaStorageNodeNames;
Review Comment:
Looks like it's not done =)
##########
modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java:
##########
@@ -271,14 +277,17 @@ private List<IgniteComponent> startPartialNode(
var logicalTopology = new LogicalTopologyImpl(clusterStateStorage);
+ var distributedConfigurationUpdater = new
DistributedConfigurationUpdater();
Review Comment:
This object must be added to the `otherComponents` list below
##########
modules/rest/src/test/java/org/apache/ignite/internal/rest/authentication/DelegatingAuthenticationProviderTest.java:
##########
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.rest.authentication;
+
+import static
org.apache.ignite.internal.testframework.flow.TestFlowUtils.subscribeToValue;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willFailFast;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static reactor.adapter.JdkFlowAdapter.publisherToFlowPublisher;
+
+import io.micronaut.http.HttpMethod;
+import io.micronaut.http.simple.SimpleHttpRequest;
+import io.micronaut.security.authentication.AuthenticationException;
+import io.micronaut.security.authentication.AuthenticationResponse;
+import io.micronaut.security.authentication.UsernamePasswordCredentials;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import org.apache.ignite.internal.configuration.AuthenticationChange;
+import org.apache.ignite.internal.configuration.AuthenticationConfiguration;
+import org.apache.ignite.internal.configuration.AuthenticationView;
+import
org.apache.ignite.internal.configuration.BasicAuthenticationProviderChange;
+import
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
+import
org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+
+@ExtendWith(ConfigurationExtension.class)
+class DelegatingAuthenticationProviderTest {
+
+ private final SimpleHttpRequest<Object> httpRequest = new
SimpleHttpRequest<>(HttpMethod.GET, "/", null);
+
+ private final DelegatingAuthenticationProvider provider = new
DelegatingAuthenticationProvider();
+
+ @InjectConfiguration
+ private AuthenticationConfiguration authenticationConfiguration;
+
+ @Test
+ public void enableAuth() {
+ // when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // unsuccessful authentication with invalid credentials
+ UsernamePasswordCredentials invalidCredentials = new
UsernamePasswordCredentials("admin", "wrong-password");
+ assertThat(authenticate(provider, invalidCredentials),
willFailFast(AuthenticationException.class));
+
+ }
+
+ @Test
+ public void leaveOldSettingWhenInvalidConfiguration() {
+ // when
+ AuthenticationView invalidAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeEnabled(true);
+ })
+ .value();
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
invalidAuthView)).join();
+
+ // then
+ // authentication is still disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void disableAuthEmptyProviders() {
+ //when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+
+ // just to be sure that authentication is enabled
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // disable authentication
+ AuthenticationView disabledAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.delete("basic"));
+ change.changeEnabled(false);
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView, disabledAuthView)).join();
+
+ // then
+ // authentication is disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void disableAuthNotEmptyProviders() {
+ //when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials validCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, validCredentials),
willCompleteSuccessfully());
+
+ // disable authentication
+ AuthenticationView disabledAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeEnabled(false);
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView, disabledAuthView)).join();
+
+ // then
+ // authentication is disabled
+ UsernamePasswordCredentials emptyCredentials = new
UsernamePasswordCredentials();
+ assertThat(authenticate(provider, emptyCredentials),
willCompleteSuccessfully());
+ }
+
+ @Test
+ public void changedCredentials() {
+ // when
+ AuthenticationView adminPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.create("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("password")
+ .changeName("basic");
+ }));
+ change.changeEnabled(true);
+ })
+ .value();
+
+ provider.onUpdate(new StubAuthenticationViewEvent(null,
adminPasswordAuthView)).join();
+
+ // then
+ // successful authentication with valid credentials
+ UsernamePasswordCredentials adminAdminCredentials = new
UsernamePasswordCredentials("admin", "password");
+ assertThat(authenticate(provider, adminAdminCredentials),
willCompleteSuccessfully());
+
+ // change authentication settings - change password
+ AuthenticationView adminNewPasswordAuthView = mutateConfiguration(
+ authenticationConfiguration, change -> {
+ change.changeProviders(providers ->
providers.update("basic", provider -> {
+
provider.convert(BasicAuthenticationProviderChange.class)
+ .changeLogin("admin")
+ .changePassword("new-password")
+ .changeName("basic");
+ }));
+ })
+ .value();
+
+ provider.onUpdate(new
StubAuthenticationViewEvent(adminPasswordAuthView,
adminNewPasswordAuthView)).join();
+
+ assertThat(authenticate(provider, adminAdminCredentials),
willFailFast(AuthenticationException.class));
+
+ // then
+ // successful authentication with the new password
+ UsernamePasswordCredentials adminPasswordCredentials = new
UsernamePasswordCredentials("admin", "new-password");
+ assertThat(authenticate(provider, adminPasswordCredentials),
willCompleteSuccessfully());
Review Comment:
Don't we want to check that the authentication response is successful?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]