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

Authentication under domains #82639

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
f60e490
Done
albertzaharovits Jan 13, 2022
b46e19d
WIP
albertzaharovits Jan 14, 2022
c1dc80f
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 15, 2022
fe1a6f9
Revert wrong commit
albertzaharovits Jan 15, 2022
fd9fd89
Spotless
albertzaharovits Jan 15, 2022
056d407
Authentication nits, all besides the ownership check not yet implemented
albertzaharovits Jan 15, 2022
cce9d7d
Authentication constructors still need some attention
albertzaharovits Jan 16, 2022
de04b20
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 26, 2022
7aa25ac
Almost
albertzaharovits Jan 27, 2022
e6bb998
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 27, 2022
173ca59
Update docs/changelog/82639.yaml
albertzaharovits Jan 27, 2022
1ee5b76
Oops
albertzaharovits Jan 27, 2022
acee911
Checkstyle
albertzaharovits Jan 27, 2022
4d94838
ApiKeyService compile check
albertzaharovits Jan 27, 2022
00d821e
More compilation fixes
albertzaharovits Jan 27, 2022
18a9987
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 28, 2022
bc0c8e7
Revert
albertzaharovits Jan 28, 2022
07ca5d4
Spotless
albertzaharovits Jan 28, 2022
05206d0
RunAs
albertzaharovits Jan 28, 2022
bf5ff84
Fix UserPrivilegeResolverTests
albertzaharovits Jan 28, 2022
4c0b00f
APIKeys
albertzaharovits Jan 28, 2022
d89baf5
Fix SecondaryAuthenticationTests
albertzaharovits Jan 28, 2022
7a89a2f
Separate realm configure method
albertzaharovits Jan 28, 2022
94d6bf0
Tests fix
albertzaharovits Jan 28, 2022
ddea5c7
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 28, 2022
a47625c
Fix tests because realm ref mustnt have null fields
albertzaharovits Jan 29, 2022
d4a994a
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 29, 2022
964d5b4
Anonymous and internal authentication
albertzaharovits Jan 29, 2022
e2b8642
Fix run-as
albertzaharovits Jan 29, 2022
a9540f0
Spotless
albertzaharovits Jan 29, 2022
2091ba6
Token
albertzaharovits Jan 29, 2022
084516f
Nit APIKey
albertzaharovits Jan 29, 2022
6e2da6f
Spotless
albertzaharovits Jan 29, 2022
24e2465
Do not assert fallback user
albertzaharovits Jan 29, 2022
859db73
Nits
albertzaharovits Jan 29, 2022
5e0bbc3
Log domain erasure
albertzaharovits Jan 29, 2022
9ee55c6
Spotless
albertzaharovits Jan 29, 2022
1905e96
maybeRewrite
albertzaharovits Jan 29, 2022
a25eefa
Meh
albertzaharovits Jan 29, 2022
d2bb436
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 29, 2022
8d4a68a
Nit
albertzaharovits Jan 30, 2022
54cd104
Nits and javadoc
albertzaharovits Jan 30, 2022
a31cb63
some tests
albertzaharovits Jan 31, 2022
53d6925
Meh
albertzaharovits Jan 31, 2022
b0e951c
WIP
albertzaharovits Jan 31, 2022
cb529f8
Merge branch 'master' into authentication-under-domains
albertzaharovits Jan 31, 2022
48a6389
Meh
albertzaharovits Feb 1, 2022
1624429
WIP
albertzaharovits Feb 1, 2022
6895440
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 1, 2022
c768a64
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 1, 2022
1626943
WIP
albertzaharovits Feb 2, 2022
c4dceb3
RealmsTests
albertzaharovits Feb 2, 2022
924e342
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 2, 2022
a3448d5
Not final because mockito
albertzaharovits Feb 2, 2022
66e7693
better realm compare method
albertzaharovits Feb 2, 2022
68cb549
Tests nit fix
albertzaharovits Feb 2, 2022
7440c17
RealmsAuthenticatorTests
albertzaharovits Feb 2, 2022
2a4f8f9
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 2, 2022
1c7f70a
Revert "better realm compare method"
albertzaharovits Feb 2, 2022
13a1502
Ooops order
albertzaharovits Feb 2, 2022
c7f0e84
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 2, 2022
9e737cf
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 3, 2022
fcaab0e
AuthenticationServiceTests
albertzaharovits Feb 3, 2022
e769275
Rest Authenticate test
albertzaharovits Feb 3, 2022
3cc6596
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 3, 2022
b3c3cd5
Revert Realms and RealmSettings
albertzaharovits Feb 3, 2022
0ebd996
Ugly but terse
albertzaharovits Feb 3, 2022
419d331
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 4, 2022
56405c3
Move log warning about the rewrite
albertzaharovits Feb 4, 2022
d8181ec
Bump version for realm domains
albertzaharovits Feb 4, 2022
e9e9bd6
Replace exception with assert
albertzaharovits Feb 4, 2022
232f87e
initDomain -> initRealmRef
albertzaharovits Feb 4, 2022
1ce7d74
canAccess with API Key with runAs
albertzaharovits Feb 4, 2022
7da1b0e
Remove dead-code
albertzaharovits Feb 4, 2022
ba35ee8
ServiceToken cannot create token
albertzaharovits Feb 4, 2022
3c7be85
Proper RealmDomain randomization
albertzaharovits Feb 4, 2022
a09c9be
Random realm domain in authn integ test
albertzaharovits Feb 4, 2022
e7c5ffe
Nit
albertzaharovits Feb 4, 2022
e9a3e0d
Spotless
albertzaharovits Feb 4, 2022
9c46de6
ServiceAccount cannot token test
albertzaharovits Feb 4, 2022
941f31d
Merge branch 'master' into authentication-under-domains
albertzaharovits Feb 4, 2022
aceb2f9
Remove changelog, so it is recreated correctly
albertzaharovits Feb 4, 2022
a7aa9ae
Update docs/changelog/82639.yaml
albertzaharovits Feb 4, 2022
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
5 changes: 5 additions & 0 deletions docs/changelog/82639.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 82639
summary: Authentication under domains
area: Authentication
type: feature
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,23 @@
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version;
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.core.Nullable;
import org.elasticsearch.node.Node;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xpack.core.security.authc.Authentication;
import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType;
import org.elasticsearch.xpack.core.security.authc.AuthenticationField;
import org.elasticsearch.xpack.core.security.authc.support.AuthenticationContextSerializer;
import org.elasticsearch.xpack.core.security.authc.support.SecondaryAuthentication;
import org.elasticsearch.xpack.core.security.user.SystemUser;
import org.elasticsearch.xpack.core.security.user.User;

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.ATTACH_REALM_NAME;
import static org.elasticsearch.xpack.core.security.authc.AuthenticationField.ATTACH_REALM_TYPE;

/**
* A lightweight utility that can find the current user and authentication information for the local thread.
*/
Expand Down Expand Up @@ -107,41 +95,32 @@ public ThreadContext getThreadContext() {
* Sets the user forcefully to the provided user. There must not be an existing user in the ThreadContext otherwise an exception
* will be thrown. This method is package private for testing.
*/
public void setUser(User user, Version version) {
Objects.requireNonNull(user);
final Authentication.RealmRef authenticatedBy = new Authentication.RealmRef(ATTACH_REALM_NAME, ATTACH_REALM_TYPE, nodeName);
final Authentication.RealmRef lookedUpBy;
if (user.isRunAs()) {
lookedUpBy = authenticatedBy;
} else {
lookedUpBy = null;
}
setAuthentication(
new Authentication(user, authenticatedBy, lookedUpBy, version, AuthenticationType.INTERNAL, Collections.emptyMap())
);
}

/** Writes the authentication to the thread context */
private void setAuthentication(Authentication authentication) {
try {
authentication.writeToContext(threadContext);
} catch (IOException e) {
throw new AssertionError("how can we have a IOException with a user we set", e);
}
public void setInternalUser(User internalUser, Version version) {
assert User.isInternal(internalUser);
setAuthentication(Authentication.newInternalAuthentication(internalUser, version, nodeName));
}

/**
* Runs the consumer in a new context as the provided user. The original context is provided to the consumer. When this method
* returns, the original context is restored.
*/
public void executeAsUser(User user, Consumer<StoredContext> consumer, Version version) {
public void executeAsInternalUser(User internalUser, Version version, Consumer<StoredContext> consumer) {
assert User.isInternal(internalUser);
final StoredContext original = threadContext.newStoredContext(true);
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
setUser(user, version);
setInternalUser(internalUser, version);
consumer.accept(original);
}
}

public void executeAsSystemUser(Consumer<StoredContext> consumer) {
executeAsSystemUser(Version.CURRENT, consumer);
}

public void executeAsSystemUser(Version version, Consumer<StoredContext> consumer) {
executeAsInternalUser(SystemUser.INSTANCE, version, consumer);
}

/**
* Runs the consumer in a new context as the provided user. The original context is provided to the consumer. When this method
* returns, the original context is restored.
Expand All @@ -164,16 +143,7 @@ public void executeAfterRewritingAuthentication(Consumer<StoredContext> consumer
final StoredContext original = threadContext.newStoredContext(true);
final Authentication authentication = getAuthentication();
try (ThreadContext.StoredContext ignore = threadContext.stashContext()) {
setAuthentication(
new Authentication(
authentication.getUser(),
authentication.getAuthenticatedBy(),
authentication.getLookedUpBy(),
version,
authentication.getAuthenticationType(),
rewriteMetadataForApiKeyRoleDescriptors(version, authentication)
)
);
setAuthentication(new Authentication(authentication, version));
albertzaharovits marked this conversation as resolved.
Show resolved Hide resolved
existingRequestHeaders.forEach((k, v) -> {
if (threadContext.getHeader(k) == null) {
threadContext.putHeader(k, v);
Expand All @@ -183,54 +153,12 @@ public void executeAfterRewritingAuthentication(Consumer<StoredContext> consumer
}
}

@SuppressWarnings("unchecked")
private Map<String, Object> rewriteMetadataForApiKeyRoleDescriptors(Version streamVersion, Authentication authentication) {
Map<String, Object> metadata = authentication.getMetadata();
// If authentication type is API key, regardless whether it has run-as, the metadata must contain API key role descriptors
if (authentication.isAuthenticatedWithApiKey()) {
if (authentication.getVersion().onOrAfter(VERSION_API_KEY_ROLES_AS_BYTES)
&& streamVersion.before(VERSION_API_KEY_ROLES_AS_BYTES)) {
metadata = new HashMap<>(metadata);
metadata.put(
AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY,
convertRoleDescriptorsBytesToMap((BytesReference) metadata.get(AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY))
);
metadata.put(
AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY,
convertRoleDescriptorsBytesToMap(
(BytesReference) metadata.get(AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY)
)
);
} else if (authentication.getVersion().before(VERSION_API_KEY_ROLES_AS_BYTES)
&& streamVersion.onOrAfter(VERSION_API_KEY_ROLES_AS_BYTES)) {
metadata = new HashMap<>(metadata);
metadata.put(
AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY,
convertRoleDescriptorsMapToBytes(
(Map<String, Object>) metadata.get(AuthenticationField.API_KEY_ROLE_DESCRIPTORS_KEY)
)
);
metadata.put(
AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY,
convertRoleDescriptorsMapToBytes(
(Map<String, Object>) metadata.get(AuthenticationField.API_KEY_LIMITED_ROLE_DESCRIPTORS_KEY)
)
);
}
}
return metadata;
}

private Map<String, Object> convertRoleDescriptorsBytesToMap(BytesReference roleDescriptorsBytes) {
return XContentHelper.convertToMap(roleDescriptorsBytes, false, XContentType.JSON).v2();
}

private BytesReference convertRoleDescriptorsMapToBytes(Map<String, Object> roleDescriptorsMap) {
try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) {
builder.map(roleDescriptorsMap);
return BytesReference.bytes(builder);
/** Writes the authentication to the thread context */
private void setAuthentication(Authentication authentication) {
try {
authentication.writeToContext(threadContext);
} catch (IOException e) {
throw new UncheckedIOException(e);
throw new AssertionError("how can we have a IOException with a user we set", e);
}
}
}
Loading