Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password-based authentication with Cassandra does not work with Spring Boot 2.3.0 #21487

Closed
andyfromktm opened this issue May 18, 2020 · 6 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@andyfromktm
Copy link

andyfromktm commented May 18, 2020

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();
	}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 18, 2020
@valeyko
Copy link

valeyko commented May 19, 2020

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")
    }
}

@wilkinsona
Copy link
Member

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.

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label May 20, 2020
@wilkinsona
Copy link
Member

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");
    }
}

@valeyko
Copy link

valeyko commented May 20, 2020

Thank you, @wilkinsona, your solution works as well for me

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 20, 2020
@wilkinsona wilkinsona changed the title Spring data cassandra authentication config issue Password-based authentication with Cassandra does not work with Spring Boot 2.3.0 May 20, 2020
@wilkinsona wilkinsona added type: regression A regression from a previous release and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels May 20, 2020
@wilkinsona wilkinsona added this to the 2.3.x milestone May 20, 2020
@wilkinsona wilkinsona self-assigned this May 20, 2020
@snicoll snicoll assigned snicoll and wilkinsona and unassigned wilkinsona Jun 9, 2020
@snicoll snicoll modified the milestones: 2.3.x, 2.4.0-M1, 2.3.1 Jun 9, 2020
@wilkinsona
Copy link
Member

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.

@wilkinsona wilkinsona reopened this Jun 10, 2020
@snicoll
Copy link
Member

snicoll commented Jun 11, 2020

@adutra do you have any insight as why it would be flaky?

camposer added a commit to camposer/Hopding.github.io that referenced this issue Apr 1, 2021
The previous command works when you connect from the internally (inside the container) but fails if you try from the outside - because the previous config was not removed!

BTW, thanks for your contribution. I realised the problem after reading: spring-projects/spring-boot#21487
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants