From ae690e0679a764af60675579d6447d7066cadcce Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Fri, 18 May 2018 12:46:13 +0200 Subject: [PATCH] KEYCLOAK-5522 Base for Fuse 7 adapter --- adapters/oidc/osgi-adapter/pom.xml | 2 +- .../osgi/PaxWebIntegrationService.java | 107 +++++++++++++++++- .../osgi/PaxWebSecurityConstraintMapping.java | 73 ++++++++++++ adapters/oidc/pom.xml | 1 + examples/fuse/pom.xml | 2 +- pom.xml | 9 +- 6 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebSecurityConstraintMapping.java diff --git a/adapters/oidc/osgi-adapter/pom.xml b/adapters/oidc/osgi-adapter/pom.xml index a73721429c..135eacd3cf 100755 --- a/adapters/oidc/osgi-adapter/pom.xml +++ b/adapters/oidc/osgi-adapter/pom.xml @@ -36,7 +36,7 @@ org.keycloak.adapters.osgi.* - org.ops4j.pax.web.*;version="[3.0,5)", + org.ops4j.pax.web.*;version="[3.0,8)", javax.servlet.*;version="[2.5,4)";resolution:=optional, org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional, org.keycloak.*;version="${project.version}", diff --git a/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java index f295b30945..76cd62f9d5 100644 --- a/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java +++ b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java @@ -29,6 +29,7 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer; import java.net.URL; import java.security.SecureRandom; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -47,7 +48,7 @@ public class PaxWebIntegrationService { private BundleContext bundleContext; private String jettyWebXmlLocation; - private List constraintMappings; // Using jetty constraint mapping just because of compatibility with other fuse services + private List constraintMappings; private ServiceTracker webContainerTracker; private HttpContext httpContext; @@ -68,11 +69,11 @@ public class PaxWebIntegrationService { this.jettyWebXmlLocation = jettyWebXmlLocation; } - public List getConstraintMappings() { + public List getConstraintMappings() { return constraintMappings; } - public void setConstraintMappings(List constraintMappings) { + public void setConstraintMappings(List constraintMappings) { this.constraintMappings = constraintMappings; } @@ -120,8 +121,25 @@ public class PaxWebIntegrationService { if (constraintMappings == null) { throw new IllegalStateException("constraintMappings was null!"); } - for (ConstraintMapping constraintMapping : constraintMappings) { - addConstraintMapping(service, constraintMapping); + List handlers = new ArrayList<>(); + try { + handlers.add(new JettyConstraintHandler()); + } catch (Throwable t) { + // Ignore + } + try { + handlers.add(new PaxWebConstraintHandler()); + } catch (Throwable t) { + // Ignore + } + for (Object constraintMapping : constraintMappings) { + boolean handled = false; + for (ConstraintHandler handler : handlers) { + handled |= handler.addConstraintMapping(httpContext, service, constraintMapping); + } + if (!handled) { + log.warnv("Unable to add constraint mapping for constraint of type " + constraintMapping.getClass().toString()); + } } service.registerLoginConfig("BASIC", "does-not-matter", null, null, httpContext); @@ -146,6 +164,16 @@ public class PaxWebIntegrationService { } } + protected void addConstraintMapping(WebContainer service, PaxWebSecurityConstraintMapping constraintMapping) { + String name = constraintMapping.getConstraintName(); + if (name == null) { + name = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE); + } + log.debug("Adding security constraint name=" + name + ", url=" + constraintMapping.getUrl() + ", dataConstraint=" + constraintMapping.getDataConstraint() + ", canAuthenticate=" + + constraintMapping.isAuthentication() + ", roles=" + constraintMapping.getRoles()); + service.registerConstraintMapping(name, constraintMapping.getUrl(), constraintMapping.getMapping(), constraintMapping.getDataConstraint(), constraintMapping.isAuthentication(), constraintMapping.getRoles(), httpContext); + } + protected void addConstraintMapping(WebContainer service, ConstraintMapping constraintMapping) { Constraint constraint = constraintMapping.getConstraint(); String[] roles = constraint.getRoles(); @@ -178,4 +206,71 @@ public class PaxWebIntegrationService { service.unregisterConstraintMapping(httpContext); } } -} + + private interface ConstraintHandler { + boolean addConstraintMapping(HttpContext httpContext, WebContainer service, Object cm); + } + + private static class PaxWebConstraintHandler implements ConstraintHandler { + + @Override + public boolean addConstraintMapping(HttpContext httpContext, WebContainer service, Object cm) { + if (cm instanceof PaxWebSecurityConstraintMapping) { + PaxWebSecurityConstraintMapping constraintMapping = (PaxWebSecurityConstraintMapping) cm; + String name = constraintMapping.getConstraintName(); + if (name == null) { + name = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE); + } + log.debug("Adding security constraint name=" + name + ", url=" + constraintMapping.getUrl() + ", dataConstraint=" + constraintMapping.getDataConstraint() + ", canAuthenticate=" + + constraintMapping.isAuthentication() + ", roles=" + constraintMapping.getRoles()); + service.registerConstraintMapping(name, constraintMapping.getUrl(), constraintMapping.getMapping(), constraintMapping.getDataConstraint(), constraintMapping.isAuthentication(), constraintMapping.getRoles(), httpContext); + return true; + } + return false; + } + + } + + private static class JettyConstraintHandler implements ConstraintHandler { + + @Override + public boolean addConstraintMapping(HttpContext httpContext, WebContainer service, Object cm) { + if (cm instanceof ConstraintMapping) { + ConstraintMapping constraintMapping = (ConstraintMapping) cm; + Constraint constraint = constraintMapping.getConstraint(); + String[] roles = constraint.getRoles(); + // name property is unavailable on constraint object :/ + + String name = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE); + + int dataConstraint = constraint.getDataConstraint(); + String dataConstraintStr; + switch (dataConstraint) { + case Constraint.DC_UNSET: + dataConstraintStr = null; + break; + case Constraint.DC_NONE: + dataConstraintStr = "NONE"; + break; + case Constraint.DC_CONFIDENTIAL: + dataConstraintStr = "CONFIDENTIAL"; + break; + case Constraint.DC_INTEGRAL: + dataConstraintStr = "INTEGRAL"; + break; + default: + log.warnv("Unknown data constraint: " + dataConstraint); + dataConstraintStr = "CONFIDENTIAL"; + } + List rolesList = Arrays.asList(roles); + + log.debug("Adding security constraint name=" + name + ", url=" + constraintMapping.getPathSpec() + ", dataConstraint=" + dataConstraintStr + ", canAuthenticate=" + + constraint.getAuthenticate() + ", roles=" + rolesList); + service.registerConstraintMapping(name, constraintMapping.getPathSpec(), null, dataConstraintStr, constraint.getAuthenticate(), rolesList, httpContext); + return true; + } + return false; + } + + } +} \ No newline at end of file diff --git a/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebSecurityConstraintMapping.java b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebSecurityConstraintMapping.java new file mode 100644 index 0000000000..d73baf297c --- /dev/null +++ b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebSecurityConstraintMapping.java @@ -0,0 +1,73 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.keycloak.adapters.osgi; + +import java.security.SecureRandom; +import java.util.LinkedList; +import java.util.List; + +/** + * + * @author hmlnarik + */ +public class PaxWebSecurityConstraintMapping { + + private String constraintName = "Constraint-" + new SecureRandom().nextInt(Integer.MAX_VALUE); + private String mapping; + private String url; + private String dataConstraint = "NONE"; + private boolean authentication = true; + private List roles = new LinkedList<>(); + + public String getConstraintName() { + return constraintName; + } + + public void setConstraintName(String constraintName) { + this.constraintName = constraintName; + } + + public String getMapping() { + return mapping; + } + + public void setMapping(String mapping) { + this.mapping = mapping; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getDataConstraint() { + return dataConstraint; + } + + public void setDataConstraint(String dataConstraint) { + this.dataConstraint = dataConstraint; + } + + public boolean isAuthentication() { + return authentication; + } + + public void setAuthentication(boolean authentication) { + this.authentication = authentication; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + +} diff --git a/adapters/oidc/pom.xml b/adapters/oidc/pom.xml index 43c1b09d56..d63c8b7b41 100755 --- a/adapters/oidc/pom.xml +++ b/adapters/oidc/pom.xml @@ -34,6 +34,7 @@ adapter-core as7-eap6 installed + fuse7 kcinit jaxrs-oauth-client jetty diff --git a/examples/fuse/pom.xml b/examples/fuse/pom.xml index 0233ced3eb..3c2f9fb704 100755 --- a/examples/fuse/pom.xml +++ b/examples/fuse/pom.xml @@ -30,7 +30,7 @@ keycloak-examples-fuse-parent pom - 2.17.0 + 2.21.0 customer-app-fuse diff --git a/pom.xml b/pom.xml index a87ff5f7cb..59c302314e 100755 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ 0.6 1.4.1.Final 1.56 - 3.1.13 + 3.2.0 1.6.1 2011.1 1.4.193 @@ -105,7 +105,7 @@ 3.4.1 5.1.29 4.2.0 - 4.2.4 + 7.1.0 9.3-1100-jdbc41 1.3.7 1.0.2.Final @@ -697,6 +697,11 @@ pax-web-api ${pax.web.version} + + org.ops4j.pax.web + pax-web-spi + ${pax.web.version} + org.jboss.aesh aesh