Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ywangd committed Apr 28, 2022
1 parent 3d4dea8 commit e621d44
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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;
Expand All @@ -19,7 +20,7 @@
*/
public class GetUsersResponse extends ActionResponse {

private User[] users;
private final User[] users;

public GetUsersResponse(StreamInput in) throws IOException {
super(in);
Expand All @@ -29,7 +30,9 @@ public GetUsersResponse(StreamInput in) throws IOException {
} else {
users = new User[size];
for (int i = 0; i < size; i++) {
users[i] = User.readFrom(in);
final User user = Authentication.AuthenticationSerializationHelper.readUserFrom(in);
assert false == User.isInternal(user) : "should not get internal users";
users[i] = user;
}
}
}
Expand All @@ -55,7 +58,7 @@ public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(users == null ? -1 : users.length);
if (users != null) {
for (User user : users) {
User.writeTo(user, out);
Authentication.AuthenticationSerializationHelper.writeUserTo(user, out);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@
import org.elasticsearch.xpack.core.security.authc.service.ServiceAccountSettings;
import org.elasticsearch.xpack.core.security.authc.support.AuthenticationContextSerializer;
import org.elasticsearch.xpack.core.security.user.AnonymousUser;
import org.elasticsearch.xpack.core.security.user.InternalUserSerializationHelper;
import org.elasticsearch.xpack.core.security.user.AsyncSearchUser;
import org.elasticsearch.xpack.core.security.user.SecurityProfileUser;
import org.elasticsearch.xpack.core.security.user.SystemUser;
import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.core.security.user.XPackSecurityUser;
import org.elasticsearch.xpack.core.security.user.XPackUser;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -111,7 +115,7 @@ public Authentication(
}

public Authentication(StreamInput in) throws IOException {
this.user = InternalUserSerializationHelper.readFrom(in);
this.user = AuthenticationSerializationHelper.readUserFrom(in);
this.authenticatedBy = new RealmRef(in);
if (in.readBoolean()) {
this.lookedUpBy = new RealmRef(in);
Expand Down Expand Up @@ -245,7 +249,7 @@ public Authentication runAs(User runAs, @Nullable RealmRef lookupRealmRef) {
assert false == getUser().isRunAs();
assert AuthenticationType.REALM == getAuthenticationType() || AuthenticationType.API_KEY == getAuthenticationType();
return new Authentication(
new User(runAs, getUser()),
new RunAsUser(runAs, getUser()),
getAuthenticatedBy(),
lookupRealmRef,
getVersion(),
Expand Down Expand Up @@ -304,7 +308,7 @@ public Authentication maybeAddAnonymousRoles(@Nullable AnonymousUser anonymousUs
final String[] allRoleNames = ArrayUtils.concat(getUser().roles(), anonymousUser.roles());

return new Authentication(
new User(
new RunAsUser(
new User(
getUser().principal(),
allRoleNames,
Expand Down Expand Up @@ -394,7 +398,7 @@ public String encode() throws IOException {
}

public void writeTo(StreamOutput out) throws IOException {
InternalUserSerializationHelper.writeTo(user, out);
AuthenticationSerializationHelper.writeUserTo(user, out);
authenticatedBy.writeTo(out);
if (lookedUpBy != null) {
out.writeBoolean(true);
Expand Down Expand Up @@ -874,4 +878,96 @@ public enum AuthenticationType {
ANONYMOUS,
INTERNAL
}

// Package private for testing
static class RunAsUser extends User {
final User authenticatingUser;

RunAsUser(User effectiveUser, User authenticatingUser) {
super(
effectiveUser.principal(),
effectiveUser.roles(),
effectiveUser.fullName(),
effectiveUser.email(),
effectiveUser.metadata(),
effectiveUser.enabled()
);
this.authenticatingUser = authenticatingUser;
}
}

public static class AuthenticationSerializationHelper {

private AuthenticationSerializationHelper() {}

public static User readUserFrom(StreamInput input) throws IOException {
final boolean isInternalUser = input.readBoolean();
final String username = input.readString();
if (isInternalUser) {
if (SystemUser.is(username)) {
return SystemUser.INSTANCE;
} else if (XPackUser.is(username)) {
return XPackUser.INSTANCE;
} else if (XPackSecurityUser.is(username)) {
return XPackSecurityUser.INSTANCE;
} else if (SecurityProfileUser.is(username)) {
return SecurityProfileUser.INSTANCE;
} else if (AsyncSearchUser.is(username)) {
return AsyncSearchUser.INSTANCE;
}
throw new IllegalStateException("user [" + username + "] is not an internal user");
}
return partialReadUserFrom(username, input);
}

public static void writeUserTo(User user, StreamOutput output) throws IOException {
if (SystemUser.is(user)) {
output.writeBoolean(true);
output.writeString(SystemUser.NAME);
} else if (XPackUser.is(user)) {
output.writeBoolean(true);
output.writeString(XPackUser.NAME);
} else if (XPackSecurityUser.is(user)) {
output.writeBoolean(true);
output.writeString(XPackSecurityUser.NAME);
} else if (SecurityProfileUser.is(user)) {
output.writeBoolean(true);
output.writeString(SecurityProfileUser.NAME);
} else if (AsyncSearchUser.is(user)) {
output.writeBoolean(true);
output.writeString(AsyncSearchUser.NAME);
} else {
doWriteUserTo(user, output);
}
}

private static User partialReadUserFrom(String username, StreamInput input) throws IOException {
String[] roles = input.readStringArray();
Map<String, Object> metadata = input.readMap();
String fullName = input.readOptionalString();
String email = input.readOptionalString();
boolean enabled = input.readBoolean();
User outerUser = new User(username, roles, fullName, email, metadata, enabled);
boolean hasInnerUser = input.readBoolean();
if (hasInnerUser) {
User innerUser = readUserFrom(input);
assert false == User.isInternal(innerUser) : "authenticating user cannot be internal";
return new RunAsUser(outerUser, innerUser);
} else {
return outerUser;
}
}

private static void doWriteUserTo(User user, StreamOutput output) throws IOException {
if (user instanceof RunAsUser runAsUser) {
User.writeUser(user, output);
output.writeBoolean(true);
User.writeUser(runAsUser.authenticatingUser, output);
} else {
// no backcompat necessary, since there is no inner user
User.writeUser(user, output);
}
output.writeBoolean(false); // last user written, regardless of bwc, does not have an inner user
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.elasticsearch.xpack.core.security.authc.Authentication;
import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl;
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor;
import org.elasticsearch.xpack.core.security.user.User;

import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -53,8 +52,7 @@
* necessary to authorize the given user. It is important to note that the {@link RequestInfo}
* may contain an {@link Authentication} object that actually has two users when the
* <i>run as</i> feature is used and this method should resolve the information for both.
* To check for the presence of run as, use the {@link User#isRunAs()} method on the user
* retrieved using the {@link Authentication#getUser()} method.</li>
* To check for the presence of run as, use the {@link Authentication#isRunAs()} method.</li>
* <li>{@link #authorizeRunAs(RequestInfo, AuthorizationInfo, ActionListener)} if the request
* is making use of the run as feature. This method is used to ensure the authenticated user
* can actually impersonate the user running the request.</li>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
package org.elasticsearch.xpack.core.security.user;

import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xpack.core.security.authc.Authentication;

import java.io.IOException;
import java.util.Arrays;
Expand Down Expand Up @@ -116,7 +116,7 @@ public boolean enabled() {
}

/**
* @deprecated We are transitioning to AuthenticationContext which frees User from managing the run-as information.
* @deprecated Use {@link Authentication#getAuthenticatingSubject()}.
* @return The user that was originally authenticated.
* This may be the user itself, or a different user which used runAs.
*/
Expand All @@ -126,7 +126,7 @@ public User authenticatedUser() {
}

/**
* @deprecated We are transitioning to AuthenticationContext which frees User from managing the run-as information.
* @deprecated Use {@link Authentication#isRunAs()}.
* Return true if this user was not the originally authenticated user, false otherwise.
* */
@Deprecated
Expand Down Expand Up @@ -192,41 +192,6 @@ public final XContentBuilder toXContent(XContentBuilder builder, Params params)
return builder.endObject();
}

public static User partialReadFrom(String username, StreamInput input) throws IOException {
String[] roles = input.readStringArray();
Map<String, Object> metadata = input.readMap();
String fullName = input.readOptionalString();
String email = input.readOptionalString();
boolean enabled = input.readBoolean();
User outerUser = new User(username, roles, fullName, email, metadata, enabled, null);
boolean hasInnerUser = input.readBoolean();
if (hasInnerUser) {
User innerUser = readFrom(input);
return new User(outerUser, innerUser);
} else {
return outerUser;
}
}

public static User readFrom(StreamInput input) throws IOException {
final boolean isInternalUser = input.readBoolean();
assert isInternalUser == false : "should always return false. Internal users should use the InternalUserSerializationHelper";
final String username = input.readString();
return partialReadFrom(username, input);
}

public static void writeTo(User user, StreamOutput output) throws IOException {
if (user.authenticatedUser == null) {
// no backcompat necessary, since there is no inner user
writeUser(user, output);
} else {
writeUser(user, output);
output.writeBoolean(true);
writeUser(user.authenticatedUser, output);
}
output.writeBoolean(false); // last user written, regardless of bwc, does not have an inner user
}

public static boolean isInternal(User user) {
return SystemUser.is(user)
|| XPackUser.is(user)
Expand All @@ -244,7 +209,7 @@ public static boolean isInternalUsername(String username) {
}

/** Write just the given {@link User}, but not the inner {@link #authenticatedUser}. */
private static void writeUser(User user, StreamOutput output) throws IOException {
public static void writeUser(User user, StreamOutput output) throws IOException {
output.writeBoolean(false); // not a system user
output.writeString(user.username);
output.writeStringArray(user.roles);
Expand Down
Loading

0 comments on commit e621d44

Please sign in to comment.