|
@@ -25,13 +25,13 @@ import org.elasticsearch.xpack.core.security.SecurityContext;
|
|
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
|
import org.elasticsearch.xpack.core.security.authc.Authentication;
|
|
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
|
import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef;
|
|
import org.elasticsearch.xpack.core.security.authc.AuthenticationField;
|
|
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.core.security.user.User;
|
|
|
|
+import org.elasticsearch.xpack.security.audit.AuditTrail;
|
|
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
|
import org.elasticsearch.xpack.security.audit.AuditTrailService;
|
|
-import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine.AuthorizationInfo;
|
|
|
|
|
|
|
|
import java.util.Collections;
|
|
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.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.AUTHORIZATION_INFO_KEY;
|
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
|
import static org.elasticsearch.xpack.security.authz.AuthorizationService.ORIGINATING_ACTION_KEY;
|
|
@@ -41,6 +41,7 @@ import static org.mockito.Matchers.eq;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
+import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
|
import static org.mockito.Mockito.when;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
|
|
@@ -94,9 +95,11 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
testSearchContext.scrollContext().scroll = new Scroll(TimeValue.timeValueSeconds(2L));
|
|
testSearchContext.scrollContext().scroll = new Scroll(TimeValue.timeValueSeconds(2L));
|
|
XPackLicenseState licenseState = mock(XPackLicenseState.class);
|
|
XPackLicenseState licenseState = mock(XPackLicenseState.class);
|
|
when(licenseState.isAuthAllowed()).thenReturn(true);
|
|
when(licenseState.isAuthAllowed()).thenReturn(true);
|
|
|
|
+ when(licenseState.isAuditingAllowed()).thenReturn(true);
|
|
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
|
ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
|
final SecurityContext securityContext = new SecurityContext(Settings.EMPTY, threadContext);
|
|
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);
|
|
SecuritySearchOperationListener listener = new SecuritySearchOperationListener(securityContext, licenseState, auditTrailService);
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
@@ -104,7 +107,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
authentication.writeToContext(threadContext);
|
|
authentication.writeToContext(threadContext);
|
|
listener.validateSearchContext(testSearchContext, Empty.INSTANCE);
|
|
listener.validateSearchContext(testSearchContext, Empty.INSTANCE);
|
|
verify(licenseState).isAuthAllowed();
|
|
verify(licenseState).isAuthAllowed();
|
|
- verifyZeroInteractions(auditTrailService);
|
|
|
|
|
|
+ verifyZeroInteractions(auditTrail);
|
|
}
|
|
}
|
|
|
|
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
@@ -114,7 +117,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
authentication.writeToContext(threadContext);
|
|
authentication.writeToContext(threadContext);
|
|
listener.validateSearchContext(testSearchContext, Empty.INSTANCE);
|
|
listener.validateSearchContext(testSearchContext, Empty.INSTANCE);
|
|
verify(licenseState, times(2)).isAuthAllowed();
|
|
verify(licenseState, times(2)).isAuthAllowed();
|
|
- verifyZeroInteractions(auditTrailService);
|
|
|
|
|
|
+ verifyZeroInteractions(auditTrail);
|
|
}
|
|
}
|
|
|
|
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
try (StoredContext ignore = threadContext.newStoredContext(false)) {
|
|
@@ -131,7 +134,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
|
assertEquals(testSearchContext.id(), expected.contextId());
|
|
assertEquals(testSearchContext.id(), expected.contextId());
|
|
verify(licenseState, times(3)).isAuthAllowed();
|
|
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()));
|
|
authzInfoRoles(authentication.getUser().roles()));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -148,7 +151,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
|
final InternalScrollSearchRequest request = new InternalScrollSearchRequest();
|
|
listener.validateSearchContext(testSearchContext, request);
|
|
listener.validateSearchContext(testSearchContext, request);
|
|
verify(licenseState, times(4)).isAuthAllowed();
|
|
verify(licenseState, times(4)).isAuthAllowed();
|
|
- verifyNoMoreInteractions(auditTrailService);
|
|
|
|
|
|
+ verifyNoMoreInteractions(auditTrail);
|
|
}
|
|
}
|
|
|
|
|
|
// the user that authenticated for the run as request
|
|
// the user that authenticated for the run as request
|
|
@@ -167,7 +170,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
|
expectThrows(SearchContextMissingException.class, () -> listener.validateSearchContext(testSearchContext, request));
|
|
assertEquals(testSearchContext.id(), expected.contextId());
|
|
assertEquals(testSearchContext.id(), expected.contextId());
|
|
verify(licenseState, times(5)).isAuthAllowed();
|
|
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()));
|
|
authzInfoRoles(authentication.getUser().roles()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -179,10 +182,14 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
SearchContextId contextId = new SearchContextId(UUIDs.randomBase64UUID(), randomLong());
|
|
SearchContextId contextId = new SearchContextId(UUIDs.randomBase64UUID(), randomLong());
|
|
final String action = randomAlphaOfLength(4);
|
|
final String action = randomAlphaOfLength(4);
|
|
TransportRequest request = Empty.INSTANCE;
|
|
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);
|
|
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()));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()));
|
|
verifyZeroInteractions(auditTrail);
|
|
verifyZeroInteractions(auditTrail);
|
|
|
|
|
|
@@ -190,7 +197,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
User user = new User(new User("test", "role"), new User("authenticated", "runas"));
|
|
User user = new User(new User("test", "role"), new User("authenticated", "runas"));
|
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), "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()));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()));
|
|
verifyZeroInteractions(auditTrail);
|
|
verifyZeroInteractions(auditTrail);
|
|
|
|
|
|
@@ -198,7 +205,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
current = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), "file", "node"));
|
|
Authentication runAs = current;
|
|
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()));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles()));
|
|
verifyZeroInteractions(auditTrail);
|
|
verifyZeroInteractions(auditTrail);
|
|
|
|
|
|
@@ -206,7 +213,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
Authentication differentRealmType =
|
|
Authentication differentRealmType =
|
|
new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null);
|
|
new Authentication(new User("test", "role"), new RealmRef("realm", randomAlphaOfLength(5), "node"), null);
|
|
SearchContextMissingException e = expectThrows(SearchContextMissingException.class,
|
|
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())));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())));
|
|
assertEquals(contextId, e.contextId());
|
|
assertEquals(contextId, e.contextId());
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(differentRealmType), eq(action), eq(request),
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(differentRealmType), eq(action), eq(request),
|
|
@@ -216,7 +223,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
Authentication differentUser =
|
|
Authentication differentUser =
|
|
new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null);
|
|
new Authentication(new User("test2", "role"), new RealmRef("realm", "realm", "node"), null);
|
|
e = expectThrows(SearchContextMissingException.class,
|
|
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())));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())));
|
|
assertEquals(contextId, e.contextId());
|
|
assertEquals(contextId, e.contextId());
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(differentUser), eq(action), eq(request),
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(differentUser), eq(action), eq(request),
|
|
@@ -226,7 +233,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
|
Authentication diffRunAs = new Authentication(new User(new User("test2", "role"), new User("authenticated", "runas")),
|
|
new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1"));
|
|
new RealmRef("realm", "file", "node1"), new RealmRef("realm", "file", "node1"));
|
|
e = expectThrows(SearchContextMissingException.class,
|
|
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())));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())));
|
|
assertEquals(contextId, e.contextId());
|
|
assertEquals(contextId, e.contextId());
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(diffRunAs), eq(action), eq(request), authzInfoRoles(original.getUser().roles()));
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(diffRunAs), eq(action), eq(request), authzInfoRoles(original.getUser().roles()));
|
|
@@ -235,7 +242,7 @@ public class SecuritySearchOperationListenerTests extends ESTestCase {
|
|
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
Authentication runAsDiffType = new Authentication(user, new RealmRef("realm", "file", "node"),
|
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node"));
|
|
new RealmRef(randomAlphaOfLengthBetween(1, 16), randomAlphaOfLengthBetween(5, 12), "node"));
|
|
e = expectThrows(SearchContextMissingException.class,
|
|
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())));
|
|
() -> Collections.singletonMap(PRINCIPAL_ROLES_FIELD_NAME, original.getUser().roles())));
|
|
assertEquals(contextId, e.contextId());
|
|
assertEquals(contextId, e.contextId());
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(runAsDiffType), eq(action), eq(request),
|
|
verify(auditTrail).accessDenied(eq(auditId), eq(runAsDiffType), eq(action), eq(request),
|