Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/filter user ops #2186

Merged
merged 4 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -355,4 +355,9 @@ public void validate(Map<String,List<String>> parameters) throws IllegalArgument
public UserOperations getUserOperations() {
return delegate.getUserOperations();
}

@Override
public void preInitialize(Query settings, Set<Authorizations> queryAuths) {
delegate.preInitialize(settings, queryAuths);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,15 @@ default long getResultLimit(Query settings) {
* @return A user operations interface implementation. Null if NA (i.e. the local principal is sufficient)
*/
UserOperations getUserOperations();

/**
* This is to be used prior to requesting user operations for a logic that is not yet initialized. The main use case is for the FilteredQueryLogic to allow
* it to filter this call as well. Most query logics will not implement this.
*
* @param settings
* @param userAuthorizations
*/
default void preInitialize(Query settings, Set<Authorizations> userAuthorizations) {
// noop
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public Set<Authorizations> updateRuntimeAuthorizationsAndQueryAuths(QueryLogic<?
if (userOperations != null) {
principal = userOperations.getRemoteUser(principal);
}
logic.preInitialize(settings, AuthorizationsUtil.buildAuthorizations(Collections.singleton(requestedAuths)));
if (logic.getUserOperations() != null) {
queryPrincipal = logic.getUserOperations().getRemoteUser(queryPrincipal);
}
Expand Down Expand Up @@ -511,6 +512,13 @@ public void setQueryLogics(Map<String,QueryLogic<?>> queryLogics) {
this.queryLogics = new TreeMap<>(queryLogics);
}

@Override
public void preInitialize(Query settings, Set<Authorizations> queryAuths) {
for (QueryLogic logic : getUninitializedLogics().values()) {
logic.preInitialize(settings, queryAuths);
}
}

public UserOperations getUserOperations() {
// if any of the underlying logics have a non-null user operations, then
// we need to return an instance that combines auths across the underlying
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public interface QueryLogicFilter {
boolean canRunQuery(Query settings, Set<Authorizations> auths);
}

@Override
public void preInitialize(Query settings, Set<Authorizations> userAuthorizations) {
// setup the filter
if (canRunQuery(settings, userAuthorizations)) {
super.preInitialize(settings, userAuthorizations);
}
}

public boolean canRunQuery(Query settings, Set<Authorizations> runtimeQueryAuthorizations) {
if (!filtered) {
if (!filter.canRunQuery(settings, runtimeQueryAuthorizations)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,11 @@ public GenericResponse<String> planQuery(@Required("logicName") @PathParam("logi
}

// the query principal is our local principal unless the query logic has a different user operations
if (qp.getAuths() != null) {
qd.logic.preInitialize(q, AuthorizationsUtil.buildAuthorizations(Collections.singleton(AuthorizationsUtil.splitAuths(qp.getAuths()))));
} else {
qd.logic.preInitialize(q, AuthorizationsUtil.buildAuthorizations(null));
}
DatawavePrincipal queryPrincipal = (qd.logic.getUserOperations() == null) ? (DatawavePrincipal) qd.p : qd.logic.getUserOperations().getRemoteUser(
(DatawavePrincipal) qd.p);
// the overall principal (the one with combined auths across remote user operations) is our own user operations bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ public RunningQuery(QueryMetricsBean queryMetrics, Connector connection, Accumul
this.connectionPriority = priority;
this.settings = settings;
// the query principal is our local principal unless the query logic has a different user operations
if (methodAuths != null) {
logic.preInitialize(settings, AuthorizationsUtil.buildAuthorizations(Collections.singleton(AuthorizationsUtil.splitAuths(methodAuths))));
} else {
logic.preInitialize(settings, AuthorizationsUtil.buildAuthorizations(null));
}
DatawavePrincipal queryPrincipal = (logic.getUserOperations() == null) ? (DatawavePrincipal) principal : logic.getUserOperations().getRemoteUser(
(DatawavePrincipal) principal);
// the overall principal (the one with combined auths across remote user operations) is our own user operations (probably the UserOperationsBean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import datawave.webservice.common.audit.AuditParameters;
import datawave.webservice.common.exception.DatawaveWebApplicationException;
import datawave.webservice.common.exception.NoResultsException;
import datawave.webservice.query.Query;
import datawave.webservice.query.QueryParameters;
import datawave.webservice.query.QueryParametersImpl;
import datawave.webservice.query.QueryPersistence;
Expand Down Expand Up @@ -347,7 +348,7 @@ public <T> T createUUIDQueryAndNext(final AbstractUUIDLookupCriteria unvalidated
// Override the extraneous query details
String logicName = queryParameters.getFirst(QueryParameters.QUERY_LOGIC_NAME);
String queryAuths = queryParameters.getFirst(QueryParameters.QUERY_AUTHORIZATIONS);
String userAuths = getAuths(logicName, queryAuths, principal);
String userAuths = getAuths(logicName, queryParameters, queryAuths, principal);
if (queryParameters.containsKey(QueryParameters.QUERY_AUTHORIZATIONS)) {
queryParameters.remove(QueryParameters.QUERY_AUTHORIZATIONS);
}
Expand Down Expand Up @@ -418,10 +419,29 @@ public <T> T createUUIDQueryAndNext(final AbstractUUIDLookupCriteria unvalidated
return response;
}

private String getAuths(String logicName, String queryAuths, Principal principal) {
private Query createSettings(MultivaluedMap<String,String> queryParameters) {
Query query = responseObjectFactory.getQueryImpl();
if (queryParameters != null) {
query.setOptionalQueryParameters(queryParameters);
for (String key : queryParameters.keySet()) {
if (queryParameters.get(key).size() == 1) {
query.addParameter(key, queryParameters.get(key).get(0));
}
}
}
return query;
}

private String getAuths(String logicName, MultivaluedMap<String,String> queryParameters, String queryAuths, Principal principal) {
ivakegg marked this conversation as resolved.
Show resolved Hide resolved
String userAuths;
try {
QueryLogic<?> logic = queryLogicFactory.getQueryLogic(logicName, principal);
Query settings = createSettings(queryParameters);
if (queryAuths == null) {
logic.preInitialize(settings, AuthorizationsUtil.buildAuthorizations(null));
} else {
logic.preInitialize(settings, AuthorizationsUtil.buildAuthorizations(Collections.singleton(AuthorizationsUtil.splitAuths(queryAuths))));
}
// the query principal is our local principal unless the query logic has a different user operations
DatawavePrincipal queryPrincipal = (logic.getUserOperations() == null) ? (DatawavePrincipal) principal : logic.getUserOperations().getRemoteUser(
(DatawavePrincipal) principal);
Expand Down Expand Up @@ -569,7 +589,7 @@ private <T> T lookupContentByEvents(final AbstractUUIDLookupCriteria criteria, f
String sid = principal.getName();

// Initialize the reusable query input
final String userAuths = getAuths(CONTENT_QUERY, null, principal);
final String userAuths = getAuths(CONTENT_QUERY, criteria.getQueryParameters(), null, principal);
final String queryName = sid + '-' + UUID.randomUUID();
final Date endDate = new Date();
final Date expireDate = new Date(endDate.getTime() + 1000 * 60 * 60);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datawave.webservice.query.cache;

import datawave.microservice.querymetric.QueryMetricFactoryImpl;
import datawave.security.util.AuthorizationsUtil;
import datawave.webservice.common.connection.AccumuloConnectionFactory;
import datawave.webservice.query.QueryImpl;
import datawave.webservice.query.logic.QueryLogic;
Expand Down Expand Up @@ -124,6 +125,7 @@ public void testGetRunningQueries() throws Exception {
expect(logic.isLongRunningQuery()).andReturn(false);
expect(logic.getResultLimit(q)).andReturn(-1L);
expect(logic.getMaxResults()).andReturn(-1L);
logic.preInitialize(q, AuthorizationsUtil.buildAuthorizations(null));
expect(logic.getUserOperations()).andReturn(null);

PowerMock.replayAll();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import datawave.marking.ColumnVisibilitySecurityMarking;
import datawave.marking.SecurityMarking;
import datawave.microservice.querymetric.QueryMetric;
Expand All @@ -13,6 +14,7 @@
import datawave.security.authorization.SubjectIssuerDNPair;
import datawave.security.authorization.UserOperations;
import datawave.security.user.UserOperationsBean;
import datawave.security.util.AuthorizationsUtil;
import datawave.webservice.common.audit.AuditBean;
import datawave.webservice.common.audit.AuditParameters;
import datawave.webservice.common.audit.Auditor.AuditType;
Expand Down Expand Up @@ -397,6 +399,7 @@ public void testAdminCancel_LookupAccumuloQuery() throws Exception {
expect(this.queryLogic1.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_2", "AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
cache.put(eq(queryId.toString()), isA(RunningQuery.class));
cache.remove(queryId.toString());
Expand Down Expand Up @@ -803,6 +806,7 @@ public void testCreateQueryAndNext_HappyPath() throws Exception {
expect(this.query.getDnList()).andReturn(dnList).anyTimes();
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.queryLogic1.initialize(eq(this.connector), eq(this.query), isA(Set.class))).andReturn(this.genericConfiguration);
this.queryLogic1.setupQuery(this.genericConfiguration);
Expand Down Expand Up @@ -979,6 +983,7 @@ public void testCreateQueryAndNext_BadID() throws Exception {
expect(this.query.getDnList()).andReturn(dnList).anyTimes();
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.queryLogic1.initialize(eq(this.connector), eq(this.query), isA(Set.class))).andReturn(this.genericConfiguration);
this.queryLogic1.setupQuery(this.genericConfiguration);
Expand Down Expand Up @@ -1488,6 +1493,7 @@ public void testCreateQueryAndNext_DoubleAuditValues() throws Exception {
expect(this.queryLogic1.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.queryLogic1.initialize(eq(this.connector), eq(this.query), isA(Set.class))).andReturn(this.genericConfiguration);
this.queryLogic1.setupQuery(this.genericConfiguration);
Expand Down Expand Up @@ -1824,6 +1830,7 @@ public void testCreateQueryAndNext_ButNoResults() throws Exception {

expect(this.runningQuery.getLogic()).andReturn((QueryLogic) this.queryLogic1);
expect(this.queryLogic1.getCollectQueryMetrics()).andReturn(true);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);

this.metrics.updateMetric(this.queryMetric);
Expand Down Expand Up @@ -2843,6 +2850,7 @@ public void testList_HappyPath() throws Exception {
expect(this.queryLogic1.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(null));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
this.cache.put(eq(queryId.toString()), isA(RunningQuery.class));

Expand Down Expand Up @@ -3348,6 +3356,7 @@ public void testReset_NoPreexistingRunningQuery() throws Exception {
expect(this.queryLogic1.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic1.getResultLimit(this.query)).andReturn(-1L);
expect(this.queryLogic1.getMaxResults()).andReturn(-1L);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.query.toMap()).andReturn(map);
expect(this.query.getColumnVisibility()).andReturn(authorization);
Expand Down Expand Up @@ -3931,6 +3940,7 @@ public void testPlanQuery() throws Exception {
expect(this.dwUser.getAuths()).andReturn(Collections.singleton(queryAuthorizations)).anyTimes();
expect(this.principal.getProxiedUsers()).andReturn(Collections.singletonList(dwUser));
expect(this.userOperations.getRemoteUser(this.principal)).andReturn(this.principal);
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.query.getOwner()).andReturn(userSid).anyTimes();
expect(this.query.getId()).andReturn(queryId).anyTimes();
Expand Down Expand Up @@ -4061,6 +4071,7 @@ public void testPlanQueryWithValues() throws Exception {
expect(this.queryLogic1.getAuditType(this.query)).andReturn(AuditType.PASSIVE);
expect(this.queryLogic1.getConnectionPriority()).andReturn(Priority.NORMAL);
expect(this.queryLogic1.getConnPoolName()).andReturn("connPool1");
this.queryLogic1.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Sets.newHashSet("AUTH_1"))));
expect(this.queryLogic1.getUserOperations()).andReturn(null);
expect(this.connectionFactory.getTrackingMap(isA(StackTraceElement[].class))).andReturn(null);
this.query.populateTrackingMap(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datawave.security.authorization.DatawaveUser;
import datawave.security.authorization.DatawaveUser.UserType;
import datawave.security.authorization.SubjectIssuerDNPair;
import datawave.security.util.AuthorizationsUtil;
import datawave.security.util.DnUtils.NpeUtils;
import datawave.webservice.common.connection.AccumuloConnectionFactory;
import datawave.webservice.common.connection.AccumuloConnectionFactory.Priority;
Expand Down Expand Up @@ -178,6 +179,7 @@ public void testNext_HappyPathUsingDeprecatedConstructor() throws Exception {
expect(this.genericConfiguration.getQueryString()).andReturn(query).once();
expect(this.queryLogic.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic.getResultLimit(eq(this.query))).andReturn(maxResults);
this.queryLogic.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Collections.singleton("AUTH_1"))));
expect(this.queryLogic.getUserOperations()).andReturn(null);
this.queryLogic.setPageProcessingStartTime(anyLong());

Expand Down Expand Up @@ -268,6 +270,7 @@ public void testNextMaxResults_HappyPathUsingDeprecatedConstructor() throws Exce
expect(this.queryLogic.getPageByteTrigger()).andReturn(pageByteTrigger).anyTimes();
expect(this.queryLogic.getMaxWork()).andReturn(maxWork).anyTimes();
expect(this.queryLogic.getMaxResults()).andReturn(maxResults).anyTimes();
this.queryLogic.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Collections.singleton("AUTH_1"))));
expect(this.queryLogic.getUserOperations()).andReturn(null);
expect(this.genericConfiguration.getQueryString()).andReturn(query).once();
this.queryLogic.setPageProcessingStartTime(anyLong());
Expand Down Expand Up @@ -337,6 +340,7 @@ public void testNext_NoResultsAfterCancellationUsingDeprecatedConstructor() thro
expect(this.queryLogic.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic.getResultLimit(eq(this.query))).andReturn(maxResults);
expect(this.queryLogic.getMaxResults()).andReturn(maxResults);
this.queryLogic.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Collections.singleton("AUTH_1"))));
expect(this.queryLogic.getUserOperations()).andReturn(null);
this.queryLogic.setPageProcessingStartTime(anyLong());

Expand Down Expand Up @@ -391,6 +395,7 @@ public void testCloseConnection_HappyPath() throws Exception {
expect(this.queryLogic.isLongRunningQuery()).andReturn(false);
expect(this.queryLogic.getResultLimit(eq(this.query))).andReturn(maxResults);
expect(this.queryLogic.getMaxResults()).andReturn(maxResults);
this.queryLogic.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Collections.singleton("AUTH_1"))));
expect(this.queryLogic.getUserOperations()).andReturn(null);
this.queryLogic.setupQuery(this.genericConfiguration);
this.queryMetrics.updateMetric(isA(QueryMetric.class));
Expand Down Expand Up @@ -479,6 +484,7 @@ public void testNextWithDnResultLimit_HappyPathUsingDeprecatedConstructor() thro
expect(this.queryLogic.getPageByteTrigger()).andReturn(pageByteTrigger).anyTimes();
expect(this.queryLogic.getMaxWork()).andReturn(maxWork).anyTimes();
expect(this.queryLogic.getMaxResults()).andReturn(maxResults).anyTimes();
this.queryLogic.preInitialize(this.query, AuthorizationsUtil.buildAuthorizations(Collections.singleton(Collections.singleton("AUTH_1"))));
expect(this.queryLogic.getUserOperations()).andReturn(null);
expect(this.genericConfiguration.getQueryString()).andReturn(query).once();
this.queryLogic.setPageProcessingStartTime(anyLong());
Expand Down
Loading
Loading