diff --git a/SUMMARY.adoc b/SUMMARY.adoc index cc60f2abca..1ef570a8d9 100755 --- a/SUMMARY.adoc +++ b/SUMMARY.adoc @@ -10,7 +10,13 @@ .. link:topics/oidc/java/java-adapters.adoc[Java Adapters] ... link:topics/oidc/java/java-adapter-config.adoc[Java Adapters Config] ... link:topics/oidc/java/jboss-adapter.adoc[JBoss EAP/Wildfly Adapter] - ... link:topics/oidc/java/fuse-adapter.adoc[JBoss Fuse and Apache Karaf Adapter] + ... link:topics/oidc/java/fuse-adapter.adoc[JBoss Fuse Adapter] + .... link:topics/oidc/java/fuse/classic-war.adoc[Classic WAR application] + .... link:topics/oidc/java/fuse/servlet-whiteboard.adoc[Servlet Deployed as OSGI Service] + .... link:topics/oidc/java/fuse/camel.adoc[Apache Camel] + .... link:topics/oidc/java/fuse/cxf-separate.adoc[Apache CXF on Separate Jetty] + .... link:topics/oidc/java/fuse/cxf-builtin.adoc[Apache CXF on default Jetty] + .... link:topics/oidc/java/fuse/fuse-admin.adoc[Fuse Admin Services] {% if book.community %} ... link:topics/oidc/java/tomcat-adapter.adoc[Tomcat 6, 7 and 8 Adapters] ... link:topics/oidc/java/jetty9-adapter.adoc[Jetty 9.x Adapters] diff --git a/topics/oidc/java/fuse-adapter.adoc b/topics/oidc/java/fuse-adapter.adoc index c8833f4154..f00dcefb33 100755 --- a/topics/oidc/java/fuse-adapter.adoc +++ b/topics/oidc/java/fuse-adapter.adoc @@ -1,17 +1,17 @@ [[_fuse_adapter]] -=== JBoss Fuse and Apache Karaf Adapter +=== JBoss Fuse Adapter NOTE: JBoss Fuse is a Technology Preview feature and is not fully supported -Currently Keycloak supports securing your web applications running inside http://www.jboss.org/products/fuse/overview/[JBoss Fuse] or http://karaf.apache.org/[Apache Karaf] . -It leverages <<_jetty8_adapter,Jetty 8 adapter>> as both JBoss Fuse 6.2 and Apache Karaf 3 are bundled with http://eclipse.org/jetty/[Jetty 8.1 server] +Currently {{book.project.name}} supports securing your web applications running inside http://www.jboss.org/products/fuse/overview/[JBoss Fuse] . +It leverages <> as both JBoss Fuse 6.2 are bundled with http://eclipse.org/jetty/[Jetty 8.1 server] under the covers and Jetty is used for running various kinds of web applications. -What is supported for Fuse/Karaf is: +What is supported for Fuse is: -* Security for classic WAR applications deployed on Fuse/Karaf with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War[Pax Web War Extender]. -* Security for servlets deployed on Fuse/Karaf as OSGI services with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard[Pax Web Whiteboard Extender]. +* Security for classic WAR applications deployed on Fuse with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War[Pax Web War Extender]. +* Security for servlets deployed on Fuse as OSGI services with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard[Pax Web Whiteboard Extender]. * Security for http://camel.apache.org/[Apache Camel] Jetty endpoints running with http://camel.apache.org/jetty.html[Camel Jetty] component. * Security for http://cxf.apache.org/[Apache CXF] endpoints running on their own separate http://cxf.apache.org/docs/jetty-configuration.html[Jetty engine]. * Security for http://cxf.apache.org/[Apache CXF] endpoints running on default engine provided by CXF servlet. @@ -19,84 +19,10 @@ What is supported for Fuse/Karaf is: ==== How to secure your web applications inside Fuse -The best place to start is look at Fuse demo bundled as part of Keycloak examples in directory `fuse` . Most of the steps should be understandable from testing and +Basically all mentioned web applications require to inject {{book.project.name}} Jetty authenticator into underlying Jetty server . The steps to achieve it are bit different +according to application type. The details are described in individual sub-chapters. + +{% if book.community %} +The best place to start is look at Fuse demo bundled as part of {{book.project.name}} examples in directory `fuse` . Most of the steps should be understandable from testing and understanding the demo. - -Basically all mentioned web applications require to inject Keycloak Jetty authenticator into underlying Jetty server . The steps to achieve it are bit different -according to application type. - - -===== Classic WAR application - -The needed steps are: - -* Declare needed constraints in `/WEB-INF/web.xml` -* Add `jetty-web.xml` file with the authenticator to `/WEB-INF/jetty-web.xml` and add `/WEB-INF/keycloak.json` with your Keycloak configuration -* Make sure your WAR imports `org.keycloak.adapters.jetty` and maybe some more packages in MANIFEST.MF file in header `Import-Package`. It's -recommended to use maven-bundle-plugin similarly like Fuse examples are doing, but note that "*" resolution for package doesn't import `org.keycloak.adapters.jetty` package -as it's not used by application or Blueprint or Spring descriptor, but it's used just in jetty-web.xml file. - -Take a look at `customer-portal-app` from fuse example for inspiration. - -===== Servlet web application deployed by pax-whiteboard-extender - -The needed steps are: - -* Keycloak provides PaxWebIntegrationService, which allows to inject jetty-web.xml and configure security constraints for your application. -Example `product-portal-app` declares this in `OSGI-INF/blueprint/blueprint.xml` . Note that your servlet needs to depend on it. -* Steps 2,3 are same like for classic WAR - -Take a look at `product-portal-app` for inspiration. - -===== Apache camel application - -You can secure your Apache camel endpoint using http://camel.apache.org/jetty.html[camel-jetty] endpoint by adding securityHandler with `KeycloakJettyAuthenticator` and -proper security constraints injected. Take a look at `OSGI-INF/blueprint/blueprint.xml` configuration in `camel` application on example of how it can be done in details. - -===== Apache CXF endpoint - -It's recommended to run your CXF endpoints secured by Keycloak on separate Jetty engine. You need to add `META-INF/spring/beans.xml` to your application -and then declare `httpj:engine-factory` with Jetty SecurityHandler with injected `KeycloakJettyAuthenticator` inside. - -Fore more details, take a look at example application `cxf-ws` from Keycloak Fuse demo, which is using separate endpoint on -http://localhost:8282 . All the important configuration inside this application is declared in `META-INF/spring/beans.xml` . - -===== Builtin CXF web applications - -Some services automatically come with deployed servlets on startup. One of such examples is CXF servlet running on -http://localhost:8181/cxf context. Securing such endpoints is quite tricky. The approach, which Keycloak is currently using, -is providing ServletReregistrationService, which undeploys builtin servlet at startup, so you are able to re-deploy it again on context secured by Keycloak. -You can see the `OSGI-INF/blueprint/blueprint.xml` inside `cxf-jaxrs` example, which adds JAX-RS `customerservice` endpoint and more importantly, it secures whole `/cxf` context. - -As a side effect, all other CXF services running on default CXF HTTP destination will be secured too. Once you uninstall feature `keycloak-fuse-6.2-example`, the -original unsecured servlet on `/cxf` context is deployed back and hence context will become unsecured again. - -It's recommended to use your own Jetty engine for your apps (similarly like `cxf-jaxws` application is doing). - - -==== How to secure Fuse admin services - -===== SSH authentication to Fuse terminal with Keycloak credentials - -Keycloak mainly addresses usecases for authentication of web applications, however if your admin services (like fuse admin console) are protected -with Keycloak, it may be good to protect non-web services like SSH with Keycloak credentials too. It's possible to do it by using JAAS login module, which -allows to remotely connect to Keycloak and verify credentials based on <<_direct_access_grants,Direct Access Grants>> . - -Example steps for enable SSH authentication require changing the configuration of `sshRealm` in `$FUSE_HOME/etc/org.apache.karaf.shell.cfg`, then adding -file `$FUSE_HOME/etc/keycloak-direct-access.json` (this is default location, which can be changed) and install the needed feature `keycloak-jaas`. It's described in details -in the README file of Fuse example, which in example distribution is inside `fuse/fuse-admin/README.md` . - - -===== JMX authentication with Keycloak credentials - -This may be needed in case if you really want to use jconsole or other external tool to perform remote connection to JMX through RMI. Otherwise it may -be better to use just hawt.io/jolokia as jolokia agent is installed in http://hawt.io by default. - -You need to configure `jmxRealm` in `$FUSE_HOME/etc/org.apache.karaf.management.cfg`, then adding file `$FUSE_HOME/etc/keycloak-direct-access.json` -(this is default location, which can be changed) and install the needed feature `keycloak-jaas`. -It's described in details in the README file of Fuse example, which in example distribution is inside `fuse/fuse-admin/README.md` . - - -===== Secure Fuse admin console - -Fuse admin console is Hawt.io. See http://hawt.io/configuration/index.html[Hawt.io documentation] for more info about how to secure it with Keycloak. \ No newline at end of file +{% endif %} \ No newline at end of file diff --git a/topics/oidc/java/fuse/camel.adoc b/topics/oidc/java/fuse/camel.adoc new file mode 100644 index 0000000000..b79229de6c --- /dev/null +++ b/topics/oidc/java/fuse/camel.adoc @@ -0,0 +1,95 @@ + +[[_fuse_adapter_camel]] +==== Apache Camel Application + +* You can secure your Apache camel endpoint using http://camel.apache.org/jetty.html[camel-jetty] component by adding securityHandler with `KeycloakJettyAuthenticator` and +proper security constraints injected. You can add file `OSGI-INF/blueprint/blueprint.xml` into your camel application with the configuration similar to below. +The roles, security constraint mappings and {{book.project.name}} adapter configuration may be a bit different according to your environment and needs: + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + admin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + + +* The `Import-Package` in `META-INF/MANIFEST.MF` needs to contain those imports: +[source] +---- +javax.servlet;version="[3,4)", +javax.servlet.http;version="[3,4)", +org.apache.camel.*, +org.apache.camel;version="[2.13,3)", +org.eclipse.jetty.security;version="[8,10)", +org.eclipse.jetty.server.nio;version="[8,10)", +org.eclipse.jetty.util.security;version="[8,10)", +org.keycloak.*;version="{{book.project.version}}", +org.osgi.service.blueprint, +org.osgi.service.blueprint.container, +org.osgi.service.event, +---- + diff --git a/topics/oidc/java/fuse/classic-war.adoc b/topics/oidc/java/fuse/classic-war.adoc new file mode 100644 index 0000000000..7ff0bfc98e --- /dev/null +++ b/topics/oidc/java/fuse/classic-war.adoc @@ -0,0 +1,82 @@ + +[[_fuse_adapter_classic_war]] +==== Secure Classic WAR application + +The needed steps to secure your WAR are: + +* Declare needed security constraints in `/WEB-INF/web.xml` . You also need to declare login-config and all the roles inside security-role. +The example configuration can look like this: + +[source,xml] +---- + + + + customer-portal + + + index.html + + + + + Customers + /customers/* + + + user + + + + + BASIC + does-not-matter + + + + admin + + + user + + +---- + +* Add `jetty-web.xml` file with the authenticator to `/WEB-INF/jetty-web.xml` . Typically it will look like this: + +[source,xml] +---- + + + + + + + + + + +---- + +* Add `/WEB-INF/keycloak.json` with your {{book.project.name}} configuration. The format of this config file is described +in the <> section. + +* Make sure your WAR imports `org.keycloak.adapters.jetty` and maybe some more packages in `META-INF/MANIFEST.MF` file in header `Import-Package`. It's +recommended to use `maven-bundle-plugin` in your project to properly generate OSGI headers in manifest. +Note that "*" resolution for package doesn't import `org.keycloak.adapters.jetty` package +as it's not used by application or Blueprint or Spring descriptor, but it's used just in `jetty-web.xml` file. So list of the packages to import may look like this: + +[source] +---- +org.keycloak.adapters.jetty;version="{{book.project.version}}", +org.keycloak.adapters;version="{{book.project.version}}", +org.keycloak.constants;version="{{book.project.version}}", +org.keycloak.util;version="{{book.project.version}}", +org.keycloak.*;version="{{book.project.version}}", +*;resolution:=optional +---- + diff --git a/topics/oidc/java/fuse/cxf-builtin.adoc b/topics/oidc/java/fuse/cxf-builtin.adoc new file mode 100644 index 0000000000..ff4211a8c5 --- /dev/null +++ b/topics/oidc/java/fuse/cxf-builtin.adoc @@ -0,0 +1,98 @@ + +[[_fuse_adapter_cxf_builtin]] +==== Secure Apache CXF Endpoint on default Jetty Engine + +Some services automatically come with deployed servlets on startup. One of such services is CXF servlet running on +http://localhost:8181/cxf context. Securing such endpoints is quite tricky. The approach, which {{book.project.name}} is currently using, +is providing ServletReregistrationService, which undeploys builtin servlet at startup, so you are able to re-deploy it again on context secured by {{book.project.name}}. +This is how configuration file `OSGI-INF/blueprint/blueprint.xml` inside your application may look like. Note it adds JAX-RS `customerservice` endpoint, +which is endpoint specific to your application, but more importantly, it secures whole `/cxf` context. + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +As a side effect, all other CXF services running on default CXF HTTP destination will be secured too. Similarly when the application is undeployed, then +whole `/cxf` context will become unsecured too. For this reason, it's recommended to use your own Jetty engine for your apps like +described in <> as then you have more +control over security for each application individually. + +* You may need to have directory `WEB-INF` inside your project (even if your project is not web application) and create files `/WEB-INF/jetty-web.xml` and + `/WEB-INF/keycloak.json` in similar way like it's in <>. + Note you don't need `web.xml` as the security-constrains are declared in blueprint configuration file. + + +* The `Import-Package` in `META-INF/MANIFEST.MF` needs to contain those imports: +[source] +---- +META-INF.cxf;version="[2.7,3.2)", +META-INF.cxf.osgi;version="[2.7,3.2)";resolution:=optional, +org.apache.cxf.transport.http;version="[2.7,3.2)", +org.apache.cxf.*;version="[2.7,3.2)", +com.fasterxml.jackson.jaxrs.json;version="[2.5,3)", +org.eclipse.jetty.security;version="[8,10)", +org.eclipse.jetty.util.security;version="[8,10)", +org.keycloak.*;version="{{book.project.version}}", +org.keycloak.adapters.jetty;version="{{book.project.version}}", +*;resolution:=optional +---- diff --git a/topics/oidc/java/fuse/cxf-separate.adoc b/topics/oidc/java/fuse/cxf-separate.adoc new file mode 100644 index 0000000000..86e12b76a1 --- /dev/null +++ b/topics/oidc/java/fuse/cxf-separate.adoc @@ -0,0 +1,111 @@ + +[[_fuse_adapter_cxf_separate]] +==== Secure Apache CXF Endpoint on separate Jetty + +It's recommended to run your CXF endpoints secured by {{book.project.name}} on separate Jetty engine. This is the setup described in this section. + +* You need to add `META-INF/spring/beans.xml` to your application and then declare `httpj:engine-factory` with Jetty SecurityHandler with +injected `KeycloakJettyAuthenticator` inside. The configuration may look like this for CXF JAX-WS application: + +[source,xml] +---- + + + + + + + + + + + + + + + + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + +---- + +* For the CXF JAX-RS application, the only difference might be in the configuration of the endpoint dependent on engine-factory: + +[source,xml] +---- + + + + + +---- + + +* The `Import-Package` in `META-INF/MANIFEST.MF` needs to contain those imports: +[source] +---- +META-INF.cxf;version="[2.7,3.2)", +META-INF.cxf.osgi;version="[2.7,3.2)";resolution:=optional, +org.apache.cxf.bus;version="[2.7,3.2)", +org.apache.cxf.bus.spring;version="[2.7,3.2)", +org.apache.cxf.bus.resource;version="[2.7,3.2)", +org.apache.cxf.transport.http;version="[2.7,3.2)", +org.apache.cxf.*;version="[2.7,3.2)", +org.springframework.beans.factory.config, +org.eclipse.jetty.security;version="[8,10)", +org.eclipse.jetty.util.security;version="[8,10)", +org.keycloak.*;version="{{book.project.version}}" +---- \ No newline at end of file diff --git a/topics/oidc/java/fuse/fuse-admin.adoc b/topics/oidc/java/fuse/fuse-admin.adoc new file mode 100644 index 0000000000..33223d587a --- /dev/null +++ b/topics/oidc/java/fuse/fuse-admin.adoc @@ -0,0 +1,87 @@ + +[[_fuse_adapter_admin]] +==== Secure Fuse Admin Services + +===== SSH authentication to Fuse terminal + +{{book.project.name}} mainly addresses usecases for authentication of web applications, however if your other web services and applications are protected +with {{book.project.name}}, it may be good to protect non-web admin services like SSH with {{book.project.name}} credentials too. It's possible to do it +by using JAAS login module, which allows to remotely connect to {{book.project.name}} and verify credentials based on +<> . + +Example steps for enable SSH authentication: + +* In {{book.project.name}} you need to create client (assume it's called `ssh-jmx-admin-client`), which will be used for SSH authentication. +This client needs to have switch `Direct grant enabled` to true. + +* You need to update/specify this property in file `$FUSE_HOME/etc/org.apache.karaf.shell.cfg`: + +[source] +---- +sshRealm=keycloak +---- + +* Add file `$FUSE_HOME/etc/keycloak-direct-access.json` with the content similar to this (change based on your environment and {{book.project.name}} client settings): +[source,json] +---- +{ + "realm": "demo", + "resource": "ssh-jmx-admin-client", + "realm-public-key": "MIGfMA...", + "ssl-required" : "external", + "auth-server-url" : "http://localhost:8080/auth", + "credentials": { + "secret": "password" + } +} +---- +This file contains configuration of the client application, which is used by JAAS DirectAccessGrantsLoginModule from `keycloak` JAAS realm for SSH authentication. + +* Start Fuse and install `keycloak` JAAS realm into Fuse. This could be done easily by installing `keycloak-jaas` feature, which has JAAS realm predefined +(you are able to override it by using your own `keycloak` JAAS realm with higher ranking). Use those commands in Fuse terminal: + +``` +features:addurl mvn:org.keycloak/keycloak-osgi-features/{{book.project.version}}/xml/features +features:install keycloak-jaas +``` + +* Now let's type this from your terminal to login via SSH as `admin` user: + +``` +ssh -o PubkeyAuthentication=no -p 8101 admin@localhost +``` + +And login with password `password` . Note that your user needs to have realm role `admin` . The required roles are configured in `$FUSE_HOME/etc/org.apache.karaf.shell.cfg` + + +===== JMX authentication + +This may be needed in case if you really want to use jconsole or other external tool to perform remote connection to JMX through RMI. Otherwise it may +be better to use just hawt.io/jolokia as jolokia agent is installed in hawt.io by default. + +* In file `$FUSE_HOME/etc/org.apache.karaf.management.cfg` you can change this property: + +[source] +---- +jmxRealm=keycloak +---- + +* You need `keycloak-jaas` feature and file `$FUSE_HOME/etc/keycloak-direct-access.json` as described in SSH section above. + +* In jconsole you can fill URL like: + +[source] +---- +service:jmx:rmi://localhost:44444/jndi/rmi://localhost:1099/karaf-root +---- + +and credentials: admin/password (based on the user with admin privileges according to your environment) + +Note again that users without `admin` role are not able to login as they are not authorized. However users with access to Hawt.io admin console +may be still able to access MBeans remotely via HTTP (Hawtio). So make sure to protect Hawt.io web console with same roles like JMX through RMI to +really protect JMX mbeans. + + +===== Secure Fuse admin console + +Fuse admin console is Hawt.io. See http://hawt.io/configuration/index.html[Hawt.io documentation] for more info about how to secure it with {{book.project.name}}. \ No newline at end of file diff --git a/topics/oidc/java/fuse/servlet-whiteboard.adoc b/topics/oidc/java/fuse/servlet-whiteboard.adoc new file mode 100644 index 0000000000..37c0893803 --- /dev/null +++ b/topics/oidc/java/fuse/servlet-whiteboard.adoc @@ -0,0 +1,76 @@ + +[[_fuse_adapter_servlet_whiteboard]] +==== Secure Servlet deployed as OSGI service + +This is useful for the case, when you have sevlet class inside your OSGI bundle project, which is not deployed as classic WAR. Fuse uses +https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard[Pax Web Whiteboard Extender] for deploy such servlet as web application. + +The needed steps to secure your servlet with {{book.project.name}} are: + +* Keycloak provides PaxWebIntegrationService, which allows to inject jetty-web.xml and configure security constraints for your application. + You need to declare such service in `OSGI-INF/blueprint/blueprint.xml` inside your application. Note that your servlet needs to depend on it. + The example configuration can look like this: +[source,xml] +---- + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +---- + +* You may need to have directory `WEB-INF` inside your project (even if your project is not web application) and create files `/WEB-INF/jetty-web.xml` and +`/WEB-INF/keycloak.json` in similar way like it's in <>. +Note you don't need `web.xml` as the security-constrains are declared in blueprint configuration file. + +* The `Import-Package` in `META-INF/MANIFEST.MF` needs to contain at least those imports: +[source] +---- +org.keycloak.adapters.jetty;version="{{book.project.version}}", +org.keycloak.adapters;version="{{book.project.version}}", +org.keycloak.constants;version="{{book.project.version}}", +org.keycloak.util;version="{{book.project.version}}", +org.keycloak.*;version="{{book.project.version}}", +*;resolution:=optional +----