diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/AuditTrailService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/AuditTrailService.java index ddf6d49a632ae..fb84df489ff65 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/AuditTrailService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/audit/AuditTrailService.java @@ -19,219 +19,280 @@ import java.util.Collections; import java.util.List; -public class AuditTrailService implements AuditTrail { +public class AuditTrailService { + private static final AuditTrail NOOP_AUDIT_TRAIL = new NoopAuditTrail(); + private final CompositeAuditTrail compositeAuditTrail; private final XPackLicenseState licenseState; - private final List auditTrails; - - @Override - public String name() { - return "service"; - } public AuditTrailService(List auditTrails, XPackLicenseState licenseState) { - this.auditTrails = Collections.unmodifiableList(auditTrails); + this.compositeAuditTrail = new CompositeAuditTrail(Collections.unmodifiableList(auditTrails)); this.licenseState = licenseState; } - /** Returns the audit trail implementations that this service delegates to. */ + public AuditTrail get() { + if (compositeAuditTrail.isEmpty() == false && licenseState.isAuditingAllowed()) { + return compositeAuditTrail; + } else { + return NOOP_AUDIT_TRAIL; + } + } + + // TODO: this method only exists for access to LoggingAuditTrail in a Node for testing. + // DO NOT USE IT, IT WILL BE REMOVED IN THE FUTURE public List getAuditTrails() { - return auditTrails; + return compositeAuditTrail.auditTrails; + } + + private static class NoopAuditTrail implements AuditTrail { + + @Override + public String name() { + return "noop"; + } + + @Override + public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) {} + + @Override + public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) {} + + @Override + public void anonymousAccessDenied(String requestId, String action, TransportMessage message) {} + + @Override + public void anonymousAccessDenied(String requestId, RestRequest request) {} + + @Override + public void authenticationFailed(String requestId, RestRequest request) {} + + @Override + public void authenticationFailed(String requestId, String action, TransportMessage message) {} + + @Override + public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) {} + + @Override + public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) {} + + @Override + public void authenticationFailed(String requestId, String realm, AuthenticationToken token, + String action, TransportMessage message) {} + + @Override + public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) {} + + @Override + public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) {} + + @Override + public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) {} + + @Override + public void tamperedRequest(String requestId, RestRequest request) {} + + @Override + public void tamperedRequest(String requestId, String action, TransportMessage message) {} + + @Override + public void tamperedRequest(String requestId, User user, String action, TransportMessage request) {} + + @Override + public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {} + + @Override + public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {} + + @Override + public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) {} + + @Override + public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) {} + + @Override + public void runAsDenied(String requestId, Authentication authentication, RestRequest request, + AuthorizationInfo authorizationInfo) {} + + @Override + public void explicitIndexAccessEvent(String requestId, AuditLevel eventType, Authentication authentication, + String action, String indices, String requestName, TransportAddress remoteAddress, + AuthorizationInfo authorizationInfo) {} } - @Override - public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + private static class CompositeAuditTrail implements AuditTrail { + + private final List auditTrails; + + private CompositeAuditTrail(List auditTrails) { + this.auditTrails = auditTrails; + } + + boolean isEmpty() { + return auditTrails.isEmpty(); + } + + @Override + public String name() { + return "service"; + } + + @Override + public void authenticationSuccess(String requestId, String realm, User user, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationSuccess(requestId, realm, user, request); } } - } - @Override - public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationSuccess(String requestId, String realm, User user, String action, TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationSuccess(requestId, realm, user, action, message); } } - } - @Override - public void anonymousAccessDenied(String requestId, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void anonymousAccessDenied(String requestId, String action, TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.anonymousAccessDenied(requestId, action, message); } } - } - @Override - public void anonymousAccessDenied(String requestId, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void anonymousAccessDenied(String requestId, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.anonymousAccessDenied(requestId, request); } } - } - @Override - public void authenticationFailed(String requestId, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, request); } } - } - @Override - public void authenticationFailed(String requestId, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, String action, TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, action, message); } } - } - @Override - public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, AuthenticationToken token, String action, TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, token, action, message); } } - } - @Override - public void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, String realm, AuthenticationToken token, String action, + TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, realm, token, action, message); } } - } - @Override - public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, token, request); } } - } - @Override - public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.authenticationFailed(requestId, realm, token, request); } } - } - @Override - public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage msg, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void accessGranted(String requestId, Authentication authentication, String action, TransportMessage msg, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.accessGranted(requestId, authentication, action, msg, authorizationInfo); } } - } - @Override - public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void accessDenied(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.accessDenied(requestId, authentication, action, message, authorizationInfo); } } - } - @Override - public void tamperedRequest(String requestId, RestRequest request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void tamperedRequest(String requestId, RestRequest request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.tamperedRequest(requestId, request); } } - } - @Override - public void tamperedRequest(String requestId, String action, TransportMessage message) { - if (licenseState.isAuditingAllowed()) { + @Override + public void tamperedRequest(String requestId, String action, TransportMessage message) { for (AuditTrail auditTrail : auditTrails) { auditTrail.tamperedRequest(requestId, action, message); } } - } - @Override - public void tamperedRequest(String requestId, User user, String action, TransportMessage request) { - if (licenseState.isAuditingAllowed()) { + @Override + public void tamperedRequest(String requestId, User user, String action, TransportMessage request) { for (AuditTrail auditTrail : auditTrails) { auditTrail.tamperedRequest(requestId, user, action, request); } } - } - @Override - public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) { - if (licenseState.isAuditingAllowed()) { + @Override + public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) { for (AuditTrail auditTrail : auditTrails) { auditTrail.connectionGranted(inetAddress, profile, rule); } } - } - @Override - public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) { - if (licenseState.isAuditingAllowed()) { + @Override + public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) { for (AuditTrail auditTrail : auditTrails) { auditTrail.connectionDenied(inetAddress, profile, rule); } } - } - @Override - public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void runAsGranted(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.runAsGranted(requestId, authentication, action, message, authorizationInfo); } } - } - @Override - public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void runAsDenied(String requestId, Authentication authentication, String action, TransportMessage message, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.runAsDenied(requestId, authentication, action, message, authorizationInfo); } } - } - @Override - public void runAsDenied(String requestId, Authentication authentication, RestRequest request, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void runAsDenied(String requestId, Authentication authentication, RestRequest request, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.runAsDenied(requestId, authentication, request, authorizationInfo); } } - } - @Override - public void explicitIndexAccessEvent(String requestId, AuditLevel eventType, Authentication authentication, String action, - String indices, String requestName, TransportAddress remoteAddress, - AuthorizationInfo authorizationInfo) { - if (licenseState.isAuditingAllowed()) { + @Override + public void explicitIndexAccessEvent(String requestId, AuditLevel eventType, Authentication authentication, String action, + String indices, String requestName, TransportAddress remoteAddress, + AuthorizationInfo authorizationInfo) { for (AuditTrail auditTrail : auditTrails) { auditTrail.explicitIndexAccessEvent(requestId, eventType, authentication, action, indices, requestName, remoteAddress, - authorizationInfo); + authorizationInfo); } } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java index 8a9be8b5a9cc2..fe46d078ee13e 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java @@ -77,7 +77,7 @@ public class AuthenticationService { private static final Logger logger = LogManager.getLogger(AuthenticationService.class); private final Realms realms; - private final AuditTrail auditTrail; + private final AuditTrailService auditTrailService; private final AuthenticationFailureHandler failureHandler; private final ThreadContext threadContext; private final String nodeName; @@ -90,12 +90,12 @@ public class AuthenticationService { private final boolean isAnonymousUserEnabled; private final AuthenticationContextSerializer authenticationSerializer; - public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrail, + public AuthenticationService(Settings settings, Realms realms, AuditTrailService auditTrailService, AuthenticationFailureHandler failureHandler, ThreadPool threadPool, AnonymousUser anonymousUser, TokenService tokenService, ApiKeyService apiKeyService) { this.nodeName = Node.NODE_NAME_SETTING.get(settings); this.realms = realms; - this.auditTrail = auditTrail; + this.auditTrailService = auditTrailService; this.failureHandler = failureHandler; this.threadContext = threadPool.getThreadContext(); this.anonymousUser = anonymousUser; @@ -274,16 +274,17 @@ class Authenticator { private AuthenticationResult authenticationResult = null; Authenticator(RestRequest request, boolean fallbackToAnonymous, ActionListener listener) { - this(new AuditableRestRequest(auditTrail, failureHandler, threadContext, request), null, fallbackToAnonymous, listener); + this(new AuditableRestRequest(auditTrailService.get(), failureHandler, threadContext, request), + null, fallbackToAnonymous, listener); } Authenticator(String action, TransportMessage message, boolean fallbackToAnonymous, ActionListener listener) { - this(new AuditableTransportRequest(auditTrail, failureHandler, threadContext, action, message), + this(new AuditableTransportRequest(auditTrailService.get(), failureHandler, threadContext, action, message), null, fallbackToAnonymous, listener); } Authenticator(String action, TransportMessage message, User fallbackUser, ActionListener listener) { - this(new AuditableTransportRequest(auditTrail, failureHandler, threadContext, action, message), + this(new AuditableTransportRequest(auditTrailService.get(), failureHandler, threadContext, action, message), Objects.requireNonNull(fallbackUser, "Fallback user cannot be null"), false, listener); } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 40f5e4f711ada..67d88efc0bc1d 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -63,6 +63,7 @@ import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; import org.elasticsearch.xpack.core.security.user.XPackUser; import org.elasticsearch.xpack.security.audit.AuditLevel; +import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditUtil; import org.elasticsearch.xpack.security.authc.ApiKeyService; @@ -101,7 +102,7 @@ public class AuthorizationService { private final Settings settings; private final ClusterService clusterService; - private final AuditTrailService auditTrail; + private final AuditTrailService auditTrailService; private final IndicesAndAliasesResolver indicesAndAliasesResolver; private final AuthenticationFailureHandler authcFailureHandler; private final ThreadContext threadContext; @@ -114,12 +115,12 @@ public class AuthorizationService { private final boolean anonymousAuthzExceptionEnabled; public AuthorizationService(Settings settings, CompositeRolesStore rolesStore, ClusterService clusterService, - AuditTrailService auditTrail, AuthenticationFailureHandler authcFailureHandler, + AuditTrailService auditTrailService, AuthenticationFailureHandler authcFailureHandler, ThreadPool threadPool, AnonymousUser anonymousUser, @Nullable AuthorizationEngine authorizationEngine, Set requestInterceptors, XPackLicenseState licenseState, IndexNameExpressionResolver resolver) { this.clusterService = clusterService; - this.auditTrail = auditTrail; + this.auditTrailService = auditTrailService; this.indicesAndAliasesResolver = new IndicesAndAliasesResolver(settings, clusterService, resolver); this.authcFailureHandler = authcFailureHandler; this.threadContext = threadPool.getThreadContext(); @@ -172,7 +173,7 @@ public void authorize(final Authentication authentication, final String action, if (isInternalUser(authentication.getUser()) != false) { auditId = AuditUtil.getOrGenerateRequestId(threadContext); } else { - auditTrail.tamperedRequest(null, authentication.getUser(), action, originalRequest); + auditTrailService.get().tamperedRequest(null, authentication.getUser(), action, originalRequest); final String message = "Attempt to authorize action [" + action + "] for [" + authentication.getUser().principal() + "] without an existing request-id"; assert false : message; @@ -204,6 +205,7 @@ private void maybeAuthorizeRunAs(final RequestInfo requestInfo, final String req final TransportRequest request = requestInfo.getRequest(); final String action = requestInfo.getAction(); final boolean isRunAs = authentication.getUser().isRunAs(); + final AuditTrail auditTrail = auditTrailService.get(); if (isRunAs) { ActionListener runAsListener = wrapPreservingContext(ActionListener.wrap(result -> { if (result.isGranted()) { @@ -236,6 +238,7 @@ private void authorizeAction(final RequestInfo requestInfo, final String request final TransportRequest request = requestInfo.getRequest(); final String action = requestInfo.getAction(); final AuthorizationEngine authzEngine = getAuthorizationEngine(authentication); + final AuditTrail auditTrail = auditTrailService.get(); if (ClusterPrivilegeResolver.isClusterAction(action)) { final ActionListener clusterAuthzListener = wrapPreservingContext(new AuthorizationResultListener<>(result -> { @@ -373,6 +376,7 @@ private AuthorizationEngine getAuthorizationEngineForUser(final User user) { private void authorizeSystemUser(final Authentication authentication, final String action, final String requestId, final TransportRequest request, final ActionListener listener) { + final AuditTrail auditTrail = auditTrailService.get(); if (SystemUser.isAuthorized(action)) { putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, IndicesAccessControl.ALLOW_ALL); putTransientIfNonExisting(AUTHORIZATION_INFO_KEY, SYSTEM_AUTHZ_INFO); @@ -394,6 +398,7 @@ private TransportRequest maybeUnwrapRequest(Authentication authentication, Trans request = TransportActionProxy.unwrapRequest(originalRequest); final boolean isOriginalRequestProxyRequest = TransportActionProxy.isProxyRequest(originalRequest); final boolean isProxyAction = TransportActionProxy.isProxyAction(action); + final AuditTrail auditTrail = auditTrailService.get(); if (isProxyAction && isOriginalRequestProxyRequest == false) { IllegalStateException cause = new IllegalStateException("originalRequest is not a proxy request: [" + originalRequest + "] but action: [" + action + "] is a proxy action"); @@ -451,6 +456,7 @@ private void authorizeBulkItems(RequestInfo requestInfo, AuthorizationInfo authz final Map resolvedIndexNames = new HashMap<>(); // Maps action -> resolved indices set final Map> actionToIndicesMap = new HashMap<>(); + final AuditTrail auditTrail = auditTrailService.get(); authorizedIndicesSupplier.getAsync(ActionListener.wrap(authorizedIndices -> { resolvedIndicesAsyncSupplier.getAsync(ActionListener.wrap(overallResolvedIndices -> { @@ -611,8 +617,8 @@ private AuthorizationResultListener(Consumer responseConsumer, Consumer> profileAllowRules = Collections.synchronizedMap(new HashMap<>()); private final Map> profileDenyRules = Collections.synchronizedMap(new HashMap<>()); - public IPFilter(final Settings settings, AuditTrailService auditTrail, ClusterSettings clusterSettings, + public IPFilter(final Settings settings, AuditTrailService auditTrailService, ClusterSettings clusterSettings, XPackLicenseState licenseState) { - this.auditTrail = auditTrail; + this.auditTrailService = auditTrailService; this.licenseState = licenseState; this.alwaysAllowBoundAddresses = ALLOW_BOUND_ADDRESSES_SETTING.get(settings); httpDenyFilter = HTTP_FILTER_DENY_SETTING.get(settings); @@ -205,6 +206,7 @@ public boolean accept(String profile, InetSocketAddress peerAddress) { return true; } + AuditTrail auditTrail = auditTrailService.get(); for (SecurityIpFilterRule rule : rules.get(profile)) { if (rule.matches(peerAddress)) { boolean isAllowed = rule.ruleType() == IpFilterRuleType.ACCEPT; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/AuditTrailServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/AuditTrailServiceTests.java index fb194ecefc671..f8951f7a43aca 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/AuditTrailServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/AuditTrailServiceTests.java @@ -58,7 +58,7 @@ public void init() throws Exception { public void testAuthenticationFailed() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, token, "_action", message); + service.get().authenticationFailed(requestId, token, "_action", message); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -71,7 +71,7 @@ public void testAuthenticationFailed() throws Exception { public void testAuthenticationFailedNoToken() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, "_action", message); + service.get().authenticationFailed(requestId, "_action", message); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -84,7 +84,7 @@ public void testAuthenticationFailedNoToken() throws Exception { public void testAuthenticationFailedRestNoToken() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, restRequest); + service.get().authenticationFailed(requestId, restRequest); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -97,7 +97,7 @@ public void testAuthenticationFailedRestNoToken() throws Exception { public void testAuthenticationFailedRest() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, token, restRequest); + service.get().authenticationFailed(requestId, token, restRequest); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -110,7 +110,7 @@ public void testAuthenticationFailedRest() throws Exception { public void testAuthenticationFailedRealm() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, "_realm", token, "_action", message); + service.get().authenticationFailed(requestId, "_realm", token, "_action", message); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -123,7 +123,7 @@ public void testAuthenticationFailedRealm() throws Exception { public void testAuthenticationFailedRestRealm() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationFailed(requestId, "_realm", token, restRequest); + service.get().authenticationFailed(requestId, "_realm", token, restRequest); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -136,7 +136,7 @@ public void testAuthenticationFailedRestRealm() throws Exception { public void testAnonymousAccess() throws Exception { final String requestId = randomAlphaOfLengthBetween(6, 12); - service.anonymousAccessDenied(requestId, "_action", message); + service.get().anonymousAccessDenied(requestId, "_action", message); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -153,7 +153,7 @@ public void testAccessGranted() throws Exception { AuthorizationInfo authzInfo = () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, new String[] { randomAlphaOfLengthBetween(1, 6) }); final String requestId = randomAlphaOfLengthBetween(6, 12); - service.accessGranted(requestId, authentication, "_action", message, authzInfo); + service.get().accessGranted(requestId, authentication, "_action", message, authzInfo); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -170,7 +170,7 @@ public void testAccessDenied() throws Exception { AuthorizationInfo authzInfo = () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, new String[] { randomAlphaOfLengthBetween(1, 6) }); final String requestId = randomAlphaOfLengthBetween(6, 12); - service.accessDenied(requestId, authentication, "_action", message, authzInfo); + service.get().accessDenied(requestId, authentication, "_action", message, authzInfo); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -184,7 +184,7 @@ public void testAccessDenied() throws Exception { public void testConnectionGranted() throws Exception { InetAddress inetAddress = InetAddress.getLoopbackAddress(); SecurityIpFilterRule rule = randomBoolean() ? SecurityIpFilterRule.ACCEPT_ALL : IPFilter.DEFAULT_PROFILE_ACCEPT_ALL; - service.connectionGranted(inetAddress, "client", rule); + service.get().connectionGranted(inetAddress, "client", rule); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -198,7 +198,7 @@ public void testConnectionGranted() throws Exception { public void testConnectionDenied() throws Exception { InetAddress inetAddress = InetAddress.getLoopbackAddress(); SecurityIpFilterRule rule = new SecurityIpFilterRule(false, "_all"); - service.connectionDenied(inetAddress, "client", rule); + service.get().connectionDenied(inetAddress, "client", rule); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -213,7 +213,7 @@ public void testAuthenticationSuccessRest() throws Exception { User user = new User("_username", "r1"); String realm = "_realm"; final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationSuccess(requestId, realm, user, restRequest); + service.get().authenticationSuccess(requestId, realm, user, restRequest); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { @@ -228,7 +228,7 @@ public void testAuthenticationSuccessTransport() throws Exception { User user = new User("_username", "r1"); String realm = "_realm"; final String requestId = randomAlphaOfLengthBetween(6, 12); - service.authenticationSuccess(requestId, realm, user, "_action", message); + service.get().authenticationSuccess(requestId, realm, user, "_action", message); verify(licenseState).isAuditingAllowed(); if (isAuditingAllowed) { for (AuditTrail auditTrail : auditTrails) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java index 953442d3a658d..e8bb282d6de4a 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java @@ -75,6 +75,7 @@ import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; +import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditUtil; import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticator; @@ -147,7 +148,8 @@ public class AuthenticationServiceTests extends ESTestCase { private Realms realms; private Realm firstRealm; private Realm secondRealm; - private AuditTrailService auditTrail; + private AuditTrail auditTrail; + private AuditTrailService auditTrailService; private AuthenticationToken token; private ThreadPool threadPool; private ThreadContext threadContext; @@ -190,6 +192,7 @@ public void init() throws Exception { when(licenseState.isAuthAllowed()).thenReturn(true); when(licenseState.isApiKeyServiceAllowed()).thenReturn(true); when(licenseState.isTokenServiceAllowed()).thenReturn(true); + when(licenseState.isAuditingAllowed()).thenReturn(true); ReservedRealm reservedRealm = mock(ReservedRealm.class); when(reservedRealm.type()).thenReturn("reserved"); when(reservedRealm.name()).thenReturn("reserved_realm"); @@ -197,7 +200,8 @@ public void init() throws Exception { licenseState, threadContext, reservedRealm, Arrays.asList(firstRealm, secondRealm), Collections.singletonList(firstRealm))); - auditTrail = mock(AuditTrailService.class); + auditTrail = mock(AuditTrail.class); + auditTrailService = new AuditTrailService(Collections.singletonList(auditTrail), licenseState); client = mock(Client.class); threadPool = new ThreadPool(settings, new FixedExecutorBuilder(settings, TokenService.THREAD_POOL_NAME, 1, 1000, "xpack.security.authc.token.thread_pool", @@ -237,7 +241,8 @@ public void init() throws Exception { apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), client, licenseState, securityIndex, clusterService, threadPool); tokenService = new TokenService(settings, Clock.systemUTC(), client, licenseState, securityContext, securityIndex, securityIndex, clusterService); - service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), + service = new AuthenticationService(settings, realms, auditTrailService, + new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), tokenService, apiKeyService); } @@ -421,7 +426,7 @@ public void testAuthenticateSmartRealmOrderingDisabled() { final Settings settings = Settings.builder() .put(AuthenticationService.SUCCESS_AUTH_CACHE_ENABLED.getKey(), false) .build(); - service = new AuthenticationService(settings, realms, auditTrail, + service = new AuthenticationService(settings, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(Settings.EMPTY), tokenService, apiKeyService); User user = new User("_username", "r1"); @@ -686,7 +691,7 @@ public void testAuthenticateTransportContextAndHeader() throws Exception { ThreadPool threadPool1 = new TestThreadPool("testAutheticateTransportContextAndHeader1"); try { ThreadContext threadContext1 = threadPool1.getThreadContext(); - service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool1, new AnonymousUser(Settings.EMPTY), tokenService, apiKeyService); @@ -710,7 +715,7 @@ public void testAuthenticateTransportContextAndHeader() throws Exception { ThreadContext threadContext2 = threadPool2.getThreadContext(); final String header; try (ThreadContext.StoredContext ignore = threadContext2.stashContext()) { - service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool2, new AnonymousUser(Settings.EMPTY), tokenService, apiKeyService); threadContext2.putHeader(AuthenticationField.AUTHENTICATION_KEY, authHeaderRef.get()); @@ -724,7 +729,7 @@ public void testAuthenticateTransportContextAndHeader() throws Exception { } threadPool2.getThreadContext().putHeader(AuthenticationField.AUTHENTICATION_KEY, header); - service = new AuthenticationService(Settings.EMPTY, realms, auditTrail, + service = new AuthenticationService(Settings.EMPTY, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool2, new AnonymousUser(Settings.EMPTY), tokenService, apiKeyService); service.authenticate("_action", new InternalMessage(), SystemUser.INSTANCE, ActionListener.wrap(result -> { @@ -763,7 +768,7 @@ public void testWrongTokenDoesNotFallbackToAnonymous() { } Settings anonymousEnabledSettings = builder.build(); final AnonymousUser anonymousUser = new AnonymousUser(anonymousEnabledSettings); - service = new AuthenticationService(anonymousEnabledSettings, realms, auditTrail, + service = new AuthenticationService(anonymousEnabledSettings, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { @@ -786,7 +791,7 @@ public void testWrongApiKeyDoesNotFallbackToAnonymous() { } Settings anonymousEnabledSettings = builder.build(); final AnonymousUser anonymousUser = new AnonymousUser(anonymousEnabledSettings); - service = new AuthenticationService(anonymousEnabledSettings, realms, auditTrail, + service = new AuthenticationService(anonymousEnabledSettings, realms, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); doAnswer(invocationOnMock -> { final GetRequest request = (GetRequest) invocationOnMock.getArguments()[0]; @@ -816,7 +821,8 @@ public void testAnonymousUserRest() throws Exception { } Settings settings = builder.build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); - service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), + service = new AuthenticationService(settings, realms, auditTrailService, + new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); RestRequest request = new FakeRestRequest(); @@ -841,7 +847,8 @@ public void testAuthenticateRestRequestDisallowAnonymous() throws Exception { Settings settings = builder.build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); - service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), + service = new AuthenticationService(settings, realms, auditTrailService, + new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); RestRequest request = new FakeRestRequest(); @@ -863,7 +870,8 @@ public void testAnonymousUserTransportNoDefaultUser() throws Exception { .putList(AnonymousUser.ROLES_SETTING.getKey(), "r1", "r2", "r3") .build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); - service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), + service = new AuthenticationService(settings, realms, auditTrailService, + new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); InternalMessage message = new InternalMessage(); @@ -879,7 +887,8 @@ public void testAnonymousUserTransportWithDefaultUser() throws Exception { .putList(AnonymousUser.ROLES_SETTING.getKey(), "r1", "r2", "r3") .build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); - service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), + service = new AuthenticationService(settings, realms, auditTrailService, + new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, tokenService, apiKeyService); InternalMessage message = new InternalMessage(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java index 2daf11ab4d23d..d13f03f531bac 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java @@ -57,6 +57,7 @@ import java.nio.charset.StandardCharsets; import java.time.Clock; import java.util.Base64; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -97,7 +98,7 @@ public void setupMocks() throws Exception { when(realms.asList()).thenReturn(List.of(realm)); when(realms.getUnlicensedRealms()).thenReturn(List.of()); - final AuditTrailService auditTrail = mock(AuditTrailService.class); + final AuditTrailService auditTrail = new AuditTrailService(Collections.emptyList(), null); final AuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler(Map.of()); final AnonymousUser anonymous = new AnonymousUser(settings); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index e1bb5dfac02cc..7bed19e4aab87 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -127,6 +127,7 @@ import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; import org.elasticsearch.xpack.core.security.user.XPackUser; import org.elasticsearch.xpack.security.audit.AuditLevel; +import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.AuditUtil; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; @@ -178,7 +179,8 @@ import static org.mockito.Mockito.when; public class AuthorizationServiceTests extends ESTestCase { - private AuditTrailService auditTrail; + private AuditTrail auditTrail; + private AuditTrailService auditTrailService; private ClusterService clusterService; private AuthorizationService authorizationService; private ThreadContext threadContext; @@ -197,7 +199,10 @@ public void setup() { final ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); when(clusterService.getClusterSettings()).thenReturn(clusterSettings); when(clusterService.state()).thenReturn(ClusterState.EMPTY_STATE); - auditTrail = mock(AuditTrailService.class); + auditTrail = mock(AuditTrail.class); + XPackLicenseState licenseState = mock(XPackLicenseState.class); + when(licenseState.isAuditingAllowed()).thenReturn(true); + auditTrailService = new AuditTrailService(Collections.singletonList(auditTrail), licenseState); threadContext = new ThreadContext(settings); threadPool = mock(ThreadPool.class); when(threadPool.getThreadContext()).thenReturn(threadContext); @@ -238,8 +243,8 @@ public void setup() { }).when(rolesStore).getRoles(any(User.class), any(Authentication.class), any(ActionListener.class)); roleMap.put(ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName(), ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR); authorizationService = new AuthorizationService(settings, rolesStore, clusterService, - auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null, - Collections.emptySet(), new XPackLicenseState(settings), new IndexNameExpressionResolver()); + auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), + null, Collections.emptySet(), licenseState, new IndexNameExpressionResolver()); } private void authorize(Authentication authentication, String action, TransportRequest request) { @@ -676,7 +681,7 @@ public void testDenialForAnonymousUser() throws IOException { ClusterState state = mockEmptyMetaData(); Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); - authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail, + authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, null, Collections.emptySet(), new XPackLicenseState(settings), new IndexNameExpressionResolver()); @@ -704,7 +709,7 @@ public void testDenialForAnonymousUserAuthorizationExceptionDisabled() throws IO .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false) .build(); final Authentication authentication = createAuthentication(new AnonymousUser(settings)); - authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail, + authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null, Collections.emptySet(), new XPackLicenseState(settings), new IndexNameExpressionResolver()); @@ -1448,8 +1453,8 @@ public void getUserPrivileges(Authentication authentication, AuthorizationInfo a XPackLicenseState licenseState = mock(XPackLicenseState.class); when(licenseState.isAuthorizationEngineAllowed()).thenReturn(true); authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService, - auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(Settings.EMPTY), - engine, Collections.emptySet(), licenseState, new IndexNameExpressionResolver()); + auditTrailService, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, + new AnonymousUser(Settings.EMPTY), engine, Collections.emptySet(), licenseState, new IndexNameExpressionResolver()); Authentication authentication; try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { authentication = createAuthentication(new User("test user", "a_all")); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/SecuritySearchOperationListenerTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/SecuritySearchOperationListenerTests.java index c766ab211c173..833d787275ba9 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/SecuritySearchOperationListenerTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/SecuritySearchOperationListenerTests.java @@ -25,13 +25,13 @@ import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.core.security.authc.AuthenticationField; +import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.AuthorizationInfo; import org.elasticsearch.xpack.core.security.user.User; +import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; -import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.AuthorizationInfo; import java.util.Collections; -import static org.elasticsearch.mock.orig.Mockito.verifyNoMoreInteractions; import static org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME; import static org.elasticsearch.xpack.security.authz.AuthorizationService.AUTHORIZATION_INFO_KEY; import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY; @@ -41,6 +41,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -94,9 +95,11 @@ public void testValidateSearchContext() throws Exception { testSearchContext.scrollContext().scroll = new Scroll(TimeValue.timeValueSeconds(2L)); XPackLicenseState licenseState = mock(XPackLicenseState.class); when(licenseState.isAuthAllowed()).thenReturn(true); + when(licenseState.isAuditingAllowed()).thenReturn(true); ThreadContext threadContext = new ThreadContext(Settings.EMPTY); final SecurityContext securityContext = new SecurityContext(Settings.EMPTY, threadContext); - AuditTrailService auditTrailService = mock(AuditTrailService.class); + AuditTrail auditTrail = mock(AuditTrail.class); + AuditTrailService auditTrailService = new AuditTrailService(Collections.singletonList(auditTrail), licenseState); SecuritySearchOperationListener listener = new SecuritySearchOperationListener(securityContext, licenseState, auditTrailService); try (StoredContext ignore = threadContext.newStoredContext(false)) { @@ -104,7 +107,7 @@ public void testValidateSearchContext() throws Exception { authentication.writeToContext(threadContext); listener.validateSearchContext(testSearchContext, Empty.INSTANCE); verify(licenseState).isAuthAllowed(); - verifyZeroInteractions(auditTrailService); + verifyZeroInteractions(auditTrail); } try (StoredContext ignore = threadContext.newStoredContext(false)) { @@ -114,7 +117,7 @@ public void testValidateSearchContext() throws Exception { authentication.writeToContext(threadContext); listener.validateSearchContext(testSearchContext, Empty.INSTANCE); verify(licenseState, times(2)).isAuthAllowed(); - verifyZeroInteractions(auditTrailService); + verifyZeroInteractions(auditTrail); } try (StoredContext ignore = threadContext.newStoredContext(false)) { @@ -131,7 +134,7 @@ public void testValidateSearchContext() throws Exception { expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request)); assertEquals(testSearchContext.id(), expected.contextId()); verify(licenseState, times(3)).isAuthAllowed(); - verify(auditTrailService).accessDenied(eq(null), eq(authentication), eq("action"), eq(request), + verify(auditTrail).accessDenied(eq(null), eq(authentication), eq("action"), eq(request), authzInfoRoles(authentication.getUser().roles())); } @@ -148,7 +151,7 @@ public void testValidateSearchContext() throws Exception { final InternalScrollSearchRequest request = new InternalScrollSearchRequest(); listener.validateSearchContext(testSearchContext, request); verify(licenseState, times(4)).isAuthAllowed(); - verifyNoMoreInteractions(auditTrailService); + verifyNoMoreInteractions(auditTrail); } // the user that authenticated for the run as request @@ -167,7 +170,7 @@ public void testValidateSearchContext() throws Exception { expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request)); assertEquals(testSearchContext.id(), expected.contextId()); verify(licenseState, times(5)).isAuthAllowed(); - verify(auditTrailService).accessDenied(eq(null), eq(authentication), eq("action"), eq(request), + verify(auditTrail).accessDenied(eq(null), eq(authentication), eq("action"), eq(request), authzInfoRoles(authentication.getUser().roles())); } } @@ -179,10 +182,14 @@ public void testEnsuredAuthenticatedUserIsSame() { SearchContextId contextId = new SearchContextId(UUIDs.randomBase64UUID(), randomLong()); final String action = randomAlphaOfLength(4); TransportRequest request = Empty.INSTANCE; - AuditTrailService auditTrail = mock(AuditTrailService.class); + XPackLicenseState licenseState = mock(XPackLicenseState.class); + when(licenseState.isAuthAllowed()).thenReturn(true); + when(licenseState.isAuditingAllowed()).thenReturn(true); + AuditTrail auditTrail = mock(AuditTrail.class); + AuditTrailService auditTrailService = new AuditTrailService(Collections.singletonList(auditTrail), licenseState); final String auditId = randomAlphaOfLengthBetween(8, 20); - ensureAuthenticatedUserIsSame(original, current, auditTrail, contextId, action, request, auditId, + ensureAuthenticatedUserIsSame(original, current, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())); verifyZeroInteractions(auditTrail); @@ -190,7 +197,7 @@ public void testEnsuredAuthenticatedUserIsSame() { User user = new User(new User("test", "role"), new User("authenticated", "runas")); current = new Authentication(user, new RealmRef("realm", "file", "node"), new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node")); - ensureAuthenticatedUserIsSame(original, current, auditTrail, contextId, action, request, auditId, + ensureAuthenticatedUserIsSame(original, current, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())); verifyZeroInteractions(auditTrail); @@ -198,7 +205,7 @@ public void testEnsuredAuthenticatedUserIsSame() { current = new Authentication(user, new RealmRef("realm", "file", "node"), new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node")); Authentication runAs = current; - ensureAuthenticatedUserIsSame(runAs, current, auditTrail, contextId, action, request, auditId, + ensureAuthenticatedUserIsSame(runAs, current, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())); verifyZeroInteractions(auditTrail); @@ -206,7 +213,7 @@ public void testEnsuredAuthenticatedUserIsSame() { Authentication differentRealmType = new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null); SearchContextMissingException e = expectThrows(SearchContextMissingException.class, - () -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrail, contextId, action, request, auditId, + () -> ensureAuthenticatedUserIsSame(original, differentRealmType, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()))); assertEquals(contextId, e.contextId()); verify(auditTrail).accessDenied(eq(auditId), eq(differentRealmType), eq(action), eq(request), @@ -216,7 +223,7 @@ public void testEnsuredAuthenticatedUserIsSame() { Authentication differentUser = new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null); e = expectThrows(SearchContextMissingException.class, - () -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrail, contextId, action, request, auditId, + () -> ensureAuthenticatedUserIsSame(original, differentUser, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()))); assertEquals(contextId, e.contextId()); verify(auditTrail).accessDenied(eq(auditId), eq(differentUser), eq(action), eq(request), @@ -226,7 +233,7 @@ public void testEnsuredAuthenticatedUserIsSame() { Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")), new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1")); e = expectThrows(SearchContextMissingException.class, - () -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrail, contextId, action, request, auditId, + () -> ensureAuthenticatedUserIsSame(original, diffRunAs, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()))); assertEquals(contextId, e.contextId()); verify(auditTrail).accessDenied(eq(auditId), eq(diffRunAs), eq(action), eq(request), authzInfoRoles(original.getUser().roles())); @@ -235,7 +242,7 @@ public void testEnsuredAuthenticatedUserIsSame() { Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"), new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node")); e = expectThrows(SearchContextMissingException.class, - () -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrail, contextId, action, request, auditId, + () -> ensureAuthenticatedUserIsSame(runAs, runAsDiffType, auditTrailService, contextId, action, request, auditId, () -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()))); assertEquals(contextId, e.contextId()); verify(auditTrail).accessDenied(eq(auditId), eq(runAsDiffType), eq(action), eq(request), diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/filter/IPFilterTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/filter/IPFilterTests.java index e3777fc854599..714f1651a440c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/filter/IPFilterTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/filter/IPFilterTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.test.junit.annotations.Network; import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.security.LocalStateSecurity; +import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.junit.Before; import org.mockito.ArgumentCaptor; @@ -49,7 +50,8 @@ public class IPFilterTests extends ESTestCase { private IPFilter ipFilter; private XPackLicenseState licenseState; - private AuditTrailService auditTrail; + private AuditTrail auditTrail; + private AuditTrailService auditTrailService; private Transport transport; private HttpServerTransport httpTransport; private ClusterSettings clusterSettings; @@ -58,7 +60,9 @@ public class IPFilterTests extends ESTestCase { public void init() { licenseState = mock(XPackLicenseState.class); when(licenseState.isIpFilteringAllowed()).thenReturn(true); - auditTrail = mock(AuditTrailService.class); + when(licenseState.isAuditingAllowed()).thenReturn(true); + auditTrail = mock(AuditTrail.class); + auditTrailService = new AuditTrailService(Collections.singletonList(auditTrail), licenseState); clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList( IPFilter.HTTP_FILTER_ALLOW_SETTING, IPFilter.HTTP_FILTER_DENY_SETTING, @@ -90,7 +94,7 @@ public void testThatIpV4AddressesCanBeProcessed() throws Exception { .put("xpack.security.transport.filter.allow", "127.0.0.1") .put("xpack.security.transport.filter.deny", "10.0.0.0/8") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("127.0.0.1"); assertAddressIsDenied("10.2.3.4"); @@ -103,7 +107,7 @@ public void testThatIpV6AddressesCanBeProcessed() throws Exception { .put("xpack.security.transport.filter.allow", "2001:0db8:1234::/48") .putList("xpack.security.transport.filter.deny", "1234:db8:85a3:0:0:8a2e:370:7334", "4321:db8:1234::/48") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("2001:0db8:1234:0000:0000:8a2e:0370:7334"); @@ -118,7 +122,7 @@ public void testThatHostnamesCanBeProcessed() throws Exception { .put("xpack.security.transport.filter.allow", "127.0.0.1") .put("xpack.security.transport.filter.deny", "*.google.com") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("127.0.0.1"); @@ -129,7 +133,7 @@ public void testThatAnAllowAllAuthenticatorWorks() throws Exception { Settings settings = Settings.builder() .put("xpack.security.transport.filter.allow", "_all") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("127.0.0.1"); assertAddressIsAllowed("173.194.70.100"); @@ -142,7 +146,7 @@ public void testThatProfilesAreSupported() throws Exception { .put("transport.profiles.client.xpack.security.filter.allow", "192.168.0.1") .put("transport.profiles.client.xpack.security.filter.deny", "_all") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("127.0.0.1"); // when "localhost" is used, ES considers all local addresses see PatternRule#isLocalhost() @@ -158,7 +162,7 @@ public void testThatProfilesAreUpdateable() throws Exception { .put("transport.profiles.client.xpack.security.filter.allow", "192.168.0.1") .put("transport.profiles.client.xpack.security.filter.deny", "_all") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); Settings newSettings = Settings.builder().putList("transport.profiles.client.xpack.security.filter.allow", "192.168.0.1", "192.168.0.2") @@ -178,7 +182,7 @@ public void testThatAllowWinsOverDeny() throws Exception { .put("xpack.security.transport.filter.allow", "10.0.0.1") .put("xpack.security.transport.filter.deny", "10.0.0.0/8") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("10.0.0.1"); assertAddressIsDenied("10.0.0.2"); @@ -186,7 +190,7 @@ public void testThatAllowWinsOverDeny() throws Exception { public void testDefaultAllow() throws Exception { Settings settings = Settings.builder().build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowed("10.0.0.1"); assertAddressIsAllowed("10.0.0.2"); @@ -199,7 +203,7 @@ public void testThatHttpWorks() throws Exception { .put("xpack.security.http.filter.allow", "10.0.0.0/8") .put("xpack.security.http.filter.deny", "192.168.0.1") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundHttpTransportAddress(httpTransport.boundAddress()); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsAllowedForProfile(IPFilter.HTTP_PROFILE_NAME, "10.2.3.4"); @@ -211,7 +215,7 @@ public void testThatHttpFallsbackToDefault() throws Exception { .put("xpack.security.transport.filter.allow", "127.0.0.1") .put("xpack.security.transport.filter.deny", "10.0.0.0/8") .build(); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundHttpTransportAddress(httpTransport.boundAddress()); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); @@ -232,7 +236,7 @@ public void testThatBoundAddressIsNeverRejected() throws Exception { } else { settings = Settings.builder().put("xpack.security.transport.filter.deny", "_all").build(); } - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); ipFilter.setBoundHttpTransportAddress(httpTransport.boundAddress()); @@ -247,7 +251,7 @@ public void testThatAllAddressesAreAllowedWhenLicenseDisablesSecurity() { .put("xpack.security.transport.filter.deny", "_all") .build(); when(licenseState.isIpFilteringAllowed()).thenReturn(false); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); // don't use the assert helper because we don't want the audit trail to be invoked here @@ -258,7 +262,7 @@ public void testThatAllAddressesAreAllowedWhenLicenseDisablesSecurity() { // for sanity enable license and check that it is denied when(licenseState.isIpFilteringAllowed()).thenReturn(true); - ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState); + ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState); ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses()); assertAddressIsDeniedForProfile("default", "8.8.8.8");