Skip to content

Commit

Permalink
RESTful Forward Rule: Replace Target Base URL and Keycloak Server ID …
Browse files Browse the repository at this point in the history
…by Web Application name dcm4che#1924
  • Loading branch information
vrindanayak committed Apr 12, 2019
1 parent 42f526c commit f23c766
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2071,8 +2071,9 @@ objectclass ( 1.2.40.0.13.1.15.110.4.25 NAME 'dcmRSForwardRule'
SUP top STRUCTURAL
MUST (
cn $
dcmURI )
dcmWebAppName )
MAY (
dcmURI $
dcmKeycloakServerID $
dcmTLSAllowAnyHostname $
dcmTLSDisableTrustManager $
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -700,9 +700,8 @@ private static void writeRSForwardRules(JsonWriter writer, Collection<RSForwardR
for (RSForwardRule rule : rules) {
writer.writeStartObject();
writer.writeNotNullOrDef("cn", rule.getCommonName(), null);
writer.writeNotNullOrDef("dcmURI", rule.getBaseURI(), null);
writer.writeNotNullOrDef("dcmWebAppName", rule.getWebAppName(), null);
writer.writeNotEmpty("dcmRSOperation", rule.getRSOperations());
writer.writeNotNullOrDef("dcmKeycloakServerID", rule.getKeycloakServerID(), null);
writer.writeNotDef("dcmTLSAllowAnyHostname", rule.isTlsAllowAnyHostname(), false);
writer.writeNotDef("dcmTLSDisableTrustManager", rule.isTlsDisableTrustManager(), false);
writer.writeNotNullOrDef("dcmURIPattern", rule.getRequestURLPattern(), null);
Expand Down Expand Up @@ -2323,15 +2322,12 @@ private static void loadRSForwardRules(Collection<RSForwardRule> rules, JsonRead
case "cn":
rule.setCommonName(reader.stringValue());
break;
case "dcmURI":
rule.setBaseURI(reader.stringValue());
case "dcmWebAppName":
rule.setWebAppName(reader.stringValue());
break;
case "dcmRSOperation":
rule.setRSOperations(reader.enumArray(RSOperation.class));
break;
case "dcmKeycloakServerID":
rule.setKeycloakServerID(reader.stringValue());
break;
case "dcmTLSAllowAnyHostname":
rule.setTlsAllowAnyHostname(reader.booleanValue());
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2796,9 +2796,8 @@ private static Attributes storeTo(ConfigurationChanges.ModifiedObject ldapObj, H
private Attributes storeTo(ConfigurationChanges.ModifiedObject ldapObj, RSForwardRule rule, BasicAttributes attrs) {
attrs.put("objectclass", "dcmRSForwardRule");
attrs.put("cn", rule.getCommonName());
LdapUtils.storeNotNullOrDef(ldapObj, attrs, "dcmURI", rule.getBaseURI(), null);
LdapUtils.storeNotNullOrDef(ldapObj, attrs, "dcmWebAppName", rule.getWebAppName(), null);
LdapUtils.storeNotEmpty(ldapObj, attrs, "dcmRSOperation", rule.getRSOperations());
LdapUtils.storeNotNullOrDef(ldapObj, attrs, "dcmKeycloakServerID", rule.getKeycloakServerID(), null);
LdapUtils.storeNotDef(ldapObj, attrs, "dcmTLSAllowAnyHostname", rule.isTlsAllowAnyHostname(), false);
LdapUtils.storeNotDef(ldapObj, attrs, "dcmTLSDisableTrustManager", rule.isTlsDisableTrustManager(), false);
LdapUtils.storeNotNullOrDef(ldapObj, attrs, "dcmURIPattern", rule.getRequestURLPattern(), null);
Expand Down Expand Up @@ -2966,9 +2965,8 @@ private void loadRSForwardRules(Collection<RSForwardRule> rules, String parentDN
SearchResult sr = ne.next();
Attributes attrs = sr.getAttributes();
RSForwardRule rule = new RSForwardRule(LdapUtils.stringValue(attrs.get("cn"), null));
rule.setBaseURI(LdapUtils.stringValue(attrs.get("dcmURI"), null));
rule.setWebAppName(LdapUtils.stringValue(attrs.get("dcmWebAppName"), null));
rule.setRSOperations(LdapUtils.enumArray(RSOperation.class, attrs.get("dcmRSOperation")));
rule.setKeycloakServerID(LdapUtils.stringValue(attrs.get("dcmKeycloakServerID"), null));
rule.setTlsAllowAnyHostname(LdapUtils.booleanValue(attrs.get("dcmTLSAllowAnyHostname"), false));
rule.setTlsDisableTrustManager(LdapUtils.booleanValue(attrs.get("dcmTLSDisableTrustManager"), false));
rule.setRequestURLPattern(LdapUtils.stringValue(attrs.get("dcmURIPattern"), null));
Expand Down Expand Up @@ -3375,10 +3373,8 @@ private static List<ModificationItem> storeDiffs(
private List<ModificationItem> storeDiffs(
ConfigurationChanges.ModifiedObject ldapObj, RSForwardRule prev, RSForwardRule rule,
ArrayList<ModificationItem> mods) {
LdapUtils.storeDiffObject(ldapObj, mods, "dcmURI", prev.getBaseURI(), rule.getBaseURI(), null);
LdapUtils.storeDiffObject(ldapObj, mods, "dcmWebAppName", prev.getWebAppName(), rule.getWebAppName(), null);
LdapUtils.storeDiff(ldapObj, mods, "dcmRSOperation", prev.getRSOperations(), rule.getRSOperations());
LdapUtils.storeDiffObject(ldapObj, mods, "dcmKeycloakServerID", prev.getKeycloakServerID(),
rule.getKeycloakServerID(), null);
LdapUtils.storeDiffObject(ldapObj, mods, "dcmURIPattern", prev.getRequestURLPattern(),
rule.getRequestURLPattern(), null);
LdapUtils.storeDiff(ldapObj, mods, "dcmTLSAllowAnyHostname",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* The Initial Developer of the Original Code is
* J4Care.
* Portions created by the Initial Developer are Copyright (C) 2016
* Portions created by the Initial Developer are Copyright (C) 2016-2019
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
Expand Down Expand Up @@ -54,12 +54,10 @@ public class RSForwardRule {

private String commonName;

private String baseURI;
private String webAppName;

private EnumSet<RSOperation> rsOperations = EnumSet.noneOf(RSOperation.class);

private String keycloakServerID;

private boolean ifNotRequestURLPattern;

private Pattern requestURLPattern;
Expand All @@ -83,12 +81,12 @@ public void setCommonName(String commonName) {
this.commonName = commonName;
}

public String getBaseURI() {
return baseURI;
public String getWebAppName() {
return webAppName;
}

public void setBaseURI(String baseURI) {
this.baseURI = baseURI;
public void setWebAppName(String webAppName) {
this.webAppName = webAppName;
}

public RSOperation[] getRSOperations() {
Expand All @@ -100,14 +98,6 @@ public void setRSOperations(RSOperation[] rsOperations) {
this.rsOperations.addAll(Arrays.asList(rsOperations));
}

public String getKeycloakServerID() {
return keycloakServerID;
}

public void setKeycloakServerID(String keycloakServerID) {
this.keycloakServerID = keycloakServerID;
}

public boolean isTlsAllowAnyHostname() {
return tlsAllowAnyHostname;
}
Expand Down Expand Up @@ -159,7 +149,7 @@ public boolean match(RSOperation rsOperation, HttpServletRequest request) {
public String toString() {
return "RSForwardRule{" +
"cn='" + commonName + '\'' +
", baseURI='" + baseURI + '\'' +
", webAppName='" + webAppName + '\'' +
", ops=" + rsOperations +
'}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ public void mergePatients(@PathParam("patientID") IDWithIssuer patientID, InputS
for (Attributes otherPID : attrs.getSequence(Tag.OtherPatientIDsSequence))
mergePatient(patientID, otherPID);

rsForward.forwardMergeMultiplePatients(RSOperation.MergePatients, arcAE, baos.toByteArray(), request);
rsForward.forward(RSOperation.MergePatients, arcAE, baos.toByteArray(), null, request);
} catch (JsonParsingException e) {
throw new WebApplicationException(
errResponse(e.getMessage() + " at location : " + e.getLocation(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* The Initial Developer of the Original Code is
* J4Care.
* Portions created by the Initial Developer are Copyright (C) 2015-2018
* Portions created by the Initial Developer are Copyright (C) 2015-2019
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
Expand All @@ -42,8 +42,7 @@
package org.dcm4chee.arc.keycloak;

import org.dcm4che3.net.Device;
import org.dcm4chee.arc.conf.ArchiveDeviceExtension;
import org.dcm4chee.arc.conf.KeycloakServer;
import org.dcm4che3.net.KeycloakClient;
import org.dcm4chee.arc.event.ArchiveServiceEvent;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.admin.client.Keycloak;
Expand Down Expand Up @@ -71,8 +70,8 @@ public void onArchiveServiceEvent(@Observes ArchiveServiceEvent event) {
cachedKeycloak = null;
}

public String getAccessTokenString(String keycloakServerID) throws Exception {
return getAccessTokenString(toCachedKeycloak(keycloakServerID));
public String getAccessTokenString(String keycloakClientID) throws Exception {
return getAccessTokenString(toCachedKeycloak(keycloakClientID));
}

private String getAccessTokenString(CachedKeycloak tmp) {
Expand All @@ -86,23 +85,25 @@ public AccessToken getAccessToken(String keycloakServerID) throws Exception {
tmp.keycloak.tokenManager().getAccessToken().getExpiresIn());
}

private CachedKeycloak toCachedKeycloak(String keycloakServerID) throws Exception {
private CachedKeycloak toCachedKeycloak(String keycloakClientID) throws Exception {
CachedKeycloak tmp = cachedKeycloak;
if (tmp == null || !tmp.keycloakServerID.equals(keycloakServerID)) {
KeycloakServer server = device.getDeviceExtensionNotNull(ArchiveDeviceExtension.class)
.getKeycloakServerNotNull(keycloakServerID);
cachedKeycloak = tmp = new CachedKeycloak(keycloakServerID, KeycloakBuilder.builder()
.serverUrl(server.getServerURL())
.realm(server.getRealm())
.clientId(server.getClientID())
.clientSecret(server.getClientSecret())
.username(server.getUserID())
.password(server.getPassword())
.grantType(server.getGrantType().name())
if (tmp == null || !tmp.keycloakClientID.equals(keycloakClientID)) {
KeycloakClient keycloakClient = device.getKeycloakClient(keycloakClientID);
if (keycloakClient == null)
throw new IllegalArgumentException("No Keycloak Client configured with ID:" + keycloakClientID);

cachedKeycloak = tmp = new CachedKeycloak(keycloakClientID, KeycloakBuilder.builder()
.serverUrl(keycloakClient.getKeycloakServerURL())
.realm(keycloakClient.getKeycloakRealm())
.clientId(keycloakClient.getKeycloakClientID())
.clientSecret(keycloakClient.getKeycloakClientSecret())
.username(keycloakClient.getUserID())
.password(keycloakClient.getPassword())
.grantType(keycloakClient.getKeycloakGrantType().name())
.resteasyClient(resteasyClientBuilder(
server.getServerURL(),
server.isTlsAllowAnyHostname(),
server.isTlsDisableTrustManager())
keycloakClient.getKeycloakServerURL(),
keycloakClient.isTLSAllowAnyHostname(),
keycloakClient.isTLSDisableTrustManager())
.build())
.build());
}
Expand All @@ -124,11 +125,11 @@ public ResteasyClientBuilder resteasyClientBuilder(
}

private static class CachedKeycloak {
final String keycloakServerID;
final String keycloakClientID;
final Keycloak keycloak;

CachedKeycloak(String keycloakServerID, Keycloak keycloak) {
this.keycloakServerID = keycloakServerID;
CachedKeycloak(String keycloakClientID, Keycloak keycloak) {
this.keycloakClientID = keycloakClientID;
this.keycloak = keycloak;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ void scheduleRequest(
String method,
String uri,
byte[] content,
String keycloakServerID,
String keycloakClientID,
boolean tlsAllowAnyHostName,
boolean tlsDisableTrustManager) throws QueueSizeLimitExceededException;

Outcome request(
String method,
String uri,
String keycloakServerID,
String keycloakClientID,
boolean tlsAllowAnyHostname,
boolean tlsDisableTrustManager,
byte[] content) throws Exception;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* The Initial Developer of the Original Code is
* J4Care.
* Portions created by the Initial Developer are Copyright (C) 2017
* Portions created by the Initial Developer are Copyright (C) 2017-2019
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
Expand All @@ -40,12 +40,13 @@

package org.dcm4chee.arc.rs.client;

import org.dcm4che3.conf.api.IWebApplicationCache;
import org.dcm4che3.data.Attributes;
import org.dcm4che3.data.IDWithIssuer;
import org.dcm4che3.json.JSONWriter;
import org.dcm4che3.net.WebApplication;
import org.dcm4che3.util.ByteUtils;
import org.dcm4chee.arc.conf.ArchiveAEExtension;
import org.dcm4chee.arc.conf.RSForwardRule;
import org.dcm4chee.arc.conf.RSOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -56,7 +57,6 @@
import javax.json.stream.JsonGenerator;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.util.List;

/**
* @author Vrinda Nayak <vrinda.nayak@j4care.com>
Expand All @@ -71,51 +71,45 @@ public class RSForward {
@Inject
private RSClient rsClient;

@Inject
private IWebApplicationCache iWebAppCache;

public void forward(RSOperation rsOp, ArchiveAEExtension arcAE, Attributes attrs, HttpServletRequest request) {
List<RSForwardRule> rules = arcAE.findRSForwardRules(rsOp, request);
for (RSForwardRule rule : rules) {
try {
String targetURI = mkForwardURI(rule.getBaseURI(), rsOp, request);
if (!targetURI.equals(request.getRequestURL().toString())) {
if (rsOp == RSOperation.CreatePatient)
targetURI += IDWithIssuer.pidOf(attrs);
rsClient.scheduleRequest(
getMethod(rsOp),
targetURI,
toContent(attrs),
rule.getKeycloakServerID(),
rule.isTlsAllowAnyHostname(),
rule.isTlsDisableTrustManager());
}
} catch (Exception e) {
LOG.warn("Failed to apply {}:\n", rule, e);
}
}
forward(rsOp, arcAE, toContent(attrs),
rsOp == RSOperation.CreatePatient ? IDWithIssuer.pidOf(attrs) : null, request);
}

public void forwardMergeMultiplePatients(RSOperation rsOp, ArchiveAEExtension arcAE, byte[] in, HttpServletRequest request) {
List<RSForwardRule> rules = arcAE.findRSForwardRules(rsOp, request);
for (RSForwardRule rule : rules) {
public void forward(
RSOperation rsOp, ArchiveAEExtension arcAE, byte[] in, IDWithIssuer patientID, HttpServletRequest request) {
LOG.info("Restful Service Forward {} {} from {}@{}", request.getMethod(), request.getRequestURI(),
request.getRemoteUser(), request.getRemoteHost());
String requestURI = request.getRequestURI();
String appendURI = requestURI.substring(requestURI.indexOf("/rs/") + 4);

arcAE.findRSForwardRules(rsOp, request).forEach(rule -> {
try {
String targetURI = mkForwardURI(rule.getBaseURI(), rsOp, request);
if (!targetURI.equals(request.getRequestURL().toString()))
WebApplication webApplication = iWebAppCache.findWebApplication(rule.getWebAppName());
String serviceURL = webApplication.getServiceURL().toString();
String targetURI = serviceURL + (serviceURL.endsWith("rs/") ? "" : "/") + appendURI;
if (!targetURI.equals(request.getRequestURL().toString())) {
if (rsOp == RSOperation.CreatePatient)
targetURI += patientID;
rsClient.scheduleRequest(
getMethod(rsOp),
targetURI,
in,
rule.getKeycloakServerID(),
webApplication.getKeycloakClientID(),
rule.isTlsAllowAnyHostname(),
rule.isTlsDisableTrustManager());
LOG.info("Forwarded {} {} from {}@{} using RSForward rule {} to device {}. Target URL is {}",
request.getMethod(), request.getRequestURI(), request.getRemoteUser(),
request.getRemoteHost(), rule, webApplication.getDevice().getDeviceName(), targetURI);
}
} catch (Exception e) {
LOG.warn("Failed to apply {}:\n", rule, e);
LOG.warn("Failed to apply RSForwardRule {} to {} {} from {}@{} for RSOperation {} :\n",
rule, request, rsOp, e);
}
}
}

private static String mkForwardURI(String baseURI, RSOperation rsOp, HttpServletRequest request) {
String requestURI = request.getRequestURI();
return baseURI + requestURI.substring(requestURI.indexOf(
rsOp == RSOperation.ApplyRetentionPolicy ? "expire/series" : "rs/"));
});
}

private static byte[] toContent(Attributes attrs) {
Expand Down
Loading

0 comments on commit f23c766

Please sign in to comment.