mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 09:28:55 -04:00
Support audit ignore policy by actions (#67477)
* Support audit ignore policy by index privileges Adding new audit ignore policy - privileges For example, following policy will filter out all events, which actions minimal required privilege is either "read" or "delete": xpack.security.audit.logfile.events.ignore_filters: example: privileges: ["read", "delete"] Resolve: #60877 Related: #10836 Related: #37148 * Support audit ignore policy by index privileges Adding new audit ignore policy - privileges For example, following policy will filter out all events, which actions required privilege is either "read" or "delete": xpack.security.audit.logfile.events.ignore_filters: example: privileges: ["read", "delete"] Resolve: #60877 Related: #10836 Related: #37148 * To avoid ambiguity (as cluster and index policies may have the same name) changing implementation to have to separate policies for `index_privileges` and `cluster_privileges`. If both are set for the same policy, throw the IllegalArgumentException. * To avoid ambiguity (as cluster and index policies may have the same name) changing implementation to have to separate policies for `index_privileges` and `cluster_privileges`. If both are set for the same policy, throw the IllegalArgumentException. * Fixing Api key related privilege check which expects request and authentication by introducing overloaded version of findPrivilegesThatGrant just checking if privileges which can grant the action regardless of the request and authentication context. * Fixing a test; adding a caching mechanism to avoid calling findPrivilegesThatGrant each time. * Support audit ignore policy by index privileges Addressing review feedback * Support audit ignore policy by index privileges Addressing review comments + changing approach: - use permission check instead of simple "checkIfGrants" - adding more testing * Support audit ignore policy by index privileges Addressing review comments + changing approach: - use permission check instead of simple "checkIfGrants" - adding more testing * Support audit ignore policy by index privileges Addressing review comments + changing approach: - use permission check instead of simple "checkIfGrants" - adding more testing * Support audit ignore policy by index privileges Addressing review comments + changing approach: - use permission check instead of simple "checkIfGrants" - adding more testing * Revert "Support audit ignore policy by index privileges" This reverts commit152821e7
* Revert "Support audit ignore policy by index privileges" This reverts commit79649e9a
* Revert "Support audit ignore policy by index privileges" This reverts commit96d22a42
* Revert "Support audit ignore policy by index privileges" This reverts commit67574b2f
* Revert "Support audit ignore policy by index privileges" This reverts commit35573c8b
* Revert "Fixing a test; adding a caching mechanism to avoid calling findPrivilegesThatGrant each time." This reverts commit7faa52f3
* Revert "Fixing Api key related privilege check which expects request and authentication by introducing overloaded version of findPrivilegesThatGrant just checking if privileges which can grant the action regardless of the request and authentication context." This reverts commit72b9aefe
* Revert "To avoid ambiguity (as cluster and index policies may have the same name) changing implementation to have to separate policies for `index_privileges` and `cluster_privileges`. If both are set for the same policy, throw the IllegalArgumentException." This reverts commit7dd8fe7d
* Revert "To avoid ambiguity (as cluster and index policies may have the same name) changing implementation to have to separate policies for `index_privileges` and `cluster_privileges`. If both are set for the same policy, throw the IllegalArgumentException." This reverts commitcb5bc09c
* Revert "Support audit ignore policy by index privileges" This reverts commita918da10
* Support audit ignore policy by actions Getting back to action filtering * Support audit ignore policy by actions Cleaning up some tests * Support audit ignore policy by actions Cleaning up some tests Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
1487a5a991
commit
ee66d6f11f
5 changed files with 466 additions and 60 deletions
|
@ -149,6 +149,15 @@ A list of authentication realm names or wildcards. The specified policy will
|
|||
not print audit events for users in these realms.
|
||||
// end::xpack-sa-lf-events-ignore-realms-tag[]
|
||||
|
||||
[[xpack-sa-lf-events-ignore-actions]]
|
||||
// tag::xpack-sa-lf-events-ignore-actions-tag[]
|
||||
`xpack.security.audit.logfile.events.ignore_filters.<policy_name>.actions`::
|
||||
(<<dynamic-cluster-setting,Dynamic>>)
|
||||
A list of action names or wildcards. Action name can be found in the `action`
|
||||
field of the audit event. The specified policy will not print audit events
|
||||
for actions matching these values.
|
||||
// end::xpack-sa-lf-events-ignore-actions-tag[]
|
||||
|
||||
[[xpack-sa-lf-events-ignore-roles]]
|
||||
// tag::xpack-sa-lf-events-ignore-roles-tag[]
|
||||
`xpack.security.audit.logfile.events.ignore_filters.<policy_name>.roles`::
|
||||
|
|
|
@ -96,7 +96,8 @@ public class AuditTrailSettingsUpdateTests extends SecurityIntegTestCase {
|
|||
final String[] allSettingsKeys = new String[] { "xpack.security.audit.logfile.events.ignore_filters.invalid.users",
|
||||
"xpack.security.audit.logfile.events.ignore_filters.invalid.realms",
|
||||
"xpack.security.audit.logfile.events.ignore_filters.invalid.roles",
|
||||
"xpack.security.audit.logfile.events.ignore_filters.invalid.indices" };
|
||||
"xpack.security.audit.logfile.events.ignore_filters.invalid.indices",
|
||||
"xpack.security.audit.logfile.events.ignore_filters.invalid.actions"};
|
||||
settingsBuilder.put(randomFrom(allSettingsKeys), invalidLuceneRegex);
|
||||
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||
() -> client().admin().cluster().prepareUpdateSettings().setTransientSettings(settingsBuilder.build()).get());
|
||||
|
@ -223,6 +224,12 @@ public class AuditTrailSettingsUpdateTests extends SecurityIntegTestCase {
|
|||
final List<String> filteredIndices = randomNonEmptyListOfFilteredNames();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters." + policyName + ".indices", filteredIndices);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
// filter by actions
|
||||
final List<String> filteredActions = randomNonEmptyListOfFilteredNames();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters." + policyName + ".actions",
|
||||
filteredActions);
|
||||
}
|
||||
} while (settingsBuilder.build().isEmpty());
|
||||
|
||||
assertFalse(settingsBuilder.build().isEmpty());
|
||||
|
|
|
@ -218,6 +218,10 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
Setting.affixKeySetting(FILTER_POLICY_PREFIX, "indices",
|
||||
(key) -> Setting.listSetting(key, Collections.singletonList("*"), Function.identity(),
|
||||
value -> EventFilterPolicy.parsePredicate(value), Property.NodeScope, Property.Dynamic));
|
||||
protected static final Setting.AffixSetting<List<String>> FILTER_POLICY_IGNORE_ACTIONS =
|
||||
Setting.affixKeySetting(FILTER_POLICY_PREFIX, "actions",
|
||||
(key) -> Setting.listSetting(key, Collections.singletonList("*"), Function.identity(),
|
||||
value -> EventFilterPolicy.parsePredicate(value), Property.NodeScope, Property.Dynamic));
|
||||
|
||||
private static final Marker AUDIT_MARKER = MarkerManager.getMarker("org.elasticsearch.xpack.security.audit");
|
||||
|
||||
|
@ -277,6 +281,12 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
final EventFilterPolicy newPolicy = policy.orElse(new EventFilterPolicy(policyName, settings)).changeIndicesFilter(filtersList);
|
||||
this.eventFilterPolicyRegistry.set(policyName, newPolicy);
|
||||
}, (policyName, filtersList) -> EventFilterPolicy.parsePredicate(filtersList));
|
||||
clusterService.getClusterSettings().addAffixUpdateConsumer(FILTER_POLICY_IGNORE_ACTIONS, (policyName, filtersList) -> {
|
||||
final Optional<EventFilterPolicy> policy = eventFilterPolicyRegistry.get(policyName);
|
||||
final EventFilterPolicy newPolicy = policy.orElse(new EventFilterPolicy(policyName, settings)).
|
||||
changeActionsFilter(filtersList);
|
||||
this.eventFilterPolicyRegistry.set(policyName, newPolicy);
|
||||
}, (policyName, filtersList) -> EventFilterPolicy.parsePredicate(filtersList));
|
||||
// this log filter ensures that audit events are not filtered out because of the log level
|
||||
final LoggerContext ctx = LoggerContext.getContext(false);
|
||||
MarkerFilter auditMarkerFilter = MarkerFilter.createFilter(AUDIT_MARKER.getName(), Result.ACCEPT, Result.NEUTRAL);
|
||||
|
@ -295,6 +305,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty())) == false) {
|
||||
// this is redundant information maintained for bwc purposes
|
||||
final String authnRealm = authentication.getAuthenticatedBy().getName();
|
||||
|
@ -323,7 +334,8 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.empty(),
|
||||
indices)) == false) {
|
||||
indices,
|
||||
Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_success")
|
||||
|
@ -345,7 +357,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (events.contains(ANONYMOUS_ACCESS_DENIED)) {
|
||||
final Optional<String[]> indices = indices(transportRequest);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices)) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "anonymous_access_denied")
|
||||
|
@ -383,7 +395,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(transportRequest);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.empty(), indices)) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.empty(), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
|
@ -421,7 +433,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (events.contains(AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(transportRequest);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices)) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
|
@ -440,7 +452,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
@Override
|
||||
public void authenticationFailed(String requestId, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(AUTHENTICATION_FAILED) && eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.empty(), Optional.empty())) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.empty(), Optional.empty(), Optional.empty())) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "authentication_failed")
|
||||
|
@ -461,7 +473,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (events.contains(REALM_AUTHENTICATION_FAILED)) {
|
||||
final Optional<String[]> indices = indices(transportRequest);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.of(realm), indices)) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.of(realm), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "realm_authentication_failed")
|
||||
|
@ -482,7 +494,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
@Override
|
||||
public void authenticationFailed(String requestId, String realm, AuthenticationToken token, RestRequest request) {
|
||||
if (events.contains(REALM_AUTHENTICATION_FAILED) && eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.of(realm), Optional.empty())) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.of(token), Optional.of(realm), Optional.empty(), Optional.empty())) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "realm_authentication_failed")
|
||||
|
@ -508,7 +520,8 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(user),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), indices)) == false) {
|
||||
Optional.of(authorizationInfo), indices,
|
||||
Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "access_granted")
|
||||
|
@ -593,7 +606,8 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
.test(new AuditEventMetaInfo(Optional.of(user),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), Optional.ofNullable(indices))) == false) {
|
||||
Optional.of(authorizationInfo), Optional.ofNullable(indices),
|
||||
Optional.of(action))) == false) {
|
||||
final LogEntryBuilder logEntryBuilder = new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, eventType == ACCESS_DENIED ? "access_denied" : "access_granted")
|
||||
|
@ -628,7 +642,8 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), indices)) == false) {
|
||||
Optional.of(authorizationInfo), indices,
|
||||
Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "access_denied")
|
||||
|
@ -667,7 +682,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (events.contains(TAMPERED_REQUEST)) {
|
||||
final Optional<String[]> indices = indices(transportRequest);
|
||||
if (eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices)) == false) {
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
|
@ -692,7 +707,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.empty(),
|
||||
indices)) == false) {
|
||||
indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "tampered_request")
|
||||
|
@ -751,7 +766,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), indices)) == false) {
|
||||
Optional.of(authorizationInfo), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "run_as_granted")
|
||||
|
@ -777,7 +792,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
if (eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), indices)) == false) {
|
||||
Optional.of(authorizationInfo), indices, Optional.of(action))) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, TRANSPORT_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "run_as_denied")
|
||||
|
@ -801,7 +816,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
new AuditEventMetaInfo(Optional.of(authentication.getUser()),
|
||||
// can be null for API keys created before version 7.7
|
||||
Optional.ofNullable(ApiKeyService.getCreatorRealmName(authentication)),
|
||||
Optional.of(authorizationInfo), Optional.empty())) == false) {
|
||||
Optional.of(authorizationInfo), Optional.empty(), Optional.empty())) == false) {
|
||||
new LogEntryBuilder()
|
||||
.with(EVENT_TYPE_FIELD_NAME, REST_ORIGIN_FIELD_VALUE)
|
||||
.with(EVENT_ACTION_FIELD_NAME, "run_as_denied")
|
||||
|
@ -1327,6 +1342,7 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
settings.add(FILTER_POLICY_IGNORE_INDICES);
|
||||
settings.add(FILTER_POLICY_IGNORE_ROLES);
|
||||
settings.add(FILTER_POLICY_IGNORE_REALMS);
|
||||
settings.add(FILTER_POLICY_IGNORE_ACTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1342,12 +1358,14 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
private final Predicate<String> ignoreRealmsPredicate;
|
||||
private final Predicate<String> ignoreRolesPredicate;
|
||||
private final Predicate<String> ignoreIndicesPredicate;
|
||||
private final Predicate<String> ignoreActionsPredicate;
|
||||
|
||||
EventFilterPolicy(String name, Settings settings) {
|
||||
this(name, parsePredicate(FILTER_POLICY_IGNORE_PRINCIPALS.getConcreteSettingForNamespace(name).get(settings)),
|
||||
parsePredicate(FILTER_POLICY_IGNORE_REALMS.getConcreteSettingForNamespace(name).get(settings)),
|
||||
parsePredicate(FILTER_POLICY_IGNORE_ROLES.getConcreteSettingForNamespace(name).get(settings)),
|
||||
parsePredicate(FILTER_POLICY_IGNORE_INDICES.getConcreteSettingForNamespace(name).get(settings)));
|
||||
parsePredicate(FILTER_POLICY_IGNORE_INDICES.getConcreteSettingForNamespace(name).get(settings)),
|
||||
parsePredicate(FILTER_POLICY_IGNORE_ACTIONS.getConcreteSettingForNamespace(name).get(settings)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1356,33 +1374,40 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
* a singleton list of the empty string ([""]).
|
||||
*/
|
||||
EventFilterPolicy(String name, Predicate<String> ignorePrincipalsPredicate, Predicate<String> ignoreRealmsPredicate,
|
||||
Predicate<String> ignoreRolesPredicate, Predicate<String> ignoreIndicesPredicate) {
|
||||
Predicate<String> ignoreRolesPredicate, Predicate<String> ignoreIndicesPredicate,
|
||||
Predicate<String> ignoreActionsPredicate) {
|
||||
this.name = name;
|
||||
// "null" values are "unexpected" and should not match any ignore policy
|
||||
this.ignorePrincipalsPredicate = ignorePrincipalsPredicate;
|
||||
this.ignoreRealmsPredicate = ignoreRealmsPredicate;
|
||||
this.ignoreRolesPredicate = ignoreRolesPredicate;
|
||||
this.ignoreIndicesPredicate = ignoreIndicesPredicate;
|
||||
this.ignoreActionsPredicate = ignoreActionsPredicate;
|
||||
}
|
||||
|
||||
private EventFilterPolicy changePrincipalsFilter(List<String> filtersList) {
|
||||
return new EventFilterPolicy(name, parsePredicate(filtersList), ignoreRealmsPredicate, ignoreRolesPredicate,
|
||||
ignoreIndicesPredicate);
|
||||
ignoreIndicesPredicate, ignoreActionsPredicate);
|
||||
}
|
||||
|
||||
private EventFilterPolicy changeRealmsFilter(List<String> filtersList) {
|
||||
return new EventFilterPolicy(name, ignorePrincipalsPredicate, parsePredicate(filtersList), ignoreRolesPredicate,
|
||||
ignoreIndicesPredicate);
|
||||
ignoreIndicesPredicate, ignoreActionsPredicate);
|
||||
}
|
||||
|
||||
private EventFilterPolicy changeRolesFilter(List<String> filtersList) {
|
||||
return new EventFilterPolicy(name, ignorePrincipalsPredicate, ignoreRealmsPredicate, parsePredicate(filtersList),
|
||||
ignoreIndicesPredicate);
|
||||
ignoreIndicesPredicate, ignoreActionsPredicate);
|
||||
}
|
||||
|
||||
private EventFilterPolicy changeIndicesFilter(List<String> filtersList) {
|
||||
return new EventFilterPolicy(name, ignorePrincipalsPredicate, ignoreRealmsPredicate, ignoreRolesPredicate,
|
||||
parsePredicate(filtersList));
|
||||
parsePredicate(filtersList), ignoreActionsPredicate);
|
||||
}
|
||||
|
||||
private EventFilterPolicy changeActionsFilter(List<String> filtersList) {
|
||||
return new EventFilterPolicy(name, ignorePrincipalsPredicate, ignoreRealmsPredicate, ignoreRolesPredicate,
|
||||
ignoreIndicesPredicate, parsePredicate(filtersList));
|
||||
}
|
||||
|
||||
static Predicate<String> parsePredicate(List<String> l) {
|
||||
|
@ -1408,16 +1433,20 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
* predicate of the corresponding field.
|
||||
*/
|
||||
Predicate<AuditEventMetaInfo> ignorePredicate() {
|
||||
return eventInfo -> eventInfo.principal != null && ignorePrincipalsPredicate.test(eventInfo.principal)
|
||||
return eventInfo -> {
|
||||
return eventInfo.principal != null && ignorePrincipalsPredicate.test(eventInfo.principal)
|
||||
&& eventInfo.realm != null && ignoreRealmsPredicate.test(eventInfo.realm)
|
||||
&& eventInfo.action != null && ignoreActionsPredicate.test(eventInfo.action)
|
||||
&& eventInfo.roles.get().allMatch(role -> role != null && ignoreRolesPredicate.test(role))
|
||||
&& eventInfo.indices.get().allMatch(index -> index != null && ignoreIndicesPredicate.test(index));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[users]:" + ignorePrincipalsPredicate.toString() + "&[realms]:" + ignoreRealmsPredicate.toString() + "&[roles]:"
|
||||
+ ignoreRolesPredicate.toString() + "&[indices]:" + ignoreIndicesPredicate.toString();
|
||||
+ ignoreRolesPredicate.toString() + "&[indices]:" + ignoreIndicesPredicate.toString() + "&[actions]:"
|
||||
+ ignoreActionsPredicate.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,11 +1506,13 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
static final class AuditEventMetaInfo {
|
||||
final String principal;
|
||||
final String realm;
|
||||
final String action;
|
||||
final Supplier<Stream<String>> roles;
|
||||
final Supplier<Stream<String>> indices;
|
||||
|
||||
// empty is used for events can be filtered out only by the lack of a field
|
||||
static final AuditEventMetaInfo EMPTY = new AuditEventMetaInfo(Optional.empty(), Optional.empty(), Optional.empty());
|
||||
static final AuditEventMetaInfo EMPTY = new AuditEventMetaInfo(Optional.empty(), Optional.empty(), Optional.empty(),
|
||||
Optional.empty());
|
||||
|
||||
/**
|
||||
* If a field is missing for an event, its value for filtering purposes is the
|
||||
|
@ -1492,9 +1523,10 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
* "elastic" username.
|
||||
*/
|
||||
AuditEventMetaInfo(Optional<User> user, Optional<String> realm, Optional<AuthorizationInfo> authorizationInfo,
|
||||
Optional<String[]> indices) {
|
||||
Optional<String[]> indices, Optional<String> action) {
|
||||
this.principal = user.map(u -> u.principal()).orElse("");
|
||||
this.realm = realm.orElse("");
|
||||
this.action = action.orElse("");
|
||||
// Supplier indirection and lazy generation of Streams serves 2 purposes:
|
||||
// 1. streams might not get generated due to short circuiting logical
|
||||
// conditions on the `principal` and `realm` fields
|
||||
|
@ -1510,9 +1542,11 @@ public class LoggingAuditTrail implements AuditTrail, ClusterStateListener {
|
|||
.map(Arrays::stream).orElse(Stream.of(""));
|
||||
}
|
||||
|
||||
AuditEventMetaInfo(Optional<AuthenticationToken> authenticationToken, Optional<String> realm, Optional<String[]> indices) {
|
||||
AuditEventMetaInfo(Optional<AuthenticationToken> authenticationToken, Optional<String> realm, Optional<String[]> indices,
|
||||
Optional<String> action) {
|
||||
this.principal = authenticationToken.map(u -> u.principal()).orElse("");
|
||||
this.realm = realm.orElse("");
|
||||
this.action = action.orElse("");
|
||||
this.roles = () -> Stream.of("");
|
||||
this.indices = () -> indices.filter(r -> r.length != 0).map(i -> Arrays.stream(i)).orElse(Stream.of(""));
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME;
|
||||
|
@ -120,12 +121,17 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
// filter by indices
|
||||
final List<String> filteredIndices = randomNonEmptyListOfFilteredNames();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.indicesPolicy.indices", filteredIndices);
|
||||
// filter by actions
|
||||
final List<String> filteredActions = randomNonEmptyListOfFilteredActions();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.actionsPolicy.actions",
|
||||
filteredActions);
|
||||
|
||||
final LoggingAuditTrail auditTrail = new LoggingAuditTrail(settingsBuilder.build(), clusterService, logger, threadContext);
|
||||
|
||||
// user field matches
|
||||
assertTrue("Matches the user filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(
|
||||
new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.empty(), Optional.empty(), Optional.empty())));
|
||||
new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.empty(), Optional.empty(), Optional.empty(),
|
||||
Optional.empty())));
|
||||
final User unfilteredUser = mock(User.class);
|
||||
if (randomBoolean()) {
|
||||
when(unfilteredUser.authenticatedUser()).thenReturn(new User(randomFrom(filteredUsernames)));
|
||||
|
@ -133,39 +139,52 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
// null user field does NOT match
|
||||
assertFalse("Does not match the user filter predicate because of null username.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(unfilteredUser), Optional.empty(), Optional.empty(), Optional.empty())));
|
||||
.test(new AuditEventMetaInfo(Optional.of(unfilteredUser), Optional.empty(), Optional.empty(), Optional.empty(),
|
||||
Optional.empty())));
|
||||
// realm field matches
|
||||
assertTrue("Matches the realm filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(
|
||||
new AuditEventMetaInfo(Optional.empty(), Optional.of(randomFrom(filteredRealms)), Optional.empty(), Optional.empty())));
|
||||
new AuditEventMetaInfo(Optional.empty(), Optional.of(randomFrom(filteredRealms)), Optional.empty(), Optional.empty(),
|
||||
Optional.empty())));
|
||||
// null realm field does NOT match
|
||||
assertFalse("Does not match the realm filter predicate because of null realm.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.ofNullable(null), Optional.empty(), Optional.empty())));
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.ofNullable(null), Optional.empty(), Optional.empty(),
|
||||
Optional.empty())));
|
||||
// role field matches
|
||||
assertTrue("Matches the role filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(),
|
||||
Optional.of(authzInfo(
|
||||
randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles).toArray(new String[0]))),
|
||||
Optional.empty())));
|
||||
Optional.empty(), Optional.empty())));
|
||||
// action field matches
|
||||
Random random = random();
|
||||
assertTrue("Matches the actions filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(
|
||||
new AuditEventMetaInfo(Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
// null privilege field does NOT match
|
||||
assertFalse("Does not matches the actions filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
|
||||
Optional.ofNullable(null))));
|
||||
final List<String> unfilteredRoles = new ArrayList<>();
|
||||
unfilteredRoles.add(null);
|
||||
unfilteredRoles.addAll(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles));
|
||||
// null role among roles field does NOT match
|
||||
assertFalse("Does not match the role filter predicate because of null role.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(),
|
||||
Optional.of(authzInfo(unfilteredRoles.toArray(new String[0]))), Optional.empty())));
|
||||
Optional.of(authzInfo(unfilteredRoles.toArray(new String[0]))), Optional.empty(), Optional.empty())));
|
||||
// indices field matches
|
||||
assertTrue("Matches the index filter predicate.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.empty())));
|
||||
final List<String> unfilteredIndices = new ArrayList<>();
|
||||
unfilteredIndices.add(null);
|
||||
unfilteredIndices.addAll(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices));
|
||||
// null index among indices field does NOT match
|
||||
assertFalse("Does not match the indices filter predicate because of null index.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.empty(), Optional.empty(),
|
||||
Optional.empty(), Optional.of(unfilteredIndices.toArray(new String[0])))));
|
||||
Optional.empty(), Optional.of(unfilteredIndices.toArray(new String[0])), Optional.empty())));
|
||||
}
|
||||
|
||||
public void testSingleCompletePolicyPredicate() throws Exception {
|
||||
|
@ -192,15 +211,21 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
// filter by indices
|
||||
final List<String> filteredIndices = randomNonEmptyListOfFilteredNames();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.completeFilterPolicy.indices", filteredIndices);
|
||||
// filter by actions
|
||||
final List<String> filteredActions = randomNonEmptyListOfFilteredActions();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.completeFilterPolicy.actions",
|
||||
filteredActions);
|
||||
|
||||
final LoggingAuditTrail auditTrail = new LoggingAuditTrail(settingsBuilder.build(), clusterService, logger, threadContext);
|
||||
|
||||
// all fields match
|
||||
Random random = random();
|
||||
assertTrue("Matches the filter predicate.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(
|
||||
Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles).toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final User unfilteredUser;
|
||||
if (randomBoolean()) {
|
||||
unfilteredUser = new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8));
|
||||
|
@ -214,25 +239,36 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the empty user.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.empty(),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the realm.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the empty realm.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.empty(),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the empty actions.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.empty())));
|
||||
final List<String> someRolesDoNotMatch = new ArrayList<>(randomSubsetOf(randomIntBetween(0, filteredRoles.size()), filteredRoles));
|
||||
for (int i = 0; i < randomIntBetween(1, 8); i++) {
|
||||
someRolesDoNotMatch.add(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8));
|
||||
|
@ -240,12 +276,14 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
assertFalse("Does not match the filter predicate because of some of the roles.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)), Optional.of(authzInfo(someRolesDoNotMatch.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final Optional<AuthorizationInfo> emptyRoles = randomBoolean() ? Optional.empty() : Optional.of(authzInfo(new String[0]));
|
||||
assertFalse("Does not match the filter predicate because of the empty roles.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)), emptyRoles,
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final List<String> someIndicesDoNotMatch = new ArrayList<>(
|
||||
randomSubsetOf(randomIntBetween(0, filteredIndices.size()), filteredIndices));
|
||||
for (int i = 0; i < randomIntBetween(1, 8); i++) {
|
||||
|
@ -256,14 +294,15 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])))));
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final Optional<String[]> emptyIndices = randomBoolean() ? Optional.empty() : Optional.of(new String[0]);
|
||||
assertFalse("Does not match the filter predicate because of the empty indices.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
emptyIndices)));
|
||||
emptyIndices, Optional.of(randomFrom(filteredActions)))));
|
||||
}
|
||||
|
||||
public void testSingleCompleteWithEmptyFieldPolicyPredicate() throws Exception {
|
||||
|
@ -297,16 +336,22 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
filteredIndices.add(""); // filter by missing index name
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.completeFilterPolicy.indices", filteredIndices);
|
||||
filteredIndices.remove("");
|
||||
// filter by actions
|
||||
final List<String> filteredActions = randomNonEmptyListOfFilteredActions();
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.completeFilterPolicy.actions",
|
||||
filteredActions);
|
||||
|
||||
final LoggingAuditTrail auditTrail = new LoggingAuditTrail(settingsBuilder.build(), clusterService, logger, threadContext);
|
||||
|
||||
// all fields match
|
||||
Random random = random();
|
||||
assertTrue("Matches the filter predicate.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final User unfilteredUser;
|
||||
if (randomBoolean()) {
|
||||
unfilteredUser = new User(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8));
|
||||
|
@ -320,25 +365,36 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertTrue("Matches the filter predicate because of the empty user.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.empty(),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the realm.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertTrue("Matches the filter predicate because of the empty realm.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.empty(),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertFalse("Does not match the filter predicate because of the pivilege.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8)))));
|
||||
final List<String> someRolesDoNotMatch = new ArrayList<>(randomSubsetOf(randomIntBetween(0, filteredRoles.size()), filteredRoles));
|
||||
for (int i = 0; i < randomIntBetween(1, 8); i++) {
|
||||
someRolesDoNotMatch.add(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8));
|
||||
|
@ -346,12 +402,14 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
assertFalse("Does not match the filter predicate because of some of the roles.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)), Optional.of(authzInfo(someRolesDoNotMatch.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final Optional<AuthorizationInfo> emptyRoles = randomBoolean() ? Optional.empty() : Optional.of(authzInfo(new String[0]));
|
||||
assertTrue("Matches the filter predicate because of the empty roles.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(randomFrom(filteredRealms)), emptyRoles,
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
final List<String> someIndicesDoNotMatch = new ArrayList<>(
|
||||
randomSubsetOf(randomIntBetween(0, filteredIndices.size()), filteredIndices));
|
||||
for (int i = 0; i < randomIntBetween(1, 8); i++) {
|
||||
|
@ -362,22 +420,24 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])))));
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
assertTrue("Matches the filter predicate because of the empty indices.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(
|
||||
randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles).toArray(new String[0]))),
|
||||
Optional.empty())));
|
||||
Optional.empty(), Optional.of(randomFrom(filteredActions)))));
|
||||
assertTrue("Matches the filter predicate because of the empty indices.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(
|
||||
randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles).toArray(new String[0]))),
|
||||
Optional.of(new String[0]))));
|
||||
Optional.of(new String[0]), Optional.of(randomFrom(filteredActions)))));
|
||||
assertTrue("Matches the filter predicate because of the empty indices.", auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)), Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(
|
||||
randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles).toArray(new String[0]))),
|
||||
Optional.of(new String[] { null }))));
|
||||
Optional.of(new String[] { null }),
|
||||
Optional.of(randomFrom(filteredActions)))));
|
||||
}
|
||||
|
||||
public void testTwoPolicyPredicatesWithMissingFields() throws Exception {
|
||||
|
@ -427,27 +487,29 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.empty())));
|
||||
// matches first policy but not the second
|
||||
assertTrue("Matches the first filter predicate but not the second.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(unfilteredUser),
|
||||
Optional.of(randomFrom(filteredRealms)),
|
||||
Optional.of(authzInfo(randomSubsetOf(randomIntBetween(1, filteredRoles.size()), filteredRoles)
|
||||
.toArray(new String[0]))),
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])))));
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])), Optional.of("_action"))));
|
||||
// matches the second policy but not the first
|
||||
assertTrue("Matches the second filter predicate but not the first.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate().test(new AuditEventMetaInfo(Optional.of(randomFrom(filteredUsers)),
|
||||
Optional.of(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8)),
|
||||
Optional.of(authzInfo(someRolesDoNotMatch.toArray(new String[0]))),
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])))));
|
||||
Optional.of(randomSubsetOf(randomIntBetween(1, filteredIndices.size()), filteredIndices).toArray(new String[0])),
|
||||
Optional.empty())));
|
||||
// matches neither the first nor the second policies
|
||||
assertFalse("Matches neither the first nor the second filter predicates.",
|
||||
auditTrail.eventFilterPolicyRegistry.ignorePredicate()
|
||||
.test(new AuditEventMetaInfo(Optional.of(unfilteredUser),
|
||||
Optional.of(UNFILTER_MARKER + randomAlphaOfLengthBetween(1, 8)),
|
||||
Optional.of(authzInfo(someRolesDoNotMatch.toArray(new String[0]))),
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])))));
|
||||
Optional.of(someIndicesDoNotMatch.toArray(new String[0])), Optional.empty())));
|
||||
}
|
||||
|
||||
public void testUsersFilter() throws Exception {
|
||||
|
@ -1817,6 +1879,231 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
threadContext.stashContext();
|
||||
}
|
||||
|
||||
public void testActionsFilter() throws Exception {
|
||||
final Logger logger = CapturingLogger.newCapturingLogger(Level.INFO, null);
|
||||
final ThreadContext threadContext = new ThreadContext(Settings.EMPTY);
|
||||
final List<String> filteredActions = randomNonEmptyListOfFilteredActions();
|
||||
|
||||
final Settings.Builder settingsBuilder = Settings.builder().put(settings);
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.actionsPolicy.actions",
|
||||
filteredActions);
|
||||
// a filter for a field consisting of an empty string ("") or an empty list([])
|
||||
// will match events that lack that field
|
||||
final boolean filterMissingAction = randomBoolean();
|
||||
if (filterMissingAction) {
|
||||
if (randomBoolean()) {
|
||||
filteredActions.add("");
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.missingPolicy.actions",
|
||||
filteredActions);
|
||||
} else {
|
||||
settingsBuilder.putList("xpack.security.audit.logfile.events.ignore_filters.missingPolicy.actions",
|
||||
Collections.emptyList());
|
||||
}
|
||||
}
|
||||
final String filteredAction = randomFrom(filteredActions);
|
||||
final String unfilteredAction = "mock_action/mock_action";
|
||||
User user;
|
||||
if (randomBoolean()) {
|
||||
user = new User("user1", new String[] { "r1" }, new User("authUsername", new String[] { "r2" }));
|
||||
} else {
|
||||
user = new User("user1", new String[] { "r1" });
|
||||
}
|
||||
final TransportRequest request = randomBoolean() ? new MockRequest(threadContext)
|
||||
: new MockIndicesRequest(threadContext, new String[] { "idx1", "idx2" });
|
||||
final MockToken authToken = new MockToken("token1");
|
||||
final LoggingAuditTrail auditTrail = new LoggingAuditTrail(settingsBuilder.build(), clusterService, logger, threadContext);
|
||||
final List<String> logOutput = CapturingLogger.output(logger.getName(), Level.INFO);
|
||||
|
||||
// anonymous accessDenied
|
||||
auditTrail.anonymousAccessDenied(randomAlphaOfLength(8), filteredAction, request);
|
||||
assertThat("Anonymous message: not filtered out by the action filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.anonymousAccessDenied(randomAlphaOfLength(8), getRestRequest());
|
||||
if (filterMissingAction){
|
||||
assertThat("Anonymous rest request: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("Anonymous rest request: filtered out by action filter", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// authenticationFailed
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), getRestRequest());
|
||||
if (filterMissingAction){
|
||||
assertThat("AuthenticationFailed: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AuthenticationFailed: filtered out by action filter", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), authToken, filteredAction, request);
|
||||
assertThat("AuthenticationFailed: not filtered out by the action filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), filteredAction, request);
|
||||
assertThat("AuthenticationFailed no token message: not filtered out by the action filter", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), authToken, getRestRequest());
|
||||
if (filterMissingAction) {
|
||||
assertThat("AuthenticationFailed rest request: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AuthenticationFailed rest request: filtered out by action filter", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), "realm", authToken, unfilteredAction, request);
|
||||
assertThat("AuthenticationFailed realm message: unfiltered action is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), "realm", authToken, filteredAction, request);
|
||||
assertThat("AuthenticationFailed realm message: filtered action is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationFailed(randomAlphaOfLength(8), "realm", authToken, getRestRequest());
|
||||
if (filterMissingAction) {
|
||||
assertThat("AuthenticationFailed realm rest request: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AuthenticationFailed realm rest request: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessGranted
|
||||
Authentication authentication = createAuthentication(user, "realm");
|
||||
auditTrail.accessGranted(randomAlphaOfLength(8), authentication, filteredAction, request, authzInfo(new String[]{"role1"}));
|
||||
assertThat("AccessGranted message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessGranted(randomAlphaOfLength(8), authentication, unfilteredAction, request, authzInfo(new String[]{"role1"}));
|
||||
assertThat("AccessGranted message: unfiltered action filtered out by the action filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// accessDenied
|
||||
auditTrail.accessDenied(randomAlphaOfLength(8), authentication, filteredAction, request, authzInfo(new String[]{"role1"}));
|
||||
assertThat("AccessDenied message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.accessDenied(randomAlphaOfLength(8), authentication, unfilteredAction, request, authzInfo(new String[]{"role1"}));
|
||||
assertThat("AccessDenied message: unfiltered action filtered out by the action filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// tamperedRequest
|
||||
auditTrail.tamperedRequest(randomAlphaOfLength(8), getRestRequest());
|
||||
if (filterMissingAction) {
|
||||
assertThat("Tampered rest: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("Tampered rest: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.tamperedRequest(randomAlphaOfLength(8), filteredAction, request);
|
||||
assertThat("Tampered message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.tamperedRequest(randomAlphaOfLength(8), authentication, filteredAction, request);
|
||||
assertThat("Tampered message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.tamperedRequest(randomAlphaOfLength(8), authentication, unfilteredAction, request);
|
||||
assertThat("Tampered message: unfiltered action filtered out by the action filter", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// connection denied
|
||||
auditTrail.connectionDenied(InetAddress.getLoopbackAddress(), "default", new SecurityIpFilterRule(false, "_all"));
|
||||
if (filterMissingAction) {
|
||||
assertThat("Connection denied: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("Connection denied: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// connection granted
|
||||
auditTrail.connectionGranted(InetAddress.getLoopbackAddress(), "default", new SecurityIpFilterRule(false, "_all"));
|
||||
if (filterMissingAction) {
|
||||
assertThat("Connection granted: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("Connection granted: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsGranted
|
||||
auditTrail.runAsGranted(randomAlphaOfLength(8), createAuthentication(user, "realm"), filteredAction,
|
||||
new MockRequest(threadContext), authzInfo(new String[] { "role1" }));
|
||||
assertThat("RunAsGranted message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsGranted(randomAlphaOfLength(8), createAuthentication(user, "realm"), unfilteredAction,
|
||||
new MockRequest(threadContext), authzInfo(new String[] { "role1" }));
|
||||
assertThat("RunAsGranted message: unfiltered action is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// runAsDenied
|
||||
auditTrail.runAsDenied(randomAlphaOfLength(8), createAuthentication(user, "realm"), filteredAction, new MockRequest(threadContext),
|
||||
authzInfo(new String[] { "role1" }));
|
||||
assertThat("RunAsDenied message: not filtered out by the action filters", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(randomAlphaOfLength(8), createAuthentication(user, "realm"), unfilteredAction,
|
||||
new MockRequest(threadContext), authzInfo(new String[] { "role1" }));
|
||||
assertThat("RunAsDenied message: unfiltered action filtered out by the action filters", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.runAsDenied(randomAlphaOfLength(8), createAuthentication(user, "realm"), getRestRequest(),
|
||||
authzInfo(new String[] { "role1" }));
|
||||
if (filterMissingAction) {
|
||||
assertThat("RunAsDenied rest request: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("RunAsDenied rest request: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
// authentication Success
|
||||
auditTrail.authenticationSuccess(randomAlphaOfLength(8), createAuthentication(user, "realm"), getRestRequest());
|
||||
if (filterMissingAction) {
|
||||
assertThat("AuthenticationSuccess rest request: not filtered out by the missing action filter", logOutput.size(), is(0));
|
||||
} else {
|
||||
assertThat("AuthenticationSuccess rest request: filtered out by the action filters", logOutput.size(), is(1));
|
||||
}
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess(randomAlphaOfLength(8), createAuthentication(user, "realm"), filteredAction, request);
|
||||
assertThat("AuthenticationSuccess message: filtered action is not filtered out", logOutput.size(), is(0));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
|
||||
auditTrail.authenticationSuccess(randomAlphaOfLength(8), createAuthentication(user, "realm"), unfilteredAction, request);
|
||||
assertThat("AuthenticationSuccess message: unfiltered action is filtered out", logOutput.size(), is(1));
|
||||
logOutput.clear();
|
||||
threadContext.stashContext();
|
||||
}
|
||||
|
||||
private <T> List<T> randomListFromLengthBetween(List<T> l, int min, int max) {
|
||||
assert (min >= 0) && (min <= max) && (max <= l.size());
|
||||
final int len = randomIntBetween(min, max);
|
||||
|
@ -1851,6 +2138,65 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||
return filtered;
|
||||
}
|
||||
|
||||
private List<String> randomNonEmptyListOfFilteredActions() {
|
||||
final List<String> filtered = new ArrayList<>(4);
|
||||
final String[] actionPatterns = {
|
||||
"internal:transport/proxy/indices:*",
|
||||
"indices:data/read/*",
|
||||
"internal:transport/proxy/indices:data/read/*",
|
||||
"indices:data/write/index*",
|
||||
"indices:data/write/bulk*",
|
||||
"indices:data/write/index",
|
||||
"indices:data/write/index[*",
|
||||
"indices:data/write/index:op_type/create",
|
||||
"indices:data/write/update*",
|
||||
"indices:data/write/delete*",
|
||||
"indices:data/write/*",
|
||||
"indices:monitor/*",
|
||||
"indices:admin/*",
|
||||
"indices:admin/ilm/*",
|
||||
"indices:admin/refresh*",
|
||||
"indices:admin/flush*",
|
||||
"indices:admin/synced_flush",
|
||||
"indices:admin/forcemerge*",
|
||||
"cluster:admin/xpack/security/*",
|
||||
"cluster:admin/xpack/security/saml/*",
|
||||
"cluster:admin/xpack/security/oidc/*",
|
||||
"cluster:admin/xpack/security/token/*",
|
||||
"cluster:admin/xpack/security/api_key/*",
|
||||
"cluster:monitor/*",
|
||||
"cluster:monitor/xpack/ml/*",
|
||||
"cluster:monitor/text_structure/*",
|
||||
"cluster:monitor/data_frame/*",
|
||||
"cluster:monitor/xpack/watcher/*",
|
||||
"cluster:monitor/xpack/rollup/*",
|
||||
"cluster:*",
|
||||
"indices:admin/index_template/*",
|
||||
"indices:admin/data_stream/*",
|
||||
"cluster:admin/xpack/ml/*",
|
||||
"cluster:admin/data_frame/*",
|
||||
"cluster:monitor/data_frame/*",
|
||||
"cluster:monitor/transform/*",
|
||||
"cluster:admin/transform/*",
|
||||
"cluster:admin/xpack/watcher/*",
|
||||
"cluster:monitor/nodes/liveness",
|
||||
"cluster:monitor/state",
|
||||
"indices:admin/template/*",
|
||||
"cluster:admin/component_template/*",
|
||||
"cluster:admin/ingest/pipeline/*",
|
||||
"cluster:admin/xpack/rollup/*",
|
||||
"cluster:admin/xpack/ccr/*",
|
||||
"cluster:admin/ilm/*",
|
||||
"cluster:admin/slm/*",
|
||||
"cluster:admin/xpack/enrich/*"};
|
||||
Random random = random();
|
||||
for (int i = 0; i < randomIntBetween(1, 4); i++) {
|
||||
Object name = actionPatterns[random.nextInt(actionPatterns.length)];
|
||||
filtered.add((String)name);
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
private RestRequest getRestRequest() throws IOException {
|
||||
final RestContent content = randomFrom(RestContent.values());
|
||||
final FakeRestRequest.Builder builder = new Builder(NamedXContentRegistry.EMPTY);
|
||||
|
|
|
@ -273,7 +273,8 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
LoggingAuditTrail.INCLUDE_EVENT_SETTINGS, LoggingAuditTrail.EXCLUDE_EVENT_SETTINGS,
|
||||
LoggingAuditTrail.INCLUDE_REQUEST_BODY, LoggingAuditTrail.FILTER_POLICY_IGNORE_PRINCIPALS,
|
||||
LoggingAuditTrail.FILTER_POLICY_IGNORE_REALMS, LoggingAuditTrail.FILTER_POLICY_IGNORE_ROLES,
|
||||
LoggingAuditTrail.FILTER_POLICY_IGNORE_INDICES, Loggers.LOG_LEVEL_SETTING));
|
||||
LoggingAuditTrail.FILTER_POLICY_IGNORE_INDICES, LoggingAuditTrail.FILTER_POLICY_IGNORE_ACTIONS,
|
||||
Loggers.LOG_LEVEL_SETTING));
|
||||
when(clusterService.getClusterSettings()).thenReturn(clusterSettings);
|
||||
commonFields = new LoggingAuditTrail.EntryCommonFields(settings, localNode).commonFields;
|
||||
threadContext = new ThreadContext(Settings.EMPTY);
|
||||
|
@ -342,6 +343,15 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||
e = expectThrows(IllegalArgumentException.class,
|
||||
() -> LoggingAuditTrail.FILTER_POLICY_IGNORE_INDICES.getConcreteSettingForNamespace("filter4").get(settings4));
|
||||
assertThat(e, hasToString(containsString("invalid pattern [/no-inspiration]")));
|
||||
|
||||
Settings settings5 = Settings.builder()
|
||||
.putList(prefix + "ignore_filters.filter2.users", Arrays.asList("tom", "cruise"))
|
||||
.putList(prefix + "ignore_filters.filter2.actions", Arrays.asList("indices:data/read/*", "/foo")).build();
|
||||
assertThat(LoggingAuditTrail.FILTER_POLICY_IGNORE_PRINCIPALS.getConcreteSettingForNamespace("filter2").get(settings5),
|
||||
containsInAnyOrder("tom", "cruise"));
|
||||
e = expectThrows(IllegalArgumentException.class,
|
||||
() -> LoggingAuditTrail.FILTER_POLICY_IGNORE_ACTIONS.getConcreteSettingForNamespace("filter2").get(settings5));
|
||||
assertThat(e, hasToString(containsString("invalid pattern [/foo]")));
|
||||
}
|
||||
|
||||
public void testSecurityConfigChangeEventFormattingForRoles() throws IOException {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue