forked from OpenIdentityPlatform/OpenIG
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ICAP Filter for DLP and Antivirus protection (OpenIdentityPlatform#29)
{ "type": "ConditionalFilter", "config": { "condition": "${not empty system['icap'] and (request.method == 'POST' or request.method == 'PUT')}", "delegate": { "type": "ICAP", "name": "icap-dlp", "config": { "server": "${system['icap']}", "service": "${empty system['icap.service'] ? '' : system['icap.service']}", "rewrite": "${empty system['icap.rewrite'] ? 'true' : system['icap.rewrite']}", "connect_timeout": "${empty system['icap.connect_timeout'] ? '5000' : system['icap.connect_timeout']}", "read_timeout": "${empty system['icap.read_timeout'] ? '20000' : system['icap.read_timeout']}" } } } }
- Loading branch information
Showing
9 changed files
with
205 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,3 @@ | ||
[submodule "OpenDJ"] | ||
path = OpenDJ | ||
url = https://github.com/OpenIdentityPlatform/OpenDJ | ||
[submodule "OpenAM"] | ||
path = OpenAM | ||
url = https://github.com/OpenIdentityPlatform/OpenAM | ||
[submodule "openig-core/icap-client"] | ||
path = openig-core/icap-client | ||
url = https://github.com/OpenIdentityPlatform/icap-client.git |
Submodule icap-client
added at
5e7d6d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
openig-core/src/main/java/org/openidentityplatform/openig/filter/ICAPFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package org.openidentityplatform.openig.filter; | ||
|
||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.util.List; | ||
import java.util.Map.Entry; | ||
|
||
import org.forgerock.http.Filter; | ||
import org.forgerock.http.Handler; | ||
import org.forgerock.http.protocol.Request; | ||
import org.forgerock.http.protocol.Response; | ||
import org.forgerock.http.protocol.Status; | ||
import org.forgerock.openig.heap.GenericHeaplet; | ||
import org.forgerock.openig.heap.HeapException; | ||
import org.forgerock.services.context.Context; | ||
import org.forgerock.util.promise.NeverThrowsException; | ||
import org.forgerock.util.promise.Promise; | ||
import org.forgerock.util.promise.Promises; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import net.rfc3507.client.ICAPClient; | ||
import net.rfc3507.client.ICAPException; | ||
import net.rfc3507.client.ICAPRequest; | ||
import net.rfc3507.client.ICAPRequest.Mode; | ||
import net.rfc3507.client.ICAPResponse; | ||
|
||
public class ICAPFilter implements Filter { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(ICAPFilter.class); | ||
|
||
ICAPClient icap=null; | ||
String service=null; | ||
Boolean rewrite=true; | ||
|
||
public static class Heaplet extends GenericHeaplet { | ||
|
||
ICAPFilter filter; | ||
|
||
@Override | ||
public Object create() throws HeapException { | ||
filter=new ICAPFilter(); | ||
return filter; | ||
} | ||
|
||
@Override | ||
public void start() throws HeapException { | ||
super.start(); | ||
String server=config.get("server").required().as(expression(String.class)).eval(); | ||
|
||
if (server==null || server.trim().isEmpty()) { | ||
logger.debug("server is empty"); | ||
return; | ||
} | ||
try { | ||
final URI uri=new URI(server); | ||
filter.icap=new ICAPClient(uri.getHost(), uri.getPort()>0?uri.getPort():1344); | ||
filter.icap.setConnectTimeout(Integer.parseInt(config.get("connect_timeout").defaultTo("5000").as(expression(String.class)).eval())); | ||
filter.icap.setReadTimeout(Integer.parseInt(config.get("read_timeout").defaultTo("15000").as(expression(String.class)).eval())); | ||
filter.service=config.get("service").defaultTo("").as(expression(String.class)).eval(); | ||
filter.rewrite=Boolean.parseBoolean(config.get("rewrite").defaultTo("true").as(expression(String.class)).eval()); | ||
logger.info("start {} connect_timeout={} read_timeout={}",uri,filter.icap.getConnectTimeout(),filter.icap.getReadTimeout()); | ||
} catch (URISyntaxException e) { | ||
logger.warn("invalid server format: \"{}\" use icap://server:port",server); | ||
} | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
super.destroy(); | ||
if (filter.icap!=null) { | ||
filter.icap=null; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public Promise<Response, NeverThrowsException> filter(Context context, Request request, Handler next) { | ||
if (icap!=null && !request.getEntity().isRawContentEmpty()) { | ||
final ICAPRequest req=new ICAPRequest(service, Mode.REQMOD); | ||
try { | ||
req.setHttpRequestBody(request.getEntity().getBytes()); | ||
final ICAPResponse res=icap.execute(req); | ||
if (res.getStatus()==204) { //allow content | ||
return next.handle(context, request); | ||
}else if (res.getStatus()==200) { //modify response | ||
request.getHeaders().add("x-icap-status", ""+res.getStatus()); | ||
request.getHeaders().add("x-icap-message", res.getMessage()); | ||
for (Entry<String, List<String>> header : res.getHeaderEntries().entrySet()) { | ||
request.getHeaders().add(header.getKey(), header.getValue()); | ||
} | ||
if (rewrite) { | ||
final ICAPResponse.ResponseHeader responseHeader=res.getResponseHeader(); | ||
final Response response = new Response(Status.valueOf(responseHeader.getStatus(), responseHeader.getMessage())); | ||
for (Entry<String, List<String>> header : responseHeader.getHeaderEntries().entrySet()) { | ||
response.getHeaders().add(header.getKey(), header.getValue()); | ||
} | ||
response.setEntity(res.getHttpShrinkResponseBody()); | ||
return Promises.newResultPromise(response); | ||
} | ||
}else { //ignore error | ||
logger.error("{}",res); | ||
} | ||
}catch (ICAPException e) { | ||
logger.error("{}",e.toString()); | ||
}catch (IOException e) { | ||
logger.warn("{}",e.toString()); | ||
} | ||
} | ||
return next.handle(context, request); | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
openig-core/src/test/java/org/openidentityplatform/openig/icap/ICAP_Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package org.openidentityplatform.openig.icap; | ||
|
||
import java.io.IOException; | ||
|
||
import org.forgerock.openig.heap.HeapException; | ||
import org.junit.Test; | ||
|
||
import net.rfc3507.client.ICAPClient; | ||
import net.rfc3507.client.ICAPException; | ||
import net.rfc3507.client.ICAPRequest; | ||
import net.rfc3507.client.ICAPRequest.Mode; | ||
import net.rfc3507.client.ICAPResponse; | ||
|
||
|
||
public class ICAP_Test { | ||
|
||
|
||
@Test | ||
public void test() throws HeapException, IOException { | ||
try { | ||
final ICAPClient client=new ICAPClient("localhost", 1344); | ||
final ICAPRequest request=new ICAPRequest("srv_clamav", Mode.REQMOD); | ||
request.setHttpRequestBody(new String("X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*").getBytes()); | ||
final ICAPResponse response=client.execute(request); | ||
System.out.println(new String(response.getHttpRawResponseBody())); | ||
}catch (ICAPException e) { | ||
// # start service - after start you can use the java library | ||
// docker run --rm --name icap-server -p 1344:1344 toolarium/toolarium-icap-calmav-docker:0.0.1 | ||
// | ||
// # optional you can login into the container | ||
// docker exec -it icap-server /bin/bash | ||
// | ||
// # the configuration you will see under | ||
// more /etc/c-icap/c-icap.conf | ||
// | ||
// # view / tail access-log | ||
// tail -f /var/log/c-icap/access.log | ||
// | ||
// # view / tail server-log | ||
// tail -f /var/log/c-icap/server.log | ||
// | ||
// # test with c-icap client inside the container | ||
// c-icap-client -v -f entrypoint.sh -s "srv_clamav" -w 1024 -req http://request -d 5 | ||
// | ||
// # stop service | ||
// docker stop icap-server | ||
} | ||
|
||
} | ||
|
||
} |