Internal: Remove interfaces for auth services

Both AuthenticationService and AuthorizationService are currently
interfaces with single implementations. This is unnecessary, and makes
it harder to deguice. This change removes the abstractions and leaves
just AuthenticationService and AuthorizationService.

Original commit: elastic/x-pack-elasticsearch@d04c897ae4
This commit is contained in:
Ryan Ernst 2016-07-19 14:38:51 -07:00
parent 12eb53f239
commit 94b9b332d4
29 changed files with 797 additions and 856 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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. */

View File

@ -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;

View File

@ -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);

View File

@ -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<Request> 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);

View File

@ -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();
}
/**

View File

@ -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<Boolean> SIGN_USER_HEADER =
Setting.boolSetting(setting("authc.sign_user_header"), true, Property.NodeScope);
public static final Setting<Boolean> 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<Setting<?>> settings) {
settings.add(SIGN_USER_HEADER);
settings.add(RUN_AS_ENABLED);
}
}

View File

@ -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<Boolean> SIGN_USER_HEADER =
Setting.boolSetting(setting("authc.sign_user_header"), true, Property.NodeScope);
public static final Setting<Boolean> 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<Setting<?>> settings) {
settings.add(SIGN_USER_HEADER);
settings.add(RUN_AS_ENABLED);
}
}

View File

@ -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();
}
}

View File

@ -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<Boolean> 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<String> 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<String> authorizedIndicesAndAliases(User user, String action);
public List<String> 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<Predicate<String>> 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<String> predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2));
List<String> 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<String, AliasOrIndex> 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<String> 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<Alias> aliases = ((CreateIndexRequest) request).aliases();
if (!aliases.isEmpty()) {
Set<String> 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<String> 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<Setting<?>> settings) {
settings.add(ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING);
}
}

View File

@ -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;
}

View File

@ -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<Boolean> 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<String> 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<String> 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<Predicate<String>> 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<String> predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2));
List<String> 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<String, AliasOrIndex> 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<String> 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<Alias> aliases = ((CreateIndexRequest) request).aliases();
if (!aliases.isEmpty()) {
Set<String> 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<String> 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<Setting<?>> settings) {
settings.add(ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING);
}
}

View File

@ -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;

View File

@ -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");
}

View File

@ -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;

View File

@ -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;
/**

View File

@ -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);

View File

@ -95,7 +95,7 @@ public class RunAsIntegTests extends SecurityIntegTestCase {
// let's run as without authorization
try {
Map<String, String> headers = Collections.singletonMap(InternalAuthenticationService.RUN_AS_USER_HEADER,
Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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));

View File

@ -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());

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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<String> 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()));