Merge pull request #10 from mposolda/master

More Fuse adapter documentation. Remove references to Apache Karaf
This commit is contained in:
Bill Burke 2016-06-03 16:15:19 -04:00
commit faaf1460b1
8 changed files with 568 additions and 87 deletions

View file

@ -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]

View file

@ -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 <<fake/../jetty8-adapter.adoc#_jetty8_adapter,Jetty 8 adapter>> 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.
{% endif %}

View file

@ -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]
----
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
<property name="realm" value="demo"/>
<property name="resource" value="admin-camel-endpoint"/>
<property name="realmKey" value="MIGfMA0G..."/>
<property name="bearerOnly" value="true"/>
<property name="authServerUrl" value="http://localhost:8080/auth" />
<property name="sslRequired" value="EXTERNAL"/>
</bean>
<bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
<property name="adapterConfig" ref="kcAdapterConfig"/>
</bean>
<bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
<property name="name" value="Customers"/>
<property name="roles">
<list>
<value>admin</value>
</list>
</property>
<property name="authenticate" value="true"/>
<property name="dataConstraint" value="0"/>
</bean>
<bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
<property name="constraint" ref="constraint"/>
<property name="pathSpec" value="/*"/>
</bean>
<bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
<property name="authenticator" ref="keycloakAuthenticator" />
<property name="constraintMappings">
<list>
<ref component-id="constraintMapping" />
</list>
</property>
<property name="authMethod" value="BASIC"/>
<property name="realmName" value="does-not-matter"/>
</bean>
<bean id="sessionHandler" class="org.keycloak.adapters.jetty.spi.WrappingSessionHandler">
<property name="handler" ref="securityHandler" />
</bean>
<bean id="helloProcessor" class="org.keycloak.example.CamelHelloProcessor" />
<camelContext id="blueprintContext"
trace="false"
xmlns="http://camel.apache.org/schema/blueprint">
<route id="httpBridge">
<from uri="jetty:http://0.0.0.0:8383/admin-camel-endpoint?handlers=sessionHandler&amp;matchOnUriPrefix=true" />
<process ref="helloProcessor" />
<log message="The message from camel endpoint contains ${body}"/>
</route>
</camelContext>
</blueprint>
----
* 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,
----

View file

@ -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]
----
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<module-name>customer-portal</module-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</web-resource-name>
<url-pattern>/customers/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>does-not-matter</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
----
* Add `jetty-web.xml` file with the authenticator to `/WEB-INF/jetty-web.xml` . Typically it will look like this:
[source,xml]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Get name="securityHandler">
<Set name="authenticator">
<New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
</New>
</Set>
</Get>
</Configure>
----
* Add `/WEB-INF/keycloak.json` with your {{book.project.name}} configuration. The format of this config file is described
in the <<fake/../../java-adapter-config.adoc#_java_adapter_config,Java Adapters Config>> 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
----

View file

@ -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]
----
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd">
<!-- JAXRS Application -->
<bean id="customerBean" class="org.keycloak.example.rs.CxfCustomerService" />
<jaxrs:server id="cxfJaxrsServer" address="/customerservice">
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
</jaxrs:providers>
<jaxrs:serviceBeans>
<ref component-id="customerBean" />
</jaxrs:serviceBeans>
</jaxrs:server>
<!-- Securing of whole /cxf context by unregister default cxf servlet from paxweb and re-register with applied security constraints -->
<bean id="cxfConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
<property name="constraint">
<bean class="org.eclipse.jetty.util.security.Constraint">
<property name="name" value="cst1"/>
<property name="roles">
<list>
<value>user</value>
</list>
</property>
<property name="authenticate" value="true"/>
<property name="dataConstraint" value="0"/>
</bean>
</property>
<property name="pathSpec" value="/cxf/*"/>
</bean>
<bean id="cxfKeycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
init-method="start" destroy-method="stop">
<property name="bundleContext" ref="blueprintBundleContext" />
<property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
<property name="constraintMappings">
<list>
<ref component-id="cxfConstraintMapping" />
</list>
</property>
</bean>
<bean id="defaultCxfReregistration" class="org.keycloak.adapters.osgi.ServletReregistrationService" depends-on="cxfKeycloakPaxWebIntegration"
init-method="start" destroy-method="stop">
<property name="bundleContext" ref="blueprintBundleContext" />
<property name="managedServiceReference">
<reference interface="org.osgi.service.cm.ManagedService" filter="(service.pid=org.apache.cxf.osgi)" timeout="5000" />
</property>
</bean>
</blueprint>
----
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 <<fake/../cxf-separate.adoc#_fuse_adapter_cxf_separate,Secure CXF Application on separate Jetty Engine>> 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 <<fake/../classic-war.adoc#_fuse_adapter_classic_war,Classic WAR application>>.
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
----

View file

@ -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]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
<property name="realm" value="demo"/>
<property name="resource" value="custom-cxf-endpoint"/>
<property name="realmKey" value="MIGfMA0..."/>
<property name="bearerOnly" value="true"/>
<property name="authServerUrl" value="http://localhost:8080/auth" />
<property name="sslRequired" value="EXTERNAL"/>
</bean>
<bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
<property name="adapterConfig">
<ref local="kcAdapterConfig" />
</property>
</bean>
<bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
<property name="name" value="Customers"/>
<property name="roles">
<list>
<value>user</value>
</list>
</property>
<property name="authenticate" value="true"/>
<property name="dataConstraint" value="0"/>
</bean>
<bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
<property name="constraint" ref="constraint"/>
<property name="pathSpec" value="/*"/>
</bean>
<bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
<property name="authenticator" ref="keycloakAuthenticator" />
<property name="constraintMappings">
<list>
<ref local="constraintMapping" />
</list>
</property>
<property name="authMethod" value="BASIC"/>
<property name="realmName" value="does-not-matter"/>
</bean>
<httpj:engine-factory bus="cxf" id="kc-cxf-endpoint">
<httpj:engine port="8282">
<httpj:handlers>
<ref local="securityHandler" />
</httpj:handlers>
<httpj:sessionSupport>true</httpj:sessionSupport>
</httpj:engine>
</httpj:engine-factory>
<jaxws:endpoint
implementor="org.keycloak.example.ws.ProductImpl"
address="http://localhost:8282/ProductServiceCF" depends-on="kc-cxf-endpoint" />
</beans>
----
* For the CXF JAX-RS application, the only difference might be in the configuration of the endpoint dependent on engine-factory:
[source,xml]
----
<jaxrs:server serviceClass="org.keycloak.example.rs.CustomerService" address="http://localhost:8282/rest"
depends-on="kc-cxf-endpoint">
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
----
* 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}}"
----

View file

@ -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
<<fake/../../../oidc-generic.adoc#_resource_owner_password_credentials_flow,Resource Owner Password Credentials>> .
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}}.

View file

@ -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]
----
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<!-- Using jetty bean just for the compatibility with other fuse services -->
<bean id="servletConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
<property name="constraint">
<bean class="org.eclipse.jetty.util.security.Constraint">
<property name="name" value="cst1"/>
<property name="roles">
<list>
<value>user</value>
</list>
</property>
<property name="authenticate" value="true"/>
<property name="dataConstraint" value="0"/>
</bean>
</property>
<property name="pathSpec" value="/product-portal/*"/>
</bean>
<bean id="keycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
init-method="start" destroy-method="stop">
<property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
<property name="bundleContext" ref="blueprintBundleContext" />
<property name="constraintMappings">
<list>
<ref component-id="servletConstraintMapping" />
</list>
</property>
</bean>
<bean id="productServlet" class="org.keycloak.example.ProductPortalServlet" depends-on="keycloakPaxWebIntegration">
</bean>
<service ref="productServlet" interface="javax.servlet.Servlet">
<service-properties>
<entry key="alias" value="/product-portal" />
<entry key="servlet-name" value="ProductServlet" />
<entry key="keycloak.config.file" value="/keycloak.json" />
</service-properties>
</service>
</blueprint>
----
* 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 <<fake/../classic-war.adoc#_fuse_adapter_classic_war,Classic WAR application>>.
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
----