JAMES-2428 [DLP] Webadmin DLP markdown documentation
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/55cd111c Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/55cd111c Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/55cd111c Branch: refs/heads/master Commit: 55cd111c6ef2e5db545bd1101a8034515f69e623 Parents: dec6e89 Author: duc <[email protected]> Authored: Fri Jun 15 15:13:47 2018 +0700 Committer: benwa <[email protected]> Committed: Wed Jun 20 09:08:10 2018 +0700 ---------------------------------------------------------------------- .../main/java/org/apache/james/core/Domain.java | 5 +- .../apache/james/CassandraJamesServerMain.java | 4 +- .../org/apache/james/MemoryJamesServerMain.java | 4 +- .../james/modules/server/DLPRoutesModule.java | 35 +++ .../james/modules/server/DataRoutesModules.java | 2 - .../james/webadmin/utils/ErrorResponder.java | 2 +- .../james/webadmin/utils/JsonExtractor.java | 3 +- .../org/apache/james/webadmin/DLPModule.java | 36 --- .../james/webadmin/dto/DLPConfigurationDTO.java | 20 +- .../webadmin/dto/DLPConfigurationItemDTO.java | 55 ++--- .../webadmin/routes/DLPConfigurationRoutes.java | 67 +++--- .../dto/DLPConfigurationItemDTOTest.java | 49 ++-- .../routes/DLPConfigurationRoutesTest.java | 225 +++++++++++++++---- src/site/markdown/server/manage-webadmin.md | 115 ++++++++++ 14 files changed, 440 insertions(+), 182 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/core/src/main/java/org/apache/james/core/Domain.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/james/core/Domain.java b/core/src/main/java/org/apache/james/core/Domain.java index 808de41..1bcea59 100644 --- a/core/src/main/java/org/apache/james/core/Domain.java +++ b/core/src/main/java/org/apache/james/core/Domain.java @@ -37,8 +37,9 @@ public class Domain implements Serializable { } public static Domain of(String domain) { - Preconditions.checkNotNull(domain); - Preconditions.checkArgument(!domain.isEmpty() && !domain.contains("@")); + Preconditions.checkNotNull(domain, "Domain can not be null"); + Preconditions.checkArgument(!domain.isEmpty() && !domain.contains("@"), + "Domain can not be empty nor contain `@`"); return new Domain(domain); } http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java ---------------------------------------------------------------------- diff --git a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java index 035a272..4878e1e 100644 --- a/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java +++ b/server/container/guice/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java @@ -44,6 +44,7 @@ import org.apache.james.modules.protocols.ProtocolHandlerModule; import org.apache.james.modules.protocols.SMTPServerModule; import org.apache.james.modules.server.ActiveMQQueueModule; import org.apache.james.modules.server.CassandraRoutesModule; +import org.apache.james.modules.server.DLPRoutesModule; import org.apache.james.modules.server.DataRoutesModules; import org.apache.james.modules.server.ElasticSearchMetricReporterModule; import org.apache.james.modules.server.JMXServerModule; @@ -67,7 +68,8 @@ public class CassandraJamesServerMain { new MailQueueRoutesModule(), new MailRepositoriesRoutesModule(), new SwaggerRoutesModule(), - new WebAdminServerModule()); + new WebAdminServerModule(), + new DLPRoutesModule()); public static final Module PROTOCOLS = Modules.combine( new CassandraJmapModule(), http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java ---------------------------------------------------------------------- diff --git a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java index 99783fd..fc80fe6 100644 --- a/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java +++ b/server/container/guice/memory-guice/src/main/java/org/apache/james/MemoryJamesServerMain.java @@ -33,6 +33,7 @@ import org.apache.james.modules.protocols.POP3ServerModule; import org.apache.james.modules.protocols.ProtocolHandlerModule; import org.apache.james.modules.protocols.SMTPServerModule; import org.apache.james.modules.server.CamelMailetContainerModule; +import org.apache.james.modules.server.DLPRoutesModule; import org.apache.james.modules.server.DataRoutesModules; import org.apache.james.modules.server.JMXServerModule; import org.apache.james.modules.server.MailQueueRoutesModule; @@ -56,7 +57,8 @@ public class MemoryJamesServerMain { new MailboxRoutesModule(), new MailQueueRoutesModule(), new MailRepositoriesRoutesModule(), - new SwaggerRoutesModule()); + new SwaggerRoutesModule(), + new DLPRoutesModule()); public static final Module PROTOCOLS = Modules.combine( new IMAPServerModule(), http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DLPRoutesModule.java ---------------------------------------------------------------------- diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DLPRoutesModule.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DLPRoutesModule.java new file mode 100644 index 0000000..96fcdde --- /dev/null +++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DLPRoutesModule.java @@ -0,0 +1,35 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.modules.server; + +import org.apache.james.webadmin.Routes; +import org.apache.james.webadmin.routes.DLPConfigurationRoutes; + +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; + +public class DLPRoutesModule extends AbstractModule { + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), Routes.class) + .addBinding() + .to(DLPConfigurationRoutes.class); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java ---------------------------------------------------------------------- diff --git a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java index 2cb95c5..2ae64ec 100644 --- a/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java +++ b/server/container/guice/protocols/webadmin-data/src/main/java/org/apache/james/modules/server/DataRoutesModules.java @@ -20,7 +20,6 @@ package org.apache.james.modules.server; import org.apache.james.webadmin.Routes; -import org.apache.james.webadmin.routes.DLPConfigurationRoutes; import org.apache.james.webadmin.routes.DomainsRoutes; import org.apache.james.webadmin.routes.ForwardRoutes; import org.apache.james.webadmin.routes.GroupsRoutes; @@ -34,7 +33,6 @@ public class DataRoutesModules extends AbstractModule { @Override protected void configure() { Multibinder<Routes> routesMultibinder = Multibinder.newSetBinder(binder(), Routes.class); - routesMultibinder.addBinding().to(DLPConfigurationRoutes.class); routesMultibinder.addBinding().to(DomainsRoutes.class); routesMultibinder.addBinding().to(ForwardRoutes.class); routesMultibinder.addBinding().to(GroupsRoutes.class); http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/ErrorResponder.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/ErrorResponder.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/ErrorResponder.java index 73dde47..e72cbec 100644 --- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/ErrorResponder.java +++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/ErrorResponder.java @@ -115,7 +115,7 @@ public class ErrorResponder { cause.map(Throwable::getMessage))); } - static class ErrorDetail { + public static class ErrorDetail { private final int statusCode; private final String type; private final String message; http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java index fcecc3d..83be263 100644 --- a/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java +++ b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/utils/JsonExtractor.java @@ -20,11 +20,11 @@ package org.apache.james.webadmin.utils; import java.io.IOException; -import java.util.Collection; import java.util.List; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.guava.GuavaModule; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.google.common.collect.ImmutableList; @@ -40,6 +40,7 @@ public class JsonExtractor<RequestT> { public JsonExtractor(Class<RequestT> type, List<Module> modules) { this.objectMapper = new ObjectMapper() .registerModule(new Jdk8Module()) + .registerModule(new GuavaModule()) .registerModules(modules); this.type = type; } http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/DLPModule.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/DLPModule.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/DLPModule.java deleted file mode 100644 index 0363ca3..0000000 --- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/DLPModule.java +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ - -package org.apache.james.webadmin; - -import org.apache.james.webadmin.utils.JsonTransformerModule; - -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.datatype.guava.GuavaModule; - -public class DLPModule implements JsonTransformerModule { - - public DLPModule() { - } - - @Override - public Module asJacksonModule() { - return new GuavaModule(); - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationDTO.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationDTO.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationDTO.java index d1265a6..5849f71 100644 --- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationDTO.java +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationDTO.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.james.dlp.api.DLPConfigurationItem; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.github.steveash.guavate.Guavate; import com.google.common.base.Preconditions; @@ -31,15 +32,6 @@ import com.google.common.collect.ImmutableList; public class DLPConfigurationDTO { - public static List<DLPConfigurationItem> toDLPConfigurations(DLPConfigurationDTO dto) { - Preconditions.checkNotNull(dto); - - return dto.rules - .stream() - .map(DLPConfigurationItemDTO::toDLPConfiguration) - .collect(Guavate.toImmutableList()); - } - public static DLPConfigurationDTO toDTO(List<DLPConfigurationItem> dlpConfigurations) { Preconditions.checkNotNull(dlpConfigurations); @@ -54,11 +46,19 @@ public class DLPConfigurationDTO { @JsonCreator public DLPConfigurationDTO( - @JsonProperty("rules") ImmutableList<DLPConfigurationItemDTO> rules) { + @JsonProperty("rules") ImmutableList<DLPConfigurationItemDTO> rules) { this.rules = rules; } public ImmutableList<DLPConfigurationItemDTO> getRules() { return rules; } + + @JsonIgnore + public List<DLPConfigurationItem> toDLPConfigurations() { + return rules + .stream() + .map(DLPConfigurationItemDTO::toDLPConfiguration) + .collect(Guavate.toImmutableList()); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTO.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTO.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTO.java index 502615a..5f3da5f 100644 --- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTO.java +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTO.java @@ -19,58 +19,47 @@ package org.apache.james.webadmin.dto; -import java.util.List; import java.util.Objects; import java.util.Optional; import org.apache.james.dlp.api.DLPConfigurationItem; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.github.steveash.guavate.Guavate; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; public class DLPConfigurationItemDTO { @VisibleForTesting - static DLPConfigurationItem toDLPConfiguration(DLPConfigurationItemDTO dto) { - return DLPConfigurationItem.builder() - .id(DLPConfigurationItem.Id.of(dto.id)) - .expression(dto.expression) - .explanation(dto.explanation) - .targetsSender(dto.targetsSender) - .targetsRecipients(dto.targetsRecipients) - .targetsContent(dto.targetsContent) - .build(); - } - - @VisibleForTesting static DLPConfigurationItemDTO toDTO(DLPConfigurationItem dlpConfiguration) { DLPConfigurationItem.Targets targets = dlpConfiguration.getTargets(); return new DLPConfigurationItemDTO( dlpConfiguration.getId().asString(), - dlpConfiguration.getRegexp(), + dlpConfiguration.getRegexp().pattern(), dlpConfiguration.getExplanation(), - Optional.of(targets.isSenderTargeted()), - Optional.of(targets.isRecipientTargeted()), - Optional.of(targets.isContentTargeted())); + targets.isSenderTargeted(), + targets.isRecipientTargeted(), + targets.isRecipientTargeted()); } + + private final String id; private final String expression; private final Optional<String> explanation; - private final Optional<Boolean> targetsSender; - private final Optional<Boolean> targetsRecipients; - private final Optional<Boolean> targetsContent; + private final boolean targetsSender; + private final boolean targetsRecipients; + private final boolean targetsContent; @JsonCreator public DLPConfigurationItemDTO(@JsonProperty("id") String id, @JsonProperty("expression") String expression, @JsonProperty("explanation") Optional<String> explanation, - @JsonProperty("targetsSender") Optional<Boolean> targetsSender, - @JsonProperty("targetsRecipients") Optional<Boolean> targetsRecipients, - @JsonProperty("targetsContent") Optional<Boolean> targetsContent) { + @JsonProperty("targetsSender") boolean targetsSender, + @JsonProperty("targetsRecipients") boolean targetsRecipients, + @JsonProperty("targetsContent") boolean targetsContent) { Preconditions.checkNotNull(id, "'id' is mandatory"); Preconditions.checkNotNull(expression, "'expression' is mandatory"); this.id = id; @@ -93,18 +82,30 @@ public class DLPConfigurationItemDTO { return explanation; } - public Optional<Boolean> getTargetsSender() { + public boolean getTargetsSender() { return targetsSender; } - public Optional<Boolean> getTargetsRecipients() { + public boolean getTargetsRecipients() { return targetsRecipients; } - public Optional<Boolean> getTargetsContent() { + public boolean getTargetsContent() { return targetsContent; } + @JsonIgnore + public DLPConfigurationItem toDLPConfiguration() { + return DLPConfigurationItem.builder() + .id(DLPConfigurationItem.Id.of(id)) + .expression(expression) + .explanation(explanation) + .targetsSender(targetsSender) + .targetsRecipients(targetsRecipients) + .targetsContent(targetsContent) + .build(); + } + @Override public final boolean equals(Object o) { if (o instanceof DLPConfigurationItemDTO) { http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DLPConfigurationRoutes.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DLPConfigurationRoutes.java b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DLPConfigurationRoutes.java index 73b1d33..c735337 100644 --- a/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DLPConfigurationRoutes.java +++ b/server/protocols/webadmin/webadmin-data/src/main/java/org/apache/james/webadmin/routes/DLPConfigurationRoutes.java @@ -46,11 +46,12 @@ import org.apache.james.webadmin.utils.JsonExtractor; import org.apache.james.webadmin.utils.JsonTransformer; import org.eclipse.jetty.http.HttpStatus; -import com.fasterxml.jackson.datatype.guava.GuavaModule; import com.github.steveash.guavate.Guavate; + import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @@ -59,6 +60,9 @@ import spark.Request; import spark.Service; @Api(tags = "DLPRules") +@ApiModel(description = "DLP (stands for Data Leak Prevention) is supported by James. A DLP matcher will, on incoming emails, " + + "execute regular expressions on email sender, recipients or content, in order to report suspicious emails to" + + "an administrator. WebAdmin can be used to manage these DLP rules on a per sender-domain basis.") @Path(DLPConfigurationRoutes.BASE_PATH) @Produces(JSON_CONTENT_TYPE) public class DLPConfigurationRoutes implements Routes { @@ -73,46 +77,47 @@ public class DLPConfigurationRoutes implements Routes { private final JsonExtractor<DLPConfigurationDTO> jsonExtractor; private final DomainList domainList; - private Service service; - @Inject public DLPConfigurationRoutes(DLPConfigurationStore dlpConfigurationStore, DomainList domainList, JsonTransformer jsonTransformer) { this.dlpConfigurationStore = dlpConfigurationStore; this.domainList = domainList; this.jsonTransformer = jsonTransformer; - this.jsonExtractor = new JsonExtractor<>(DLPConfigurationDTO.class, new GuavaModule()); + this.jsonExtractor = new JsonExtractor<>(DLPConfigurationDTO.class); } @Override public void define(Service service) { - this.service = service; - defineStore(); + defineStore(service); - defineList(); + defineList(service); - defineClear(); + defineClear(service); } @PUT @Path("/{senderDomain}") - @ApiOperation(value = "Store a list of dlp configs for given senderDomain") + @ApiOperation(value = "Store a DLP configuration for given senderDomain") @ApiImplicitParams({ - @ApiImplicitParam(required = true, dataType = "string", name = "senderDomain", paramType = "path") + @ApiImplicitParam(required = true, dataType = "string", name = "senderDomain", paramType = "path"), + @ApiImplicitParam(required = true, dataType = "org.apache.james.webadmin.dto.DLPConfigurationDTO", paramType = "body") }) @ApiResponses(value = { - @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. dlp config is stored."), - @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain or payload in request"), - @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. DLP configuration is stored."), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain or payload in request", + response = ErrorResponder.ErrorDetail.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist.", + response = ErrorResponder.ErrorDetail.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, - message = "Internal server error - Something went bad on the server side.") + message = "Internal server error - Something went bad on the server side.", + response = ErrorResponder.ErrorDetail.class) }) - public void defineStore() { + public void defineStore(Service service) { service.put(SPECIFIC_DLP_RULE_DOMAIN, (request, response) -> { Domain senderDomain = parseDomain(request); DLPConfigurationDTO dto = jsonExtractor.parse(request.body()); - dlpConfigurationStore.store(senderDomain, DLPConfigurationDTO.toDLPConfigurations(dto)); + dlpConfigurationStore.store(senderDomain, dto.toDLPConfigurations()); response.status(HttpStatus.NO_CONTENT_204); return EMPTY_BODY; @@ -121,18 +126,21 @@ public class DLPConfigurationRoutes implements Routes { @GET @Path("/{senderDomain}") - @ApiOperation(value = "Retrieve a list of dlp configs for given senderDomain") + @ApiOperation(value = "Return a DLP configuration for given senderDomain") @ApiImplicitParams({ @ApiImplicitParam(required = true, dataType = "string", name = "senderDomain", paramType = "path") }) @ApiResponses(value = { - @ApiResponse(code = HttpStatus.OK_200, message = "OK. dlp configs returned"), - @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain in request"), - @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.OK_200, message = "OK. DLP configuration is returned", response = DLPConfigurationDTO.class), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain in request", + response = ErrorResponder.ErrorDetail.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist.", + response = ErrorResponder.ErrorDetail.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, - message = "Internal server error - Something went bad on the server side.") + message = "Internal server error - Something went bad on the server side.", + response = ErrorResponder.ErrorDetail.class) }) - public void defineList() { + public void defineList(Service service) { service.get(SPECIFIC_DLP_RULE_DOMAIN, (request, response) -> { Domain senderDomain = parseDomain(request); List<DLPConfigurationItem> dlpConfigurations = dlpConfigurationStore @@ -148,18 +156,21 @@ public class DLPConfigurationRoutes implements Routes { @DELETE @Path("/{senderDomain}") - @ApiOperation(value = "Clear all dlp configs for given senderDomain") + @ApiOperation(value = "Clear a DLP configuration for a given senderDomain") @ApiImplicitParams({ @ApiImplicitParam(required = true, dataType = "string", name = "senderDomain", paramType = "path") }) @ApiResponses(value = { - @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. dlp configs are cleared"), - @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain in request"), - @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist."), + @ApiResponse(code = HttpStatus.NO_CONTENT_204, message = "OK. DLP configuration is cleared"), + @ApiResponse(code = HttpStatus.BAD_REQUEST_400, message = "Invalid senderDomain in request", + response = ErrorResponder.ErrorDetail.class), + @ApiResponse(code = HttpStatus.NOT_FOUND_404, message = "The domain does not exist.", + response = ErrorResponder.ErrorDetail.class), @ApiResponse(code = HttpStatus.INTERNAL_SERVER_ERROR_500, - message = "Internal server error - Something went bad on the server side.") + message = "Internal server error - Something went bad on the server side.", + response = ErrorResponder.ErrorDetail.class) }) - public void defineClear() { + public void defineClear(Service service) { service.delete(SPECIFIC_DLP_RULE_DOMAIN, (request, response) -> { Domain senderDomain = parseDomain(request); dlpConfigurationStore.clear(senderDomain); http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTOTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTOTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTOTest.java index a4b0da8..1c8f1f6 100644 --- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTOTest.java +++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/dto/DLPConfigurationItemDTOTest.java @@ -21,15 +21,12 @@ package org.apache.james.webadmin.dto; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import java.util.List; import java.util.Optional; import org.apache.james.dlp.api.DLPConfigurationItem; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; -import com.google.common.collect.ImmutableList; - class DLPConfigurationItemDTOTest { private static final String ID = "id"; @@ -39,41 +36,41 @@ class DLPConfigurationItemDTOTest { private static final String NULL_EXPRESSION = null; @Test - void toDTOsShouldBeSetAllFields() { + void toDTOsShouldSetAllFields() { DLPConfigurationItemDTO dto = DLPConfigurationItemDTO.toDTO( DLPConfigurationItem.builder() .id(DLPConfigurationItem.Id.of(ID)) .expression(EXPRESSION) .explanation(EXPLANATION) - .targetsSender(Optional.of(true)) - .targetsRecipients(Optional.of(true)) - .targetsContent(Optional.of(true)) + .targetsSender(true) + .targetsRecipients(true) + .targetsContent(true) .build()); SoftAssertions.assertSoftly(softly -> { softly.assertThat(dto.getId()).isEqualTo(ID); softly.assertThat(dto.getExpression()).isEqualTo(EXPRESSION); softly.assertThat(dto.getExplanation().get()).isEqualTo(EXPLANATION); - softly.assertThat(dto.getTargetsSender().get()).isTrue(); - softly.assertThat(dto.getTargetsRecipients().get()).isTrue(); - softly.assertThat(dto.getTargetsContent().get()).isTrue(); + softly.assertThat(dto.getTargetsSender()).isTrue(); + softly.assertThat(dto.getTargetsRecipients()).isTrue(); + softly.assertThat(dto.getTargetsContent()).isTrue(); }); } @Test - void toDLPConfigurationsShouldBeSetAllFields() { - DLPConfigurationItem item = DLPConfigurationItemDTO.toDLPConfiguration( - new DLPConfigurationItemDTO( - ID, - EXPRESSION, - Optional.of(EXPLANATION), - Optional.of(true), - Optional.of(true), - Optional.of(true))); + void toDLPConfigurationsShouldSetAllFields() { + DLPConfigurationItemDTO itemDTO = new DLPConfigurationItemDTO( + ID, + EXPRESSION, + Optional.of(EXPLANATION), + true, + true, + true); + DLPConfigurationItem item = itemDTO.toDLPConfiguration(); SoftAssertions.assertSoftly(softly -> { softly.assertThat(item.getId().asString()).isEqualTo(ID); - softly.assertThat(item.getRegexp()).isEqualTo(EXPRESSION); + softly.assertThat(item.getRegexp().pattern()).isEqualTo(EXPRESSION); softly.assertThat(item.getExplanation().get()).isEqualTo(EXPLANATION); softly.assertThat(item.getTargets().isSenderTargeted()).isTrue(); softly.assertThat(item.getTargets().isRecipientTargeted()).isTrue(); @@ -86,9 +83,9 @@ class DLPConfigurationItemDTOTest { assertThatThrownBy(() -> new DLPConfigurationItemDTO(NULL_ID, EXPRESSION, Optional.of(EXPLANATION), - Optional.of(true), - Optional.of(true), - Optional.of(true))) + true, + true, + true)) .isInstanceOf(NullPointerException.class); } @@ -97,9 +94,9 @@ class DLPConfigurationItemDTOTest { assertThatThrownBy(() -> new DLPConfigurationItemDTO(ID, NULL_EXPRESSION, Optional.of(EXPLANATION), - Optional.of(true), - Optional.of(true), - Optional.of(true))) + true, + true, + true)) .isInstanceOf(NullPointerException.class); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DLPConfigurationRoutesTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DLPConfigurationRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DLPConfigurationRoutesTest.java index 74d3468..49b6614 100644 --- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DLPConfigurationRoutesTest.java +++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/DLPConfigurationRoutesTest.java @@ -31,10 +31,8 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import java.net.InetAddress; -import java.util.List; import org.apache.james.core.Domain; -import org.apache.james.dlp.api.DLPConfigurationItem; import org.apache.james.dlp.api.DLPConfigurationStore; import org.apache.james.dlp.eventsourcing.EventSourcingDLPConfigurationStore; import org.apache.james.dnsservice.api.DNSService; @@ -42,7 +40,6 @@ import org.apache.james.domainlist.api.DomainList; import org.apache.james.domainlist.memory.MemoryDomainList; import org.apache.james.eventsourcing.eventstore.memory.InMemoryEventStore; import org.apache.james.metrics.logger.DefaultMetricFactory; -import org.apache.james.webadmin.DLPModule; import org.apache.james.webadmin.WebAdminServer; import org.apache.james.webadmin.WebAdminUtils; import org.apache.james.webadmin.utils.JsonTransformer; @@ -52,7 +49,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import com.google.common.collect.ImmutableList; import com.jayway.restassured.RestAssured; import com.jayway.restassured.http.ContentType; import com.jayway.restassured.specification.RequestSpecification; @@ -64,35 +60,13 @@ class DLPConfigurationRoutesTest { private static final String DOMAIN_2 = "apache.org"; private static final Domain SENDER_DOMAIN_2 = Domain.of(DOMAIN_2); - private static final DLPConfigurationItem CONFIGURATION_ITEM_1 = DLPConfigurationItem.builder() - .id(DLPConfigurationItem.Id.of("1")) - .explanation("explanation 1") - .expression(DEFAULT_DOMAIN) - .targetsSender() - .targetsRecipients() - .targetsContent() - .build(); - private static final DLPConfigurationItem CONFIGURATION_ITEM_2 = DLPConfigurationItem.builder() - .id(DLPConfigurationItem.Id.of("2")) - .expression(DEFAULT_DOMAIN) - .targetsSender() - .build(); - - private static final List<DLPConfigurationItem> CONFIGURATION_ITEMS_FOR_DOMAIN_2 = ImmutableList.of(DLPConfigurationItem.builder() - .id(DLPConfigurationItem.Id.of("3")) - .expression(DOMAIN_2) - .targetsSender() - .build()); - - private static final List<DLPConfigurationItem> CONFIGURATION_ITEMS = ImmutableList.of(CONFIGURATION_ITEM_1, CONFIGURATION_ITEM_2); - private WebAdminServer webAdminServer; private EventSourcingDLPConfigurationStore dlpStore; private void createServer(DLPConfigurationStore dlpConfigurationStore, DomainList domainList) throws Exception { webAdminServer = WebAdminUtils.createWebAdminServer( new DefaultMetricFactory(), - new DLPConfigurationRoutes(dlpConfigurationStore, domainList, new JsonTransformer(new DLPModule()))); + new DLPConfigurationRoutes(dlpConfigurationStore, domainList, new JsonTransformer())); webAdminServer.configure(NO_CONFIGURATION); webAdminServer.await(); @@ -247,13 +221,13 @@ class DLPConfigurationRoutesTest { @Test void putShouldReturnBadRequestWhenIdIsNotSpecified() { String body = - "{" + + "{\"rules\": [{" + " \"expression\": \"expression 4\"," + " \"explanation\": \"explanation 4\"," + " \"targetsSender\": false," + " \"targetsRecipients\": false," + " \"targetsContent\": false" + - "}"; + "}]}"; given() .body(body) @@ -264,19 +238,20 @@ class DLPConfigurationRoutesTest { .contentType(JSON_CONTENT_TYPE) .body("statusCode", is(400)) .body("type", is("InvalidArgument")) - .body("message", is("JSON payload of the request is not valid")); + .body("message", is("JSON payload of the request is not valid")) + .body("details", is("Instantiation of [simple type, class org.apache.james.webadmin.dto.DLPConfigurationItemDTO] value failed: 'id' is mandatory (through reference chain: org.apache.james.webadmin.dto.DLPConfigurationDTO[\"rules\"])")); } @Test void putShouldReturnBadRequestWhenExpressionIsNotSpecified() { String body = - "{" + + "{\"rules\": [{" + " \"id\": \"5\"," + " \"explanation\": \"explanation 5\"," + " \"targetsSender\": false," + " \"targetsRecipients\": false," + " \"targetsContent\": false" + - "}"; + "}]}"; given() .body(body) @@ -287,7 +262,8 @@ class DLPConfigurationRoutesTest { .contentType(JSON_CONTENT_TYPE) .body("statusCode", is(400)) .body("type", is("InvalidArgument")) - .body("message", is("JSON payload of the request is not valid")); + .body("message", is("JSON payload of the request is not valid")) + .body("details", is("Instantiation of [simple type, class org.apache.james.webadmin.dto.DLPConfigurationItemDTO] value failed: 'expression' is mandatory (through reference chain: org.apache.james.webadmin.dto.DLPConfigurationDTO[\"rules\"])")); } @Test @@ -351,7 +327,8 @@ class DLPConfigurationRoutesTest { .contentType(JSON_CONTENT_TYPE) .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) .body("type", is("InvalidArgument")) - .body("message", is("Invalid request for domain: [email protected]")); + .body("message", is("Invalid request for domain: [email protected]")) + .body("details", is("Domain can not be empty nor contain `@`")); } } @@ -360,7 +337,31 @@ class DLPConfigurationRoutesTest { @Test void deleteShouldRemoveTheConfigurations() { - dlpStore.store(SENDER_DOMAIN, CONFIGURATION_ITEMS); + String storeBody = + "{\"rules\": [" + + " {" + + " \"id\": \"1\"," + + " \"expression\": \"expression 1\"," + + " \"explanation\": \"explanation 1\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": true," + + " \"targetsContent\": true" + + " }," + + " {" + + " \"id\": \"2\"," + + " \"expression\": \"expression 2\"," + + " \"explanation\": \"explanation 2\"," + + " \"targetsSender\": false," + + " \"targetsRecipients\": false," + + " \"targetsContent\": false" + + " }]}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); when() .delete(DEFAULT_DOMAIN) @@ -380,8 +381,48 @@ class DLPConfigurationRoutesTest { @Test void deleteShouldRemoveOnlyConfigurationsFromCorrespondingDomain() { - dlpStore.store(SENDER_DOMAIN, CONFIGURATION_ITEMS); - dlpStore.store(SENDER_DOMAIN_2, CONFIGURATION_ITEMS_FOR_DOMAIN_2); + String storeBody = + "{\"rules\": [" + + " {" + + " \"id\": \"1\"," + + " \"expression\": \"expression 1\"," + + " \"explanation\": \"explanation 1\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": true," + + " \"targetsContent\": true" + + " }," + + " {" + + " \"id\": \"2\"," + + " \"expression\": \"expression 2\"," + + " \"explanation\": \"explanation 2\"," + + " \"targetsSender\": false," + + " \"targetsRecipients\": false," + + " \"targetsContent\": false" + + " }]}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); + + + String storeDomain2Body = + "{\"rules\": [" + + " {" + + " \"id\": \"3\"," + + " \"expression\": \"apache.org\"," + + " \"targetsSender\": true" + + " }" + + "]}"; + + given() + .body(storeDomain2Body) + .when() + .put(DOMAIN_2) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); when() .delete(DEFAULT_DOMAIN) @@ -441,7 +482,8 @@ class DLPConfigurationRoutesTest { .contentType(JSON_CONTENT_TYPE) .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) .body("type", is("InvalidArgument")) - .body("message", is("Invalid request for domain: [email protected]")); + .body("message", is("Invalid request for domain: [email protected]")) + .body("details", is("Domain can not be empty nor contain `@`")); } } @@ -450,7 +492,24 @@ class DLPConfigurationRoutesTest { @Test void getShouldReturnOK() { - dlpStore.store(SENDER_DOMAIN, CONFIGURATION_ITEMS); + String storeBody = + "{\"rules\": [" + + " {" + + " \"id\": \"1\"," + + " \"expression\": \"expression 1\"," + + " \"explanation\": \"explanation 1\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": true," + + " \"targetsContent\": true" + + " }" + + "]}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); when() .get(DEFAULT_DOMAIN) @@ -461,7 +520,31 @@ class DLPConfigurationRoutesTest { @Test void getShouldReturnABody() { - dlpStore.store(SENDER_DOMAIN, CONFIGURATION_ITEMS); + String storeBody = + "{\"rules\": [" + + " {" + + " \"id\": \"1\"," + + " \"expression\": \"james.org\"," + + " \"explanation\": \"explanation 1\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": true," + + " \"targetsContent\": true" + + " }," + + " {" + + " \"id\": \"2\"," + + " \"expression\": \"james.org\"," + + " \"explanation\": \"explanation 2\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": false," + + " \"targetsContent\": false" + + " }]}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); String body = when() .get(DEFAULT_DOMAIN) @@ -485,7 +568,7 @@ class DLPConfigurationRoutesTest { " {" + " \"id\": \"2\"," + " \"expression\": \"james.org\"," + - " \"explanation\": null," + + " \"explanation\": \"explanation 2\"," + " \"targetsSender\": true," + " \"targetsRecipients\": false," + " \"targetsContent\": false" + @@ -495,7 +578,14 @@ class DLPConfigurationRoutesTest { @Test void getShouldReturnAnEmptyBodyWhenDLPStoreIsEmpty() { - dlpStore.store(SENDER_DOMAIN, ImmutableList.of()); + String storeBody = "{\"rules\": []}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); String body = when() .get(DEFAULT_DOMAIN) @@ -511,8 +601,48 @@ class DLPConfigurationRoutesTest { @Test void getShouldReturnOnlyConfigurationsFromCorrespondingDomain() { - dlpStore.store(SENDER_DOMAIN, CONFIGURATION_ITEMS); - dlpStore.store(SENDER_DOMAIN_2, CONFIGURATION_ITEMS_FOR_DOMAIN_2); + String storeBody = + "{\"rules\": [" + + " {" + + " \"id\": \"1\"," + + " \"expression\": \"james.org\"," + + " \"explanation\": \"explanation 1\"," + + " \"targetsSender\": true," + + " \"targetsRecipients\": true," + + " \"targetsContent\": true" + + " }," + + " {" + + " \"id\": \"2\"," + + " \"expression\": \"james.org\"," + + " \"explanation\": \"explanation 2\"," + + " \"targetsSender\": false," + + " \"targetsRecipients\": false," + + " \"targetsContent\": false" + + " }]}"; + + given() + .body(storeBody) + .when() + .put(DEFAULT_DOMAIN) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); + + + String storeDomain2Body = + "{\"rules\": [" + + " {" + + " \"id\": \"3\"," + + " \"expression\": \"apache.org\"," + + " \"targetsSender\": true" + + " }" + + "]}"; + + given() + .body(storeDomain2Body) + .when() + .put(DOMAIN_2) + .then() + .statusCode(HttpStatus.NO_CONTENT_204); String body = when() .get(DEFAULT_DOMAIN) @@ -536,8 +666,8 @@ class DLPConfigurationRoutesTest { " {" + " \"id\": \"2\"," + " \"expression\": \"james.org\"," + - " \"explanation\": null," + - " \"targetsSender\": true," + + " \"explanation\": \"explanation 2\"," + + " \"targetsSender\": false," + " \"targetsRecipients\": false," + " \"targetsContent\": false" + " }" + @@ -565,7 +695,8 @@ class DLPConfigurationRoutesTest { .contentType(JSON_CONTENT_TYPE) .body("statusCode", is(HttpStatus.BAD_REQUEST_400)) .body("type", is("InvalidArgument")) - .body("message", is("Invalid request for domain: [email protected]")); + .body("message", is("Invalid request for domain: [email protected]")) + .body("details", is("Domain can not be empty nor contain `@`")); } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/55cd111c/src/site/markdown/server/manage-webadmin.md ---------------------------------------------------------------------- diff --git a/src/site/markdown/server/manage-webadmin.md b/src/site/markdown/server/manage-webadmin.md index 1a574d3..7ba63af 100644 --- a/src/site/markdown/server/manage-webadmin.md +++ b/src/site/markdown/server/manage-webadmin.md @@ -33,6 +33,7 @@ In case of any error, the system will return an error message which is json form - [Creating address forwards](#Creating_address_forwards) - [Administrating mail repositories](#Administrating_mail_repositories) - [Administrating mail queues](#Administrating_mail_queues) + - [Administrating DLP Configuration](#Administrating_dlp_configuration) - [Task management](#Task_management) ## Administrating domains @@ -1754,6 +1755,120 @@ Response codes: - 404: The mail queue does not exist - 500: Internal error +## Administrating DLP Configuration + +DLP (stands for Data Leak Prevention) is supported by James. A DLP matcher will, on incoming emails, +execute regular expressions on email sender, recipients or content, in order to report suspicious emails to +an administrator. WebAdmin can be used to manage these DLP rules on a per `senderDomain` basis. + +`senderDomain` is domain of the sender of incoming emails, for example: `apache.org`, `james.org`,... +Each `senderDomain` correspond to a distinct DLP configuration. + +- [List DLP configuration by sender domain](List_dlp_configuration_by_sender_domain) +- [Store DLP configuration by sender domain](Store_dlp_configuration_by_sender_domain) +- [Remove DLP configuration by sender domain](Remove_dlp_configuration_by_sender_domain) + +### List DLP configuration by sender domain + +Retrieve a DLP configuration for corresponding `senderDomain`, a configuration contains list of configuration items + +``` +curl -XGET http://ip:port/dlp/rules/senderDomain +``` + +Response codes: + + - 200: A list of dlp configuration items is returned + - 400: Invalid senderDomain or payload in request + - 404: The domain does not exist. + - 500: Internal error + +This is an example of returned body. The rules field is a list of rules as described below. + +``` +{"rules : [ + { + "id": "1", + "expression": "james.org", + "explanation": "Find senders or recipients containing james[any char]org", + "targetsSender": true, + "targetsRecipients": true, + "targetsContent": false + }, + { + "id": "2", + "expression": "Find senders containing apache[any char]org", + "explanation": "apache.org", + "targetsSender": true, + "targetsRecipients": false, + "targetsContent": false + } +]} +``` + +### Store DLP configuration by sender domain + +Store a DLP configuration for corresponding `senderDomain`, if any item of DLP configuration in the request is stored before, +it will not be stored anymore + +``` +curl -XPUT http://ip:port/dlp/rules/senderDomain +``` + +The body can contain a list of DLP configuration items formed by those fields: +- `id`(String) is mandatory, unique identifier of the configuration item +- `expression`(String) is mandatory, regular expression to match contents of targets +- `explanation`(String) is optional, description of the configuration item +- `targetsSender`(boolean) is optional and defaults to false. If true, `expression` will be applied to Sender and to From headers of the mail +- `targetsContent`(boolean) is optional and defaults to false. If true, `expression` will be applied to Subject headers and textual bodies (text/plain and text/html) of the mail +- `targetsRecipients`(boolean) is optional and defaults to false. If true, `expression` will be applied to recipients of the mail + +This is an example of returned body. The rules field is a list of rules as described below. + +``` +{"rules": [ + { + "id": "1", + "expression": "james.org", + "explanation": "Find senders or recipients containing james[any char]org", + "targetsSender": true, + "targetsRecipients": true, + "targetsContent": false + }, + { + "id": "2", + "expression": "Find senders containing apache[any char]org", + "explanation": "apache.org", + "targetsSender": true, + "targetsRecipients": false, + "targetsContent": false + } +]} +``` + +Response codes: + + - 204: List of dlp configuration items is stored + - 400: Invalid senderDomain or payload in request + - 404: The domain does not exist. + - 500: Internal error + +### Remove DLP configuration by sender domain + +Remove a DLP configuration for corresponding `senderDomain` + +``` +curl -XDELETE http://ip:port/dlp/rules/senderDomain +``` + +Response codes: + + - 204: DLP configuration is removed + - 400: Invalid senderDomain or payload in request + - 404: The domain does not exist. + - 500: Internal error + + ## Task management Some webadmin features schedules tasks. The task management API allow to monitor and manage the execution of the following tasks. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
