-
Notifications
You must be signed in to change notification settings - Fork 25.7k
HLRest: add security authenticate API #33552
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
HLRest: add security authenticate API #33552
Conversation
|
Pinging @elastic/es-core-infra |
|
Pinging @elastic/es-security |
| * under the License. | ||
| */ | ||
|
|
||
| package org.elasticsearch.client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not in the .security package.
| return request; | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The request is a singleton, so there is no need for a "request converter function". The converted is a member of the singleton.
| static { | ||
| PARSER.declareString(constructorArg(), USERNAME); | ||
| PARSER.declareStringArray(optionalConstructorArg(), ROLES); | ||
| PARSER.declareStringOrNull(optionalConstructorArg(), FULL_NAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
declareStringOrNull together with optionalConstructorArg is extra cautious.
I am comfortable with it, although I guess optional is unnecessary.
| (Map<String, Object>) a[4], (Boolean) a[5])); | ||
| static { | ||
| PARSER.declareString(constructorArg(), USERNAME); | ||
| PARSER.declareStringArray(optionalConstructorArg(), ROLES); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there would have been a null version for this I would have picked it.
I see the XContentBuilder adds null for every object type it serializes but the parser is not expecting null for each of these, maybe it should?
In addition to the empty collection vs null, in JSON we could also have the field missing 🎃 Do we have a rule for these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XContentBuilder serializes null arrays with a null JSON value
elasticsearch/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
Line 567 in b8fb83d
| if (values == null) { |
ObjectParser will fail to parse it Line 187 in b8fb83d
| public void declareStringArray(BiConsumer<Value, List<String>> consumer, ParseField field) { |
In practice this should not happen because on the server side we don't serialize null arrays in this case, but there is no guarantee for this, as there are no assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the parser should handle nulls; how about adding support to object parser to have a string array or null?
|
|
||
| The returned `AuthenticateResponse` contains a single field, `user`. This field | ||
| , accessed with `getUser`, contains all the information about this | ||
| authenticated user. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if could link to javadocs here ? I would like to link to the User javadoc class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about that, maybe @nik9000 knows? I am pretty sure he was working on some improvements around the docs for the HLRC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a way to point to the root Javadoc, see /docs/java-rest/high-level/getting-started.asciidoc but I wanted a link to a specific class's javadoc. There does not seem to be any practical way for this (other than crafting rickety links).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@albertzaharovits We can make the links slightly-less rickety by adding shared attributes for the javadoc package URLs. For example, if we define:
:javadoc-client: {rest-high-level-client-javadoc}/org/elasticsearch/client
Then you can link to specific classes in the client package by specifying {javadoc-client}/ClassName.html.
If that seems workable, I can add the attributes to the Versions.asciidoc file: #34934
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@debadair
I will be trying it, thank you for the air support!
hub-cap
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont see any tests other than the documentation ones. I also noticed there is no SecurityIT, like the other tests have in HLRC's test module. Maybe this PR can add it :)
client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java
Outdated
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/security/User.java
Outdated
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/EmptyBodyRequest.java
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| /** | ||
| * Authenticate the current user (pertaining to request headers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd remove pertaining to request headers since there is PKI which doesn't use headers
| import org.elasticsearch.client.EmptyBodyRequest; | ||
| import org.elasticsearch.client.Request; | ||
|
|
||
| public class AuthenticateRequest extends EmptyBodyRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add javadocs and make the class final
| import java.io.IOException; | ||
| import java.util.Objects; | ||
|
|
||
| public class AuthenticateResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make the class final and add javadocs
| (Map<String, Object>) a[4], (Boolean) a[5])); | ||
| static { | ||
| PARSER.declareString(constructorArg(), USERNAME); | ||
| PARSER.declareStringArray(optionalConstructorArg(), ROLES); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the parser should handle nulls; how about adding support to object parser to have a string array or null?
| @Nullable private final String email; | ||
|
|
||
| private User(String username, @Nullable String[] roles, @Nullable String fullName, @Nullable String email, | ||
| @Nullable Map<String, Object> metadata, Boolean enabled) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about we just accept the boolean primitive here?
| /** | ||
| * An authenticated user | ||
| */ | ||
| public class User { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make the class final
|
|
||
| The returned `AuthenticateResponse` contains a single field, `user`. This field | ||
| , accessed with `getUser`, contains all the information about this | ||
| authenticated user. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about that, maybe @nik9000 knows? I am pretty sure he was working on some improvements around the docs for the HLRC
|
run gradle build tests SUCCESS |
|
run sample packaging tests |
hub-cap
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super minor stuff. <3 and it looks like its very close to being done!
...nt/rest-high-level/src/main/java/org/elasticsearch/client/security/AuthenticateResponse.java
Outdated
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/User.java
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/User.java
Outdated
Show resolved
Hide resolved
client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityIT.java
Show resolved
Hide resolved
jaymode
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, just a few comments
client/rest-high-level/src/main/java/org/elasticsearch/client/security/AuthenticateRequest.java
Outdated
Show resolved
Hide resolved
...nt/rest-high-level/src/main/java/org/elasticsearch/client/security/AuthenticateResponse.java
Outdated
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/security/user/User.java
Outdated
Show resolved
Hide resolved
...nt/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java
Outdated
Show resolved
Hide resolved
| public final class User { | ||
|
|
||
| private final String username; | ||
| private final Collection<String> roles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a Collection now instead of List.
| -------------------------------------------------- | ||
| <1> `getUser` retrieves the `User` instance containing the information, | ||
| see {javadoc-client}/security/user/User.html. | ||
| <2> `enabled` tells if this user is usable or is deactivated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well... this is always true in the current implementation. If the user would have been disabled the _authenticate call would be failing.
|
test this please |
jaymode
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left one comment, otherwise LGTM
| } | ||
|
|
||
| public Request getRequest() { | ||
| return request; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should return a new request with this method; the request member is not immutable so we should not allow it to be returned via a public API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very good point!
|
https://elasticsearch-ci.elastic.co/job/elastic+elasticsearch+pull-request/1459/console |
This adds the security `_authenticate` API to the HLREST client. It is unlike some of the other APIs because the request does not have a body. The commit also creates the `User` entity. It is important to note that the `User` entity does not have the `enabled` flag. The `enabled` flag is part of the response, alongside the `User` entity. Moreover this adds the `SecurityIT` test class (extending `ESRestHighLevelClientTestCase`). Relates #29827
This follows #33552 , when the `_authenticate` API added a new `User` object for the API's response. This changes the `put_user` API to also employ a `User` object in the request. The User object changed slightly. A bug with put_user only putting/updating enabled (but not disabled) users has been fixed.
This follows #33552 , when the `_authenticate` API added a new `User` object for the API's response. This changes the `put_user` API to also employ a `User` object in the request. The User object changed slightly. A bug with put_user only putting/updating enabled (but not disabled) users has been fixed.
This adds the security authenticate API.
This API is exceptional because it does not have a request body 🦄
I have added
EmptyBodyRequestup from thesecuritypackage.