Add realm information for Authenticate API (#35648)
- Add the authentication realm and lookup realm name and type in the response for the _authenticate API - The authentication realm is set as the lookup realm too (instead of setting the lookup realm to null or empty ) when no lookup realm is used.
This commit is contained in:
parent
fe603e9163
commit
580b5baf21
|
@ -46,27 +46,43 @@ public final class AuthenticateResponse {
|
|||
static final ParseField FULL_NAME = new ParseField("full_name");
|
||||
static final ParseField EMAIL = new ParseField("email");
|
||||
static final ParseField ENABLED = new ParseField("enabled");
|
||||
static final ParseField AUTHENTICATION_REALM = new ParseField("authentication_realm");
|
||||
static final ParseField LOOKUP_REALM = new ParseField("lookup_realm");
|
||||
static final ParseField REALM_NAME = new ParseField("name");
|
||||
static final ParseField REALM_TYPE = new ParseField("type");
|
||||
|
||||
@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]));
|
||||
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7]));
|
||||
static {
|
||||
final ConstructingObjectParser<RealmInfo, Void> realmInfoParser = new ConstructingObjectParser<>("realm_info",
|
||||
a -> new RealmInfo((String) a[0], (String) a[1]));
|
||||
realmInfoParser.declareString(constructorArg(), REALM_NAME);
|
||||
realmInfoParser.declareString(constructorArg(), REALM_TYPE);
|
||||
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);
|
||||
PARSER.declareBoolean(constructorArg(), ENABLED);
|
||||
PARSER.declareObject(constructorArg(), realmInfoParser, AUTHENTICATION_REALM);
|
||||
PARSER.declareObject(constructorArg(), realmInfoParser, LOOKUP_REALM);
|
||||
}
|
||||
|
||||
private final User user;
|
||||
private final boolean enabled;
|
||||
private final RealmInfo authenticationRealm;
|
||||
private final RealmInfo lookupRealm;
|
||||
|
||||
public AuthenticateResponse(User user, boolean enabled) {
|
||||
|
||||
public AuthenticateResponse(User user, boolean enabled, RealmInfo authenticationRealm,
|
||||
RealmInfo lookupRealm) {
|
||||
this.user = user;
|
||||
this.enabled = enabled;
|
||||
this.authenticationRealm = authenticationRealm;
|
||||
this.lookupRealm = lookupRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,25 +101,69 @@ public final class AuthenticateResponse {
|
|||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the realm that authenticated the user
|
||||
*/
|
||||
public RealmInfo getAuthenticationRealm() {
|
||||
return authenticationRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the realm where the user information was looked up
|
||||
*/
|
||||
public RealmInfo getLookupRealm() {
|
||||
return lookupRealm;
|
||||
}
|
||||
|
||||
@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;
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
AuthenticateResponse that = (AuthenticateResponse) o;
|
||||
return enabled == that.enabled &&
|
||||
Objects.equals(user, that.user) &&
|
||||
Objects.equals(authenticationRealm, that.authenticationRealm) &&
|
||||
Objects.equals(lookupRealm, that.lookupRealm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(user, enabled);
|
||||
return Objects.hash(user, enabled, authenticationRealm, lookupRealm);
|
||||
}
|
||||
|
||||
public static AuthenticateResponse fromXContent(XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser, null);
|
||||
}
|
||||
|
||||
public static class RealmInfo {
|
||||
private String name;
|
||||
private String type;
|
||||
|
||||
RealmInfo(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RealmInfo realmInfo = (RealmInfo) o;
|
||||
return Objects.equals(name, realmInfo.name) &&
|
||||
Objects.equals(type, realmInfo.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -532,6 +532,10 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
//tag::authenticate-response
|
||||
User user = response.getUser(); // <1>
|
||||
boolean enabled = response.enabled(); // <2>
|
||||
final String authenticationRealmName = response.getAuthenticationRealm().getName(); // <3>
|
||||
final String authenticationRealmType = response.getAuthenticationRealm().getType(); // <4>
|
||||
final String lookupRealmName = response.getLookupRealm().getName(); // <5>
|
||||
final String lookupRealmType = response.getLookupRealm().getType(); // <6>
|
||||
//end::authenticate-response
|
||||
|
||||
assertThat(user.getUsername(), is("test_user"));
|
||||
|
@ -540,6 +544,10 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(user.getEmail(), nullValue());
|
||||
assertThat(user.getMetadata().isEmpty(), is(true));
|
||||
assertThat(enabled, is(true));
|
||||
assertThat(authenticationRealmName, is("default_file"));
|
||||
assertThat(authenticationRealmType, is("file"));
|
||||
assertThat(lookupRealmName, is("default_file"));
|
||||
assertThat(lookupRealmType, is("file"));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -70,7 +70,14 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
final String fullName = randomFrom(random(), null, randomAlphaOfLengthBetween(0, 4));
|
||||
final String email = randomFrom(random(), null, randomAlphaOfLengthBetween(0, 4));
|
||||
final boolean enabled = randomBoolean();
|
||||
return new AuthenticateResponse(new User(username, roles, metadata, fullName, email), enabled);
|
||||
final String authenticationRealmName = randomAlphaOfLength(5);
|
||||
final String authenticationRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
|
||||
final String lookupRealmName = randomAlphaOfLength(5);
|
||||
final String lookupRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
|
||||
return new AuthenticateResponse(
|
||||
new User(username, roles, metadata, fullName, email), enabled,
|
||||
new AuthenticateResponse.RealmInfo(authenticationRealmName, authenticationRealmType),
|
||||
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType));
|
||||
}
|
||||
|
||||
private void toXContent(AuthenticateResponse response, XContentBuilder builder) throws IOException {
|
||||
|
@ -87,6 +94,14 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
builder.field(AuthenticateResponse.EMAIL.getPreferredName(), user.getEmail());
|
||||
}
|
||||
builder.field(AuthenticateResponse.ENABLED.getPreferredName(), enabled);
|
||||
builder.startObject(AuthenticateResponse.AUTHENTICATION_REALM.getPreferredName());
|
||||
builder.field(AuthenticateResponse.REALM_NAME.getPreferredName(), response.getAuthenticationRealm().getName());
|
||||
builder.field(AuthenticateResponse.REALM_TYPE.getPreferredName(), response.getAuthenticationRealm().getType());
|
||||
builder.endObject();
|
||||
builder.startObject(AuthenticateResponse.LOOKUP_REALM.getPreferredName());
|
||||
builder.field(AuthenticateResponse.REALM_NAME.getPreferredName(), response.getLookupRealm().getName());
|
||||
builder.field(AuthenticateResponse.REALM_TYPE.getPreferredName(), response.getLookupRealm().getType());
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
|
@ -94,34 +109,49 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
final User originalUser = response.getUser();
|
||||
final User copyUser = new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail());
|
||||
return new AuthenticateResponse(copyUser, response.enabled());
|
||||
return new AuthenticateResponse(copyUser, response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
}
|
||||
|
||||
private AuthenticateResponse mutate(AuthenticateResponse response) {
|
||||
final User originalUser = response.getUser();
|
||||
switch (randomIntBetween(1, 6)) {
|
||||
switch (randomIntBetween(1, 8)) {
|
||||
case 1:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
|
||||
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled());
|
||||
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
case 2:
|
||||
final Collection<String> wrongRoles = new ArrayList<>(originalUser.getRoles());
|
||||
wrongRoles.add(randomAlphaOfLengthBetween(1, 4));
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), wrongRoles, originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled());
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
case 3:
|
||||
final Map<String, Object> wrongMetadata = new HashMap<>(originalUser.getMetadata());
|
||||
wrongMetadata.put("wrong_string", randomAlphaOfLengthBetween(0, 4));
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), wrongMetadata,
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled());
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
case 4:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled());
|
||||
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
case 5:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled());
|
||||
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
case 6:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), !response.enabled());
|
||||
originalUser.getFullName(), originalUser.getEmail()), !response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
case 7:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
|
||||
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)));
|
||||
case 8:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
|
||||
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm());
|
||||
}
|
||||
throw new IllegalStateException("Bad random number");
|
||||
}
|
||||
|
|
|
@ -24,10 +24,14 @@ This method does not require a request object. The client waits for the
|
|||
[id="{upid}-{api}-response"]
|
||||
==== Response
|
||||
|
||||
The returned +{response}+ contains two fields. Firstly, the `user` field
|
||||
The returned +{response}+ contains four fields. The `user` field
|
||||
, accessed with `getUser`, contains all the information about this
|
||||
authenticated user. The other field, `enabled`, tells if this user is actually
|
||||
usable or has been temporalily deactivated.
|
||||
authenticated user. The field `enabled`, tells if this user is actually
|
||||
usable or has been temporarily deactivated. The field `authentication_realm`,
|
||||
accessed with `getAuthenticationRealm` contains the name and type of the
|
||||
Realm that has authenticated the user and the field `lookup_realm`,
|
||||
accessed with `getLookupRealm` contains the name and type of the Realm where
|
||||
the user information were retrieved from.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
|
@ -36,6 +40,10 @@ include-tagged::{doc-tests-file}[{api}-response]
|
|||
<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.
|
||||
<3> `getAuthenticationRealm().getName()` retrieves the name of the realm that authenticated the user.
|
||||
<4> `getAuthenticationRealm().getType()` retrieves the type of the realm that authenticated the user.
|
||||
<5> `getLookupRealm().getName()` retrieves the name of the realm from where the user information is looked up.
|
||||
<6> `getLookupRealm().getType()` retrieves the type of the realm from where the user information is looked up.
|
||||
|
||||
[id="{upid}-{api}-async"]
|
||||
==== Asynchronous Execution
|
||||
|
|
|
@ -13,8 +13,8 @@ authenticate a user and retrieve information about the authenticated user.
|
|||
|
||||
==== Description
|
||||
|
||||
A successful call returns a JSON structure that shows what roles are assigned
|
||||
to the user as well as any assigned metadata.
|
||||
A successful call returns a JSON structure that shows user information such as their username, the roles that are
|
||||
assigned to the user, any assigned metadata, and information about the realms that authenticated and authorized the user.
|
||||
|
||||
If the user cannot be authenticated, this API returns a 401 status code.
|
||||
|
||||
|
@ -41,7 +41,15 @@ The following example output provides information about the "rdeniro" user:
|
|||
"full_name": null,
|
||||
"email": null,
|
||||
"metadata": { },
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"authentication_realm": {
|
||||
"name" : "default_file",
|
||||
"type" : "file"
|
||||
},
|
||||
"lookup_realm": {
|
||||
"name" : "default_file",
|
||||
"type" : "file"
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// TESTRESPONSE[s/"rdeniro"/"$body.username"/]
|
||||
|
|
|
@ -5,36 +5,49 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.core.security.action.user;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AuthenticateResponse extends ActionResponse {
|
||||
|
||||
private User user;
|
||||
private Authentication authentication;
|
||||
|
||||
public AuthenticateResponse() {}
|
||||
|
||||
public AuthenticateResponse(User user) {
|
||||
this.user = user;
|
||||
public AuthenticateResponse(Authentication authentication){
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
public User user() {
|
||||
return user;
|
||||
public Authentication authentication() {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
super.writeTo(out);
|
||||
User.writeTo(user, out);
|
||||
if (out.getVersion().before(Version.V_7_0_0)) {
|
||||
User.writeTo(authentication.getUser(), out);
|
||||
} else {
|
||||
authentication.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
user = User.readFrom(in);
|
||||
if (in.getVersion().before(Version.V_7_0_0)) {
|
||||
final User user = User.readFrom(in);
|
||||
final Authentication.RealmRef unknownRealm = new Authentication.RealmRef("__unknown", "__unknown", "__unknown");
|
||||
authentication = new Authentication(user, unknownRealm, unknownRealm);
|
||||
} else {
|
||||
authentication = new Authentication(in);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
|||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.xpack.core.security.user.InternalUserSerializationHelper;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
|
||||
|
@ -20,7 +22,7 @@ import java.util.Objects;
|
|||
|
||||
// TODO(hub-cap) Clean this up after moving User over - This class can re-inherit its field AUTHENTICATION_KEY in AuthenticationField.
|
||||
// That interface can be removed
|
||||
public class Authentication {
|
||||
public class Authentication implements ToXContentObject {
|
||||
|
||||
private final User user;
|
||||
private final RealmRef authenticatedBy;
|
||||
|
@ -163,6 +165,31 @@ public class Authentication {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(User.Fields.USERNAME.getPreferredName(), user.principal());
|
||||
builder.array(User.Fields.ROLES.getPreferredName(), user.roles());
|
||||
builder.field(User.Fields.FULL_NAME.getPreferredName(), user.fullName());
|
||||
builder.field(User.Fields.EMAIL.getPreferredName(), user.email());
|
||||
builder.field(User.Fields.METADATA.getPreferredName(), user.metadata());
|
||||
builder.field(User.Fields.ENABLED.getPreferredName(), user.enabled());
|
||||
builder.startObject(User.Fields.AUTHENTICATION_REALM.getPreferredName());
|
||||
builder.field(User.Fields.REALM_NAME.getPreferredName(), getAuthenticatedBy().getName());
|
||||
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getAuthenticatedBy().getType());
|
||||
builder.endObject();
|
||||
builder.startObject(User.Fields.LOOKUP_REALM.getPreferredName());
|
||||
if (getLookedUpBy() != null) {
|
||||
builder.field(User.Fields.REALM_NAME.getPreferredName(), getLookedUpBy().getName());
|
||||
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getLookedUpBy().getType());
|
||||
} else {
|
||||
builder.field(User.Fields.REALM_NAME.getPreferredName(), getAuthenticatedBy().getName());
|
||||
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getAuthenticatedBy().getType());
|
||||
}
|
||||
builder.endObject();
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static class RealmRef {
|
||||
|
||||
private final String nodeName;
|
||||
|
|
|
@ -230,6 +230,10 @@ public class User implements ToXContentObject {
|
|||
ParseField METADATA = new ParseField("metadata");
|
||||
ParseField ENABLED = new ParseField("enabled");
|
||||
ParseField TYPE = new ParseField("type");
|
||||
ParseField AUTHENTICATION_REALM = new ParseField("authentication_realm");
|
||||
ParseField LOOKUP_REALM = new ParseField("lookup_realm");
|
||||
ParseField REALM_TYPE = new ParseField("type");
|
||||
ParseField REALM_NAME = new ParseField("name");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.xpack.core.security.SecurityContext;
|
|||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateAction;
|
||||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateRequest;
|
||||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateResponse;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.core.security.user.XPackUser;
|
||||
|
@ -34,7 +35,8 @@ public class TransportAuthenticateAction extends HandledTransportAction<Authenti
|
|||
|
||||
@Override
|
||||
protected void doExecute(Task task, AuthenticateRequest request, ActionListener<AuthenticateResponse> listener) {
|
||||
final User runAsUser = securityContext.getUser();
|
||||
final Authentication authentication = securityContext.getAuthentication();
|
||||
final User runAsUser = authentication == null ? null : authentication.getUser();
|
||||
final User authUser = runAsUser == null ? null : runAsUser.authenticatedUser();
|
||||
if (authUser == null) {
|
||||
listener.onFailure(new ElasticsearchSecurityException("did not find an authenticated user"));
|
||||
|
@ -43,7 +45,7 @@ public class TransportAuthenticateAction extends HandledTransportAction<Authenti
|
|||
} else if (SystemUser.is(runAsUser) || XPackUser.is(runAsUser)) {
|
||||
listener.onFailure(new IllegalArgumentException("user [" + runAsUser.principal() + "] is internal"));
|
||||
} else {
|
||||
listener.onResponse(new AuthenticateResponse(runAsUser));
|
||||
listener.onResponse(new AuthenticateResponse(authentication));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class RestAuthenticateAction extends SecurityBaseRestHandler {
|
|||
new RestBuilderListener<AuthenticateResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(AuthenticateResponse authenticateResponse, XContentBuilder builder) throws Exception {
|
||||
authenticateResponse.user().toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
authenticateResponse.authentication().toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
return new BytesRestResponse(RestStatus.OK, builder);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.transport.TransportService;
|
|||
import org.elasticsearch.xpack.core.security.SecurityContext;
|
||||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateRequest;
|
||||
import org.elasticsearch.xpack.core.security.action.user.AuthenticateResponse;
|
||||
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.core.security.user.ElasticUser;
|
||||
import org.elasticsearch.xpack.core.security.user.KibanaUser;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
|
@ -37,7 +38,9 @@ public class TransportAuthenticateActionTests extends ESTestCase {
|
|||
|
||||
public void testInternalUser() {
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
when(securityContext.getUser()).thenReturn(randomFrom(SystemUser.INSTANCE, XPackUser.INSTANCE));
|
||||
final Authentication authentication = new Authentication(randomFrom(SystemUser.INSTANCE, XPackUser.INSTANCE),
|
||||
new Authentication.RealmRef("native", "default_native", "node1"), null);
|
||||
when(securityContext.getAuthentication()).thenReturn(authentication);
|
||||
TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
|
||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
|
||||
TransportAuthenticateAction action = new TransportAuthenticateAction(transportService,
|
||||
|
@ -88,9 +91,12 @@ public class TransportAuthenticateActionTests extends ESTestCase {
|
|||
assertThat(throwableRef.get().getMessage(), containsString("did not find an authenticated user"));
|
||||
}
|
||||
|
||||
public void testValidUser() {
|
||||
public void testValidAuthentication(){
|
||||
final User user = randomFrom(new ElasticUser(true), new KibanaUser(true), new User("joe"));
|
||||
final Authentication authentication = new Authentication(user, new Authentication.RealmRef("native_realm", "native", "node1"),
|
||||
null);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
when(securityContext.getAuthentication()).thenReturn(authentication);
|
||||
when(securityContext.getUser()).thenReturn(user);
|
||||
TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
|
||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
|
||||
|
@ -112,7 +118,7 @@ public class TransportAuthenticateActionTests extends ESTestCase {
|
|||
});
|
||||
|
||||
assertThat(responseRef.get(), notNullValue());
|
||||
assertThat(responseRef.get().user(), sameInstance(user));
|
||||
assertThat(responseRef.get().authentication(), sameInstance(authentication));
|
||||
assertThat(throwableRef.get(), nullValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
request.username(SecuritySettingsSource.TEST_SUPERUSER);
|
||||
client.execute(AuthenticateAction.INSTANCE, request, authFuture);
|
||||
AuthenticateResponse response = authFuture.actionGet();
|
||||
assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.user().principal());
|
||||
assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.authentication().getUser().principal());
|
||||
|
||||
authFuture = new PlainActionFuture<>();
|
||||
request = new AuthenticateRequest();
|
||||
|
@ -330,7 +330,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
client.filterWithHeader(Collections.singletonMap("Authorization", "Bearer " + createTokenResponse.getTokenString()))
|
||||
.execute(AuthenticateAction.INSTANCE, request, authFuture);
|
||||
response = authFuture.actionGet();
|
||||
assertEquals(SecuritySettingsSource.TEST_USER_NAME, response.user().principal());
|
||||
assertEquals(SecuritySettingsSource.TEST_USER_NAME, response.authentication().getUser().principal());
|
||||
|
||||
authFuture = new PlainActionFuture<>();
|
||||
request = new AuthenticateRequest();
|
||||
|
@ -338,7 +338,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
client.filterWithHeader(Collections.singletonMap("Authorization", "Bearer " + refreshResponse.getTokenString()))
|
||||
.execute(AuthenticateAction.INSTANCE, request, authFuture);
|
||||
response = authFuture.actionGet();
|
||||
assertEquals(SecuritySettingsSource.TEST_USER_NAME, response.user().principal());
|
||||
assertEquals(SecuritySettingsSource.TEST_USER_NAME, response.authentication().getUser().principal());
|
||||
}
|
||||
|
||||
public void testClientCredentialsGrant() throws Exception {
|
||||
|
@ -357,7 +357,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
client.filterWithHeader(Collections.singletonMap("Authorization", "Bearer " + createTokenResponse.getTokenString()))
|
||||
.execute(AuthenticateAction.INSTANCE, request, authFuture);
|
||||
AuthenticateResponse response = authFuture.get();
|
||||
assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.user().principal());
|
||||
assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.authentication().getUser().principal());
|
||||
|
||||
// invalidate
|
||||
PlainActionFuture<InvalidateTokenResponse> invalidateResponseFuture = new PlainActionFuture<>();
|
||||
|
|
|
@ -64,6 +64,7 @@ import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECU
|
|||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -576,7 +577,10 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
basicAuthHeaderValue(username, getReservedPassword())))
|
||||
.execute(AuthenticateAction.INSTANCE, new AuthenticateRequest(username))
|
||||
.get();
|
||||
assertThat(authenticateResponse.user().principal(), is(username));
|
||||
assertThat(authenticateResponse.authentication().getUser().principal(), is(username));
|
||||
assertThat(authenticateResponse.authentication().getAuthenticatedBy().getName(), equalTo("reserved"));
|
||||
assertThat(authenticateResponse.authentication().getAuthenticatedBy().getType(), equalTo("reserved"));
|
||||
assertNull(authenticateResponse.authentication().getLookedUpBy());
|
||||
}
|
||||
|
||||
public void testOperationsOnReservedRoles() throws Exception {
|
||||
|
|
|
@ -58,8 +58,13 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase {
|
|||
options.addHeader("Authorization", basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME,
|
||||
new SecureString(SecuritySettingsSourceField.TEST_PASSWORD.toCharArray())));
|
||||
request.setOptions(options);
|
||||
ObjectPath objectPath = ObjectPath.createFromResponse(getRestClient().performRequest(request));
|
||||
Response a = getRestClient().performRequest(request);
|
||||
ObjectPath objectPath = ObjectPath.createFromResponse(a);
|
||||
assertThat(objectPath.evaluate("username").toString(), equalTo(SecuritySettingsSource.TEST_USER_NAME));
|
||||
assertThat(objectPath.evaluate("authentication_realm.name").toString(), equalTo("file"));
|
||||
assertThat(objectPath.evaluate("authentication_realm.type").toString(), equalTo("file"));
|
||||
assertThat(objectPath.evaluate("lookup_realm.name").toString(), equalTo("file"));
|
||||
assertThat(objectPath.evaluate("lookup_realm.type").toString(), equalTo("file"));
|
||||
List<String> roles = objectPath.evaluate("roles");
|
||||
assertThat(roles.size(), is(1));
|
||||
assertThat(roles, contains(SecuritySettingsSource.TEST_ROLE));
|
||||
|
|
|
@ -65,7 +65,7 @@ public class ActiveDirectoryRunAsIT extends AbstractAdLdapRealmTestCase {
|
|||
final AuthenticateRequest request = new AuthenticateRequest(avenger);
|
||||
final ActionFuture<AuthenticateResponse> future = runAsClient(avenger).execute(AuthenticateAction.INSTANCE, request);
|
||||
final AuthenticateResponse response = future.get(30, TimeUnit.SECONDS);
|
||||
assertThat(response.user().principal(), Matchers.equalTo(avenger));
|
||||
assertThat(response.authentication().getUser().principal(), Matchers.equalTo(avenger));
|
||||
}
|
||||
|
||||
protected Client runAsClient(String user) {
|
||||
|
|
Loading…
Reference in New Issue