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

Support user info in Elasticsearch URIs #21381

Closed
wants to merge 1 commit into from

Conversation

evgeniycheban
Copy link
Contributor

Fixes gh-21291

@wilkinsona
Copy link
Member

Thanks very much for the PR, @evgeniycheban

Could you please take a look at adding some tests for the new functionality? I think they could be implemented as additions to org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfigurationTests. It looks like you can get the nodes from the RestClient to verify that the configuration has been applied correctly. As part of the tests, it would be good to verify the behaviour of URIs with and without any user info and how the separate username and password properties are used.

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

Thanks very much for the PR, @evgeniycheban

Could you please take a look at adding some tests for the new functionality? I think they could be implemented as additions to org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfigurationTests. It looks like you can get the nodes from the RestClient to verify that the configuration has been applied correctly. As part of the tests, it would be good to verify the behaviour of URIs with and without any user info and how the separate username and password properties are used.

Thanks for the review, @wilkinsona

Sure, I will add tests.

@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 11, 2020
@evgeniycheban evgeniycheban marked this pull request as ready for review May 12, 2020 01:38
@evgeniycheban evgeniycheban force-pushed the gh-21291 branch 2 times, most recently from 6da09b1 to 03c7ca3 Compare May 12, 2020 02:27
@evgeniycheban
Copy link
Contributor Author

@wilkinsona I added tests.

When you have a moment, please take a look.

Copy link
Member

@wilkinsona wilkinsona left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates. I've left a few more comments. Could you please take a look when you have a moment?

@@ -114,25 +123,48 @@ RestClient elasticsearchRestClient(RestClientBuilder builder) {

private final ElasticsearchRestClientProperties properties;

private CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a field for the CredentialsProvider and allowing it to be injected doesn't seem to be related to supporting user info in the URI. Can you please revert this part of the changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to make testing easer, because we can not access credentialsProvider field from InternalHttpAsyncClient. It can also be useful in some cases when the user needs to use a custom CredentialsProvider.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's safe to expose a CredentialProvider as a bean. In this case the credentials that it provides are specific to Elasticsearch, but there's nothing about the bean that indicates that's the case. It could be accidentally consumed and used anywhere that's working with an Apache HTTP client, potentially leaking credentials to another service.

For this sort of situation, we prefer to use AssertJ's support for extracting fields. In this case it would look something like this:

assertThat(client).extracting("client")
		.extracting("credentialsProvider", InstanceOfAssertFactories.type(CredentialsProvider.class))
		.satisfies((credentialsProvider) -> {
			Credentials uriCredentials = credentialsProvider.getCredentials(new AuthScope("localhost", 9200));
			assertThat(uriCredentials.getUserPrincipal().getName()).isEqualTo("user");
			assertThat(uriCredentials.getPassword()).isEqualTo("password");
			Credentials defaultCredentials = credentialsProvider.getCredentials(new AuthScope("localhost", 9201));
			assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("admin");
			assertThat(defaultCredentials.getPassword()).isEqualTo("admin");
		});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the AssertJ example, @wilkinsona
I will update tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


Credentials defaultCredentials = credentialsProvider
.getCredentials(new AuthScope("localhost", 9201));
assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("admin");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the username in the URI should win so the name of the principal should be user.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is right, in this assert we are checking that if the URI does not contain credentials then spring.elasticsearch.rest.username and spring.elasticsearch.rest.password will be used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'd missed that there are two URIs being configured, one with credentials and one without.

Credentials defaultCredentials = credentialsProvider
.getCredentials(new AuthScope("localhost", 9201));
assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("admin");
assertThat(defaultCredentials.getPassword()).isEqualTo("admin");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I think the password in the URI should win so it should be password.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, ignore this. I'd missed that there are two URIs being configured, one with credentials and one without.

@@ -114,25 +123,48 @@ RestClient elasticsearchRestClient(RestClientBuilder builder) {

private final ElasticsearchRestClientProperties properties;

private CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's safe to expose a CredentialProvider as a bean. In this case the credentials that it provides are specific to Elasticsearch, but there's nothing about the bean that indicates that's the case. It could be accidentally consumed and used anywhere that's working with an Apache HTTP client, potentially leaking credentials to another service.

For this sort of situation, we prefer to use AssertJ's support for extracting fields. In this case it would look something like this:

assertThat(client).extracting("client")
		.extracting("credentialsProvider", InstanceOfAssertFactories.type(CredentialsProvider.class))
		.satisfies((credentialsProvider) -> {
			Credentials uriCredentials = credentialsProvider.getCredentials(new AuthScope("localhost", 9200));
			assertThat(uriCredentials.getUserPrincipal().getName()).isEqualTo("user");
			assertThat(uriCredentials.getPassword()).isEqualTo("password");
			Credentials defaultCredentials = credentialsProvider.getCredentials(new AuthScope("localhost", 9201));
			assertThat(defaultCredentials.getUserPrincipal().getName()).isEqualTo("admin");
			assertThat(defaultCredentials.getPassword()).isEqualTo("admin");
		});

@evgeniycheban
Copy link
Contributor Author

@wilkinsona Could you please take a look at the latest changes when you have a moment?

@wilkinsona wilkinsona changed the title Support userInfo in elasticsearch uri Support user info in Elasticsearch URIs May 19, 2020
@wilkinsona wilkinsona added type: enhancement A general enhancement and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels May 19, 2020
@wilkinsona wilkinsona added this to the 2.4.x milestone May 19, 2020
@murdos
Copy link

murdos commented Jun 2, 2020

@wilkinsona : is there any chance to get this in 2.3.x ?
Indeed this feature was available with Jest, but support has been removed in 2.3.

@philwebb philwebb added the for: team-attention An issue we'd like other members of the team to review label Jun 4, 2020
@philwebb philwebb modified the milestones: 2.4.x, 2.3.x Jun 5, 2020
@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label Jun 5, 2020
@wilkinsona
Copy link
Member

Yes. Given the situation with Jest, it seems reasonable to include this in 2.3.x.

@philwebb philwebb self-assigned this Jun 7, 2020
@philwebb philwebb modified the milestones: 2.3.x, 2.3.1 Jun 7, 2020
philwebb pushed a commit that referenced this pull request Jun 7, 2020
philwebb added a commit that referenced this pull request Jun 7, 2020
@philwebb philwebb closed this in 8ac8329 Jun 7, 2020
@philwebb
Copy link
Member

philwebb commented Jun 7, 2020

Thanks very much for the PR @evgeniycheban, this is now in 2.3.x and master. I made some minor tweaks in f8982bd (mainly to protect against URL parse exceptions).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Elasticsearch: Support REST URIs including userInfo
5 participants