diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/InternalClient.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/InternalClient.java index e5de9537f5f..b6112beb514 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/InternalClient.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/InternalClient.java @@ -20,7 +20,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.node.Node; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.authc.Authentication; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.crypto.CryptoService; import org.elasticsearch.xpack.security.user.XPackUser; @@ -43,7 +43,7 @@ public class InternalClient extends FilterClient { public InternalClient(Settings settings, ThreadPool threadPool, Client in, CryptoService cryptoService) { super(settings, threadPool, in); this.cryptoService = cryptoService; - this.signUserHeader = InternalAuthenticationService.SIGN_USER_HEADER.get(settings); + this.signUserHeader = AuthenticationService.SIGN_USER_HEADER.get(settings); this.nodeName = Node.NODE_NAME_SETTING.get(settings); } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java index b2697c9bb06..b41a1c2b854 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -11,7 +11,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -76,7 +75,7 @@ import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail; import org.elasticsearch.xpack.security.authc.AuthenticationModule; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm; @@ -90,7 +89,7 @@ import org.elasticsearch.xpack.security.authc.pki.PkiRealm; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.authz.AuthorizationModule; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor; import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache; import org.elasticsearch.xpack.security.authz.accesscontrol.SecurityIndexSearcherWrapper; @@ -358,8 +357,8 @@ public class Security implements ActionPlugin, IngestPlugin { Realms.addSettings(settingsList); NativeUsersStore.addSettings(settingsList); NativeRolesStore.addSettings(settingsList); - InternalAuthenticationService.addSettings(settingsList); - InternalAuthorizationService.addSettings(settingsList); + AuthenticationService.addSettings(settingsList); + AuthorizationService.addSettings(settingsList); // HTTP settings SecurityNetty3HttpServerTransport.addSettings(settingsList); diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/SecurityContext.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/SecurityContext.java index 6b5ebcb2cc6..2942d135272 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/SecurityContext.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/SecurityContext.java @@ -13,7 +13,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.authc.Authentication; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.crypto.CryptoService; import org.elasticsearch.xpack.security.user.User; @@ -36,7 +36,7 @@ public class SecurityContext { this.logger = Loggers.getLogger(getClass(), settings); this.threadContext = threadPool.getThreadContext(); this.cryptoService = cryptoService; - this.signUserHeader = InternalAuthenticationService.SIGN_USER_HEADER.get(settings); + this.signUserHeader = AuthenticationService.SIGN_USER_HEADER.get(settings); } /** Returns the current user information, or null if the current request has no authentication info. */ diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilter.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilter.java index ad7c4e12559..10c0bf70ff1 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilter.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/filter/SecurityActionFilter.java @@ -24,12 +24,12 @@ import org.elasticsearch.xpack.security.SecurityContext; import org.elasticsearch.xpack.security.action.SecurityActionMapper; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.Authentication; +import org.elasticsearch.xpack.security.authc.AuthenticationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.action.interceptor.RequestInterceptor; import org.elasticsearch.xpack.security.audit.AuditTrail; -import org.elasticsearch.xpack.security.authc.AuthenticationService; -import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.AuthorizationUtils; import org.elasticsearch.xpack.security.authz.privilege.HealthAndStatsPrivilege; import org.elasticsearch.xpack.security.crypto.CryptoService; diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/BulkRequestInterceptor.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/BulkRequestInterceptor.java index ee6db9b477d..8f974e688fe 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/BulkRequestInterceptor.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/BulkRequestInterceptor.java @@ -15,7 +15,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportRequest; @@ -34,7 +34,7 @@ public class BulkRequestInterceptor extends AbstractComponent implements Request } public void intercept(BulkRequest request, User user) { - IndicesAccessControl indicesAccessControl = threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY); + IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY); for (IndicesRequest indicesRequest : request.subRequests()) { for (String index : indicesRequest.indices()) { IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index); diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java index e81e7e4cd15..b2a1c159708 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/action/interceptor/FieldAndDocumentLevelSecurityRequestInterceptor.java @@ -12,7 +12,7 @@ import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; import java.util.Collections; @@ -42,7 +42,7 @@ public abstract class FieldAndDocumentLevelSecurityRequestInterceptor e throw new IllegalArgumentException(LoggerMessageFormat.format("Expected a request of type [{}] or [{}] but got [{}] instead", CompositeIndicesRequest.class, IndicesRequest.class, request.getClass())); } - IndicesAccessControl indicesAccessControl = threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY); + IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY); for (IndicesRequest indicesRequest : indicesRequests) { for (String index : indicesRequest.indices()) { IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index); diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java index 57491d0c12e..c77680e998c 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationModule.java @@ -34,7 +34,7 @@ public class AuthenticationModule extends AbstractSecurityModule.Node { } else { bind(AuthenticationFailureHandler.class).to(authcFailureHandler).asEagerSingleton(); } - bind(AuthenticationService.class).to(InternalAuthenticationService.class).asEagerSingleton(); + bind(AuthenticationService.class).asEagerSingleton(); } /** diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java index ec6d2e49e0b..b63b56d050a 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java @@ -6,16 +6,66 @@ package org.elasticsearch.xpack.security.authc; import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.Setting.Property; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.node.Node; import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.xpack.security.audit.AuditTrailService; +import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; +import org.elasticsearch.xpack.security.user.AnonymousUser; import org.elasticsearch.xpack.security.user.User; +import org.elasticsearch.xpack.security.audit.AuditTrail; +import org.elasticsearch.xpack.security.crypto.CryptoService; +import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportMessage; import java.io.IOException; +import java.util.List; + +import static org.elasticsearch.xpack.security.Security.setting; /** - * Responsible for authenticating the Users behind requests + * An authentication service that delegates the authentication process to its configured {@link Realm realms}. + * This service also supports request level caching of authenticated users (i.e. once a user authenticated + * successfully, it is set on the request context to avoid subsequent redundant authentication process) */ -public interface AuthenticationService { +public class AuthenticationService extends AbstractComponent { + + public static final Setting SIGN_USER_HEADER = + Setting.boolSetting(setting("authc.sign_user_header"), true, Property.NodeScope); + public static final Setting RUN_AS_ENABLED = + Setting.boolSetting(setting("authc.run_as.enabled"), true, Property.NodeScope); + public static final String RUN_AS_USER_HEADER = "es-security-runas-user"; + + private final Realms realms; + private final AuditTrail auditTrail; + private final CryptoService cryptoService; + private final AuthenticationFailureHandler failureHandler; + private final ThreadContext threadContext; + private final String nodeName; + private final boolean signUserHeader; + private final boolean runAsEnabled; + + @Inject + public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, CryptoService cryptoService, + AuthenticationFailureHandler failureHandler, ThreadPool threadPool) { + super(settings); + this.nodeName = Node.NODE_NAME_SETTING.get(settings); + this.realms = realms; + this.auditTrail = auditTrail; + this.cryptoService = cryptoService; + this.failureHandler = failureHandler; + this.threadContext = threadPool.getThreadContext(); + this.signUserHeader = SIGN_USER_HEADER.get(settings); + this.runAsEnabled = RUN_AS_ENABLED.get(settings); + } /** * Authenticates the user that is associated with the given request. If the user was authenticated successfully (i.e. @@ -28,7 +78,9 @@ public interface AuthenticationService { * user credentials were found to be invalid * @throws IOException If an error occurs when reading or writing */ - Authentication authenticate(RestRequest request) throws IOException, ElasticsearchSecurityException; + public Authentication authenticate(RestRequest request) throws IOException, ElasticsearchSecurityException { + return createAuthenticator(request).authenticate(); + } /** * Authenticates the user that is associated with the given message. If the user was authenticated successfully (i.e. @@ -47,9 +99,11 @@ public interface AuthenticationService { * * @throws ElasticsearchSecurityException If the associated user credentials were found to be invalid or in the * case where there was no user associated with the request, if the defautl - * token could not be authenticated. + * token could not be authenticated. */ - Authentication authenticate(String action, TransportMessage message, User fallbackUser) throws IOException; + public Authentication authenticate(String action, TransportMessage message, User fallbackUser) throws IOException { + return createAuthenticator(action, message, fallbackUser).authenticate(); + } /** * Checks if there's already a user header attached to the given message. If missing, a new header is @@ -57,5 +111,310 @@ public interface AuthenticationService { * * @param user The user to be attached if the header is missing */ - void attachUserIfMissing(User user) throws IOException, IllegalArgumentException; + public void attachUserIfMissing(User user) throws IOException { + Authentication authentication = new Authentication(user, new RealmRef("__attach", "__attach", nodeName), null); + authentication.writeToContextIfMissing(threadContext, cryptoService, signUserHeader); + } + + Authenticator createAuthenticator(RestRequest request) { + return new Authenticator(request); + } + + Authenticator createAuthenticator(String action, TransportMessage message, User fallbackUser) { + return new Authenticator(action, message, fallbackUser); + } + + class Authenticator { + + private final AuditableRequest request; + private final User fallbackUser; + + private RealmRef authenticatedBy = null; + private RealmRef lookedupBy = null; + + Authenticator(RestRequest request) { + this.request = new Rest(request); + this.fallbackUser = null; + } + + Authenticator(String action, TransportMessage message, User fallbackUser) { + this.request = new Transport(action, message); + this.fallbackUser = fallbackUser; + } + + Authentication authenticate() throws IOException, IllegalArgumentException { + Authentication existing = getCurrentAuthentication(); + if (existing != null) { + return existing; + } + + AuthenticationToken token = extractToken(); + if (token == null) { + return handleNullToken(); + } + + User user = authenticateToken(token); + if (user == null) { + throw handleNullUser(token); + } + user = lookupRunAsUserIfNecessary(user, token); + + final Authentication authentication = new Authentication(user, authenticatedBy, lookedupBy); + authentication.writeToContext(threadContext, cryptoService, signUserHeader); + return authentication; + } + + Authentication getCurrentAuthentication() { + Authentication authentication; + try { + authentication = Authentication.readFromContext(threadContext, cryptoService, signUserHeader); + } catch (Exception e) { + throw request.tamperedRequest(); + } + + // make sure this isn't a rest request since we don't allow authentication to be read via a HTTP request... + if (authentication != null && request instanceof Rest) { + throw request.tamperedRequest(); + } + return authentication; + } + + AuthenticationToken extractToken() { + AuthenticationToken token = null; + try { + for (Realm realm : realms) { + token = realm.token(threadContext); + if (token != null) { + logger.trace("realm [{}] resolved authentication token [{}] from [{}]", realm, token.principal(), request); + break; + } + } + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("failed to extract token from request: [{}]", e, request); + } else { + logger.warn("failed to extract token from request: [{}]: {}", request, e.getMessage()); + } + throw request.exceptionProcessingRequest(e, null); + } + return token; + } + + Authentication handleNullToken() throws IOException { + Authentication authentication = null; + if (fallbackUser != null) { + RealmRef authenticatedBy = new RealmRef("__fallback", "__fallback", nodeName); + authentication = new Authentication(fallbackUser, authenticatedBy, null); + } else if (AnonymousUser.enabled()) { + RealmRef authenticatedBy = new RealmRef("__anonymous", "__anonymous", nodeName); + authentication = new Authentication(AnonymousUser.INSTANCE, authenticatedBy, null); + } + + if (authentication != null) { + authentication.writeToContext(threadContext, cryptoService, signUserHeader); + return authentication; + } + throw request.anonymousAccessDenied(); + } + + User authenticateToken(AuthenticationToken token) { + User user = null; + try { + for (Realm realm : realms) { + if (realm.supports(token)) { + user = realm.authenticate(token); + if (user != null) { + authenticatedBy = new RealmRef(realm.name(), realm.type(), nodeName); + break; + } + request.realmAuthenticationFailed(token, realm.name()); + } + } + } catch (Exception e) { + logger.debug("authentication failed for principal [{}], [{}] ", e, token.principal(), request); + throw request.exceptionProcessingRequest(e, token); + } finally { + token.clearCredentials(); + } + return user; + } + + ElasticsearchSecurityException handleNullUser(AuthenticationToken token) { + throw request.authenticationFailed(token); + } + + boolean shouldTryToRunAs(User authenticatedUser, AuthenticationToken token) { + if (runAsEnabled == false) { + return false; + } + + String runAsUsername = threadContext.getHeader(RUN_AS_USER_HEADER); + if (runAsUsername == null) { + return false; + } + + if (runAsUsername.isEmpty()) { + logger.debug("user [{}] attempted to runAs with an empty username", authenticatedUser.principal()); + throw request.runAsDenied(new User(authenticatedUser.principal(), authenticatedUser.roles(), + new User(runAsUsername, Strings.EMPTY_ARRAY)), token); + } + return true; + } + + User lookupRunAsUserIfNecessary(User authenticatedUser, AuthenticationToken token) { + User user = authenticatedUser; + if (shouldTryToRunAs(user, token) == false) { + return user; + } + + final String runAsUsername = threadContext.getHeader(RUN_AS_USER_HEADER); + try { + for (Realm realm : realms) { + if (realm.userLookupSupported()) { + User runAsUser = realm.lookupUser(runAsUsername); + if (runAsUser != null) { + lookedupBy = new RealmRef(realm.name(), realm.type(), nodeName); + user = new User(user.principal(), user.roles(), runAsUser); + return user; + } + } + } + + // the requested run as user does not exist, but we don't throw an error here otherwise this could let + // information leak about users in the system... instead we'll just let the authz service fail throw an + // authorization error + user = new User(user.principal(), user.roles(), new User(runAsUsername, Strings.EMPTY_ARRAY)); + } catch (Exception e) { + logger.debug("run as failed for principal [{}], [{}], run as username [{}]", e, token.principal(), request, runAsUsername); + throw request.exceptionProcessingRequest(e, token); + } + return user; + } + + abstract class AuditableRequest { + + abstract void realmAuthenticationFailed(AuthenticationToken token, String realm); + + abstract ElasticsearchSecurityException tamperedRequest(); + + abstract ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token); + + abstract ElasticsearchSecurityException authenticationFailed(AuthenticationToken token); + + abstract ElasticsearchSecurityException anonymousAccessDenied(); + + abstract ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token); + } + + class Transport extends AuditableRequest { + + private final String action; + private final TransportMessage message; + + Transport(String action, TransportMessage message) { + this.action = action; + this.message = message; + } + + @Override + void realmAuthenticationFailed(AuthenticationToken token, String realm) { + auditTrail.authenticationFailed(realm, token, action, message); + } + + @Override + ElasticsearchSecurityException tamperedRequest() { + auditTrail.tamperedRequest(action, message); + return new ElasticsearchSecurityException("failed to verify signed authentication information"); + } + + @Override + ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) { + if (token != null) { + auditTrail.authenticationFailed(token, action, message); + } else { + auditTrail.authenticationFailed(action, message); + } + return failureHandler.exceptionProcessingRequest(message, action, e, threadContext); + } + + @Override + ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) { + auditTrail.authenticationFailed(token, action, message); + return failureHandler.failedAuthentication(message, token, action, threadContext); + } + + @Override + ElasticsearchSecurityException anonymousAccessDenied() { + auditTrail.anonymousAccessDenied(action, message); + return failureHandler.missingToken(message, action, threadContext); + } + + @Override + ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) { + auditTrail.runAsDenied(user, action, message); + return failureHandler.failedAuthentication(message, token, action, threadContext); + } + + public String toString() { + return "transport request action [" + action + "]"; + } + } + + class Rest extends AuditableRequest { + + private final RestRequest request; + + Rest(RestRequest request) { + this.request = request; + } + + @Override + void realmAuthenticationFailed(AuthenticationToken token, String realm) { + auditTrail.authenticationFailed(realm, token, request); + } + + @Override + ElasticsearchSecurityException tamperedRequest() { + auditTrail.tamperedRequest(request); + return new ElasticsearchSecurityException("rest request attempted to inject a user"); + } + + @Override + ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) { + if (token != null) { + auditTrail.authenticationFailed(token, request); + } else { + auditTrail.authenticationFailed(request); + } + return failureHandler.exceptionProcessingRequest(request, e, threadContext); + } + + @Override + ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) { + auditTrail.authenticationFailed(token, request); + return failureHandler.failedAuthentication(request, token, threadContext); + } + + @Override + ElasticsearchSecurityException anonymousAccessDenied() { + auditTrail.anonymousAccessDenied(request); + return failureHandler.missingToken(request, threadContext); + } + + @Override + ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) { + auditTrail.runAsDenied(user, request); + return failureHandler.failedAuthentication(request, token, threadContext); + } + + public String toString() { + return "rest request uri [" + request.uri() + "]"; + } + } + } + + public static void addSettings(List> settings) { + settings.add(SIGN_USER_HEADER); + settings.add(RUN_AS_ENABLED); + } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationService.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationService.java deleted file mode 100644 index 13bc0ca86f5..00000000000 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationService.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.security.authc; - -import org.elasticsearch.ElasticsearchSecurityException; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Setting.Property; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.node.Node; -import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.xpack.security.audit.AuditTrailService; -import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; -import org.elasticsearch.xpack.security.user.AnonymousUser; -import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.audit.AuditTrail; -import org.elasticsearch.xpack.security.crypto.CryptoService; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportMessage; - -import java.io.IOException; -import java.util.List; - -import static org.elasticsearch.xpack.security.Security.setting; - -/** - * An authentication service that delegates the authentication process to its configured {@link Realm realms}. - * This service also supports request level caching of authenticated users (i.e. once a user authenticated - * successfully, it is set on the request context to avoid subsequent redundant authentication process) - */ -public class InternalAuthenticationService extends AbstractComponent implements AuthenticationService { - - public static final Setting SIGN_USER_HEADER = - Setting.boolSetting(setting("authc.sign_user_header"), true, Property.NodeScope); - public static final Setting RUN_AS_ENABLED = - Setting.boolSetting(setting("authc.run_as.enabled"), true, Property.NodeScope); - public static final String RUN_AS_USER_HEADER = "es-security-runas-user"; - - private final Realms realms; - private final AuditTrail auditTrail; - private final CryptoService cryptoService; - private final AuthenticationFailureHandler failureHandler; - private final ThreadContext threadContext; - private final String nodeName; - private final boolean signUserHeader; - private final boolean runAsEnabled; - - @Inject - public InternalAuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, CryptoService cryptoService, - AuthenticationFailureHandler failureHandler, ThreadPool threadPool) { - super(settings); - this.nodeName = Node.NODE_NAME_SETTING.get(settings); - this.realms = realms; - this.auditTrail = auditTrail; - this.cryptoService = cryptoService; - this.failureHandler = failureHandler; - this.threadContext = threadPool.getThreadContext(); - this.signUserHeader = SIGN_USER_HEADER.get(settings); - this.runAsEnabled = RUN_AS_ENABLED.get(settings); - } - - @Override - public Authentication authenticate(RestRequest request) throws IOException, ElasticsearchSecurityException { - return createAuthenticator(request).authenticate(); - } - - @Override - public Authentication authenticate(String action, TransportMessage message, User fallbackUser) throws IOException { - return createAuthenticator(action, message, fallbackUser).authenticate(); - } - - @Override - public void attachUserIfMissing(User user) throws IOException { - Authentication authentication = new Authentication(user, new RealmRef("__attach", "__attach", nodeName), null); - authentication.writeToContextIfMissing(threadContext, cryptoService, signUserHeader); - } - - Authenticator createAuthenticator(RestRequest request) { - return new Authenticator(request); - } - - Authenticator createAuthenticator(String action, TransportMessage message, User fallbackUser) { - return new Authenticator(action, message, fallbackUser); - } - - class Authenticator { - - private final AuditableRequest request; - private final User fallbackUser; - - private RealmRef authenticatedBy = null; - private RealmRef lookedupBy = null; - - Authenticator(RestRequest request) { - this.request = new Rest(request); - this.fallbackUser = null; - } - - Authenticator(String action, TransportMessage message, User fallbackUser) { - this.request = new Transport(action, message); - this.fallbackUser = fallbackUser; - } - - Authentication authenticate() throws IOException, IllegalArgumentException { - Authentication existing = getCurrentAuthentication(); - if (existing != null) { - return existing; - } - - AuthenticationToken token = extractToken(); - if (token == null) { - return handleNullToken(); - } - - User user = authenticateToken(token); - if (user == null) { - throw handleNullUser(token); - } - user = lookupRunAsUserIfNecessary(user, token); - - final Authentication authentication = new Authentication(user, authenticatedBy, lookedupBy); - authentication.writeToContext(threadContext, cryptoService, signUserHeader); - return authentication; - } - - Authentication getCurrentAuthentication() { - Authentication authentication; - try { - authentication = Authentication.readFromContext(threadContext, cryptoService, signUserHeader); - } catch (Exception e) { - throw request.tamperedRequest(); - } - - // make sure this isn't a rest request since we don't allow authentication to be read via a HTTP request... - if (authentication != null && request instanceof Rest) { - throw request.tamperedRequest(); - } - return authentication; - } - - AuthenticationToken extractToken() { - AuthenticationToken token = null; - try { - for (Realm realm : realms) { - token = realm.token(threadContext); - if (token != null) { - logger.trace("realm [{}] resolved authentication token [{}] from [{}]", realm, token.principal(), request); - break; - } - } - } catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("failed to extract token from request: [{}]", e, request); - } else { - logger.warn("failed to extract token from request: [{}]: {}", request, e.getMessage()); - } - throw request.exceptionProcessingRequest(e, null); - } - return token; - } - - Authentication handleNullToken() throws IOException { - Authentication authentication = null; - if (fallbackUser != null) { - RealmRef authenticatedBy = new RealmRef("__fallback", "__fallback", nodeName); - authentication = new Authentication(fallbackUser, authenticatedBy, null); - } else if (AnonymousUser.enabled()) { - RealmRef authenticatedBy = new RealmRef("__anonymous", "__anonymous", nodeName); - authentication = new Authentication(AnonymousUser.INSTANCE, authenticatedBy, null); - } - - if (authentication != null) { - authentication.writeToContext(threadContext, cryptoService, signUserHeader); - return authentication; - } - throw request.anonymousAccessDenied(); - } - - User authenticateToken(AuthenticationToken token) { - User user = null; - try { - for (Realm realm : realms) { - if (realm.supports(token)) { - user = realm.authenticate(token); - if (user != null) { - authenticatedBy = new RealmRef(realm.name(), realm.type(), nodeName); - break; - } - request.realmAuthenticationFailed(token, realm.name()); - } - } - } catch (Exception e) { - logger.debug("authentication failed for principal [{}], [{}] ", e, token.principal(), request); - throw request.exceptionProcessingRequest(e, token); - } finally { - token.clearCredentials(); - } - return user; - } - - ElasticsearchSecurityException handleNullUser(AuthenticationToken token) { - throw request.authenticationFailed(token); - } - - boolean shouldTryToRunAs(User authenticatedUser, AuthenticationToken token) { - if (runAsEnabled == false) { - return false; - } - - String runAsUsername = threadContext.getHeader(RUN_AS_USER_HEADER); - if (runAsUsername == null) { - return false; - } - - if (runAsUsername.isEmpty()) { - logger.debug("user [{}] attempted to runAs with an empty username", authenticatedUser.principal()); - throw request.runAsDenied(new User(authenticatedUser.principal(), authenticatedUser.roles(), - new User(runAsUsername, Strings.EMPTY_ARRAY)), token); - } - return true; - } - - User lookupRunAsUserIfNecessary(User authenticatedUser, AuthenticationToken token) { - User user = authenticatedUser; - if (shouldTryToRunAs(user, token) == false) { - return user; - } - - final String runAsUsername = threadContext.getHeader(RUN_AS_USER_HEADER); - try { - for (Realm realm : realms) { - if (realm.userLookupSupported()) { - User runAsUser = realm.lookupUser(runAsUsername); - if (runAsUser != null) { - lookedupBy = new RealmRef(realm.name(), realm.type(), nodeName); - user = new User(user.principal(), user.roles(), runAsUser); - return user; - } - } - } - - // the requested run as user does not exist, but we don't throw an error here otherwise this could let - // information leak about users in the system... instead we'll just let the authz service fail throw an - // authorization error - user = new User(user.principal(), user.roles(), new User(runAsUsername, Strings.EMPTY_ARRAY)); - } catch (Exception e) { - logger.debug("run as failed for principal [{}], [{}], run as username [{}]", e, token.principal(), request, runAsUsername); - throw request.exceptionProcessingRequest(e, token); - } - return user; - } - - abstract class AuditableRequest { - - abstract void realmAuthenticationFailed(AuthenticationToken token, String realm); - - abstract ElasticsearchSecurityException tamperedRequest(); - - abstract ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token); - - abstract ElasticsearchSecurityException authenticationFailed(AuthenticationToken token); - - abstract ElasticsearchSecurityException anonymousAccessDenied(); - - abstract ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token); - } - - class Transport extends AuditableRequest { - - private final String action; - private final TransportMessage message; - - Transport(String action, TransportMessage message) { - this.action = action; - this.message = message; - } - - @Override - void realmAuthenticationFailed(AuthenticationToken token, String realm) { - auditTrail.authenticationFailed(realm, token, action, message); - } - - @Override - ElasticsearchSecurityException tamperedRequest() { - auditTrail.tamperedRequest(action, message); - return new ElasticsearchSecurityException("failed to verify signed authentication information"); - } - - @Override - ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) { - if (token != null) { - auditTrail.authenticationFailed(token, action, message); - } else { - auditTrail.authenticationFailed(action, message); - } - return failureHandler.exceptionProcessingRequest(message, action, e, threadContext); - } - - @Override - ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) { - auditTrail.authenticationFailed(token, action, message); - return failureHandler.failedAuthentication(message, token, action, threadContext); - } - - @Override - ElasticsearchSecurityException anonymousAccessDenied() { - auditTrail.anonymousAccessDenied(action, message); - return failureHandler.missingToken(message, action, threadContext); - } - - @Override - ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) { - auditTrail.runAsDenied(user, action, message); - return failureHandler.failedAuthentication(message, token, action, threadContext); - } - - public String toString() { - return "transport request action [" + action + "]"; - } - } - - class Rest extends AuditableRequest { - - private final RestRequest request; - - Rest(RestRequest request) { - this.request = request; - } - - @Override - void realmAuthenticationFailed(AuthenticationToken token, String realm) { - auditTrail.authenticationFailed(realm, token, request); - } - - @Override - ElasticsearchSecurityException tamperedRequest() { - auditTrail.tamperedRequest(request); - return new ElasticsearchSecurityException("rest request attempted to inject a user"); - } - - @Override - ElasticsearchSecurityException exceptionProcessingRequest(Exception e, @Nullable AuthenticationToken token) { - if (token != null) { - auditTrail.authenticationFailed(token, request); - } else { - auditTrail.authenticationFailed(request); - } - return failureHandler.exceptionProcessingRequest(request, e, threadContext); - } - - @Override - ElasticsearchSecurityException authenticationFailed(AuthenticationToken token) { - auditTrail.authenticationFailed(token, request); - return failureHandler.failedAuthentication(request, token, threadContext); - } - - @Override - ElasticsearchSecurityException anonymousAccessDenied() { - auditTrail.anonymousAccessDenied(request); - return failureHandler.missingToken(request, threadContext); - } - - @Override - ElasticsearchSecurityException runAsDenied(User user, AuthenticationToken token) { - auditTrail.runAsDenied(user, request); - return failureHandler.failedAuthentication(request, token, threadContext); - } - - public String toString() { - return "rest request uri [" + request.uri() + "]"; - } - } - } - - public static void addSettings(List> settings) { - settings.add(SIGN_USER_HEADER); - settings.add(RUN_AS_ENABLED); - } -} diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationModule.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationModule.java index 81b584f0d81..0494bfb52ba 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationModule.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationModule.java @@ -36,7 +36,7 @@ public class AuthorizationModule extends AbstractSecurityModule.Node { bind(NativeRolesStore.class).asEagerSingleton(); // Then the composite roles store (which combines both) can be bound bind(RolesStore.class).to(CompositeRolesStore.class).asEagerSingleton(); - bind(AuthorizationService.class).to(InternalAuthorizationService.class).asEagerSingleton(); + bind(AuthorizationService.class).asEagerSingleton(); } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index d80f693f2d5..7a7edf4b54d 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -6,16 +6,94 @@ package org.elasticsearch.xpack.security.authz; import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.action.CompositeIndicesRequest; +import org.elasticsearch.action.IndicesRequest; +import org.elasticsearch.action.admin.indices.alias.Alias; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; +import org.elasticsearch.action.search.ClearScrollAction; +import org.elasticsearch.action.search.SearchScrollAction; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.AliasOrIndex; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.Setting.Property; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.common.util.set.Sets; +import org.elasticsearch.search.action.SearchTransportService; +import org.elasticsearch.xpack.security.SecurityTemplateService; +import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.Authentication; +import org.elasticsearch.xpack.security.user.AnonymousUser; +import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.xpack.security.user.User; +import org.elasticsearch.xpack.security.user.XPackUser; +import org.elasticsearch.xpack.security.audit.AuditTrail; +import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; +import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; +import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; +import org.elasticsearch.xpack.security.authz.indicesresolver.IndicesAndAliasesResolver; +import org.elasticsearch.xpack.security.authz.permission.ClusterPermission; +import org.elasticsearch.xpack.security.authz.permission.DefaultRole; +import org.elasticsearch.xpack.security.authz.permission.GlobalPermission; +import org.elasticsearch.xpack.security.authz.permission.Role; +import org.elasticsearch.xpack.security.authz.permission.RunAsPermission; +import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; +import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.security.authz.store.RolesStore; +import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportRequest; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +import static org.elasticsearch.xpack.security.Security.setting; +import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError; /** * */ -public interface AuthorizationService { +public class AuthorizationService extends AbstractComponent { + + public static final Setting ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING = + Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope); + public static final String INDICES_PERMISSIONS_KEY = "_indices_permissions"; + static final String ORIGINATING_ACTION_KEY = "_originating_action_name"; + + private static final Predicate MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate(); + + private final ClusterService clusterService; + private final RolesStore rolesStore; + private final AuditTrail auditTrail; + private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers; + private final AuthenticationFailureHandler authcFailureHandler; + private final ThreadContext threadContext; + private final boolean anonymousAuthzExceptionEnabled; + + @Inject + public AuthorizationService(Settings settings, RolesStore rolesStore, ClusterService clusterService, + AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler, + ThreadPool threadPool, IndexNameExpressionResolver nameExpressionResolver) { + super(settings); + this.rolesStore = rolesStore; + this.clusterService = clusterService; + this.auditTrail = auditTrail; + this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] { + new DefaultIndicesAndAliasesResolver(this, nameExpressionResolver) + }; + this.authcFailureHandler = authcFailureHandler; + this.threadContext = threadPool.getThreadContext(); + this.anonymousAuthzExceptionEnabled = ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.get(settings); + } /** * Returns all indices and aliases the given user is allowed to execute the given action on. @@ -23,7 +101,49 @@ public interface AuthorizationService { * @param user The user * @param action The action */ - List authorizedIndicesAndAliases(User user, String action); + public List authorizedIndicesAndAliases(User user, String action) { + final String[] anonymousRoles = AnonymousUser.enabled() ? AnonymousUser.getRoles() : Strings.EMPTY_ARRAY; + String[] rolesNames = user.roles(); + if (rolesNames.length == 0 && anonymousRoles.length == 0) { + return Collections.emptyList(); + } + + List> predicates = new ArrayList<>(); + for (String roleName : rolesNames) { + Role role = rolesStore.role(roleName); + if (role != null) { + predicates.add(role.indices().allowedIndicesMatcher(action)); + } + } + if (AnonymousUser.is(user) == false) { + for (String roleName : anonymousRoles) { + Role role = rolesStore.role(roleName); + if (role != null) { + predicates.add(role.indices().allowedIndicesMatcher(action)); + } + } + } + Predicate predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2)); + + List indicesAndAliases = new ArrayList<>(); + MetaData metaData = clusterService.state().metaData(); + // TODO: can this be done smarter? I think there are usually more indices/aliases in the cluster then indices defined a roles? + for (Map.Entry entry : metaData.getAliasAndIndexLookup().entrySet()) { + String aliasOrIndex = entry.getKey(); + if (predicate.test(aliasOrIndex)) { + indicesAndAliases.add(aliasOrIndex); + } + } + + if (XPackUser.is(user) == false) { + // we should filter out the .security index from wildcards + if (indicesAndAliases.remove(SecurityTemplateService.SECURITY_INDEX_NAME)) { + logger.debug("removed [{}] from user [{}] list of authorized indices", + SecurityTemplateService.SECURITY_INDEX_NAME, user.principal()); + } + } + return Collections.unmodifiableList(indicesAndAliases); + } /** * Verifies that the given user can execute the given request (and action). If the user doesn't @@ -35,6 +155,226 @@ public interface AuthorizationService { * @param request The request * @throws ElasticsearchSecurityException If the given user is no allowed to execute the given request */ - void authorize(Authentication authentication, String action, TransportRequest request) throws ElasticsearchSecurityException; + public void authorize(Authentication authentication, String action, TransportRequest request) throws ElasticsearchSecurityException { + // prior to doing any authorization lets set the originating action in the context only + setOriginatingAction(action); + // first we need to check if the user is the system. If it is, we'll just authorize the system access + if (SystemUser.is(authentication.getRunAsUser())) { + if (SystemUser.isAuthorized(action) && SystemUser.is(authentication.getUser())) { + setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL); + grant(authentication, action, request); + return; + } + throw denial(authentication, action, request); + } + + // get the roles of the authenticated user, which may be different than the effective + GlobalPermission permission = permission(authentication.getUser().roles()); + + final boolean isRunAs = authentication.getUser() != authentication.getRunAsUser(); + // permission can be null as it might be that the user's role + // is unknown + if (permission == null || permission.isEmpty()) { + if (isRunAs) { + // the request is a run as request so we should call the specific audit event for a denied run as attempt + throw denyRunAs(authentication, action, request); + } else { + throw denial(authentication, action, request); + } + } + + // check if the request is a run as request + if (isRunAs) { + // first we must authorize for the RUN_AS action + RunAsPermission runAs = permission.runAs(); + if (runAs != null && runAs.check(authentication.getRunAsUser().principal())) { + grantRunAs(authentication, action, request); + permission = permission(authentication.getRunAsUser().roles()); + + // permission can be null as it might be that the user's role + // is unknown + if (permission == null || permission.isEmpty()) { + throw denial(authentication, action, request); + } + } else { + throw denyRunAs(authentication, action, request); + } + } + + // first, we'll check if the action is a cluster action. If it is, we'll only check it + // against the cluster permissions + if (ClusterPrivilege.ACTION_MATCHER.test(action)) { + ClusterPermission cluster = permission.cluster(); + // we use the effectiveUser for permission checking since we are running as a user! + if (cluster != null && cluster.check(action, request, authentication)) { + setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL); + grant(authentication, action, request); + return; + } + throw denial(authentication, action, request); + } + + // ok... this is not a cluster action, let's verify it's an indices action + if (!IndexPrivilege.ACTION_MATCHER.test(action)) { + throw denial(authentication, action, request); + } + + // some APIs are indices requests that are not actually associated with indices. For example, + // search scroll request, is categorized under the indices context, but doesn't hold indices names + // (in this case, the security check on the indices was done on the search request that initialized + // the scroll... and we rely on the signed scroll id to provide security over this request). + // so we only check indices if indeed the request is an actual IndicesRequest, if it's not, + // we just grant it if it's a scroll, deny otherwise + if (!(request instanceof IndicesRequest) && !(request instanceof CompositeIndicesRequest)) { + if (isScrollRelatedAction(action)) { + //note that clear scroll shard level actions can originate from a clear scroll all, which doesn't require any + //indices permission as it's categorized under cluster. This is why the scroll check is performed + //even before checking if the user has any indices permission. + grant(authentication, action, request); + return; + } + assert false : "only scroll related requests are known indices api that don't support retrieving the indices they relate to"; + throw denial(authentication, action, request); + } + + if (permission.indices() == null || permission.indices().isEmpty()) { + throw denial(authentication, action, request); + } + + ClusterState clusterState = clusterService.state(); + Set indexNames = resolveIndices(authentication, action, request, clusterState); + assert !indexNames.isEmpty() : "every indices request needs to have its indices set thus the resolved indices must not be empty"; + MetaData metaData = clusterState.metaData(); + IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData); + if (!indicesAccessControl.isGranted()) { + throw denial(authentication, action, request); + } else if (indicesAccessControl.getIndexPermissions(SecurityTemplateService.SECURITY_INDEX_NAME) != null + && indicesAccessControl.getIndexPermissions(SecurityTemplateService.SECURITY_INDEX_NAME).isGranted() + && XPackUser.is(authentication.getRunAsUser()) == false + && MONITOR_INDEX_PREDICATE.test(action) == false) { + // only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging + // purposes. These monitor requests also sometimes resolve indices concretely and then requests them + // FIXME its not just the XPackUser. We said the elastic user and superusers could access this! + logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]", + authentication.getRunAsUser().principal(), action, SecurityTemplateService.SECURITY_INDEX_NAME); + throw denial(authentication, action, request); + } else { + setIndicesAccessControl(indicesAccessControl); + } + + //if we are creating an index we need to authorize potential aliases created at the same time + if (IndexPrivilege.CREATE_INDEX_MATCHER.test(action)) { + assert request instanceof CreateIndexRequest; + Set aliases = ((CreateIndexRequest) request).aliases(); + if (!aliases.isEmpty()) { + Set aliasesAndIndices = Sets.newHashSet(indexNames); + for (Alias alias : aliases) { + aliasesAndIndices.add(alias.name()); + } + indicesAccessControl = permission.authorize("indices:admin/aliases", aliasesAndIndices, metaData); + if (!indicesAccessControl.isGranted()) { + throw denial(authentication, "indices:admin/aliases", request); + } + // no need to re-add the indicesAccessControl in the context, + // because the create index call doesn't do anything FLS or DLS + } + } + + grant(authentication, action, request); + } + + private void setIndicesAccessControl(IndicesAccessControl accessControl) { + if (threadContext.getTransient(INDICES_PERMISSIONS_KEY) == null) { + threadContext.putTransient(INDICES_PERMISSIONS_KEY, accessControl); + } + } + + private void setOriginatingAction(String action) { + String originatingAction = threadContext.getTransient(ORIGINATING_ACTION_KEY); + if (originatingAction == null) { + threadContext.putTransient(ORIGINATING_ACTION_KEY, action); + } + } + + private GlobalPermission permission(String[] roleNames) { + if (roleNames.length == 0) { + return DefaultRole.INSTANCE; + } + + if (roleNames.length == 1) { + Role role = rolesStore.role(roleNames[0]); + return role == null ? DefaultRole.INSTANCE : GlobalPermission.Compound.builder().add(DefaultRole.INSTANCE).add(role).build(); + } + + // we'll take all the roles and combine their associated permissions + + GlobalPermission.Compound.Builder roles = GlobalPermission.Compound.builder().add(DefaultRole.INSTANCE); + for (String roleName : roleNames) { + Role role = rolesStore.role(roleName); + if (role != null) { + roles.add(role); + } + } + return roles.build(); + } + + private Set resolveIndices(Authentication authentication, String action, TransportRequest request, ClusterState clusterState) { + MetaData metaData = clusterState.metaData(); + for (IndicesAndAliasesResolver resolver : indicesAndAliasesResolvers) { + if (resolver.requestType().isInstance(request)) { + return resolver.resolve(authentication.getRunAsUser(), action, request, metaData); + } + } + assert false : "we should be able to resolve indices for any known request that requires indices privileges"; + throw denial(authentication, action, request); + } + + private static boolean isScrollRelatedAction(String action) { + return action.equals(SearchScrollAction.NAME) || + action.equals(SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME) || + action.equals(SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME) || + action.equals(SearchTransportService.QUERY_SCROLL_ACTION_NAME) || + action.equals(SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME) || + action.equals(ClearScrollAction.NAME) || + action.equals(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME); + } + + private ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request) { + auditTrail.accessDenied(authentication.getUser(), action, request); + return denialException(authentication, action); + } + + private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request) { + auditTrail.runAsDenied(authentication.getUser(), action, request); + return denialException(authentication, action); + } + + private void grant(Authentication authentication, String action, TransportRequest request) { + auditTrail.accessGranted(authentication.getUser(), action, request); + } + + private void grantRunAs(Authentication authentication, String action, TransportRequest request) { + auditTrail.runAsGranted(authentication.getUser(), action, request); + } + + private ElasticsearchSecurityException denialException(Authentication authentication, String action) { + final User user = authentication.getUser(); + // Special case for anonymous user + if (AnonymousUser.enabled() && AnonymousUser.is(user)) { + if (anonymousAuthzExceptionEnabled == false) { + throw authcFailureHandler.authenticationRequired(action, threadContext); + } + } + // check for run as + if (user != authentication.getRunAsUser()) { + return authorizationError("action [{}] is unauthorized for user [{}] run as [{}]", action, user.principal(), + authentication.getRunAsUser().principal()); + } + return authorizationError("action [{}] is unauthorized for user [{}]", action, user.principal()); + } + + public static void addSettings(List> settings) { + settings.add(ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING); + } } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java index 955e64f2258..b3c7344e68e 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationUtils.java @@ -8,8 +8,6 @@ package org.elasticsearch.xpack.security.authz; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.user.SystemUser; -import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; import org.elasticsearch.xpack.security.support.AutomatonPredicate; import org.elasticsearch.xpack.security.support.Automatons; @@ -52,7 +50,7 @@ public final class AuthorizationUtils { // we have a internal action being executed by a user that is not the system user, lets verify that there is a // originating action that is not a internal action - final String originatingAction = threadContext.getTransient(InternalAuthorizationService.ORIGINATING_ACTION_KEY); + final String originatingAction = threadContext.getTransient(AuthorizationService.ORIGINATING_ACTION_KEY); if (originatingAction != null && isInternalAction(originatingAction) == false) { return true; } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationService.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationService.java deleted file mode 100644 index 0e350fc565a..00000000000 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationService.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.security.authz; - -import org.elasticsearch.ElasticsearchSecurityException; -import org.elasticsearch.action.CompositeIndicesRequest; -import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.admin.indices.alias.Alias; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.search.ClearScrollAction; -import org.elasticsearch.action.search.SearchScrollAction; -import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.cluster.service.ClusterService; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.metadata.AliasOrIndex; -import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Setting.Property; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.common.util.set.Sets; -import org.elasticsearch.search.action.SearchTransportService; -import org.elasticsearch.xpack.security.SecurityTemplateService; -import org.elasticsearch.xpack.security.audit.AuditTrailService; -import org.elasticsearch.xpack.security.authc.Authentication; -import org.elasticsearch.xpack.security.user.AnonymousUser; -import org.elasticsearch.xpack.security.user.SystemUser; -import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.user.XPackUser; -import org.elasticsearch.xpack.security.audit.AuditTrail; -import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; -import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; -import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; -import org.elasticsearch.xpack.security.authz.indicesresolver.IndicesAndAliasesResolver; -import org.elasticsearch.xpack.security.authz.permission.ClusterPermission; -import org.elasticsearch.xpack.security.authz.permission.DefaultRole; -import org.elasticsearch.xpack.security.authz.permission.GlobalPermission; -import org.elasticsearch.xpack.security.authz.permission.Role; -import org.elasticsearch.xpack.security.authz.permission.RunAsPermission; -import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; -import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; -import org.elasticsearch.xpack.security.authz.store.RolesStore; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportRequest; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; - -import static org.elasticsearch.xpack.security.Security.setting; -import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError; - -/** - * - */ -public class InternalAuthorizationService extends AbstractComponent implements AuthorizationService { - - public static final Setting ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING = - Setting.boolSetting(setting("authc.anonymous.authz_exception"), true, Property.NodeScope); - public static final String INDICES_PERMISSIONS_KEY = "_indices_permissions"; - static final String ORIGINATING_ACTION_KEY = "_originating_action_name"; - - private static final Predicate MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate(); - - private final ClusterService clusterService; - private final RolesStore rolesStore; - private final AuditTrail auditTrail; - private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers; - private final AuthenticationFailureHandler authcFailureHandler; - private final ThreadContext threadContext; - private final boolean anonymousAuthzExceptionEnabled; - - @Inject - public InternalAuthorizationService(Settings settings, RolesStore rolesStore, ClusterService clusterService, - AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler, - ThreadPool threadPool, IndexNameExpressionResolver nameExpressionResolver) { - super(settings); - this.rolesStore = rolesStore; - this.clusterService = clusterService; - this.auditTrail = auditTrail; - this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] { - new DefaultIndicesAndAliasesResolver(this, nameExpressionResolver) - }; - this.authcFailureHandler = authcFailureHandler; - this.threadContext = threadPool.getThreadContext(); - this.anonymousAuthzExceptionEnabled = ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.get(settings); - } - - @Override - public List authorizedIndicesAndAliases(User user, String action) { - final String[] anonymousRoles = AnonymousUser.enabled() ? AnonymousUser.getRoles() : Strings.EMPTY_ARRAY; - String[] rolesNames = user.roles(); - if (rolesNames.length == 0 && anonymousRoles.length == 0) { - return Collections.emptyList(); - } - - List> predicates = new ArrayList<>(); - for (String roleName : rolesNames) { - Role role = rolesStore.role(roleName); - if (role != null) { - predicates.add(role.indices().allowedIndicesMatcher(action)); - } - } - if (AnonymousUser.is(user) == false) { - for (String roleName : anonymousRoles) { - Role role = rolesStore.role(roleName); - if (role != null) { - predicates.add(role.indices().allowedIndicesMatcher(action)); - } - } - } - Predicate predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2)); - - List indicesAndAliases = new ArrayList<>(); - MetaData metaData = clusterService.state().metaData(); - // TODO: can this be done smarter? I think there are usually more indices/aliases in the cluster then indices defined a roles? - for (Map.Entry entry : metaData.getAliasAndIndexLookup().entrySet()) { - String aliasOrIndex = entry.getKey(); - if (predicate.test(aliasOrIndex)) { - indicesAndAliases.add(aliasOrIndex); - } - } - - if (XPackUser.is(user) == false) { - // we should filter out the .security index from wildcards - if (indicesAndAliases.remove(SecurityTemplateService.SECURITY_INDEX_NAME)) { - logger.debug("removed [{}] from user [{}] list of authorized indices", - SecurityTemplateService.SECURITY_INDEX_NAME, user.principal()); - } - } - return Collections.unmodifiableList(indicesAndAliases); - } - - @Override - public void authorize(Authentication authentication, String action, TransportRequest request) throws ElasticsearchSecurityException { - // prior to doing any authorization lets set the originating action in the context only - setOriginatingAction(action); - - // first we need to check if the user is the system. If it is, we'll just authorize the system access - if (SystemUser.is(authentication.getRunAsUser())) { - if (SystemUser.isAuthorized(action) && SystemUser.is(authentication.getUser())) { - setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL); - grant(authentication, action, request); - return; - } - throw denial(authentication, action, request); - } - - // get the roles of the authenticated user, which may be different than the effective - GlobalPermission permission = permission(authentication.getUser().roles()); - - final boolean isRunAs = authentication.getUser() != authentication.getRunAsUser(); - // permission can be null as it might be that the user's role - // is unknown - if (permission == null || permission.isEmpty()) { - if (isRunAs) { - // the request is a run as request so we should call the specific audit event for a denied run as attempt - throw denyRunAs(authentication, action, request); - } else { - throw denial(authentication, action, request); - } - } - - // check if the request is a run as request - if (isRunAs) { - // first we must authorize for the RUN_AS action - RunAsPermission runAs = permission.runAs(); - if (runAs != null && runAs.check(authentication.getRunAsUser().principal())) { - grantRunAs(authentication, action, request); - permission = permission(authentication.getRunAsUser().roles()); - - // permission can be null as it might be that the user's role - // is unknown - if (permission == null || permission.isEmpty()) { - throw denial(authentication, action, request); - } - } else { - throw denyRunAs(authentication, action, request); - } - } - - // first, we'll check if the action is a cluster action. If it is, we'll only check it - // against the cluster permissions - if (ClusterPrivilege.ACTION_MATCHER.test(action)) { - ClusterPermission cluster = permission.cluster(); - // we use the effectiveUser for permission checking since we are running as a user! - if (cluster != null && cluster.check(action, request, authentication)) { - setIndicesAccessControl(IndicesAccessControl.ALLOW_ALL); - grant(authentication, action, request); - return; - } - throw denial(authentication, action, request); - } - - // ok... this is not a cluster action, let's verify it's an indices action - if (!IndexPrivilege.ACTION_MATCHER.test(action)) { - throw denial(authentication, action, request); - } - - // some APIs are indices requests that are not actually associated with indices. For example, - // search scroll request, is categorized under the indices context, but doesn't hold indices names - // (in this case, the security check on the indices was done on the search request that initialized - // the scroll... and we rely on the signed scroll id to provide security over this request). - // so we only check indices if indeed the request is an actual IndicesRequest, if it's not, - // we just grant it if it's a scroll, deny otherwise - if (!(request instanceof IndicesRequest) && !(request instanceof CompositeIndicesRequest)) { - if (isScrollRelatedAction(action)) { - //note that clear scroll shard level actions can originate from a clear scroll all, which doesn't require any - //indices permission as it's categorized under cluster. This is why the scroll check is performed - //even before checking if the user has any indices permission. - grant(authentication, action, request); - return; - } - assert false : "only scroll related requests are known indices api that don't support retrieving the indices they relate to"; - throw denial(authentication, action, request); - } - - if (permission.indices() == null || permission.indices().isEmpty()) { - throw denial(authentication, action, request); - } - - ClusterState clusterState = clusterService.state(); - Set indexNames = resolveIndices(authentication, action, request, clusterState); - assert !indexNames.isEmpty() : "every indices request needs to have its indices set thus the resolved indices must not be empty"; - MetaData metaData = clusterState.metaData(); - IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData); - if (!indicesAccessControl.isGranted()) { - throw denial(authentication, action, request); - } else if (indicesAccessControl.getIndexPermissions(SecurityTemplateService.SECURITY_INDEX_NAME) != null - && indicesAccessControl.getIndexPermissions(SecurityTemplateService.SECURITY_INDEX_NAME).isGranted() - && XPackUser.is(authentication.getRunAsUser()) == false - && MONITOR_INDEX_PREDICATE.test(action) == false) { - // only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging - // purposes. These monitor requests also sometimes resolve indices concretely and then requests them - // FIXME its not just the XPackUser. We said the elastic user and superusers could access this! - logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]", - authentication.getRunAsUser().principal(), action, SecurityTemplateService.SECURITY_INDEX_NAME); - throw denial(authentication, action, request); - } else { - setIndicesAccessControl(indicesAccessControl); - } - - //if we are creating an index we need to authorize potential aliases created at the same time - if (IndexPrivilege.CREATE_INDEX_MATCHER.test(action)) { - assert request instanceof CreateIndexRequest; - Set aliases = ((CreateIndexRequest) request).aliases(); - if (!aliases.isEmpty()) { - Set aliasesAndIndices = Sets.newHashSet(indexNames); - for (Alias alias : aliases) { - aliasesAndIndices.add(alias.name()); - } - indicesAccessControl = permission.authorize("indices:admin/aliases", aliasesAndIndices, metaData); - if (!indicesAccessControl.isGranted()) { - throw denial(authentication, "indices:admin/aliases", request); - } - // no need to re-add the indicesAccessControl in the context, - // because the create index call doesn't do anything FLS or DLS - } - } - - grant(authentication, action, request); - } - - private void setIndicesAccessControl(IndicesAccessControl accessControl) { - if (threadContext.getTransient(INDICES_PERMISSIONS_KEY) == null) { - threadContext.putTransient(INDICES_PERMISSIONS_KEY, accessControl); - } - } - - private void setOriginatingAction(String action) { - String originatingAction = threadContext.getTransient(ORIGINATING_ACTION_KEY); - if (originatingAction == null) { - threadContext.putTransient(ORIGINATING_ACTION_KEY, action); - } - } - - private GlobalPermission permission(String[] roleNames) { - if (roleNames.length == 0) { - return DefaultRole.INSTANCE; - } - - if (roleNames.length == 1) { - Role role = rolesStore.role(roleNames[0]); - return role == null ? DefaultRole.INSTANCE : GlobalPermission.Compound.builder().add(DefaultRole.INSTANCE).add(role).build(); - } - - // we'll take all the roles and combine their associated permissions - - GlobalPermission.Compound.Builder roles = GlobalPermission.Compound.builder().add(DefaultRole.INSTANCE); - for (String roleName : roleNames) { - Role role = rolesStore.role(roleName); - if (role != null) { - roles.add(role); - } - } - return roles.build(); - } - - private Set resolveIndices(Authentication authentication, String action, TransportRequest request, ClusterState clusterState) { - MetaData metaData = clusterState.metaData(); - for (IndicesAndAliasesResolver resolver : indicesAndAliasesResolvers) { - if (resolver.requestType().isInstance(request)) { - return resolver.resolve(authentication.getRunAsUser(), action, request, metaData); - } - } - assert false : "we should be able to resolve indices for any known request that requires indices privileges"; - throw denial(authentication, action, request); - } - - private static boolean isScrollRelatedAction(String action) { - return action.equals(SearchScrollAction.NAME) || - action.equals(SearchTransportService.FETCH_ID_SCROLL_ACTION_NAME) || - action.equals(SearchTransportService.QUERY_FETCH_SCROLL_ACTION_NAME) || - action.equals(SearchTransportService.QUERY_SCROLL_ACTION_NAME) || - action.equals(SearchTransportService.FREE_CONTEXT_SCROLL_ACTION_NAME) || - action.equals(ClearScrollAction.NAME) || - action.equals(SearchTransportService.CLEAR_SCROLL_CONTEXTS_ACTION_NAME); - } - - private ElasticsearchSecurityException denial(Authentication authentication, String action, TransportRequest request) { - auditTrail.accessDenied(authentication.getUser(), action, request); - return denialException(authentication, action); - } - - private ElasticsearchSecurityException denyRunAs(Authentication authentication, String action, TransportRequest request) { - auditTrail.runAsDenied(authentication.getUser(), action, request); - return denialException(authentication, action); - } - - private void grant(Authentication authentication, String action, TransportRequest request) { - auditTrail.accessGranted(authentication.getUser(), action, request); - } - - private void grantRunAs(Authentication authentication, String action, TransportRequest request) { - auditTrail.runAsGranted(authentication.getUser(), action, request); - } - - private ElasticsearchSecurityException denialException(Authentication authentication, String action) { - final User user = authentication.getUser(); - // Special case for anonymous user - if (AnonymousUser.enabled() && AnonymousUser.is(user)) { - if (anonymousAuthzExceptionEnabled == false) { - throw authcFailureHandler.authenticationRequired(action, threadContext); - } - } - // check for run as - if (user != authentication.getRunAsUser()) { - return authorizationError("action [{}] is unauthorized for user [{}] run as [{}]", action, user.principal(), - authentication.getRunAsUser().principal()); - } - return authorizationError("action [{}] is unauthorized for user [{}]", action, user.principal()); - } - - public static void addSettings(List> settings) { - settings.add(ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING); - } -} diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/OptOutQueryCache.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/OptOutQueryCache.java index 7cf8a0e0e83..ad4f0d7823e 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/OptOutQueryCache.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/OptOutQueryCache.java @@ -14,7 +14,7 @@ import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.cache.query.QueryCache; import org.elasticsearch.indices.IndicesQueryCache; import org.elasticsearch.search.internal.ShardSearchRequest; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import java.util.HashSet; import java.util.Set; @@ -50,7 +50,7 @@ public final class OptOutQueryCache extends AbstractIndexComponent implements Qu throw new IllegalStateException("opting out of the query cache. current request can't be found"); } IndicesAccessControl indicesAccessControl = context.getThreadContext().getTransient( - InternalAuthorizationService.INDICES_PERMISSIONS_KEY); + AuthorizationService.INDICES_PERMISSIONS_KEY); if (indicesAccessControl == null) { logger.debug("opting out of the query cache. current request doesn't hold indices permissions"); return weight; diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/SecurityIndexSearcherWrapper.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/SecurityIndexSearcherWrapper.java index 2e133336eea..5a938235b02 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/SecurityIndexSearcherWrapper.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/SecurityIndexSearcherWrapper.java @@ -43,7 +43,7 @@ import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.IndexSearcherWrapper; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardUtils; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.accesscontrol.DocumentSubsetReader.DocumentSubsetDirectoryReader; import org.elasticsearch.xpack.security.SecurityLicenseState; import org.elasticsearch.xpack.security.support.Exceptions; @@ -263,7 +263,7 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper { } protected IndicesAccessControl getIndicesAccessControl() { - IndicesAccessControl indicesAccessControl = threadContext.getTransient(InternalAuthorizationService.INDICES_PERMISSIONS_KEY); + IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY); if (indicesAccessControl == null) { throw Exceptions.authorizationError("no indices permissions found"); } diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java index 5ee3d53cf94..440ad73eab7 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java @@ -7,9 +7,7 @@ package org.elasticsearch.xpack.security.authz.indicesresolver; import org.elasticsearch.action.AliasesRequest; import org.elasticsearch.action.CompositeIndicesRequest; -import org.elasticsearch.action.DocumentRequest; import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.cluster.metadata.AliasOrIndex; @@ -19,8 +17,8 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.index.IndexNotFoundException; -import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.authz.AuthorizationService; +import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.transport.TransportRequest; import java.util.ArrayList; diff --git a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/transport/ServerTransportFilter.java b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/transport/ServerTransportFilter.java index ebc923e6ad8..bc17f7fe4ea 100644 --- a/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/transport/ServerTransportFilter.java +++ b/elasticsearch/x-pack/security/src/main/java/org/elasticsearch/xpack/security/transport/ServerTransportFilter.java @@ -5,26 +5,26 @@ */ package org.elasticsearch.xpack.security.transport; -import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.transport.TcpTransportChannel; -import org.elasticsearch.xpack.security.authc.Authentication; -import org.elasticsearch.xpack.security.action.SecurityActionMapper; -import org.elasticsearch.xpack.security.authc.AuthenticationService; -import org.elasticsearch.xpack.security.authc.pki.PkiRealm; -import org.elasticsearch.xpack.security.authz.AuthorizationService; -import org.elasticsearch.transport.DelegatingTransportChannel; -import org.elasticsearch.transport.TransportChannel; -import org.elasticsearch.transport.TransportRequest; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.handler.ssl.SslHandler; - import javax.net.ssl.SSLPeerUnverifiedException; import java.io.IOException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.transport.DelegatingTransportChannel; +import org.elasticsearch.transport.TcpTransportChannel; +import org.elasticsearch.transport.TransportChannel; +import org.elasticsearch.transport.TransportRequest; +import org.elasticsearch.xpack.security.action.SecurityActionMapper; +import org.elasticsearch.xpack.security.authc.Authentication; +import org.elasticsearch.xpack.security.authc.AuthenticationService; +import org.elasticsearch.xpack.security.authc.pki.PkiRealm; +import org.elasticsearch.xpack.security.authz.AuthorizationService; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.handler.ssl.SslHandler; + import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError; /** diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationServiceTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java similarity index 94% rename from elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationServiceTests.java rename to elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java index dbca9ce2b91..b53277f96b3 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/InternalAuthenticationServiceTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java @@ -25,7 +25,7 @@ import org.elasticsearch.xpack.security.SecurityLicenseState; import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService.Authenticator; +import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticator; import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; @@ -59,9 +59,9 @@ import static org.mockito.Mockito.when; /** * */ -public class InternalAuthenticationServiceTests extends ESTestCase { +public class AuthenticationServiceTests extends ESTestCase { - InternalAuthenticationService service; + AuthenticationService service; TransportMessage message; RestRequest restRequest; Realms realms; @@ -109,7 +109,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { threadContext = new ThreadContext(Settings.EMPTY); when(threadPool.getThreadContext()).thenReturn(threadContext); when(cryptoService.sign(any(String.class))).thenReturn("_signed_auth"); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); } @@ -308,7 +308,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { InternalMessage message1 = new InternalMessage(); ThreadContext threadContext1 = new ThreadContext(Settings.EMPTY); when(threadPool.getThreadContext()).thenReturn(threadContext1); - service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); threadContext1.putTransient(Authentication.AUTHENTICATION_KEY, threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); @@ -322,7 +322,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { // checking authentication from the user header threadContext1 = new ThreadContext(Settings.EMPTY); when(threadPool.getThreadContext()).thenReturn(threadContext1); - service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); threadContext1.putHeader(Authentication.AUTHENTICATION_KEY, threadContext.getHeader(Authentication.AUTHENTICATION_KEY)); when(cryptoService.unsignAndVerify("_signed_auth")).thenReturn(authentication.encode()); @@ -334,7 +334,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { threadContext1.readHeaders(input); when(threadPool.getThreadContext()).thenReturn(threadContext1); - service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); Authentication result = service.authenticate("_action", new InternalMessage(), SystemUser.INSTANCE); assertThat(result, notNullValue()); @@ -343,8 +343,8 @@ public class InternalAuthenticationServiceTests extends ESTestCase { } public void testAuthenticateTransportContextAndHeaderNoSigning() throws Exception { - Settings settings = Settings.builder().put(InternalAuthenticationService.SIGN_USER_HEADER.getKey(), false).build(); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, + Settings settings = Settings.builder().put(AuthenticationService.SIGN_USER_HEADER.getKey(), false).build(); + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); User user1 = new User("username", "r1", "r2"); @@ -361,7 +361,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { InternalMessage message1 = new InternalMessage(); ThreadContext threadContext1 = new ThreadContext(Settings.EMPTY); when(threadPool.getThreadContext()).thenReturn(threadContext1); - service = new InternalAuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); threadContext1.putTransient(Authentication.AUTHENTICATION_KEY, threadContext.getTransient(Authentication.AUTHENTICATION_KEY)); threadContext1.putHeader(Authentication.AUTHENTICATION_KEY, threadContext.getHeader(Authentication.AUTHENTICATION_KEY)); @@ -381,7 +381,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { threadContext1.readHeaders(input); when(threadPool.getThreadContext()).thenReturn(threadContext1); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); Authentication result = service.authenticate("_action", new InternalMessage(), SystemUser.INSTANCE); assertThat(result, notNullValue()); @@ -444,7 +444,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { } Settings settings = builder.build(); AnonymousUser.initialize(settings); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); RestRequest request = new FakeRestRequest(); @@ -460,7 +460,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { .putArray(AnonymousUser.ROLES_SETTING.getKey(), "r1", "r2", "r3") .build(); AnonymousUser.initialize(settings); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); InternalMessage message = new InternalMessage(); @@ -475,7 +475,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { .putArray(AnonymousUser.ROLES_SETTING.getKey(), "r1", "r2", "r3") .build(); AnonymousUser.initialize(settings); - service = new InternalAuthenticationService(settings, realms, auditTrail, cryptoService, + service = new AuthenticationService(settings, realms, auditTrail, cryptoService, new DefaultAuthenticationFailureHandler(), threadPool); InternalMessage message = new InternalMessage(); @@ -564,7 +564,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRealmLookupThrowingException() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, "run_as"); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"})); @@ -582,7 +582,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRealmLookupThrowingExceptionRest() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, "run_as"); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"})); @@ -600,7 +600,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRunAsLookupSameRealm() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, "run_as"); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"})); @@ -627,7 +627,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRunAsLookupDifferentRealm() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "run_as"); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, "run_as"); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(new User("lookup user", new String[]{"user"})); @@ -656,7 +656,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRunAsWithEmptyRunAsUsernameRest() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); User user = new User("lookup user", new String[]{"user"}); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, ""); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, ""); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(user); @@ -674,7 +674,7 @@ public class InternalAuthenticationServiceTests extends ESTestCase { public void testRunAsWithEmptyRunAsUsername() throws Exception { AuthenticationToken token = mock(AuthenticationToken.class); User user = new User("lookup user", new String[]{"user"}); - threadContext.putHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, ""); + threadContext.putHeader(AuthenticationService.RUN_AS_USER_HEADER, ""); when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.authenticate(token)).thenReturn(user); diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RunAsIntegTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RunAsIntegTests.java index bf72fb46915..19d9b77676d 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RunAsIntegTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authc/RunAsIntegTests.java @@ -95,7 +95,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { // let's run as without authorization try { - Map headers = Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER, + Map headers = Collections.singletonMap(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME); client.filterWithHeader(headers) .admin().cluster().prepareHealth().get(); @@ -108,7 +108,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { Map headers = new HashMap<>(); headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))); - headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME); + headers.put(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME); // lets set the user ClusterHealthResponse response = client.filterWithHeader(headers).admin().cluster().prepareHealth().get(); assertThat(response.isTimedOut(), is(false)); @@ -122,7 +122,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, UsernamePasswordToken.basicAuthHeaderValue(TRANSPORT_CLIENT_USER, SecuredStringTests.build(SecuritySettingsSource.DEFAULT_PASSWORD))), - new BasicHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME)); + new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME)); fail("request should have failed"); } catch(ResponseException e) { assertThat(e.getResponse().getStatusLine().getStatusCode(), is(403)); @@ -144,7 +144,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, SecuredStringTests.build(SecuritySettingsSource.DEFAULT_PASSWORD))), - new BasicHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME))) { + new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, SecuritySettingsSource.DEFAULT_USER_NAME))) { assertThat(response.getStatusLine().getStatusCode(), is(200)); } } @@ -161,7 +161,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { Map headers = new HashMap<>(); headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))); - headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, ""); + headers.put(AuthenticationService.RUN_AS_USER_HEADER, ""); client.filterWithHeader(headers).admin().cluster().prepareHealth().get(); fail("run as header should not be allowed to be empty"); @@ -177,7 +177,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, SecuredStringTests.build(SecuritySettingsSource.DEFAULT_PASSWORD))), - new BasicHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "")); + new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, "")); fail("request should have failed"); } catch(ResponseException e) { assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401)); @@ -196,7 +196,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { Map headers = new HashMap<>(); headers.put("Authorization", UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, new SecuredString(SecuritySettingsSource.DEFAULT_PASSWORD.toCharArray()))); - headers.put(InternalAuthenticationService.RUN_AS_USER_HEADER, "idontexist"); + headers.put(AuthenticationService.RUN_AS_USER_HEADER, "idontexist"); client.filterWithHeader(headers).admin().cluster().prepareHealth().get(); fail("run as header should not accept non-existent users"); @@ -212,7 +212,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase { new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, UsernamePasswordToken.basicAuthHeaderValue(RUN_AS_USER, SecuredStringTests.build(SecuritySettingsSource.DEFAULT_PASSWORD))), - new BasicHeader(InternalAuthenticationService.RUN_AS_USER_HEADER, "idontexist")); + new BasicHeader(AuthenticationService.RUN_AS_USER_HEADER, "idontexist")); fail("request should have failed"); } catch (ResponseException e) { assertThat(e.getResponse().getStatusLine().getStatusCode(), is(403)); diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationServiceTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java similarity index 98% rename from elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationServiceTests.java rename to elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index d546218ecd8..7979c5e4059 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/InternalAuthorizationServiceTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -93,11 +93,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -public class InternalAuthorizationServiceTests extends ESTestCase { +public class AuthorizationServiceTests extends ESTestCase { private AuditTrailService auditTrail; private RolesStore rolesStore; private ClusterService clusterService; - private InternalAuthorizationService internalAuthorizationService; + private AuthorizationService internalAuthorizationService; private ThreadContext threadContext; private ThreadPool threadPool; @@ -112,7 +112,7 @@ public class InternalAuthorizationServiceTests extends ESTestCase { IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg()); - internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, + internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver); } @@ -359,7 +359,7 @@ public class InternalAuthorizationServiceTests extends ESTestCase { AnonymousUser.initialize(Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build()); IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg()); - internalAuthorizationService = new InternalAuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, + internalAuthorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); @@ -384,13 +384,13 @@ public class InternalAuthorizationServiceTests extends ESTestCase { ClusterState state = mock(ClusterState.class); AnonymousUser.initialize(Settings.builder() .put(AnonymousUser.ROLES_SETTING.getKey(), "a_all") - .put(InternalAuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false) + .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false) .build()); User anonymousUser = AnonymousUser.INSTANCE; IndexNameExpressionResolver nameExpressionResolver = mock(IndexNameExpressionResolver.class); when(nameExpressionResolver.resolveDateMathExpression(any(String.class))).thenAnswer(returnsFirstArg()); - internalAuthorizationService = new InternalAuthorizationService( - Settings.builder().put(InternalAuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false).build(), + internalAuthorizationService = new AuthorizationService( + Settings.builder().put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false).build(), rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, nameExpressionResolver); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationUtilsTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationUtilsTests.java index 540af489890..fdaa0eb50e5 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationUtilsTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationUtilsTests.java @@ -44,7 +44,7 @@ public class AuthorizationUtilsTests extends ESTestCase { User user = new User(randomAsciiOfLength(6), new String[] {}); Authentication authentication = new Authentication(user, new RealmRef("test", "test", "foo"), null); threadContext.putTransient(Authentication.AUTHENTICATION_KEY, authentication); - threadContext.putTransient(InternalAuthorizationService.ORIGINATING_ACTION_KEY, randomFrom("indices:foo", "cluster:bar")); + threadContext.putTransient(AuthorizationService.ORIGINATING_ACTION_KEY, randomFrom("indices:foo", "cluster:bar")); assertThat(AuthorizationUtils.shouldReplaceUserWithSystem(threadContext, "internal:something"), is(true)); } @@ -52,7 +52,7 @@ public class AuthorizationUtilsTests extends ESTestCase { User user = new User(randomAsciiOfLength(6), new String[] {}); Authentication authentication = new Authentication(user, new RealmRef("test", "test", "foo"), null); threadContext.putTransient(Authentication.AUTHENTICATION_KEY, authentication); - threadContext.putTransient(InternalAuthorizationService.ORIGINATING_ACTION_KEY, randomFrom("internal:foo/bar")); + threadContext.putTransient(AuthorizationService.ORIGINATING_ACTION_KEY, randomFrom("internal:foo/bar")); assertThat(AuthorizationUtils.shouldReplaceUserWithSystem(threadContext, "internal:something"), is(false)); } } diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java index 011aff9ebb6..83ae40a1442 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java @@ -36,7 +36,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; @@ -101,7 +101,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(metaData); - InternalAuthorizationService authzService = new InternalAuthorizationService(settings, rolesStore, clusterService, + AuthorizationService authzService = new AuthorizationService(settings, rolesStore, clusterService, mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class), indexNameExpressionResolver); defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService, indexNameExpressionResolver); diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/SecurityRestFilterTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/SecurityRestFilterTests.java index bde8c10079b..badc05f9d2c 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/SecurityRestFilterTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/SecurityRestFilterTests.java @@ -13,10 +13,10 @@ import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestFilterChain; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.xpack.security.authc.Authentication; -import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.SecurityLicenseState; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.junit.Before; import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError; diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/action/RestAuthenticateActionTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/action/RestAuthenticateActionTests.java index b48fec3e5f8..e678d696f59 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/action/RestAuthenticateActionTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/rest/action/RestAuthenticateActionTests.java @@ -17,7 +17,7 @@ import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.test.rest.ObjectPath; import org.elasticsearch.xpack.security.authc.support.SecuredString; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.user.AnonymousUser; import org.junit.BeforeClass; @@ -46,7 +46,7 @@ public class RestAuthenticateActionTests extends SecurityIntegTestCase { if (anonymousEnabled) { builder.put(AnonymousUser.USERNAME_SETTING.getKey(), "anon") .putArray(AnonymousUser.ROLES_SETTING.getKey(), SecuritySettingsSource.DEFAULT_ROLE, "foo") - .put(InternalAuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false); + .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false); } return builder.build(); } diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ClientTransportFilterTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ClientTransportFilterTests.java index 9d2f78e6af8..15951ec09a7 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ClientTransportFilterTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ClientTransportFilterTests.java @@ -5,8 +5,8 @@ */ package org.elasticsearch.xpack.security.transport; -import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.xpack.security.authc.AuthenticationService; +import org.elasticsearch.xpack.security.user.SystemUser; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; import org.junit.Before; diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterTests.java index 376f7456d55..1075f1ae2b0 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterTests.java @@ -11,11 +11,11 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.transport.TransportChannel; import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.action.SecurityActionMapper; -import org.elasticsearch.xpack.security.authc.AuthenticationService; -import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.transport.TransportSettings; +import org.elasticsearch.xpack.security.authc.AuthenticationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.junit.Before; import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError; diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/TransportFilterTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/TransportFilterTests.java index 18aa09574df..f6ad400e782 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/TransportFilterTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/transport/TransportFilterTests.java @@ -17,8 +17,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.transport.MockTcpTransportPlugin; import org.elasticsearch.xpack.security.action.SecurityActionMapper; -import org.elasticsearch.xpack.security.authc.AuthenticationService; -import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.SecurityLicenseState; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; @@ -32,6 +30,8 @@ import org.elasticsearch.transport.TransportResponse; import org.elasticsearch.transport.TransportResponseHandler; import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportSettings; +import org.elasticsearch.xpack.security.authc.AuthenticationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.mockito.InOrder; import java.io.IOException; diff --git a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/user/AnonymousUserIntegTests.java b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/user/AnonymousUserIntegTests.java index 85f72ef525d..d249390fe4b 100644 --- a/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/user/AnonymousUserIntegTests.java +++ b/elasticsearch/x-pack/security/src/test/java/org/elasticsearch/xpack/security/user/AnonymousUserIntegTests.java @@ -10,7 +10,7 @@ import org.elasticsearch.client.ResponseException; import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.SecurityIntegTestCase; -import org.elasticsearch.xpack.security.authz.InternalAuthorizationService; +import org.elasticsearch.xpack.security.authz.AuthorizationService; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -26,7 +26,7 @@ public class AnonymousUserIntegTests extends SecurityIntegTestCase { .put(super.nodeSettings(nodeOrdinal)) .put(NetworkModule.HTTP_ENABLED.getKey(), true) .put(AnonymousUser.ROLES_SETTING.getKey(), "anonymous") - .put(InternalAuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), authorizationExceptionsEnabled) + .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), authorizationExceptionsEnabled) .build(); } diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index 78e6b22f86e..a3be4582f3b 100644 --- a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -70,7 +70,7 @@ import org.elasticsearch.xpack.rest.action.RestXPackUsageAction; import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.authc.AuthenticationModule; -import org.elasticsearch.xpack.security.authc.InternalAuthenticationService; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.support.clock.Clock; import org.elasticsearch.xpack.support.clock.SystemClock; @@ -223,8 +223,8 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I } Set headers = new HashSet<>(); headers.add(UsernamePasswordToken.BASIC_AUTH_HEADER); - if (InternalAuthenticationService.RUN_AS_ENABLED.get(settings)) { - headers.add(InternalAuthenticationService.RUN_AS_USER_HEADER); + if (AuthenticationService.RUN_AS_ENABLED.get(settings)) { + headers.add(AuthenticationService.RUN_AS_USER_HEADER); } headers.addAll(extensionsService.getExtensions().stream() .flatMap(e -> e.getRestHeaders().stream()).collect(Collectors.toList()));