After upgrading to spring boot 2.3.0, the spring data cassandra reactive failed to work due to authentication issue. We are using plain text username & password authentication. The issue seems to be you need to set advanced.auth-provider.class
here:
private Config cassandraConfiguration(CassandraProperties properties) {
CassandraDriverOptions options = new CassandraDriverOptions();
PropertyMapper map = PropertyMapper.get();
map.from(properties.getSessionName()).whenHasText()
.to((sessionName) -> options.add(DefaultDriverOption.SESSION_NAME, sessionName));
map.from(properties::getUsername).whenNonNull()
.to((username) -> options.add(DefaultDriverOption.AUTH_PROVIDER_USER_NAME, username)
.add(DefaultDriverOption.AUTH_PROVIDER_PASSWORD, properties.getPassword()));
map.from(properties::getCompression).whenNonNull()
.to((compression) -> options.add(DefaultDriverOption.PROTOCOL_COMPRESSION, compression));
mapConnectionOptions(properties, options);
mapPoolingOptions(properties, options);
mapRequestOptions(properties, options);
map.from(mapContactPoints(properties))
.to((contactPoints) -> options.add(DefaultDriverOption.CONTACT_POINTS, contactPoints));
map.from(properties.getLocalDatacenter()).to(
(localDatacenter) -> options.add(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, localDatacenter));
ConfigFactory.invalidateCaches();
return ConfigFactory.defaultOverrides().withFallback(options.build())
.withFallback(ConfigFactory.defaultReference()).resolve();
}
Comment From: valeyko
I have the same issue. As workaround, you can specify auth provider class using DriverConfigLoaderBuilderCustomizer
:
@Configuration
class CassandraConfiguration {
@Bean
fun authProviderCustomizer() = DriverConfigLoaderBuilderCustomizer { builder ->
builder.withString(DefaultDriverOption.AUTH_PROVIDER_CLASS, "com.datastax.oss.driver.internal.core.auth.PlainTextAuthProvider")
}
}
Comment From: wilkinsona
Thanks, @valeyko. Rather than settiing advanced.auth-provider.class
, the recommendation in the documentation seems to be that withAuthCredentials(String, String)
on the CqlSessionBuilder
is used instead. This has the benefit of removing the reference to a class in an internal package.
You can configure the auth credentials in Spring Boot with a CqlSessionBuilderCustomizer
:
@Bean
CqlSessionBuilderCustomizer authCustomizer(CassandraProperties properties) {
return (builder) -> builder.withAuthCredentials(properties.getUsername(), properties.getPassword());
}
@valeyko @andyfromktm can you please try the above and let us know if it resolves your problem. If it does, we can update CassandraAutoConfiguration
to apply this configuration automatically.
Comment From: wilkinsona
When we fix this, we should add an integration test that covers username and password authentication. With thanks to @bsideup for some guidance, we can create a Cassandra instance with its password authenticator configured using the following custom container:
static final class PasswordAuthenticatorCassandraContainer
extends CassandraContainer<PasswordAuthenticatorCassandraContainer> {
@Override
protected void containerIsCreated(String containerId) {
String config = this.copyFileFromContainer("/etc/cassandra/cassandra.yaml",
(stream) -> StreamUtils.copyToString(stream, StandardCharsets.UTF_8));
String updatedConfig = config.replace("authenticator: AllowAllAuthenticator",
"authenticator: PasswordAuthenticator");
this.copyFileToContainer(Transferable.of(updatedConfig.getBytes(StandardCharsets.UTF_8)),
"/etc/cassandra/cassandra.yaml");
}
}
Comment From: valeyko
Thank you, @wilkinsona, your solution works as well for me
Comment From: wilkinsona
The test that was added for this seems to flaky fairly consistently. On the first attempt, authentication fails:
2020-06-10 09:25:32.606 INFO 3332 --- [ s4-admin-0] c.d.oss.driver.internal.core.time.Clock : Using native clock for microsecond precision |
-- | --
| 2020-06-10 09:25:32.612 INFO 3332 --- [ s4-io-0] c.d.o.d.i.core.channel.ChannelFactory : [s4] Failed to connect with protocol DSE_V2, retrying with DSE_V1 |
| 2020-06-10 09:25:32.620 INFO 3332 --- [ s4-io-1] c.d.o.d.i.core.channel.ChannelFactory : [s4] Failed to connect with protocol DSE_V1, retrying with V4 |
| 2020-06-10 09:25:32.633 WARN 3332 --- [ s4-admin-1] c.d.o.d.i.c.control.ControlConnection : [s4] Authentication error (AuthenticationException: Authentication error on node /172.17.0.1:32835: server replied with 'Provided username cassandra and/or password are incorrect' to AuthResponse request) |
| 2020-06-10 09:25:32.633 WARN 3332 --- [ s4-admin-1] c.d.o.d.i.c.control.ControlConnection : [s4] Authentication errors encountered on all contact points. Please check your authentication configuration.
It then succeeds upon retry.
Comment From: snicoll
@adutra do you have any insight as why it would be flaky?