mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-25 07:37:19 -04:00
Include authentication type for the authenticate response (#61247)
Add a new "authentication_type" field to the response of "GET _security/_authenticate".
This commit is contained in:
parent
051e79d27d
commit
eecee4438e
14 changed files with 57 additions and 21 deletions
|
@ -50,12 +50,13 @@ public final class AuthenticateResponse {
|
|||
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");
|
||||
static final ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ConstructingObjectParser<AuthenticateResponse, Void> PARSER = new ConstructingObjectParser<>(
|
||||
"client_security_authenticate_response", true,
|
||||
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], (RealmInfo) a[6], (RealmInfo) a[7]));
|
||||
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7], (String) a[8]));
|
||||
static {
|
||||
final ConstructingObjectParser<RealmInfo, Void> realmInfoParser = new ConstructingObjectParser<>("realm_info", true,
|
||||
a -> new RealmInfo((String) a[0], (String) a[1]));
|
||||
|
@ -69,20 +70,23 @@ public final class AuthenticateResponse {
|
|||
PARSER.declareBoolean(constructorArg(), ENABLED);
|
||||
PARSER.declareObject(constructorArg(), realmInfoParser, AUTHENTICATION_REALM);
|
||||
PARSER.declareObject(constructorArg(), realmInfoParser, LOOKUP_REALM);
|
||||
PARSER.declareString(constructorArg(), AUTHENTICATION_TYPE);
|
||||
}
|
||||
|
||||
private final User user;
|
||||
private final boolean enabled;
|
||||
private final RealmInfo authenticationRealm;
|
||||
private final RealmInfo lookupRealm;
|
||||
private final String authenticationType;
|
||||
|
||||
|
||||
public AuthenticateResponse(User user, boolean enabled, RealmInfo authenticationRealm,
|
||||
RealmInfo lookupRealm) {
|
||||
RealmInfo lookupRealm, String authenticationType) {
|
||||
this.user = user;
|
||||
this.enabled = enabled;
|
||||
this.authenticationRealm = authenticationRealm;
|
||||
this.lookupRealm = lookupRealm;
|
||||
this.authenticationType = authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,6 +119,10 @@ public final class AuthenticateResponse {
|
|||
return lookupRealm;
|
||||
}
|
||||
|
||||
public String getAuthenticationType() {
|
||||
return authenticationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -123,12 +131,13 @@ public final class AuthenticateResponse {
|
|||
return enabled == that.enabled &&
|
||||
Objects.equals(user, that.user) &&
|
||||
Objects.equals(authenticationRealm, that.authenticationRealm) &&
|
||||
Objects.equals(lookupRealm, that.lookupRealm);
|
||||
Objects.equals(lookupRealm, that.lookupRealm) &&
|
||||
Objects.equals(authenticationType, that.authenticationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(user, enabled, authenticationRealm, lookupRealm);
|
||||
return Objects.hash(user, enabled, authenticationRealm, lookupRealm, authenticationType);
|
||||
}
|
||||
|
||||
public static AuthenticateResponse fromXContent(XContentParser parser) throws IOException {
|
||||
|
|
|
@ -108,6 +108,7 @@ public class SecurityIT extends ESRestHighLevelClientTestCase {
|
|||
|
||||
assertThat(authenticateResponse.getUser(), is(putUserRequest.getUser()));
|
||||
assertThat(authenticateResponse.enabled(), is(true));
|
||||
assertThat(authenticateResponse.getAuthenticationType(), is("realm"));
|
||||
|
||||
// get user
|
||||
final GetUsersRequest getUsersRequest =
|
||||
|
|
|
@ -750,6 +750,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
final String authenticationRealmType = response.getAuthenticationRealm().getType(); // <4>
|
||||
final String lookupRealmName = response.getLookupRealm().getName(); // <5>
|
||||
final String lookupRealmType = response.getLookupRealm().getType(); // <6>
|
||||
final String authenticationType = response.getAuthenticationType(); // <7>
|
||||
//end::authenticate-response
|
||||
|
||||
assertThat(user.getUsername(), is("test_user"));
|
||||
|
@ -762,6 +763,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(authenticationRealmType, is("file"));
|
||||
assertThat(lookupRealmName, is("default_file"));
|
||||
assertThat(lookupRealmType, is("file"));
|
||||
assertThat(authenticationType, is("realm"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2341,6 +2343,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(authnRealm, is(notNullValue()));
|
||||
assertThat(authnRealm.getName(), is("pki1"));
|
||||
assertThat(authnRealm.getType(), is("pki"));
|
||||
assertThat(resp.getAuthenticationType(), is("token"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2384,6 +2387,7 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
|
|||
assertThat(authnRealm, is(notNullValue()));
|
||||
assertThat(authnRealm.getName(), is("pki1"));
|
||||
assertThat(authnRealm.getType(), is("pki"));
|
||||
assertThat(resp.getAuthenticationType(), is("token"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,10 +75,11 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
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");
|
||||
final String authenticationType = randomFrom("realm", "api_key", "token", "anonymous", "internal");
|
||||
return new AuthenticateResponse(
|
||||
new User(username, roles, metadata, fullName, email), enabled,
|
||||
new AuthenticateResponse.RealmInfo(authenticationRealmName, authenticationRealmType),
|
||||
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType));
|
||||
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType), authenticationType);
|
||||
}
|
||||
|
||||
private void toXContent(AuthenticateResponse response, XContentBuilder builder) throws IOException {
|
||||
|
@ -103,6 +104,7 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
builder.field(AuthenticateResponse.REALM_NAME.getPreferredName(), response.getLookupRealm().getName());
|
||||
builder.field(AuthenticateResponse.REALM_TYPE.getPreferredName(), response.getLookupRealm().getType());
|
||||
builder.endObject();
|
||||
builder.field(AuthenticateResponse.AUTHENTICATION_TYPE.getPreferredName(), response.getAuthenticationType());
|
||||
builder.endObject();
|
||||
}
|
||||
|
||||
|
@ -111,48 +113,56 @@ public class AuthenticateResponseTests extends ESTestCase {
|
|||
final User copyUser = new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail());
|
||||
return new AuthenticateResponse(copyUser, response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
response.getLookupRealm(), response.getAuthenticationType());
|
||||
}
|
||||
|
||||
private AuthenticateResponse mutate(AuthenticateResponse response) {
|
||||
final User originalUser = response.getUser();
|
||||
switch (randomIntBetween(1, 8)) {
|
||||
switch (randomIntBetween(1, 9)) {
|
||||
case 1:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
|
||||
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
|
||||
case 2:
|
||||
final List<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(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
response.getLookupRealm(), response.getAuthenticationType());
|
||||
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(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
response.getLookupRealm(), response.getAuthenticationType());
|
||||
case 4:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
|
||||
case 5:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
|
||||
response.getAuthenticationRealm(), response.getLookupRealm());
|
||||
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
|
||||
case 6:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), !response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm());
|
||||
response.getLookupRealm(), response.getAuthenticationType());
|
||||
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)));
|
||||
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)),
|
||||
response.getAuthenticationType());
|
||||
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());
|
||||
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm(),
|
||||
response.getAuthenticationType());
|
||||
case 9:
|
||||
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
|
||||
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
|
||||
response.getLookupRealm(),
|
||||
randomValueOtherThan(response.getAuthenticationType(),
|
||||
() -> randomFrom("realm", "api_key", "token", "anonymous", "internal")));
|
||||
}
|
||||
throw new IllegalStateException("Bad random number");
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ see {javadoc-client}/security/user/User.html.
|
|||
<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.
|
||||
<7> `getAuthenticationType()` retrieves the authentication type of the authenticated user.
|
||||
|
||||
[id="{upid}-{api}-async"]
|
||||
==== Asynchronous Execution
|
||||
|
|
|
@ -56,7 +56,8 @@ The following example output provides information about the "rdeniro" user:
|
|||
"lookup_realm": {
|
||||
"name" : "file",
|
||||
"type" : "file"
|
||||
}
|
||||
},
|
||||
"authentication_type": "realm"
|
||||
}
|
||||
--------------------------------------------------
|
||||
// TESTRESPONSE[s/"rdeniro"/"$body.username"/]
|
||||
|
|
|
@ -34,4 +34,4 @@ public class AuthenticateResponse extends ActionResponse {
|
|||
authentication.writeTo(out);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.xpack.core.security.user.User;
|
|||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -176,6 +177,7 @@ public class Authentication implements ToXContentObject {
|
|||
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getAuthenticatedBy().getType());
|
||||
}
|
||||
builder.endObject();
|
||||
builder.field(User.Fields.AUTHENTICATION_TYPE.getPreferredName(), getAuthenticationType().name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -261,4 +263,3 @@ public class Authentication implements ToXContentObject {
|
|||
INTERNAL
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,6 +238,7 @@ public class User implements ToXContentObject {
|
|||
ParseField LOOKUP_REALM = new ParseField("lookup_realm");
|
||||
ParseField REALM_TYPE = new ParseField("type");
|
||||
ParseField REALM_NAME = new ParseField("name");
|
||||
ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
|
|||
AuthenticateResponse authResponse = restClient.security().authenticate(RequestOptions.DEFAULT.toBuilder().addHeader("Authorization",
|
||||
"ApiKey " + base64ApiKeyKeyValue).build());
|
||||
assertThat(authResponse.getUser().getUsername(), equalTo(SecuritySettingsSource.TEST_SUPERUSER));
|
||||
assertThat(authResponse.getAuthenticationType(), equalTo("api_key"));
|
||||
|
||||
// use the first ApiKey for an unauthorized action
|
||||
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class, () ->
|
||||
|
|
|
@ -525,8 +525,9 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
assertNotEquals(refreshResponse.getRefreshToken(), createTokenResponse.getRefreshToken());
|
||||
|
||||
AuthenticateResponse response = restClient.security().authenticate(superuserOptions);
|
||||
;
|
||||
|
||||
assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.getUser().getUsername());
|
||||
assertEquals("realm", response.getAuthenticationType());
|
||||
|
||||
assertAuthenticateWithToken(createTokenResponse.getAccessToken(), SecuritySettingsSource.TEST_USER_NAME);
|
||||
assertAuthenticateWithToken(refreshResponse.getAccessToken(), SecuritySettingsSource.TEST_USER_NAME);
|
||||
|
@ -604,6 +605,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
AuthenticateResponse authResponse = restClient.security().authenticate(RequestOptions.DEFAULT.toBuilder().addHeader("Authorization",
|
||||
"Bearer " + accessToken).build());
|
||||
assertThat(authResponse.getUser().getUsername(), equalTo(expectedUser));
|
||||
assertThat(authResponse.getAuthenticationType(), equalTo("token"));
|
||||
}
|
||||
|
||||
private void assertUnauthorizedToken(String accessToken) {
|
||||
|
|
|
@ -160,6 +160,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
|
|||
assertThat(authnRealm, is(notNullValue()));
|
||||
assertThat(authnRealm.getName(), is("pki3"));
|
||||
assertThat(authnRealm.getType(), is("pki"));
|
||||
assertThat(resp.getAuthenticationType(), is("token"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +206,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
|
|||
assertThat(authnRealm, is(notNullValue()));
|
||||
assertThat(authnRealm.getName(), is("pki3"));
|
||||
assertThat(authnRealm.getType(), is("pki"));
|
||||
assertThat(resp.getAuthenticationType(), is("token"));
|
||||
// invalidate
|
||||
InvalidateTokenRequest invalidateRequest = new InvalidateTokenRequest(token, null, null, null);
|
||||
optionsBuilder = RequestOptions.DEFAULT.toBuilder();
|
||||
|
@ -291,6 +293,7 @@ public class PkiAuthDelegationIntegTests extends SecurityIntegTestCase {
|
|||
assertThat(authnRealm, is(notNullValue()));
|
||||
assertThat(authnRealm.getName(), is("pki3"));
|
||||
assertThat(authnRealm.getType(), is("pki"));
|
||||
assertThat(resp.getAuthenticationType(), is("token"));
|
||||
// delete role mappings for delegated PKI
|
||||
restClient.security().deleteRoleMapping(new DeleteRoleMappingRequest("role_by_delegated_user", RefreshPolicy.IMMEDIATE),
|
||||
testUserOptions);
|
||||
|
|
|
@ -65,6 +65,7 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase {
|
|||
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"));
|
||||
assertThat(objectPath.evaluate("authentication_type").toString(), equalTo("realm"));
|
||||
List<String> roles = objectPath.evaluate("roles");
|
||||
assertThat(roles.size(), is(1));
|
||||
assertThat(roles, contains(SecuritySettingsSource.TEST_ROLE));
|
||||
|
|
|
@ -35,3 +35,4 @@ teardown:
|
|||
- match: { username: "authenticate_user" }
|
||||
- match: { roles.0: "superuser" }
|
||||
- match: { full_name: "Authenticate User" }
|
||||
- match: { authentication_type: "realm" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue