Skip to content
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

Improve role cache efficiency for API key roles (#58156) #59397

Merged
merged 2 commits into from
Jul 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ public void declareLong(BiConsumer<Value, Long> consumer, ParseField field) {
declareField(consumer, p -> p.longValue(), field, ValueType.LONG);
}

public void declareLongOrNull(BiConsumer<Value, Long> consumer, long nullValue, ParseField field) {
// Using a method reference here angers some compilers
declareField(consumer, p -> p.currentToken() == XContentParser.Token.VALUE_NULL ? nullValue : p.longValue(),
field, ValueType.LONG_OR_NULL);
}

public void declareInt(BiConsumer<Value, Integer> consumer, ParseField field) {
// Using a method reference here angers some compilers
declareField(consumer, p -> p.intValue(), field, ValueType.INT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.util.concurrent.ThreadContext.StoredContext;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.node.Node;
import org.elasticsearch.xpack.core.security.authc.Authentication;
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
Expand All @@ -23,14 +26,21 @@
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

import static org.elasticsearch.xpack.core.security.authc.Authentication.VERSION_API_KEY_ROLES_AS_BYTES;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY;

/**
* A lightweight utility that can find the current user and authentication information for the local thread.
*/
public class SecurityContext {

private final Logger logger = LogManager.getLogger(SecurityContext.class);

private final ThreadContext threadContext;
Expand Down Expand Up @@ -149,8 +159,27 @@ public void executeAfterRewritingAuthentication(Consumer<StoredContext> consumer
final Authentication authentication = getAuthentication();
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
setAuthentication(new Authentication(authentication.getUser(), authentication.getAuthenticatedBy(),
authentication.getLookedUpBy(), version, authentication.getAuthenticationType(), authentication.getMetadata()));
authentication.getLookedUpBy(), version, authentication.getAuthenticationType(),
rewriteMetadataForApiKeyRoleDescriptors(version, authentication)));
consumer.accept(original);
}
}

private Map<String, Object> rewriteMetadataForApiKeyRoleDescriptors(Version streamVersion, Authentication authentication) {
Map<String, Object> metadata = authentication.getMetadata();
if (authentication.getAuthenticationType() == AuthenticationType.API_KEY
&& authentication.getVersion().onOrAfter(VERSION_API_KEY_ROLES_AS_BYTES)
&& streamVersion.before(VERSION_API_KEY_ROLES_AS_BYTES)) {
metadata = new HashMap<>(metadata);
metadata.put(
API_KEY_ROLE_DESCRIPTORS_KEY,
XContentHelper.convertToMap(
(BytesReference) metadata.get(API_KEY_ROLE_DESCRIPTORS_KEY), false, XContentType.JSON).v2());
metadata.put(
API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY,
XContentHelper.convertToMap(
(BytesReference) metadata.get(API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY), false, XContentType.JSON).v2());
}
return metadata;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
// That interface can be removed
public class Authentication implements ToXContentObject {

public static final Version VERSION_API_KEY_ROLES_AS_BYTES = Version.V_7_9_0;

private final User user;
private final RealmRef authenticatedBy;
private final RealmRef lookedUpBy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
public final class AuthenticationField {

public static final String AUTHENTICATION_KEY = "_xpack_security_authentication";
public static final String API_KEY_ROLE_DESCRIPTORS_KEY = "_security_api_key_role_descriptors";
public static final String API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY = "_security_api_key_limited_by_role_descriptors";

private AuthenticationField() {}
}
Loading