-
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
Changes from all commits
9446b19
216d625
52fe8ba
fdde4c3
090eef6
4443657
d2977ce
a390c42
4b5bb5e
4d69fec
54a0479
47dbb3a
af68c9f
82af3dc
66c390e
83f9bf1
97841e2
2de05b7
a9e5ea9
14b21a4
b0a3d15
1edce33
93ecccf
75dfd7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /* | ||
| * Licensed to Elasticsearch under one or more contributor | ||
| * license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright | ||
| * ownership. Elasticsearch 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.elasticsearch.client.security; | ||
|
|
||
| import org.apache.http.client.methods.HttpGet; | ||
| import org.elasticsearch.client.Request; | ||
| import org.elasticsearch.client.Validatable; | ||
|
|
||
| /** | ||
| * Empty request object required to make the authenticate call. The authenticate call | ||
| * retrieves metadata about the authenticated user. | ||
| */ | ||
| public final class AuthenticateRequest implements Validatable { | ||
|
|
||
| public static final AuthenticateRequest INSTANCE = new AuthenticateRequest(); | ||
|
|
||
| private AuthenticateRequest() { | ||
| } | ||
|
|
||
| public Request getRequest() { | ||
| return new Request(HttpGet.METHOD_NAME, "/_xpack/security/_authenticate"); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /* | ||
| * Licensed to Elasticsearch under one or more contributor | ||
| * license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright | ||
| * ownership. Elasticsearch 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.elasticsearch.client.security; | ||
|
|
||
| import org.elasticsearch.client.security.user.User; | ||
| import org.elasticsearch.common.ParseField; | ||
| import org.elasticsearch.common.xcontent.ConstructingObjectParser; | ||
| import org.elasticsearch.common.xcontent.XContentParser; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
|
|
||
| import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; | ||
| import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; | ||
|
|
||
| /** | ||
| * The response for the authenticate call. The response contains two fields: a | ||
| * user field and a boolean flag signaling if the user is enabled or not. The | ||
| * user object contains all user metadata which Elasticsearch uses to map roles, | ||
| * etc. | ||
| */ | ||
| public final class AuthenticateResponse { | ||
|
|
||
| static final ParseField USERNAME = new ParseField("username"); | ||
| static final ParseField ROLES = new ParseField("roles"); | ||
| static final ParseField METADATA = new ParseField("metadata"); | ||
| static final ParseField FULL_NAME = new ParseField("full_name"); | ||
| static final ParseField EMAIL = new ParseField("email"); | ||
| static final ParseField ENABLED = new ParseField("enabled"); | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static final ConstructingObjectParser<AuthenticateResponse, Void> PARSER = new ConstructingObjectParser<>( | ||
| "client_security_authenticate_response", | ||
| a -> new AuthenticateResponse(new User((String) a[0], ((List<String>) a[1]), (Map<String, Object>) a[2], | ||
| (String) a[3], (String) a[4]), (Boolean) a[5])); | ||
| static { | ||
| PARSER.declareString(constructorArg(), USERNAME); | ||
| PARSER.declareStringArray(constructorArg(), ROLES); | ||
| PARSER.<Map<String, Object>>declareObject(constructorArg(), (parser, c) -> parser.map(), METADATA); | ||
| PARSER.declareStringOrNull(optionalConstructorArg(), FULL_NAME); | ||
| PARSER.declareStringOrNull(optionalConstructorArg(), EMAIL); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hub-cap do we have any a convention for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hub-cap Not really applicable in this case, but, is there a general way about how to test that server side entities are serialized to client side ones and vice-versa. Actually, how do we make sure a server response is not breaking the client parsers. Specifically, in this case, what if Am I missing the perspective here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We dont have that yet. @vladimirdolzhenko has a PR open to help out with this. |
||
| PARSER.declareBoolean(constructorArg(), ENABLED); | ||
| } | ||
|
|
||
| private final User user; | ||
| private final boolean enabled; | ||
|
|
||
| public AuthenticateResponse(User user, boolean enabled) { | ||
| this.user = user; | ||
| this.enabled = enabled; | ||
| } | ||
|
|
||
| /** | ||
| * @return The effective user. This is the authenticated user, or, when | ||
| * submitting requests on behalf of other users, it is the | ||
| * impersonated user. | ||
| */ | ||
| public User getUser() { | ||
| return user; | ||
| } | ||
|
|
||
| /** | ||
| * @return whether the user is enabled or not | ||
| */ | ||
| public boolean enabled() { | ||
| return enabled; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) { | ||
| return true; | ||
| } | ||
| if (o == null || getClass() != o.getClass()) { | ||
| return false; | ||
| } | ||
| final AuthenticateResponse that = (AuthenticateResponse) o; | ||
| return user.equals(that.user) && enabled == that.enabled; | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(user, enabled); | ||
| } | ||
|
|
||
| public static AuthenticateResponse fromXContent(XContentParser parser) throws IOException { | ||
| return PARSER.parse(parser, null); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| /* | ||
| * Licensed to Elasticsearch under one or more contributor | ||
| * license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright | ||
| * ownership. Elasticsearch 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.elasticsearch.client.security.user; | ||
|
|
||
| import org.elasticsearch.common.Nullable; | ||
| import org.elasticsearch.common.Strings; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
|
|
||
|
|
||
| /** | ||
| * An authenticated user | ||
| */ | ||
| public final class User { | ||
albertzaharovits marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| private final String username; | ||
| private final Collection<String> roles; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a |
||
| private final Map<String, Object> metadata; | ||
| @Nullable private final String fullName; | ||
| @Nullable private final String email; | ||
|
|
||
| public User(String username, Collection<String> roles, Map<String, Object> metadata, @Nullable String fullName, | ||
| @Nullable String email) { | ||
| Objects.requireNonNull(username, "`username` cannot be null"); | ||
| Objects.requireNonNull(roles, "`roles` cannot be null. Pass an empty collection instead."); | ||
| Objects.requireNonNull(roles, "`metadata` cannot be null. Pass an empty map instead."); | ||
| this.username = username; | ||
| this.roles = roles; | ||
| this.metadata = Collections.unmodifiableMap(metadata); | ||
| this.fullName = fullName; | ||
| this.email = email; | ||
| } | ||
|
|
||
| /** | ||
| * @return The principal of this user - effectively serving as the | ||
| * unique identity of the user. Can never be {@code null}. | ||
| */ | ||
| public String username() { | ||
| return this.username; | ||
| } | ||
|
|
||
| /** | ||
| * @return The roles this user is associated with. The roles are | ||
| * identified by their unique names and each represents as | ||
| * set of permissions. Can never be {@code null}. | ||
| */ | ||
| public Collection<String> roles() { | ||
| return this.roles; | ||
| } | ||
|
|
||
| /** | ||
| * @return The metadata that is associated with this user. Can never be {@code null}. | ||
| */ | ||
| public Map<String, Object> metadata() { | ||
| return metadata; | ||
| } | ||
|
|
||
| /** | ||
| * @return The full name of this user. May be {@code null}. | ||
| */ | ||
| public @Nullable String fullName() { | ||
| return fullName; | ||
| } | ||
|
|
||
| /** | ||
| * @return The email of this user. May be {@code null}. | ||
| */ | ||
| public @Nullable String email() { | ||
| return email; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| final StringBuilder sb = new StringBuilder(); | ||
| sb.append("User[username=").append(username); | ||
| sb.append(",roles=[").append(Strings.collectionToCommaDelimitedString(roles)).append("]"); | ||
| sb.append(",metadata=").append(metadata); | ||
| sb.append(",fullName=").append(fullName); | ||
| sb.append(",email=").append(email); | ||
| sb.append("]"); | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { | ||
| if (this == o) { | ||
| return true; | ||
| } | ||
| if (o instanceof User == false) { | ||
| return false; | ||
| } | ||
|
|
||
| final User user = (User) o; | ||
|
|
||
| if (!username.equals(user.username)) { | ||
| return false; | ||
| } | ||
| if (!roles.equals(user.roles)) { | ||
| return false; | ||
| } | ||
| if (!metadata.equals(user.metadata)) { | ||
| return false; | ||
| } | ||
| if (fullName != null ? !fullName.equals(user.fullName) : user.fullName != null) { | ||
| return false; | ||
| } | ||
| return !(email != null ? !email.equals(user.email) : user.email != null); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(username, roles, metadata, fullName, email); | ||
| } | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
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.