ARTEMIS-3168 - add example using authentication delegation to keycloak, principal conversion for jms clients and oath for the web cosole
This commit is contained in:
parent
06461f146c
commit
d71d54b38a
|
@ -37,7 +37,7 @@ HAWTIO_ROLE='${role}'
|
||||||
|
|
||||||
# Java Opts
|
# Java Opts
|
||||||
if [ -z "$JAVA_ARGS" ]; then
|
if [ -z "$JAVA_ARGS" ]; then
|
||||||
JAVA_ARGS="${java-opts} -XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx2G -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=${ARTEMIS_INSTANCE_ETC_URI}jolokia-access.xml"
|
JAVA_ARGS="-XX:+PrintClassHistogram -XX:+UseG1GC -XX:+UseStringDeduplication -Xms512M -Xmx2G -Dhawtio.disableProxy=true -Dhawtio.realm=activemq -Dhawtio.offline=true -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal -Djolokia.policyLocation=${ARTEMIS_INSTANCE_ETC_URI}jolokia-access.xml ${java-opts}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -187,7 +187,7 @@ public class ArtemisCreatePlugin extends ArtemisAbstractPlugin {
|
||||||
|
|
||||||
ArrayList<String> listCommands = new ArrayList<>();
|
ArrayList<String> listCommands = new ArrayList<>();
|
||||||
|
|
||||||
add(listCommands, "create", "--allow-anonymous", "--silent", "--force", "--user", user, "--password", password, "--role", role, "--port-offset", "" + portOffset, "--data", dataFolder);
|
add(listCommands, "create", "--silent", "--force", "--user", user, "--password", password, "--role", role, "--port-offset", "" + portOffset, "--data", dataFolder);
|
||||||
|
|
||||||
if (allowAnonymous) {
|
if (allowAnonymous) {
|
||||||
add(listCommands, "--allow-anonymous");
|
add(listCommands, "--allow-anonymous");
|
||||||
|
|
|
@ -724,6 +724,12 @@ The `security-ldap` example shows you how configure and use role based security
|
||||||
with Apache ActiveMQ Artemis & an embedded instance of the Apache DS LDAP
|
with Apache ActiveMQ Artemis & an embedded instance of the Apache DS LDAP
|
||||||
server.
|
server.
|
||||||
|
|
||||||
|
## Security keycloak
|
||||||
|
|
||||||
|
The `security-keycloak` example shows you how to delegate security
|
||||||
|
with Apache ActiveMQ Artemis & an external Keycloak. Using
|
||||||
|
OAuth of the web console and direct access for JMS clients.
|
||||||
|
|
||||||
## Send Acknowledgements
|
## Send Acknowledgements
|
||||||
|
|
||||||
The `send-acknowledgements` example shows you how to use Apache ActiveMQ
|
The `send-acknowledgements` example shows you how to use Apache ActiveMQ
|
||||||
|
|
|
@ -91,6 +91,7 @@ under the License.
|
||||||
<module>request-reply</module>
|
<module>request-reply</module>
|
||||||
<module>scheduled-message</module>
|
<module>scheduled-message</module>
|
||||||
<module>security</module>
|
<module>security</module>
|
||||||
|
<module>security-keycloak</module>
|
||||||
<module>security-ldap</module>
|
<module>security-ldap</module>
|
||||||
<module>security-manager</module>
|
<module>security-manager</module>
|
||||||
<module>send-acknowledgements</module>
|
<module>send-acknowledgements</module>
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||||
|
<artifactId>jms-examples</artifactId>
|
||||||
|
<version>2.18.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>security-keycloak</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>ActiveMQ Artemis JMS Security Keycloak Example</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
|
||||||
|
<version.org.keycloak>12.0.3</version.org.keycloak>
|
||||||
|
<version.org.apache.httpcomponents>4.5.13</version.org.apache.httpcomponents>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-jms-client-all</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.googlecode.maven-download-plugin</groupId>
|
||||||
|
<artifactId>download-maven-plugin</artifactId>
|
||||||
|
<version>1.6.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>install-keycloak</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>wget</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<url>https://github.com/keycloak/keycloak/releases/download/${version.org.keycloak}/keycloak-${version.org.keycloak}.tar.gz</url>
|
||||||
|
<unpack>true</unpack>
|
||||||
|
<overwrite>false</overwrite>
|
||||||
|
<skip>${noServer}</skip>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.activemq</groupId>
|
||||||
|
<artifactId>artemis-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>create</id>
|
||||||
|
<phase>pre-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>create</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<noWeb>false</noWeb>
|
||||||
|
<!-- enable keycloak for hawtio via system property overrides, note use of "console" realm in login.config -->
|
||||||
|
<javaOptions>-Dhawtio.keycloakEnabled=true -Dhawtio.keycloakClientConfig=${ARTEMIS_INSTANCE_ETC_URI}keycloak-js-client.json -Dhawtio.authenticationEnabled=true -Dhawtio.realm=console</javaOptions>
|
||||||
|
<libListWithDeps>
|
||||||
|
<!-- allow keycloak login module classloading from the artemis lib dir-->
|
||||||
|
<arg>org.keycloak:keycloak-adapter-core:jar:${version.org.keycloak}</arg>
|
||||||
|
<arg>org.keycloak:keycloak-core:jar:${version.org.keycloak}</arg>
|
||||||
|
<arg>org.apache.httpcomponents:httpclient:jar:${version.org.apache.httpcomponents}</arg>
|
||||||
|
</libListWithDeps>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>start</id>
|
||||||
|
<goals>
|
||||||
|
<goal>cli</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<spawn>true</spawn>
|
||||||
|
<args>
|
||||||
|
<param>run</param>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>runClient</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>runClient</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<clientClass>org.apache.activemq.artemis.jms.example.KeycloakSecurityExample</clientClass>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>stop</id>
|
||||||
|
<goals>
|
||||||
|
<goal>cli</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<ignore>${noServer}</ignore>
|
||||||
|
<args>
|
||||||
|
<param>stop</param>
|
||||||
|
</args>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||||
|
<artifactId>security-keycloak</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-adapter-core</artifactId>
|
||||||
|
<version>${version.org.keycloak}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-core</artifactId>
|
||||||
|
<version>${version.org.keycloak}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>${version.org.apache.httpcomponents}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>run-keycloak</id>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<skip>${noServer}</skip>
|
||||||
|
<async>true</async>
|
||||||
|
<executable>./target/keycloak-${version.org.keycloak}/bin/standalone.sh</executable>
|
||||||
|
<arguments>
|
||||||
|
<argument>-Dkeycloak.migration.action=import</argument>
|
||||||
|
<argument>-Dkeycloak.migration.provider=singleFile</argument>
|
||||||
|
<argument>-Dkeycloak.migration.file=./src/main/resources/artemis-keycloak-demo-realm.json</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>stop-keycloak</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>exec</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<skip>${noServer}</skip>
|
||||||
|
<executable>./target/keycloak-${version.org.keycloak}/bin/jboss-cli.sh</executable>
|
||||||
|
<arguments>
|
||||||
|
<argument>--connect</argument>
|
||||||
|
<argument>command=:shutdown</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,159 @@
|
||||||
|
# JMS Security Keycloak Example
|
||||||
|
|
||||||
|
To run the example, simply type **mvn verify** from this directory, or **mvn -PnoServer verify** if you want to start and create the broker manually.
|
||||||
|
|
||||||
|
In this example, broker authentication is delegated to keycloak. A keycloak server is installed and configured with
|
||||||
|
a demo realm called "artemis-keycloak-demo".
|
||||||
|
|
||||||
|
_NOTE_: The keycloak admin user is admin:admin
|
||||||
|
The keycloak admin console is at: http://localhost:8080/auth/admin/master/console/#/realms/artemis-keycloak-demo
|
||||||
|
|
||||||
|
Artemis uses JAAS for authentication and authorization, when authentication is delegated to keycloak, JAAS needs a
|
||||||
|
way to query keycloak and resolve tokens or authenticate directly.
|
||||||
|
|
||||||
|
There are two keycloak clients configured in the "artemis-keycloak-demo" keycloak realm, one each for the two JAAS
|
||||||
|
configurations in login.config. Each are considered in turn:
|
||||||
|
|
||||||
|
###### console realm
|
||||||
|
|
||||||
|
The web console, using client id: "artemis-console" delegates authentication to keycloak using the openid-connect
|
||||||
|
protocol and presents a bearer token to JAAS.
|
||||||
|
|
||||||
|
The keycloak BearerTokenLoginModule in the "console" JAAS realm, converts the bearer token into the relevant Artemis
|
||||||
|
roles for consumption by the management console role based access control(RBAC) defined in management.xml.
|
||||||
|
Note: Hawtio does a higher level role check because -Dhawtio.role=guest is configured in the artemis run script.
|
||||||
|
The user 'jdoe' has the required "guest" role configured in keycloak.
|
||||||
|
|
||||||
|
````
|
||||||
|
org.keycloak.adapters.jaas.BearerTokenLoginModule required
|
||||||
|
keycloak-config-file="${artemis.instance}/etc/keycloak-bearer-token.json"
|
||||||
|
````
|
||||||
|
The contents of keycloak-bearer-token.json defines the url to connect to keycloak and the relevant keycloak realm.
|
||||||
|
Of note are:
|
||||||
|
````
|
||||||
|
"use-resource-role-mappings": true,
|
||||||
|
````
|
||||||
|
which is required because the relevant Artemis roles are intentionally scoped to the keycloak clients.
|
||||||
|
|
||||||
|
````
|
||||||
|
"principal-attribute": "preferred_username",
|
||||||
|
````
|
||||||
|
which tells keycloak the attribute to use as the name of the keycloak principal that maps the bearer token. The default
|
||||||
|
value 'sub' pulls in the system id of the user which is less human-readable and has no meaning outside keycloak.
|
||||||
|
|
||||||
|
|
||||||
|
###### activemq realm
|
||||||
|
|
||||||
|
The broker has to support clients that present plain credentials. In the activemq realm, the keycloak
|
||||||
|
DirectAccessGrantsLoginModule validates these credentials against keycloak and populates the relevant roles.
|
||||||
|
|
||||||
|
````
|
||||||
|
org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule required
|
||||||
|
keycloak-config-file="${artemis.instance}/etc/keycloak-direct-access.json"
|
||||||
|
role-principal-class=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
||||||
|
;
|
||||||
|
````
|
||||||
|
The 'keycloak-direct-access.json' configuration for this keycloak client is different because of the nature of
|
||||||
|
the credentials. The "artemis-broker" client must authenticate with keycloak using a secret. TLS may also make
|
||||||
|
sense here.
|
||||||
|
````
|
||||||
|
"credentials": {
|
||||||
|
"secret": "9699685c-8a30-45cf-bf19-0d38bbac5fdc"
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
Further, Artemis sessions will want to verify there is a valid Artemis UserPrincipal such that it can verify
|
||||||
|
authentication and potentially populate a message header.
|
||||||
|
The PrincipalConversionLoginModule does the necessary transformation on the first KeycloakPrincipal it encounters.
|
||||||
|
````
|
||||||
|
|
||||||
|
org.apache.activemq.artemis.spi.core.security.jaas.PrincipalConversionLoginModule required
|
||||||
|
principalClassList=org.keycloak.KeycloakPrincipal
|
||||||
|
````
|
||||||
|
|
||||||
|
###### Broker authentication configuration
|
||||||
|
|
||||||
|
The broker is configured to use the 'activemq' jaas domain via the 'jaas-security' domain in
|
||||||
|
bootstrap.xml.
|
||||||
|
|
||||||
|
````
|
||||||
|
<jaas-security domain="activemq"/>
|
||||||
|
````
|
||||||
|
|
||||||
|
The broker.xml security-settings for the Info address, it locks down consumption to users with the "amq" role while
|
||||||
|
users with the "guest" role can send messages.
|
||||||
|
|
||||||
|
````
|
||||||
|
<!-- only amq role can consume, guest role can send -->
|
||||||
|
<security-setting match="Info">
|
||||||
|
<permission roles="amq" type="createDurableQueue"/>
|
||||||
|
<permission roles="amq" type="deleteDurableQueue"/>
|
||||||
|
<permission roles="amq" type="createNonDurableQueue"/>
|
||||||
|
<permission roles="amq" type="deleteNonDurableQueue"/>
|
||||||
|
<permission roles="guest" type="send"/>
|
||||||
|
<permission roles="amq" type="consume"/>
|
||||||
|
</security-setting>
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
|
###### Web console delegate authentication configuration
|
||||||
|
|
||||||
|
The web console already uses the Artemis rolePrincipalClasses and JAAS to authenticate with the broker. When the console
|
||||||
|
delegates authentication to keycloak, the bearer token needs to be resolved to a JAAS subject such that it's roles can
|
||||||
|
be queried, this requires the use of the "console" jaas realm.
|
||||||
|
This is achieved with system property overrides, passed via the artemis.profile JAVA_ARGS from the pom.xml
|
||||||
|
command to create the broker using the artemis-maven-plugin.
|
||||||
|
|
||||||
|
JAVA_ARGS=".. -Dhawtio.rolePrincipalClasses=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
||||||
|
-Dhawtio.keycloakEnabled=true -Dhawtio.keycloakClientConfig=keycloak-js-client.json
|
||||||
|
-Dhawtio.authenticationEnabled=true -Dhawtio.realm=console"
|
||||||
|
|
||||||
|
Note the 'hawtio.realm=console' and the 'hawtio.keycloakClientConfig' in 'keycloak-js-client.json' which provides the keycloak
|
||||||
|
url, keycloak realm and client-id.
|
||||||
|
|
||||||
|
The keycloak login modules need access to keycloak jars and dependencies. These are copied into the lib directory of
|
||||||
|
the artemis instance in this example as part of broker creation via the pom.xml see: libListWithDeps
|
||||||
|
````
|
||||||
|
+- org.keycloak:keycloak-adapter-core:jar
|
||||||
|
+- org.keycloak:keycloak-core:jar
|
||||||
|
| +- org.keycloak:keycloak-common:jar
|
||||||
|
| | \- com.sun.activation:jakarta.activation:jar
|
||||||
|
| +- org.bouncycastle:bcprov-jdk15on:jar
|
||||||
|
| +- org.bouncycastle:bcpkix-jdk15on:jar
|
||||||
|
| +- com.fasterxml.jackson.core:jackson-core:jar
|
||||||
|
| \- com.fasterxml.jackson.core:jackson-databind:jar
|
||||||
|
| \- com.fasterxml.jackson.core:jackson-annotations:jar
|
||||||
|
````
|
||||||
|
|
||||||
|
###### Keycloak server configuration
|
||||||
|
|
||||||
|
In the keycloak realm "artemis-keycloak-demo", described in ./src/main/resources/artemis-keycloak-demo-realm.json
|
||||||
|
the user "jdoe" has the 'guest' role while the user "mdoe" has an additional 'amq' role from their relevant keycloak
|
||||||
|
client's.
|
||||||
|
|
||||||
|
The new keycloak installation is started with a system property indicating that it should import it's state from
|
||||||
|
'artemis-keycloak-demo-realm.json'.
|
||||||
|
|
||||||
|
|
||||||
|
###### The example client
|
||||||
|
|
||||||
|
The example jms client connects as user "mdoe" and expects to consume a message from the "Info" address.
|
||||||
|
It will block till it gets a message, so we need to send a message to the Info address from the web console
|
||||||
|
(or from another client) to have the jms client exit, allowing the example to complete.
|
||||||
|
|
||||||
|
Feel free to explore the realm configuration in keycloak via the keycloak admin console, details at the start
|
||||||
|
of this file. Note the two configured clients: 'artemis-broker' and 'artemis-console'.
|
||||||
|
|
||||||
|
To send a message to the Info address from the Artemis web console:
|
||||||
|
|
||||||
|
login on to the web console:
|
||||||
|
http://localhost:8161/console
|
||||||
|
|
||||||
|
Note: you will be redirected to the keycloak login screen where you will authenticate your browser with keycloak.
|
||||||
|
login in with user/password: jdoe/password
|
||||||
|
|
||||||
|
Navigate to the Info address and send a message. The first sent may fail, the user/password are taken from the
|
||||||
|
preferences panel and there is no password stored by default. Configure a password for jdoe in your preferences
|
||||||
|
and send a message to the Info address.
|
||||||
|
|
||||||
|
The client will get this message, print out the user from the message auth header and exit this example.
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.artemis.jms.example;
|
||||||
|
|
||||||
|
import javax.jms.Connection;
|
||||||
|
import javax.jms.ConnectionFactory;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
import javax.jms.MessageConsumer;
|
||||||
|
import javax.jms.Session;
|
||||||
|
import javax.jms.Queue;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class KeycloakSecurityExample {
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws Exception {
|
||||||
|
|
||||||
|
boolean result = true;
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
InitialContext initialContext = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Step 1. Create an initial context to perform the JNDI lookup.
|
||||||
|
initialContext = new InitialContext();
|
||||||
|
|
||||||
|
// Step 2. perform lookup on the topics
|
||||||
|
Queue genericTopic = (Queue) initialContext.lookup("queue/Info");
|
||||||
|
|
||||||
|
// Step 3. perform a lookup on the Connection Factory
|
||||||
|
ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
|
||||||
|
|
||||||
|
|
||||||
|
// Step 4. block till we make a connection as mdoe
|
||||||
|
System.out.println("------------------------blocking on connection creation----------------");
|
||||||
|
|
||||||
|
while (connection == null) {
|
||||||
|
try {
|
||||||
|
connection = createConnection("mdoe", "password", cf);
|
||||||
|
connection.start();
|
||||||
|
} catch (JMSException expectedTillInfraStarted) {
|
||||||
|
System.out.println("---- expected error on connect till broker starts: " + expectedTillInfraStarted + ", retry in 10s");
|
||||||
|
TimeUnit.SECONDS.sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5. block till we get a message
|
||||||
|
System.out.println("------------------------blocking on message receipt from console----------------");
|
||||||
|
System.out.println("------------------------send to address Info as user: jdoe password: password----------------");
|
||||||
|
|
||||||
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageConsumer consumer = session.createConsumer(genericTopic);
|
||||||
|
|
||||||
|
Message receivedMsg = null;
|
||||||
|
while (receivedMsg == null) {
|
||||||
|
receivedMsg = consumer.receive(10000);
|
||||||
|
if (receivedMsg != null) {
|
||||||
|
String validatedUser = receivedMsg.getStringProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER.toString());
|
||||||
|
System.out.println("---------------------from: " + validatedUser + " -------------------------");
|
||||||
|
System.out.println("---------------------reveived: " + receivedMsg);
|
||||||
|
System.out.println("---------------------all done!------------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
System.out.println("-------------------------------------------------------------------------------------");
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (connection != null) {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Connection createConnection(final String username,
|
||||||
|
final String password,
|
||||||
|
final ConnectionFactory cf) throws JMSException {
|
||||||
|
return cf.createConnection(username, password);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
|
||||||
|
<core xmlns="urn:activemq:core">
|
||||||
|
|
||||||
|
<bindings-directory>./data/messaging/bindings</bindings-directory>
|
||||||
|
|
||||||
|
<journal-directory>./data/messaging/journal</journal-directory>
|
||||||
|
|
||||||
|
<large-messages-directory>./data/messaging/largemessages</large-messages-directory>
|
||||||
|
|
||||||
|
<paging-directory>./data/messaging/paging</paging-directory>
|
||||||
|
|
||||||
|
<populate-validated-user>true</populate-validated-user>
|
||||||
|
|
||||||
|
<!-- Acceptors -->
|
||||||
|
<acceptors>
|
||||||
|
<acceptor name="netty-acceptor">tcp://localhost:61616</acceptor>
|
||||||
|
</acceptors>
|
||||||
|
|
||||||
|
<!-- Other config -->
|
||||||
|
|
||||||
|
<security-settings>
|
||||||
|
<!-- only amq role can consume, guest role can send -->
|
||||||
|
<security-setting match="Info">
|
||||||
|
<permission roles="amq" type="createDurableQueue"/>
|
||||||
|
<permission roles="amq" type="deleteDurableQueue"/>
|
||||||
|
<permission roles="amq" type="createNonDurableQueue"/>
|
||||||
|
<permission roles="amq" type="deleteNonDurableQueue"/>
|
||||||
|
<permission roles="guest" type="send"/>
|
||||||
|
<permission roles="amq" type="consume"/>
|
||||||
|
</security-setting>
|
||||||
|
|
||||||
|
</security-settings>
|
||||||
|
|
||||||
|
<addresses>
|
||||||
|
<address name="Info">
|
||||||
|
<anycast>
|
||||||
|
<queue name="Info"/>
|
||||||
|
</anycast>
|
||||||
|
</address>
|
||||||
|
</addresses>
|
||||||
|
|
||||||
|
|
||||||
|
</core>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"realm": "artemis-keycloak-demo",
|
||||||
|
"resource": "artemis-console",
|
||||||
|
"auth-server-url": "http://localhost:8080/auth",
|
||||||
|
"principal-attribute": "preferred_username",
|
||||||
|
"use-resource-role-mappings": true,
|
||||||
|
"ssl-required": "external",
|
||||||
|
"confidential-port": 0
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"realm": "artemis-keycloak-demo",
|
||||||
|
"resource": "artemis-broker",
|
||||||
|
"auth-server-url": "http://localhost:8080/auth",
|
||||||
|
"use-resource-role-mappings": true,
|
||||||
|
"principal-attribute": "preferred_username",
|
||||||
|
"ssl-required": "external",
|
||||||
|
"credentials": {
|
||||||
|
"secret": "9699685c-8a30-45cf-bf19-0d38bbac5fdc"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"realm" : "artemis-keycloak-demo",
|
||||||
|
"clientId" : "artemis-console",
|
||||||
|
"url" : "http://localhost:8080/auth"
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Additional logger names to configure (root logger is always configured)
|
||||||
|
# Root logger option
|
||||||
|
loggers=org.eclipse.jetty,org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms.server,org.apache.activemq.artemis.integration.bootstrap,org.apache.activemq.audit.base,org.apache.activemq.audit.message,org.apache.activemq.audit.resource
|
||||||
|
|
||||||
|
# Root logger level
|
||||||
|
logger.level=INFO
|
||||||
|
# ActiveMQ Artemis logger levels
|
||||||
|
logger.org.apache.activemq.artemis.core.server.level=INFO
|
||||||
|
logger.org.apache.activemq.artemis.journal.level=INFO
|
||||||
|
logger.org.apache.activemq.artemis.utils.level=INFO
|
||||||
|
logger.org.apache.activemq.artemis.jms.level=INFO
|
||||||
|
logger.org.apache.activemq.artemis.integration.bootstrap.level=INFO
|
||||||
|
logger.org.eclipse.jetty.level=WARN
|
||||||
|
# Root logger handlers
|
||||||
|
logger.handlers=FILE,CONSOLE
|
||||||
|
|
||||||
|
# to enable audit change the level to INFO
|
||||||
|
logger.org.apache.activemq.audit.base.level=INFO
|
||||||
|
logger.org.apache.activemq.audit.base.handlers=AUDIT_FILE
|
||||||
|
logger.org.apache.activemq.audit.base.useParentHandlers=false
|
||||||
|
|
||||||
|
logger.org.apache.activemq.audit.resource.level=INFO
|
||||||
|
logger.org.apache.activemq.audit.resource.handlers=AUDIT_FILE
|
||||||
|
logger.org.apache.activemq.audit.resource.useParentHandlers=false
|
||||||
|
|
||||||
|
logger.org.apache.activemq.audit.message.level=INFO
|
||||||
|
logger.org.apache.activemq.audit.message.handlers=AUDIT_FILE
|
||||||
|
logger.org.apache.activemq.audit.message.useParentHandlers=false
|
||||||
|
|
||||||
|
# Console handler configuration
|
||||||
|
handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
|
||||||
|
handler.CONSOLE.properties=autoFlush
|
||||||
|
handler.CONSOLE.level=DEBUG
|
||||||
|
handler.CONSOLE.autoFlush=true
|
||||||
|
handler.CONSOLE.formatter=PATTERN
|
||||||
|
|
||||||
|
# File handler configuration
|
||||||
|
handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
|
||||||
|
handler.FILE.level=DEBUG
|
||||||
|
handler.FILE.properties=suffix,append,autoFlush,fileName
|
||||||
|
handler.FILE.suffix=.yyyy-MM-dd
|
||||||
|
handler.FILE.append=true
|
||||||
|
handler.FILE.autoFlush=true
|
||||||
|
handler.FILE.fileName=${artemis.instance}/log/artemis.log
|
||||||
|
handler.FILE.formatter=PATTERN
|
||||||
|
|
||||||
|
# Formatter pattern configuration
|
||||||
|
formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
|
||||||
|
formatter.PATTERN.properties=pattern
|
||||||
|
formatter.PATTERN.pattern=%d %-5p [%c] %s%E%n
|
||||||
|
|
||||||
|
#Audit logger
|
||||||
|
handler.AUDIT_FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
|
||||||
|
handler.AUDIT_FILE.level=INFO
|
||||||
|
handler.AUDIT_FILE.properties=suffix,append,autoFlush,fileName
|
||||||
|
handler.AUDIT_FILE.suffix=.yyyy-MM-dd
|
||||||
|
handler.AUDIT_FILE.append=true
|
||||||
|
handler.AUDIT_FILE.autoFlush=true
|
||||||
|
handler.AUDIT_FILE.fileName=${artemis.instance}/log/audit.log
|
||||||
|
handler.AUDIT_FILE.formatter=AUDIT_PATTERN
|
||||||
|
|
||||||
|
formatter.AUDIT_PATTERN=org.jboss.logmanager.formatters.PatternFormatter
|
||||||
|
formatter.AUDIT_PATTERN.properties=pattern
|
||||||
|
formatter.AUDIT_PATTERN.pattern=%d [AUDIT](%t) %s%E%n
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
console {
|
||||||
|
|
||||||
|
org.keycloak.adapters.jaas.BearerTokenLoginModule required
|
||||||
|
keycloak-config-file="${artemis.instance}/etc/keycloak-bearer-token.json"
|
||||||
|
role-principal-class=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
activemq {
|
||||||
|
|
||||||
|
org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule required
|
||||||
|
keycloak-config-file="${artemis.instance}/etc/keycloak-direct-access.json"
|
||||||
|
role-principal-class=org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
||||||
|
;
|
||||||
|
|
||||||
|
org.apache.activemq.artemis.spi.core.security.jaas.PrincipalConversionLoginModule required
|
||||||
|
principalClassList=org.keycloak.KeycloakPrincipal
|
||||||
|
;
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
|
||||||
|
connectionFactory.ConnectionFactory=tcp://localhost:61616
|
||||||
|
queue.queue/Info=Info
|
1
pom.xml
1
pom.xml
|
@ -1752,6 +1752,7 @@
|
||||||
<exclude>**/*.txt</exclude>
|
<exclude>**/*.txt</exclude>
|
||||||
<exclude>**/*.md</exclude>
|
<exclude>**/*.md</exclude>
|
||||||
<exclude>etc/ide-settings/**</exclude>
|
<exclude>etc/ide-settings/**</exclude>
|
||||||
|
<exclude>**/*.json</exclude>
|
||||||
<exclude>docs/**/*.json</exclude>
|
<exclude>docs/**/*.json</exclude>
|
||||||
<exclude>docs/**/_book/</exclude>
|
<exclude>docs/**/_book/</exclude>
|
||||||
<exclude>docs/**/_layouts/</exclude>
|
<exclude>docs/**/_layouts/</exclude>
|
||||||
|
|
Loading…
Reference in New Issue