This is an automated email from the ASF dual-hosted git repository.
akshayrai09 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
The following commit(s) were added to refs/heads/master by this push:
new d64aa98 [TE] Authorize service account to prevent config modification
(#4341)
d64aa98 is described below
commit d64aa983e56c66265b3be794491edd10f884cbd1
Author: Akshay Rai <[email protected]>
AuthorDate: Thu Jun 20 15:02:35 2019 -0700
[TE] Authorize service account to prevent config modification (#4341)
---
.../datalayer/pojo/DetectionAlertConfigBean.java | 9 ++
.../datalayer/pojo/DetectionConfigBean.java | 9 ++
.../thirdeye/detection/yaml/YamlResource.java | 107 ++++++++++++++++++---
.../yaml/translator/ConfigTranslator.java | 13 +++
.../yaml/translator/DetectionConfigTranslator.java | 3 +
.../translator/SubscriptionConfigTranslator.java | 2 +
.../thirdeye/detection/yaml/YamlResourceTest.java | 21 ++--
7 files changed, 141 insertions(+), 23 deletions(-)
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionAlertConfigBean.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionAlertConfigBean.java
index 8bbda0e..38bcf94 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionAlertConfigBean.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionAlertConfigBean.java
@@ -51,6 +51,15 @@ public class DetectionAlertConfigBean extends AbstractBean {
Map<String, Object> properties;
Map<String, String> refLinks;
+ List<String> owners;
+
+ public List<String> getOwners() {
+ return owners;
+ }
+
+ public void setOwners(List<String> owners) {
+ this.owners = owners;
+ }
public boolean isActive() {
return active;
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionConfigBean.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionConfigBean.java
index eee4c45..01d6996 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionConfigBean.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/datalayer/pojo/DetectionConfigBean.java
@@ -43,6 +43,15 @@ public class DetectionConfigBean extends AbstractBean {
String yaml;
Map<String, Object> componentSpecs;
long lastTuningTimestamp;
+ List<String> owners;
+
+ public List<String> getOwners() {
+ return owners;
+ }
+
+ public void setOwners(List<String> owners) {
+ this.owners = owners;
+ }
public Map<String, Object> getComponentSpecs() {
return componentSpecs;
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/YamlResource.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/YamlResource.java
index d6e6b32..a590948 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/YamlResource.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/YamlResource.java
@@ -22,6 +22,7 @@ package org.apache.pinot.thirdeye.detection.yaml;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
+import io.dropwizard.auth.Auth;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@@ -34,9 +35,11 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
+import javax.annotation.security.PermitAll;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
@@ -49,6 +52,7 @@ import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pinot.thirdeye.anomaly.task.TaskConstants;
import org.apache.pinot.thirdeye.api.Constants;
+import org.apache.pinot.thirdeye.auth.ThirdEyePrincipal;
import org.apache.pinot.thirdeye.dataframe.util.MetricSlice;
import org.apache.pinot.thirdeye.datalayer.bao.DatasetConfigManager;
import org.apache.pinot.thirdeye.datalayer.bao.DetectionAlertConfigManager;
@@ -57,9 +61,11 @@ import
org.apache.pinot.thirdeye.datalayer.bao.EvaluationManager;
import org.apache.pinot.thirdeye.datalayer.bao.EventManager;
import org.apache.pinot.thirdeye.datalayer.bao.MergedAnomalyResultManager;
import org.apache.pinot.thirdeye.datalayer.bao.MetricConfigManager;
+import org.apache.pinot.thirdeye.datalayer.bao.SessionManager;
import org.apache.pinot.thirdeye.datalayer.bao.TaskManager;
import org.apache.pinot.thirdeye.datalayer.dto.DetectionAlertConfigDTO;
import org.apache.pinot.thirdeye.datalayer.dto.DetectionConfigDTO;
+import org.apache.pinot.thirdeye.datalayer.dto.SessionDTO;
import org.apache.pinot.thirdeye.datalayer.dto.TaskDTO;
import org.apache.pinot.thirdeye.datalayer.util.Predicate;
import org.apache.pinot.thirdeye.datasource.DAORegistry;
@@ -106,6 +112,10 @@ public class YamlResource {
private static final String PROP_SUBS_GROUP_NAME = "subscriptionGroupName";
private static final String PROP_DETECTION_NAME = "detectionName";
+ private static final String PROP_SESSION_KEY = "sessionKey";
+ private static final String PROP_PRINCIPAL_TYPE = "principalType";
+ private static final String PROP_SERVICE = "SERVICE";
+
// default onboarding replay period
private static final long ONBOARDING_REPLAY_LOOKBACK =
TimeUnit.DAYS.toMillis(30);
@@ -120,6 +130,7 @@ public class YamlResource {
private final MergedAnomalyResultManager anomalyDAO;
private final EvaluationManager evaluationDAO;
private final TaskManager taskDAO;
+ private final SessionManager sessionDAO;
private final DetectionPipelineLoader loader;
private final Yaml yaml;
@@ -132,6 +143,7 @@ public class YamlResource {
this.anomalyDAO = DAORegistry.getInstance().getMergedAnomalyResultDAO();
this.taskDAO = DAORegistry.getInstance().getTaskDAO();
this.evaluationDAO = DAORegistry.getInstance().getEvaluationManager();
+ this.sessionDAO = DAORegistry.getInstance().getSessionDAO();
this.yaml = new Yaml();
TimeSeriesLoader timeseriesLoader =
@@ -222,12 +234,23 @@ public class YamlResource {
return Response.serverError().entity(responseMessage).build();
}
+ private Response processBadAuthorizationResponse(String type, String
operation, String payload, NotAuthorizedException e) {
+ Map<String, String> responseMessage = new HashMap<>();
+ LOG.warn("Authorization error while {} {} with payload {}", operation,
type, payload, e);
+ responseMessage.put(type + "Msg", "Authorization Error!");
+ responseMessage.put(type + "Msg-moreInfo", "Configure owners property in "
+ type + " config");
+ return
Response.status(Response.Status.UNAUTHORIZED).entity(responseMessage).build();
+ }
+
@POST
@Path("/create-alert")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
+ @PermitAll
@ApiOperation("Use yaml to create both subscription and detection yaml. ")
- public Response createYamlAlert(@ApiParam(value = "a json contains both
subscription and detection yaml as string") String payload,
+ public Response createYamlAlert(
+ @Auth ThirdEyePrincipal user,
+ @ApiParam(value = "a json contains both subscription and detection yaml
as string") String payload,
@ApiParam("tuning window start time for tunable components")
@QueryParam("startTime") long startTime,
@ApiParam("tuning window end time for tunable components")
@QueryParam("endTime") long endTime) throws Exception {
Map<String, String> yamls;
@@ -266,16 +289,18 @@ public class YamlResource {
List<DetectionAlertConfigDTO> alertConfigDTOS =
detectionAlertConfigDAO.findByPredicate(Predicate.EQ("name", groupName));
if (!alertConfigDTOS.isEmpty()) {
detectionAlertConfigId = alertConfigDTOS.get(0).getId();
- updateSubscriptionGroup(detectionAlertConfigId, subscriptionYaml);
+ updateSubscriptionGroup(user, detectionAlertConfigId,
subscriptionYaml);
} else {
detectionAlertConfigId = createSubscriptionGroup(subscriptionYaml);
}
} catch (IllegalArgumentException e) {
this.detectionConfigDAO.deleteById(detectionConfigId);
- return processBadRequestResponse(PROP_SUBSCRIPTION,
YamlOperations.CREATING.name(), payload, e);
+ return processBadRequestResponse(PROP_SUBSCRIPTION,
YamlOperations.CREATING.name() + "/" + YamlOperations.UPDATING.name(), payload,
e);
+ } catch (NotAuthorizedException e) {
+ return processBadAuthorizationResponse(PROP_SUBSCRIPTION,
YamlOperations.UPDATING.name(), payload, e);
} catch (Exception e) {
this.detectionConfigDAO.deleteById(detectionConfigId);
- return processServerErrorResponse(PROP_DETECTION,
YamlOperations.CREATING.name(), payload, e);
+ return processServerErrorResponse(PROP_DETECTION,
YamlOperations.CREATING.name() + "/" + YamlOperations.UPDATING.name(), payload,
e);
}
// create an yaml onboarding task to run replay and tuning
@@ -345,16 +370,18 @@ public class YamlResource {
return Response.ok().entity(responseMessage).build();
}
- void updateDetectionPipeline(long detectionID, String yamlDetectionConfig) {
- updateDetectionPipeline(detectionID, yamlDetectionConfig, 0, 0);
+ private void updateDetectionPipeline(ThirdEyePrincipal user, long
detectionID, String yamlDetectionConfig) {
+ updateDetectionPipeline(user, detectionID, yamlDetectionConfig, 0, 0);
}
- void updateDetectionPipeline(long detectionID, String payload, long
startTime, long endTime)
+ private void updateDetectionPipeline(ThirdEyePrincipal user, long
detectionID, String payload, long startTime, long endTime)
throws IllegalArgumentException {
DetectionConfigDTO existingDetectionConfig =
this.detectionConfigDAO.findById(detectionID);
DetectionConfigDTO detectionConfig;
Preconditions.checkNotNull(existingDetectionConfig, "Cannot find detection
pipeline " + detectionID);
Preconditions.checkArgument(StringUtils.isNotBlank(payload), "The Yaml
Payload in the request is empty.");
+
+ authorizeUser(user, detectionID, PROP_DETECTION);
try {
detectionConfig = buildDetectionConfigFromYaml(startTime, endTime,
payload, existingDetectionConfig);
@@ -375,6 +402,43 @@ public class YamlResource {
}
}
+ private boolean isServiceAccount(ThirdEyePrincipal user) {
+ List<Predicate> predicates = new ArrayList<>();
+ predicates.add(Predicate.EQ(PROP_SESSION_KEY, user.getSessionKey()));
+ predicates.add(Predicate.EQ(PROP_PRINCIPAL_TYPE, PROP_SERVICE));
+
+ List<SessionDTO> sessionDTO =
this.sessionDAO.findByPredicate(Predicate.AND(predicates.toArray(new
Predicate[0])));
+ return sessionDTO != null && !sessionDTO.isEmpty();
+ }
+
+ private void validateConfigOwner(ThirdEyePrincipal user, List<String>
owners) {
+ if (owners == null || !owners.contains(user.getName())) {
+ throw new NotAuthorizedException("Service account " + user.getName() + "
is not authorized to access this resource.");
+ }
+ }
+
+ /**
+ * Enforce authorization only with service accounts to prevent risk
+ * of modifying other configs when making programmatic calls.
+ */
+ private void authorizeUser(ThirdEyePrincipal user, long id, String
authEntity) {
+ if (user == null || StringUtils.isBlank(user.getName()) ||
StringUtils.isBlank(user.getSessionKey())) {
+ throw new NotAuthorizedException("Unable to find the credentials/token
in the request");
+ }
+
+ // Authorize only service accounts
+ if (isServiceAccount(user)) {
+ if (authEntity.equals(PROP_DETECTION)) {
+ DetectionConfigDTO detectionConfig =
this.detectionConfigDAO.findById(id);
+ validateConfigOwner(user, detectionConfig.getOwners());
+ } else if (authEntity.equals(PROP_SUBSCRIPTION)) {
+ DetectionAlertConfigDTO subscriptionConfig =
this.detectionAlertConfigDAO.findById(id);
+ validateConfigOwner(user, subscriptionConfig.getOwners());
+ }
+ }
+ LOG.info("User " + user.getName() + " authorized successfully");
+ }
+
/**
Edit a detection pipeline using a YAML config
@param payload YAML config string
@@ -387,17 +451,21 @@ public class YamlResource {
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.TEXT_PLAIN)
+ @PermitAll
@ApiOperation("Edit a detection pipeline using a YAML config")
public Response updateDetectionPipelineApi(
+ @Auth ThirdEyePrincipal user,
@ApiParam("yaml config") String payload,
@ApiParam("the detection config id to edit") @PathParam("id") long id,
@ApiParam("tuning window start time for tunable components")
@QueryParam("startTime") long startTime,
@ApiParam("tuning window end time for tunable components")
@QueryParam("endTime") long endTime) {
Map<String, String> responseMessage = new HashMap<>();
try {
- updateDetectionPipeline(id, payload, startTime, endTime);
+ updateDetectionPipeline(user, id, payload, startTime, endTime);
} catch (IllegalArgumentException e) {
return processBadRequestResponse(PROP_DETECTION,
YamlOperations.UPDATING.name(), payload, e);
+ } catch (NotAuthorizedException e) {
+ return processBadAuthorizationResponse(PROP_DETECTION,
YamlOperations.UPDATING.name(), payload, e);
} catch (Exception e) {
return processServerErrorResponse(PROP_DETECTION,
YamlOperations.UPDATING.name(), payload, e);
}
@@ -427,13 +495,13 @@ public class YamlResource {
return existingDetectionConfig;
}
- long createOrUpdateDetectionPipeline(String payload) {
+ long createOrUpdateDetectionPipeline(ThirdEyePrincipal user, String payload)
{
Preconditions.checkArgument(StringUtils.isNotBlank(payload), "The Yaml
Payload in the request is empty.");
long detectionId;
DetectionConfigDTO existingDetection = fetchExistingDetection(payload);
if (existingDetection != null) {
detectionId = existingDetection.getId();
- updateDetectionPipeline(detectionId, payload);
+ updateDetectionPipeline(user, detectionId, payload);
} else {
detectionId = createDetectionPipeline(payload);
}
@@ -450,14 +518,19 @@ public class YamlResource {
@Path("/create-or-update")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.TEXT_PLAIN)
+ @PermitAll
@ApiOperation("Create a new detection pipeline or update existing if one
already exists")
- public Response createOrUpdateDetectionPipelineApi(@ApiParam("yaml config")
String payload) {
+ public Response createOrUpdateDetectionPipelineApi(
+ @Auth ThirdEyePrincipal user,
+ @ApiParam("yaml config") String payload) {
Map<String, String> responseMessage = new HashMap<>();
long detectionConfigId;
try {
- detectionConfigId = createOrUpdateDetectionPipeline(payload);
+ detectionConfigId = createOrUpdateDetectionPipeline(user, payload);
} catch (IllegalArgumentException e) {
return processBadRequestResponse(PROP_DETECTION,
YamlOperations.CREATING.name() + "/" + YamlOperations.UPDATING.name(), payload,
e);
+ } catch (NotAuthorizedException e) {
+ return processBadAuthorizationResponse(PROP_DETECTION,
YamlOperations.CREATING.name() + "/" + YamlOperations.UPDATING.name(), payload,
e);
} catch (Exception e) {
return processServerErrorResponse(PROP_DETECTION,
YamlOperations.CREATING.name() + "/" + YamlOperations.UPDATING.name(), payload,
e);
}
@@ -533,17 +606,19 @@ public class YamlResource {
oldAlertConfig.setAlertSuppressors(newAlertConfig.getAlertSuppressors());
oldAlertConfig.setProperties(newAlertConfig.getProperties());
oldAlertConfig.setYaml(newAlertConfig.getYaml());
+ oldAlertConfig.setOwners(newAlertConfig.getOwners());
return oldAlertConfig;
}
- void updateSubscriptionGroup(long oldAlertConfigID, String yamlConfig) {
+ void updateSubscriptionGroup(ThirdEyePrincipal user, long oldAlertConfigID,
String yamlConfig) {
DetectionAlertConfigDTO oldAlertConfig =
this.detectionAlertConfigDAO.findById(oldAlertConfigID);
if (oldAlertConfig == null) {
throw new RuntimeException("Cannot find subscription group " +
oldAlertConfigID);
}
Preconditions.checkArgument(StringUtils.isNotBlank(yamlConfig), "The Yaml
Payload in the request is empty.");
+ authorizeUser(user, oldAlertConfigID, PROP_SUBSCRIPTION);
DetectionAlertConfigDTO newAlertConfig = new
SubscriptionConfigTranslator(detectionConfigDAO, yamlConfig).translate();
DetectionAlertConfigDTO updatedAlertConfig =
updateDetectionAlertConfig(oldAlertConfig, newAlertConfig);
@@ -577,15 +652,19 @@ public class YamlResource {
@Path("/subscription/{id}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.TEXT_PLAIN)
+ @PermitAll
@ApiOperation("Edit a subscription group using a YAML config")
public Response updateSubscriptionGroupApi(
+ @Auth ThirdEyePrincipal user,
@ApiParam("payload") String payload,
@ApiParam("the detection alert config id to edit") @PathParam("id") long
id) {
Map<String, String> responseMessage = new HashMap<>();
try {
- updateSubscriptionGroup(id, payload);
+ updateSubscriptionGroup(user, id, payload);
} catch (IllegalArgumentException e) {
return processBadRequestResponse(PROP_SUBSCRIPTION,
YamlOperations.UPDATING.name(), payload, e);
+ } catch (NotAuthorizedException e) {
+ return processBadAuthorizationResponse(PROP_SUBSCRIPTION,
YamlOperations.UPDATING.name(), payload, e);
} catch (Exception e) {
return processServerErrorResponse(PROP_SUBSCRIPTION,
YamlOperations.UPDATING.name(), payload, e);
}
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/ConfigTranslator.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/ConfigTranslator.java
index a0f71c9..9a8a3e3 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/ConfigTranslator.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/ConfigTranslator.java
@@ -19,7 +19,10 @@
package org.apache.pinot.thirdeye.detection.yaml.translator;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import org.apache.pinot.thirdeye.datalayer.dto.AbstractDTO;
import org.apache.pinot.thirdeye.detection.ConfigUtils;
@@ -42,6 +45,16 @@ public abstract class ConfigTranslator<T extends
AbstractDTO, V extends ConfigVa
this.yaml = new Yaml();
}
+ List<String> filterOwners(List<String> configuredOwners) {
+ List<String> owners = new ArrayList<>();
+ for (String configuredOwner : configuredOwners) {
+ // TODO: check if configured owner is a valid account
+ owners.add(configuredOwner.trim());
+ }
+ // Return after removing duplicates
+ return new ArrayList<>(new HashSet<>(owners));
+ }
+
abstract T translateConfig(Map<String, Object> yamlConfigMap) throws
IllegalArgumentException;
/**
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/DetectionConfigTranslator.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/DetectionConfigTranslator.java
index 7e76d5b..9a5c5cb 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/DetectionConfigTranslator.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/DetectionConfigTranslator.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -156,6 +157,7 @@ public class DetectionConfigTranslator extends
ConfigTranslator<DetectionConfigD
private static final String PROP_DETECTION_NAME = "detectionName";
private static final String PROP_DESC_NAME = "description";
private static final String PROP_ACTIVE = "active";
+ private static final String PROP_OWNERS = "owners";
private static final String PROP_ALERTS = "alerts";
private static final String COMPOSITE_ALERT = "COMPOSITE_ALERT";
@@ -495,6 +497,7 @@ public class DetectionConfigTranslator extends
ConfigTranslator<DetectionConfigD
config.setName(MapUtils.getString(yamlConfigMap, PROP_DETECTION_NAME));
config.setDescription(MapUtils.getString(yamlConfigMap, PROP_DESC_NAME));
config.setLastTimestamp(System.currentTimeMillis());
+
config.setOwners(filterOwners(ConfigUtils.getList(yamlConfigMap.get(PROP_OWNERS))));
config.setProperties(properties);
config.setComponentSpecs(components);
diff --git
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/SubscriptionConfigTranslator.java
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/SubscriptionConfigTranslator.java
index ce75b16..bc037ca 100644
---
a/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/SubscriptionConfigTranslator.java
+++
b/thirdeye/thirdeye-pinot/src/main/java/org/apache/pinot/thirdeye/detection/yaml/translator/SubscriptionConfigTranslator.java
@@ -53,6 +53,7 @@ public class SubscriptionConfigTranslator extends
ConfigTranslator<DetectionAler
public static final String PROP_ACTIVE = "active";
public static final String PROP_APPLICATION = "application";
public static final String PROP_FROM = "fromAddress";
+ public static final String PROP_OWNERS = "owners";
public static final String PROP_EMAIL_SUBJECT_TYPE = "emailSubjectStyle";
public static final String PROP_ALERT_SCHEMES = "alertSchemes";
public static final String PROP_DETECTION_NAMES = "subscribedDetections";
@@ -168,6 +169,7 @@ public class SubscriptionConfigTranslator extends
ConfigTranslator<DetectionAler
alertConfigDTO.setName(MapUtils.getString(yamlConfigMap,
PROP_SUBS_GROUP_NAME));
alertConfigDTO.setApplication(MapUtils.getString(yamlConfigMap,
PROP_APPLICATION));
alertConfigDTO.setFrom(MapUtils.getString(yamlConfigMap, PROP_FROM));
+
alertConfigDTO.setOwners(filterOwners(ConfigUtils.getList(yamlConfigMap.get(PROP_OWNERS))));
alertConfigDTO.setCronExpression(MapUtils.getString(yamlConfigMap,
PROP_CRON, CRON_SCHEDULE_DEFAULT));
alertConfigDTO.setActive(MapUtils.getBooleanValue(yamlConfigMap,
PROP_ACTIVE, true));
diff --git
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/yaml/YamlResourceTest.java
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/yaml/YamlResourceTest.java
index 76cfdb3..3180618 100644
---
a/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/yaml/YamlResourceTest.java
+++
b/thirdeye/thirdeye-pinot/src/test/java/org/apache/pinot/thirdeye/detection/yaml/YamlResourceTest.java
@@ -1,6 +1,7 @@
package org.apache.pinot.thirdeye.detection.yaml;
import java.util.concurrent.TimeUnit;
+import org.apache.pinot.thirdeye.auth.ThirdEyePrincipal;
import org.apache.pinot.thirdeye.datalayer.bao.DAOTestBase;
import org.apache.pinot.thirdeye.datalayer.bao.DetectionConfigManager;
import org.apache.pinot.thirdeye.datalayer.dto.ApplicationDTO;
@@ -25,12 +26,14 @@ public class YamlResourceTest {
private DAOTestBase testDAOProvider;
private YamlResource yamlResource;
private DAORegistry daoRegistry;
+ private ThirdEyePrincipal user;
private static long alertId1;
private static long alertId2;
@BeforeMethod
public void beforeClass() {
testDAOProvider = DAOTestBase.getInstance();
+ this.user = new ThirdEyePrincipal("test", "test");
this.yamlResource = new YamlResource();
this.daoRegistry = DAORegistry.getInstance();
DetectionConfigManager detectionDAO =
this.daoRegistry.getDetectionConfigManager();
@@ -58,7 +61,7 @@ public class YamlResourceTest {
public void testCreateOrUpdateDetectionConfig() throws IOException {
String blankYaml = "";
try {
- this.yamlResource.createOrUpdateDetectionPipeline(blankYaml);
+ this.yamlResource.createOrUpdateDetectionPipeline(user, blankYaml);
Assert.fail("Exception not thrown on empty yaml");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "The Yaml Payload in the request is
empty.");
@@ -79,7 +82,7 @@ public class YamlResourceTest {
// Create a new detection
String validYaml =
IOUtils.toString(this.getClass().getResourceAsStream("detection/detection-config-1.yaml"));
try {
- long id = this.yamlResource.createOrUpdateDetectionPipeline(validYaml);
+ long id = this.yamlResource.createOrUpdateDetectionPipeline(user,
validYaml);
DetectionConfigDTO detection =
daoRegistry.getDetectionConfigManager().findById(id);
Assert.assertNotNull(detection);
Assert.assertEquals(detection.getName(), "testPipeline");
@@ -90,7 +93,7 @@ public class YamlResourceTest {
// Update above created detection
String updatedYaml =
IOUtils.toString(this.getClass().getResourceAsStream("detection/detection-config-2.yaml"));
try {
- long id = this.yamlResource.createOrUpdateDetectionPipeline(updatedYaml);
+ long id = this.yamlResource.createOrUpdateDetectionPipeline(user,
updatedYaml);
DetectionConfigDTO detection =
daoRegistry.getDetectionConfigManager().findById(id);
Assert.assertNotNull(detection);
Assert.assertEquals(detection.getName(), "testPipeline");
@@ -190,7 +193,7 @@ public class YamlResourceTest {
DetectionAlertConfigDTO alertDTO;
try {
- this.yamlResource.updateSubscriptionGroup(-1, "");
+ this.yamlResource.updateSubscriptionGroup(user, -1, "");
Assert.fail("Exception not thrown when the subscription group doesn't
exist");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Cannot find subscription group -1");
@@ -198,7 +201,7 @@ public class YamlResourceTest {
String blankYaml = "";
try {
- this.yamlResource.updateSubscriptionGroup(oldId, blankYaml);
+ this.yamlResource.updateSubscriptionGroup(user, oldId, blankYaml);
Assert.fail("Exception not thrown on empty yaml");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "The Yaml Payload in the request is
empty.");
@@ -206,7 +209,7 @@ public class YamlResourceTest {
String inValidYaml = "application:test:application";
try {
- this.yamlResource.updateSubscriptionGroup(oldId, inValidYaml);
+ this.yamlResource.updateSubscriptionGroup(user, oldId, inValidYaml);
Assert.fail("Exception not thrown on empty yaml");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Could not parse as map:
application:test:application");
@@ -214,7 +217,7 @@ public class YamlResourceTest {
String noSubscriptGroupYaml = "application: test_app";
try {
- this.yamlResource.updateSubscriptionGroup(oldId, noSubscriptGroupYaml);
+ this.yamlResource.updateSubscriptionGroup(user, oldId,
noSubscriptGroupYaml);
Assert.fail("Exception not thrown on empty yaml");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Subscription group name field
cannot be left empty.");
@@ -222,7 +225,7 @@ public class YamlResourceTest {
String appFieldMissingYaml =
IOUtils.toString(this.getClass().getResourceAsStream("alertconfig/alert-config-1.yaml"));
try {
- this.yamlResource.updateSubscriptionGroup(oldId, appFieldMissingYaml);
+ this.yamlResource.updateSubscriptionGroup(user, oldId,
appFieldMissingYaml);
Assert.fail("Exception not thrown on empty yaml");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Application field cannot be left
empty");
@@ -230,7 +233,7 @@ public class YamlResourceTest {
String validYaml2 =
IOUtils.toString(this.getClass().getResourceAsStream("alertconfig/alert-config-5.yaml"));
try {
- this.yamlResource.updateSubscriptionGroup(oldId, validYaml2);
+ this.yamlResource.updateSubscriptionGroup(user, oldId, validYaml2);
alertDTO = daoRegistry.getDetectionAlertConfigManager().findById(oldId);
Assert.assertNotNull(alertDTO);
Assert.assertEquals(alertDTO.getName(), "Subscription Group Name");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]