From 864f95ace288f12a1e24c57724f0a5c02d6a06e7 Mon Sep 17 00:00:00 2001 From: Harald Pehl Date: Thu, 23 Nov 2023 11:53:15 +0100 Subject: [PATCH 1/6] Initial content, data and layout for guides --- _config.yml | 29 +- _data/guides.yaml | 31 ++ _data/projectfooter.yml | 2 + _includes/header.html | 3 + _includes/index-guides.html | 20 ++ _layouts/guide.html | 15 + _layouts/guides.html | 5 + _sass/layouts/guides.scss | 3 + assets/css/main.scss | 1 + guides/_includes/_attributes.adoc | 10 + guides/_includes/_prerequisites.adoc | 9 + guides/application-logging.adoc | 159 +++++++++ guides/automate-with-ansible.adoc | 493 +++++++++++++++++++++++++++ guides/index.md | 5 + guides/template.adoc | 41 +++ guides/use-microprofile-config.adoc | 131 +++++++ guides/use-microprofile-lra.adoc | 165 +++++++++ 17 files changed, 1109 insertions(+), 13 deletions(-) create mode 100644 _data/guides.yaml create mode 100644 _includes/index-guides.html create mode 100644 _layouts/guide.html create mode 100644 _layouts/guides.html create mode 100644 _sass/layouts/guides.scss create mode 100644 guides/_includes/_attributes.adoc create mode 100644 guides/_includes/_prerequisites.adoc create mode 100644 guides/application-logging.adoc create mode 100644 guides/automate-with-ansible.adoc create mode 100644 guides/index.md create mode 100644 guides/template.adoc create mode 100644 guides/use-microprofile-config.adoc create mode 100644 guides/use-microprofile-lra.adoc diff --git a/_config.yml b/_config.yml index 9a4f3571..b6228e40 100644 --- a/_config.yml +++ b/_config.yml @@ -64,24 +64,27 @@ asciidoctor: # Pages permalink defaults: - - - scope: + - scope: + path: "" type: "posts" values: permalink: /news/:year/:month/:day/:title/ - - - scope: + - scope: path: "" # an empty string here means all files in the project type: "docs" # previously `post` in Jekyll 2.2. values: layout: "docs" + - scope: + path: "guides" # an empty string here means all files in the project + values: + layout: "guide" ############################################################ # Site configuration for the Jekyll 3 Pagination Gem # The values here represent the defaults if nothing is set pagination: - - # Site-wide kill switch, disabled here it doesn't run at all + + # Site-wide kill switch, disabled here it doesn't run at all enabled: true # Set to 'true' to enable pagination debugging. This can be enabled in the site config or only for individual pagination pages @@ -95,7 +98,7 @@ pagination: # The permalink structure for the paginated pages (this can be any level deep) permalink: '/page/:num/' # Pages are index.html inside this folder (default) - #permalink: '/page/:num.html' # Pages are simple html files + #permalink: '/page/:num.html' # Pages are simple html files #permalink: '/page/:num' # Pages are html files, linked jekyll extensionless permalink style. # Optional the title format for the paginated pages (supports :title for original page title, :num for pagination page number, :max for total number of pages) @@ -103,7 +106,7 @@ pagination: # Limit how many pagenated pages to create (default: 0, means all) limit: 0 - + # Optional, defines the field that the posts should be sorted on (omit to default to 'date') sort_field: 'date' @@ -116,13 +119,13 @@ pagination: # Optional, the default tag to use, omit to disable tag: '' - # Optional, the default locale to use, omit to disable (depends on a field 'locale' to be specified in the posts, + # Optional, the default locale to use, omit to disable (depends on a field 'locale' to be specified in the posts, # in reality this can be any value, suggested are the Microsoft locale-codes (e.g. en_US, en_GB) or simply the ISO-639 language code ) - locale: '' + locale: '' - # Optional,omit or set both before and after to zero to disable. - # Controls how the pagination trail for the paginated pages look like. - trail: + # Optional,omit or set both before and after to zero to disable. + # Controls how the pagination trail for the paginated pages look like. + trail: before: 2 after: 2 diff --git a/_data/guides.yaml b/_data/guides.yaml new file mode 100644 index 00000000..38b45a43 --- /dev/null +++ b/_data/guides.yaml @@ -0,0 +1,31 @@ + +--- +categories: + - category: Get Started + cat-id: get-started + guides: + - title: Get Started With WildFly + url: /get-started + description: Build and run a Jakarta EE application with WildFly in a few minutes + - category: Observability + cat-id: observability + guides: + - title: Configure Application Logging + url: /guides/application-logging + description: Learn how to setup and configure logging in WildFly. + - category: Eclipse MicroProfile + cat-id: microprofile + guides: + - title: Use MicroProfile Config With WildFly + url: /guides/use-microprofile-config + description: Discover how to use MicroProfile Config With WildFly. + - title: Use MicroProfile LRA With WildFly + url: /guides/use-microprofile-lra + description: Discover how to use MicroProfile LRA With WildFly. + - category: Automation + cat-id: automation + guides: + - title: Deploy WildFly With Ansible + url: /guides/automate-with-ansible + description: Learn how to automate WildFly deployments with Ansible. + diff --git a/_data/projectfooter.yml b/_data/projectfooter.yml index 05bab3e8..dadc307f 100644 --- a/_data/projectfooter.yml +++ b/_data/projectfooter.yml @@ -11,6 +11,8 @@ links: url: /get-started - page: Github url: https://github.com/wildfly/wildfly + - page: Guides + url: /guides - title: Contribute subfolderitems: - page: Submit a bug diff --git a/_includes/header.html b/_includes/header.html index a6faa5c7..4832402e 100644 --- a/_includes/header.html +++ b/_includes/header.html @@ -18,6 +18,9 @@
  • Docs
  • +
  • + Guides +
  • Downloads
  • diff --git a/_includes/index-guides.html b/_includes/index-guides.html new file mode 100644 index 00000000..aad2221a --- /dev/null +++ b/_includes/index-guides.html @@ -0,0 +1,20 @@ +
    +

    {{ page.title }}

    +
    + +
    +
    + {% for item in site.data["guides"].categories %} +

    {{ item.category }}

    + {% for guide in item.guides %} +
    +
    +

    {{ guide.title}}

    +
    +
    {{ guide.description | markdownify }}
    +
    Read More >>
    +
    + {% endfor %} + {% endfor %} +
    +
    \ No newline at end of file diff --git a/_layouts/guide.html b/_layouts/guide.html new file mode 100644 index 00000000..963ec292 --- /dev/null +++ b/_layouts/guide.html @@ -0,0 +1,15 @@ +--- +layout: base +--- + +
    +
    +

    {{page.title}} {{page.docversion}}

    +
    +
    +
    + {{ content }} +
    +
    < Back to Guides
    +
    +
    \ No newline at end of file diff --git a/_layouts/guides.html b/_layouts/guides.html new file mode 100644 index 00000000..568801cf --- /dev/null +++ b/_layouts/guides.html @@ -0,0 +1,5 @@ +--- +layout: base +--- + +{% include index-guides.html %} diff --git a/_sass/layouts/guides.scss b/_sass/layouts/guides.scss new file mode 100644 index 00000000..35eff77d --- /dev/null +++ b/_sass/layouts/guides.scss @@ -0,0 +1,3 @@ +.guide { + padding-bottom: 3rem; +} diff --git a/assets/css/main.scss b/assets/css/main.scss index 49f418f4..019cba8d 100644 --- a/assets/css/main.scss +++ b/assets/css/main.scss @@ -24,5 +24,6 @@ $content-width: 1000px; @import "layouts/error-page"; @import "layouts/contribute"; @import "layouts/getstarted"; +@import "layouts/guides"; @import "layouts/about"; @import "layouts/post"; diff --git a/guides/_includes/_attributes.adoc b/guides/_includes/_attributes.adoc new file mode 100644 index 00000000..e0ca4006 --- /dev/null +++ b/guides/_includes/_attributes.adoc @@ -0,0 +1,10 @@ +// WildFly Major version to link to its documentation +:wildfly-version: 29 +// Minimal version of Maven +:maven-version: 3.9+ +// Minimal Version of JDK +:jdk-minimal-version: 11+ +// . +:toc: right +// Default time to display in the prerequisites section +:prerequisites-time: 15 \ No newline at end of file diff --git a/guides/_includes/_prerequisites.adoc b/guides/_includes/_prerequisites.adoc new file mode 100644 index 00000000..ec4baced --- /dev/null +++ b/guides/_includes/_prerequisites.adoc @@ -0,0 +1,9 @@ +[[prerequisites]] +== Prerequisites + +To complete this guide, you need: + +* Roughly {prerequisites-time} minutes +* JDK {jdk-minimal-version} installed with `JAVA_HOME` configured appropriately +* Apache Maven {maven-version} +* You have completed the https://wildfly.org/getstarted/[Get Started Guide]. diff --git a/guides/application-logging.adoc b/guides/application-logging.adoc new file mode 100644 index 00000000..97a5c4a9 --- /dev/null +++ b/guides/application-logging.adoc @@ -0,0 +1,159 @@ += Configure Logging for your Application +:summary: Learn how to use logging in your application and configure WildFly to display them +:includedir: _includes +include::{includedir}/_attributes.adoc[] +// you can override any attributes eg to lengthen the +// time to complete the guide +:prerequisites-time: 10 + +TODO: Add a summary of what you achieve in this guide. +Something like: + +In this guide, you will learn how to use logging in your application and configure WildFly to +display the logs at the level you want. + +include::{includedir}/_prerequisites.adoc[] + +To use logging in our application, we will add a dependency to `org.jboss.logging:jboss-logging` in the Maven `pom.xml` file. +Then, we will add a few logs in our code at different levels. +Finally we will configure WildFly to change the log level of our application logs independently of WildFly own logs. + +== Add Dependency to JBoss Logging + +In order to use JBoss Logging in our application, we need to add a dependency to it in the `pom.xml`. + +The dependency is defined as: + +[source,xml] +---- + + org.jboss.logging + jboss-logging + provided + +---- + +You need to add it to the `` section of the `pom.xml`: + +[source,xml] +---- + + ... + + +---- + +== Add Logging to the Application + +As an example, you can update the `GettingStartedService.java` file to add logging to the application at different levels: + +[source,java] +---- +package org.wildfly.examples; + +import jakarta.enterprise.context.ApplicationScoped; +import org.jboss.logging.Logger; + +@ApplicationScoped +public class GettingStartedService { + + private static Logger log = Logger.getLogger(GettingStartedService.class.getName()); + + public String hello(String name) { + if (log.isEnabled(Logger.Level.TRACE)) { + log.trace("called method with: " + name); + } + + String out = String.format("Hello '%s'.", name); + log.info("returning: " + out); + return out; + } +} +---- + +You added a `log` Logger that can log message with the category correspondig to the class package `org.wildfly.examples`. +You also added two logging calls, one at the `TRACE` level and the other one at the `INFO` level. + +If you run the integration tests with `mvn clean verify`, you will only see the logs at the `INFO` level in the standard output: + +[source,bash] +---- +$ mvn clean verify +... +15:18:08,482 INFO [org.wildfly.examples.GettingStartedService] (default task-1) returning: Hello 'World'. +... +---- + +By default, WildFly only displays `INFO` logs on the console. +Let's now configure WildFly to display our application logs at the `TRACE` level. + +== Configure Logging in WildFly Subsystem + +The configuration of logging is done by WildFly in its `logging` subsystem. +There are different ways to modify WildFly configuration but as we used the `wildfly-maven-plugin` to provision WildFly, +we can pass a CLI script so that WildFly configuration will be modified whenever we invoke `mvn package`. + +First, we add a `configuration.cli` in the `src/main/scripts` directory: + +[source] +---- +# let the console display TRACE logs +/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level, value=TRACE) +# create the logger for our code (with the category org.wildfly.examples corresponding to our package) +/subsystem=logging/logger=org.wildfly.examples:add(level=TRACE) +---- + +This script contains the management operations to change WildFly configuration. We could invoke any management operations but in this case, +we only modify the `/subsystem=logging` resources that control the logging aspects. + +You then need to modify the `wildfly-maven-plugin` configuration in `pom.xml` to execute this: + +Copy the XML snippet: + +[source,xml] +---- + + + + + + + +---- + +And add it to the `` section of the `wildfly-maven-plugin`: + +[source] +---- + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.maven.plugin} + + ... + + + +---- + +With that change in place, if you provision WildFly and run the integration tests again, both log calls are now displayed: + +[source] +---- +$ mvn clean verify + +... +16:04:22,260 TRACE [org.wildfly.examples.GettingStartedService] (default task-2) called method with: World +16:04:22,260 INFO [org.wildfly.examples.GettingStartedService] (default task-2) returning: Hello 'World'. +... +---- + +== Next Steps + +WildFly provides extensive logging configuration. You can learn more by reading WildFly's https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Logging[Logging Subsystem Configuration Guide] and its https://docs.wildfly.org/{wildfly-version}/wildscribe/subsystem/logging/[model reference]. + +[[references]] +== References + +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Logging[Logging Subsystem Configuration Guide] +* https://docs.wildfly.org/{wildfly-version}/wildscribe/subsystem/logging/[Logging Subsystem Model Reference] diff --git a/guides/automate-with-ansible.adoc b/guides/automate-with-ansible.adoc new file mode 100644 index 00000000..d629adf0 --- /dev/null +++ b/guides/automate-with-ansible.adoc @@ -0,0 +1,493 @@ += Deploy WildFly using Ansible +:summary: Learn how to automate WildFly deployments with Ansible +:includedir: _includes +include::{includedir}/_attributes.adoc[] +// you can override any attributes eg to lengthen the +// time to complete the guide +:prerequisites-time: 20 + +In this brief demonstration, we’ll set up and run three instances of WildFly on the same machine (localhost). Together they will form a cluster. It’s a rather classic setup, where the appservers needs to synchronize the content of their application’s session to ensure fail over if one of the instances fails. This configuration guarantees that, if one instance fails while processing a request, another one can pick up the work without any data loss. Note that we’ll use a multicast to discover the members of the cluster and ensure that the cluster’s formation is fully automated and dynamic. + +include::{includedir}/_prerequisites.adoc[] + +== Install Ansible and its collection for WildFly + +On a Linux system using a package manager, installing Ansible is pretty straightforward: + +[source,bash] +---- +$ sudo dnf install ansible-core +---- + +Please refer to the documentation available online for installation on other operating system. Note that this demonstration assumes you are running both the Ansible controller and the target (same machine in our case) on a Linux system. However, it should work on any other operating system with a few adjustements. + +Before going further, double check that you are running a recent enough version of Ansible (2.12 or above will do, but 2.9 is the bare minimum): + +[source,bash] +---- +$ ansible --version +ansible [core 2.14.1] + config file = /etc/ansible/ansible.cfg + configured module search path = ['/home/rpelisse/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] + ansible python module location = /usr/lib/python3.11/site-packages/ansible + ansible collection location = /home/rpelisse/.ansible/collections:/usr/share/ansible/collections + executable location = /usr/bin/ansible + python version = 3.11.0 (main, Oct 24 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-2)] (/usr/bin/python3) + jinja version = 3.0.3 + libyaml = True +---- + +The next, and last, step to ready your Ansible environment is to install the Ansible collection for WildFly on the controller (the machine that will run Ansible): + +[source,bash] +---- +$ ansible-galaxy collection install middleware_automation.wildfly +Starting galaxy collection install process +Process install dependency map +Starting collection install process +Downloading https://galaxy.ansible.com/download/middleware_automation-wildfly-1.2.2.tar.gz to /root/.ansible/tmp/ansible-local-25jj_dxqei/tmpvb6d55ho/middleware_automation-wildfly-1.2.2-33znbzkb +Downloading https://galaxy.ansible.com/download/middleware_automation-redhat_csp_download-1.2.2.tar.gz to /root/.ansible/tmp/ansible-local-25jj_dxqei/tmpvb6d55ho/middleware_automation-redhat_csp_download-1.2.2-3apb_j2g +Installing 'middleware_automation.wildfly:1.2.2' to '/root/.ansible/collections/ansible_collections/middleware_automation/wildfly' +middleware_automation.wildfly:1.2.2 was installed successfully +Downloading https://galaxy.ansible.com/download/community-general-6.1.0.tar.gz to /root/.ansible/tmp/ansible-local-25jj_dxqei/tmpvb6d55ho/community-general-6.1.0-rr64e3dg +Installing 'middleware_automation.redhat_csp_download:1.2.2' to '/root/.ansible/collections/ansible_collections/middleware_automation/redhat_csp_download' +middleware_automation.redhat_csp_download:1.2.2 was installed successfully +Installing 'community.general:6.1.0' to '/root/.ansible/collections/ansible_collections/community/general' +community.general:6.1.0 was installed successfully +---- + +== Set up the WildFly cluster + +For simplicity’s sake and to allow you to reproduce this demonstration on a single machine (physical or virtual) or even a container, we opted to deploy our three instances on one target. We chose localhost as a target, so that the demonstration can even be performed without a remote host. + +There are essentially two steps to set up the WildFly cluster: + +. Install WildFly on the targeted hosts (here just localhost). This means downloading the archive from this website and decompressing the archive in the appropriate directory (JBOSS_HOME). These tasks are handled by the wildfly_install role supplied by Ansible collection for WildFly. +. Create the configuration files to run several instances of WildFly. Because we’re running multiple instances on a single host, you also need to ensure that each instance has its own subdirectories and set of ports, so that the instances can coexist and communicate. Fortunately, this functionality is provided by a role within the Ansible collection called wildfly_systemd. + +=== Ansible playbook to install WildFly + +Here is the playbook we'll use to deploy our clusters. Its content is relatively self-explanitory, at least if you are somewhat familiar with the Ansible syntax. + +[source, yml] +---- +- name: "WildFly installation and configuration" + hosts: "{{ hosts_group_name | default('localhost') }}" + become: yes + vars: + wildfly_install_workdir: '/opt/' + wildfly_config_base: standalone-ha.xml + wildfly_version: 27.0.1.Final + wildfly_java_package_name: java-11-openjdk-headless.x86_64 + wildfly_home: "/opt/wildfly-{{ wildfly_version }}" + + instance_http_ports: + - 8080 + - 8180 + - 8280 + app: + name: 'info-1.2.war' + url: 'https://drive.google.com/uc?export=download&id=13K7RCqccgH4zAU1RfOjYMehNaHB0A3Iq' + collections: + - middleware_automation.wildfly + roles: + - role: wildfly_install + tasks: + + - name: "Set up for WildFly instance {{ item }}." + ansible.builtin.include_role: + name: wildfly_systemd + vars: + wildfly_config_base: 'standalone-ha.xml' + wildfly_instance_id: "{{ item }}" + instance_name: "wildfly-{{ wildfly_instance_id }}" + wildfly_config_name: "{{ instance_name }}.xml" + wildfly_basedir_prefix: "/opt/{{ instance_name }}" + service_systemd_env_file: "/etc/wildfly-{{ item }}.conf" + service_systemd_conf_file: "/usr/lib/systemd/system/wildfly-{{ item }}.service" + loop: "{{ range(0,3) | list }}" + + - name: "Wait for each instance HTTP ports to become available." + ansible.builtin.wait_for: + port: "{{ item }}" + loop: "{{ instance_http_ports }}" + + - name: "Checks that WildFly server is running and accessible." + ansible.builtin.get_url: + url: "http://localhost:{{ port }}/" + dest: "/opt/{{ port }}" + loop: "{{ instance_http_ports }}" + loop_control: + loop_var: port +---- + +In short, this playbook uses the Ansible collection for WildFly to, first, install the appserver by using the wildfly_install role. This will download all the artifacts, create the required system groups and users, install dependency (unzip) and so on. At the end of its execution, all the tidbits required to run WildFly on the target host are installed, but the server is not yet running. That’s what happening in the next step. + +In the tasks section of the playbook, we then call on another role provided by the collection: wildfly_systemd. This role will take care of integrating WildFly, as a regular system service, into the service manager. Here, we use a loop to ensure that we create not one, but three different services. Each one will have the same configuration (standalone-ha.xml) but runs on different ports, using a different set of directories to store its data. + +=== Run the playbook! + +Now, let’s run our Ansible playbook and observe its output: + +[source, bash] +---- +$ ansible-playbook -i inventory playbook.yml +PLAY [Converge] **************************************************************** + +TASK [Gathering Facts] ********************************************************* +ok: [localhost] + +TASK [wildfly_install : Validating arguments against arg spec 'main'] ********** +ok: [localhost] + +TASK [wildfly_install : Ensures prerequirements are fullfilled.] *************** +included: /work/roles/wildfly_install/tasks/prereqs.yml for localhost + +TASK [wildfly_install : Check that required packages list has been provided.] *** +ok: [localhost] + +TASK [wildfly_install : Prepare packages list] ********************************* +skipping: [localhost] + +TASK [wildfly_install : Add JDK package java-11-openjdk-headless to packages list] *** +ok: [localhost] + +TASK [wildfly_install : Install required packages (4)] ************************* +changed: [localhost] + +TASK [wildfly_install : Ensures required local user exists.] ******************* +included: /work/roles/wildfly_install/tasks/user.yml for localhost + +TASK [wildfly_install : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_install : Set wildfly group] ************************************* +ok: [localhost] + +TASK [wildfly_install : Ensure group wildfly exists.] ************************** +changed: [localhost] + +TASK [wildfly_install : Ensure user wildfly exists.] *************************** +changed: [localhost] + +TASK [wildfly_install : Ensure workdir /opt/wildfly/ exists.] ****************** +changed: [localhost] + +TASK [wildfly_install : Ensure archive_dir /opt/wildfly/ exists.] ************** +ok: [localhost] + +TASK [wildfly_install : Ensure server is installed] **************************** +included: /work/roles/wildfly_install/tasks/install.yml for localhost + +TASK [wildfly_install : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_install : Check local download archive path] ********************* +ok: [localhost] + +TASK [wildfly_install : Set download paths] ************************************ +ok: [localhost] + +TASK [wildfly_install : Check target archive: /opt/wildfly//wildfly-27.0.0.Final.zip] *** +ok: [localhost] + +TASK [wildfly_install : Retrieve archive from website: https://github.com/wildfly/wildfly/releases/download] *** +included: /work/roles/wildfly_install/tasks/install/web.yml for localhost + +TASK [wildfly_install : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_install : Download zipfile from https://github.com/wildfly/wildfly/releases/download/27.0.0.Final/wildfly-27.0.0.Final.zip into /work/wildfly-27.0.0.Final.zip] *** +ok: [localhost] + +TASK [wildfly_install : Retrieve archive from RHN] ***************************** +skipping: [localhost] + +TASK [wildfly_install : Install server using RPM] ****************************** +skipping: [localhost] + +TASK [wildfly_install : Check downloaded archive] ****************************** +ok: [localhost] + +TASK [wildfly_install : Copy archive to target nodes] ************************** +changed: [localhost] + +TASK [wildfly_install : Check target archive: /opt/wildfly//wildfly-27.0.0.Final.zip] *** +ok: [localhost] + +TASK [wildfly_install : Read target directory information: /opt/wildfly/wildfly-27.0.0.Final/] *** +ok: [localhost] + +TASK [wildfly_install : Check target directory state: /opt/wildfly/wildfly-27.0.0.Final/] *** +ok: [localhost] + +TASK [wildfly_install : Extract files from /opt/wildfly//wildfly-27.0.0.Final.zip into /opt/wildfly/.] *** +changed: [localhost] + +TASK [wildfly_install : Note: decompression was not executed] ****************** +skipping: [localhost] + +TASK [wildfly_install : Read information on server home directory: /opt/wildfly/wildfly-27.0.0.Final/] *** +ok: [localhost] + +TASK [wildfly_install : Check state of server home directory: /opt/wildfly/wildfly-27.0.0.Final/] *** +ok: [localhost] + +TASK [wildfly_install : Set instance name] ************************************* +ok: [localhost] + +TASK [wildfly_install : Deploy configuration] ********************************** +changed: [localhost] + +TASK [wildfly_install : Ensure required parameters for cumulative patch application are provided.] *** +skipping: [localhost] + +TASK [Apply latest cumulative patch] ******************************************* +skipping: [localhost] + +TASK [wildfly_install : Ensure required parameters for elytron adapter are provided.] *** +skipping: [localhost] + +TASK [Install elytron adapter] ************************************************* +skipping: [localhost] + +TASK [wildfly_install : Check wildfly install directory state] ***************** +ok: [localhost] + +TASK [wildfly_install : Validate conditions] *********************************** +ok: [localhost] + +TASK [wildfly_systemd : Validating arguments against arg spec 'main'] ********** +ok: [localhost] + +TASK [wildfly_systemd : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_systemd : Check current EAP patch installed] ********************* +skipping: [localhost] + +TASK [wildfly_systemd : Check arguments for yaml configuration] **************** +skipping: [localhost] + +TASK [Ensure required local user and group exists.] **************************** + +TASK [wildfly_install : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_install : Set wildfly group] ************************************* +ok: [localhost] + +TASK [wildfly_install : Ensure group wildfly exists.] ************************** +ok: [localhost] + +TASK [wildfly_install : Ensure user wildfly exists.] *************************** +ok: [localhost] + +TASK [wildfly_systemd : Set destination directory for configuration] *********** +ok: [localhost] + +TASK [wildfly_systemd : Set instance destination directory for configuration] *** +ok: [localhost] + +TASK [wildfly_systemd : Check arguments] *************************************** +skipping: [localhost] + +TASK [wildfly_systemd : Set base directory for instance] *********************** +skipping: [localhost] + +TASK [wildfly_systemd : Check arguments] *************************************** +skipping: [localhost] + +TASK [wildfly_systemd : Set instance name] ************************************* +skipping: [localhost] + +TASK [wildfly_systemd : Set instance name] ************************************* +skipping: [localhost] + +TASK [wildfly_systemd : Set bind address] ************************************** +ok: [localhost] + +TASK [wildfly_systemd : Create basedir /opt/wildfly/wildfly-27.0.0.Final//standalone for instance: wildfly] *** +ok: [localhost] + +TASK [wildfly_systemd : Create deployment directories for instance: wildfly] *** +ok: [localhost] + +TASK [wildfly_systemd : Deploy configuration] ********************************** +ok: [localhost] + +TASK [wildfly_systemd : Include YAML configuration extension] ****************** +skipping: [localhost] + +TASK [wildfly_systemd : Check YAML configuration is disabled] ****************** +ok: [localhost] + +TASK [wildfly_systemd : Set systemd envfile destination] *********************** +ok: [localhost] + +TASK [wildfly_systemd : Determine JAVA_HOME for selected JVM RPM] ************** +ok: [localhost] + +TASK [wildfly_systemd : Set systemd unit file destination] ********************* +ok: [localhost] + +TASK [wildfly_systemd : Deploy service instance configuration: /etc//wildfly.conf] *** +changed: [localhost] + +TASK [wildfly_systemd : Deploy Systemd configuration for service: /usr/lib/systemd/system/wildfly.service] *** +changed: [localhost] + +TASK [wildfly_systemd : Perform daemon-reload to ensure the changes are picked up] *** +ok: [localhost] + +TASK [wildfly_systemd : Ensure service is started] ***************************** +included: /work/roles/wildfly_systemd/tasks/service.yml for localhost + +TASK [wildfly_systemd : Check arguments] *************************************** +ok: [localhost] + +TASK [wildfly_systemd : Set instance wildfly state to started] ***************** +changed: [localhost] + +TASK [wildfly_driver : Validating arguments against arg spec 'main'] *********** +ok: [localhost] + +TASK [wildfly_driver : Check arguments] **************************************** +ok: [localhost] + +TASK [wildfly_driver : Check module directory: /opt/wildfly/wildfly-27.0.0.Final//modules/org/postgresql/main] *** +ok: [localhost] + +TASK [wildfly_driver : Set up module dir for JDBC Driver: /opt/wildfly/wildfly-27.0.0.Final//modules/org/postgresql/main] *** +changed: [localhost] + +TASK [wildfly_driver : Retrieve JDBC Driver from https://repo.maven.apache.org/maven2/org/postgresql/postgresql/9.4.1212/postgresql-9.4.1212.jar] *** +changed: [localhost] + +TASK [wildfly_driver : Set source template path] ******************************* +ok: [localhost] + +TASK [wildfly_driver : Deploy module.xml for JDBC Driver] ********************** +changed: [localhost] + +TASK [wildfly_utils : Validating arguments against arg spec 'main'] ************ +ok: [localhost] + +TASK [Install second driver with wildfly_driver role] ************************** + +TASK [wildfly_driver : Validating arguments against arg spec 'main'] *********** +ok: [localhost] + +TASK [wildfly_driver : Check arguments] **************************************** +ok: [localhost] + +TASK [wildfly_driver : Check module directory: /opt/wildfly/wildfly-27.0.0.Final//modules/org/mariadb/main] *** +ok: [localhost] + +TASK [wildfly_driver : Set up module dir for JDBC Driver: /opt/wildfly/wildfly-27.0.0.Final//modules/org/mariadb/main] *** +changed: [localhost] + +TASK [wildfly_driver : Retrieve JDBC Driver from https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.7.4/mariadb-java-client-2.7.4.jar] *** +changed: [localhost] + +TASK [wildfly_driver : Set source template path] ******************************* +ok: [localhost] + +TASK [wildfly_driver : Deploy module.xml for JDBC Driver] ********************** +changed: [localhost] + +PLAY RECAP ********************************************************************* +localhost : ok=70 changed=16 unreachable=0 failed=0 skipped=16 rescued=0 ignored=0 + + +---- + +Note that the playbook is not that long, but it does a lot for us. It performs almost 100 different tasks! Starting by automatically installing the dependencies, including the JVM required by WildFly, along with downloading its binaries. And the wildfly_systemd role does even more, effortlessly setting up three distinct services, each with its own set of ports and directory layout to store instance-specific data. + +Even better, the WildFly installation is NOT duplicated. All of the binaries live under the /opt/wildfly-27.0.1 directory, but all the data files of each instance are stored in separate folders. This means that we just need to update the binaries, once, and then restart the instances, to deploy a patch or upgrade to a new version of WildFly. + +On top of everything, we configured the instances to use the standalone-ha.xml configuration as the baseline, so they are already set up for clustering. + +=== Check that everything worked as expected + +The easiest way to confirm that the playbook did indeed install WildFly and started three instances of the appserver is to use the systemctl command to check the associate services state: + +[source, bash] +---- +● wildfly.service - JBoss EAP (standalone mode) + Loaded: loaded (/usr/lib/systemd/system/wildfly.service; enabled; vendor preset: disabled) + Active: active (running) since Tue 2023-01-10 09:24:21 UTC; 6h ago + Main PID: 857 (standalone.sh) + CGroup: /system.slice/wildfly.service + ├─ 857 /bin/sh /opt/wildfly/wildfly-27.0.0.Final/bin/standalone.sh -c wildfly.xml -b 0.0.0.0 -bmanagement 127.0.0.1 -Djboss.bind.address.private=127.0.0.1 -Djboss.default.multicast.address=230.0.0.4 -Djboss.server.config.dir=/opt/wildfly/wildfly-27.0.0.Final//standalone/configuration/ -Djboss.server.base.dir=/opt/wildfly/wildfly-27.0.0.Final//standalone -Djboss.tx.node.id=wildfly -Djboss.node.name=wildfly -Dwildfly.statistics-enabled=false + └─1001 /usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el8_6.x86_64/bin/java -D[Standalone] -server -Xmx1024M -Xms512M --add-exports=java.desktop/sun.awt=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.url.ldap=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.url.ldaps=ALL-UNNAMED --add-exports=jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED -Dorg.jboss.boot.log.file=/opt/wildfly/wildfly-27.0.0.Final/standalone/log/server.log -Dlogging.configuration=file:/opt/wildfly/wildfly-27.0.0.Final/standalone/configuration/logging.properties -jar /opt/wildfly/wildfly-27.0.0.Final/jboss-modules.jar -mp /opt/wildfly/wildfly-27.0.0.Final/modules org.jboss.as.standalone -Djboss.home.dir=/opt/wildfly/wildfly-27.0.0.Final -Djboss.server.base.dir=/opt/wildfly/wildfly-27.0.0.Final/standalone -c wildfly.xml -b 0.0.0.0 -bmanagement 127.0.0.1 -Djboss.bind.address.private=127.0.0.1 -Djboss.default.multicast.address=230.0.0.4 -Djboss.server.config.dir=/opt/wildfly/wildfly-27.0.0.Final//standalone/configuration/ -Djboss.server.base.dir=/opt/wildfly/wildfly-27.0.0.Final//standalone -Djboss.tx.node.id=wildfly -Djboss.node.name=wildfly -Dwildfly.statistics-enabled=false + +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,504 INFO [org.wildfly.extension.undertow] (MSC service thread 1-6) WFLYUT0006: Undertow HTTPS listener https listening on [0:0:0:0:0:0:0:0]:8443 +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,549 INFO [org.jboss.as.ejb3] (MSC service thread 1-7) WFLYEJB0493: Jakarta Enterprise Beans subsystem suspension complete +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,623 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) WFLYJCA0001: Bound data source [java:jboss/datasources/ExampleDS] +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,691 INFO [org.jboss.as.patching] (MSC service thread 1-8) WFLYPAT0050: WildFly Full cumulative patch ID is: base, one-off patches include: none +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,696 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-5) WFLYDS0013: Started FileSystemDeploymentService for directory /opt/wildfly/wildfly-27.0.0.Final/standalone/deployments +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,755 INFO [org.jboss.ws.common.management] (MSC service thread 1-7) JBWS022052: Starting JBossWS 6.1.0.Final (Apache CXF 3.5.2.jbossorg-3) +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,905 INFO [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Resuming server +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,910 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 27.0.0.Final (WildFly Core 19.0.0.Final) started in 3859ms - Started 290 of 563 services (357 services are lazy, passive or on-demand) - Server configuration file in use: wildfly.xml +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,913 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management +Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,914 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990 + +---- + +=== Deploy an application to the Wildlfy cluster + +Now, our three WildFly are running, but the cluster has yet to form. Indeed, with no apps there is no reason for the cluster to exist. Let's modify our Ansible playbook to deploy a simple application to all instances; this will allow us to check that the cluster is working as expected. To achieve this, we'll leverage another role provided by the WildFly collection: wildfly_utils. + +In our case, we will use the jboss_cli.yml task file, which encapsulates the running of JBoss command-line interface (CLI) queries: + +[source, yaml] +---- +… + post_tasks: + - name: "Ensures webapp {{ app.name }} has been retrieved from {{ app.url }}." + ansible.builtin.get_url: + url: "{{ app.url }}" + dest: "{{ wildfly_install_workdir }}/{{ app.name }}" + + - name: "Deploy webapp" + ansible.builtin.include_role: + name: wildfly_utils + tasks_from: jboss_cli.yml + vars: + jboss_home: "{{ wildfly_home }}" + query: "'deploy --force {{ wildfly_install_workdir }}/{{ app.name }}'" + jboss_cli_controller_port: "{{ item }}" + loop: + - 9990 + - 10090 + - 10190 +---- + + +Now, we will once again execute our playbook so that the web application is deployed on all instances. Once the automation completes successfully, the deployment will trigger the formation of the cluster. + +=== Verify that the WildFly cluster is running and the app is deployed + +You can verify the cluster formation by looking at the log files of any of the three instances: + +[source, bash] +---- +… + +2022-12-23 15:02:08,252 INFO [org.infinispan.CLUSTER] (thread-7,ejb,jboss-eap-0) ISPN000094: Received new cluster view for channel ejb: [jboss-eap-0] (3) [jboss-eap-0, jboss-eap-1, jboss-eap-2] +… +---- + +=== Using the Ansible collection as an installer for Wildfly + +Last remark: while the collection is designed to be used inside a playbook, you can also use the provided playbook to directly install Wildfly: + +[source, bash] +---- +$ ansible-playbook -i inventory middleware_automation.wildfly.playbook +---- + +== Conclusion + +Here you go, with a short and simple playbook, we have fully automated the deployment of a WildFly cluster! This playbook can now be used against one, two, three remote machine or even hundreds of them! I hope this will post will have been informative and that it'll have convinced you to use Ansible to set up your own WildFly servers! \ No newline at end of file diff --git a/guides/index.md b/guides/index.md new file mode 100644 index 00000000..fea39c16 --- /dev/null +++ b/guides/index.md @@ -0,0 +1,5 @@ +--- +layout: guides +title: Guides +permalink: /guides/ +--- \ No newline at end of file diff --git a/guides/template.adoc b/guides/template.adoc new file mode 100644 index 00000000..efe65a73 --- /dev/null +++ b/guides/template.adoc @@ -0,0 +1,41 @@ += TITLE OF THE GUIDE +:summary: ONELINE EXPLANATION OF THE GUIDE +:includedir: _includes +include::{includedir}/_attributes.adoc[] +// you can override any attributes eg to lengthen the +// time to complete the guide +:prerequisites-time: 10 + +TODO: Add a summary of what you achieve in this guide. +Something like: + +In this guide, you will learn how to setup and use Eclipse MicroProfile Config in your application. + +include::{includedir}/_prerequisites.adoc[] +* Any additional prerequisites specific to this guide (eg you have completed a previous guide) + +[[requirements]] +== Requirements + +Lorem ipsum + +== A section + +Lorem ipsum + +== Another section + + +// Always keep a next steps to let the user know what could be achieve next +== Next Steps + +Something like: + +MicroProfile Config provides multiple options to read the configuration from various sources (System properties, environment variables, ConfigMaps and Secrets from Kubernetes), you can learn more by reading WildFly's https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#MicroProfile_Config_SmallRye[MicroProfile Config Subsystem Configuration Guide] or reading the specification at https://microprofile.io/specifications/microprofile-config/[Eclipse MicroProfile Config website]. + +// Always add this section last to link to any relevant content +[[references]] +== References + +* https://microprofile.io/specifications/microprofile-config/[Eclipse MicroProfile Config] +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#MicroProfile_Config_SmallRye[MicroProfile Config Subsystem Configuration] diff --git a/guides/use-microprofile-config.adoc b/guides/use-microprofile-config.adoc new file mode 100644 index 00000000..9478e3ed --- /dev/null +++ b/guides/use-microprofile-config.adoc @@ -0,0 +1,131 @@ += Use Eclipse MicroProfile Config +:summary: Learn how to use MicroProfile Config With WildFly. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 10 + +In this guide, you will learn how to setup and use Eclipse MicroProfile Config in your application. + +include::{includedir}/_prerequisites.adoc[] + +[[requirements]] +== Requirements + +In order to use MicroProfile Config in your application, you need to update the Maven `pom.xml` at different places: + +1. Add a dependency to WildFly BOM for MicroProfile in the `` section +2. Add a dependency to the MicroProfile Config API in the `` section + +Once these 2 steps will be achieved, you will be able to use MicroProfile Config in your application. + +=== Add Dependency to WildFly MicroProfile BOM + +You need to add a dependency to the WildFly MicroProfile BOM `org.wildfly.bom:wildfly-microprofile` in the `` section so that your application will use the correct version of the MicroProfile Config provided by WildFly. + +The dependency is defined as: + +[source,xml] +---- + + org.wildfly.bom + wildfly-microprofile + ${version.wildfly} + pom + import + +---- + +It must be added to the `` of your pom.xml: + +[source,xml] +---- + + + ... + + + +---- + +[NOTE] +-- +WildFly BOMS are the only dependencies that must be added to the `` section. Other dependencies are added directly to the `` section of the Maven `pom`.xml. +-- + +=== Add Dependency to MicroProfile Config API + +Then, you need to add a dependency to the MicroProfile Config API `org.eclipse.microprofile.config:microprofile-config-api`. + +The dependency is defined as: + +[source,xml] +---- + + org.eclipse.microprofile.config + microprofile-config-api + provided + +---- + +It must be added to the `` of your pom.xml: + +[source,xml] +---- + + ... + + +---- + +[[microprofile-config-api]] +== Use the MicroProfile Config API + +You can now use Eclipe MicroProfile Config in your application. + +As an example, you can update the `GettingStartedService.java` file to configure the text that displays "Hello": + +[source,java] +---- +package org.wildfly.examples; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@ApplicationScoped +public class GettingStartedService { + + @Inject + @ConfigProperty(name = "hello.text", defaultValue = "Hello") + String helloText; + + public String hello(String name) { + return String.format(helloText + " '%s'.", name); + } +} +---- + +In this example, you have annotated a `helloText` String with a `ConfigProperty` annotation. + +You can now use the `hello.text` system property or the `HELLO_TEXT` environment variable to change the output of the `hello` method. +The default value of the `helloText` is configured in the `ConfigProperty` annotation with the `defaultValue` attribute. + +Once the `GettingStartedService.java` file is modified, you can repackage your application and restart it with the `HELLO_TEXT` environment variable set to `Bonjour`: + +[source,bash] +---- +mvn clean package +HELLO_TEXT="Bonjour" ./target/server/bin/standalone.sh +---- + +If you now access the application at http://localhost:8080 and type `World` in the text field, it now returns `Bonjour, World.` + +=== Next Steps + +MicroProfile Config provides multiple options to read the configuration from various sources (System properties, environment variables, ConfigMaps and Secrets from Kubernetes), you can learn more by reading WildFly's https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#MicroProfile_Config_SmallRye[MicroProfile Config Subsystem Configuration Guide] or reading the specification at https://microprofile.io/specifications/microprofile-config/[Eclipse MicroProfile Config website]. + +[[references]] +=== References + +* https://microprofile.io/specifications/microprofile-config/[Eclipse MicroProfile Config] +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#MicroProfile_Config_SmallRye[MicroProfile Config Subsystem Configuration] diff --git a/guides/use-microprofile-lra.adoc b/guides/use-microprofile-lra.adoc new file mode 100644 index 00000000..862f3888 --- /dev/null +++ b/guides/use-microprofile-lra.adoc @@ -0,0 +1,165 @@ += Use MicroProfile LRA in WildFly +:summary: Learn how to use MicroProfile LRA With WildFly. +:includedir: _includes +include::{includedir}/_attributes.adoc[] + +In this guide, you will learn how to setup and use Eclipse MicroProfile LRA in your application. + +include::{includedir}/_prerequisites.adoc[] + + +https://download.eclipse.org/microprofile/microprofile-lra-2.0/microprofile-lra-spec-2.0.html[MicroProfile Long Running +Actions (LRA)] is a specification that defines the protocol and an API for the distributed transactions based on the +saga pattern and user-defined compensations. In WildFly 28.0.0.Final, we introduced the integration of +https://narayana.io/[Narayana LRA] which implements this specification. In this guide, we look into how you can enable +LRA in your WildFly distribution and how you can use LRA in your applications. + +== Overview of the LRA protocol + +We provide only a high-level overview of the LRA protocol in this post. The full overview of the protocol is available +at https://download.eclipse.org/microprofile/microprofile-lra-2.0/microprofile-lra-spec-2.0.html. + +In LRA, the specification API utilizes annotations from the `org.eclipse.microprofile.lra.annotation` package. The main +annotation is the `@LRA` which controls the life cycle of the LRA. It's use might seem similar to the use of +`@Transactional` annotation from JTA, however, the transaction characteristics differ greatly. If you are interested in +the comparison of the saga pattern to the ACID transactions, you can find an explanation in this talk from DevoxxUK - +https://www.youtube.com/watch?v=7DI4xXv1xGU. + +The Narayana implementation utilizes the coordinator orchestration of the LRAs. The LRA coordinator is a standalone +service that is responsible for the management operations of the LRAs started in the system. When any LRA participant +(user service) wants to start a new LRA, it contacts the LRA coordinator that in turn returns the LRA ID of the newly +started LRA that can be propagated by the LRA participant to any other services. When an LRA-aware service receives the +LRA ID, it can optionally enlist within the same LRA which is again done by the enlistment call to the coordinator. When +the LRA finishes (success or failure), the LRA coordinator is responsible for invocations of the completions or the +compensations callbacks of all enlisted LRA participants. + +== Enabling MicroProfile LRA subsystems + +The integration of the LRA specification is included in two separate subsystems: + +- `microprofile-lra-coordinator` - The LRA coordinator responsible for starting, managing, and recovery of the LRAs. + +- `microprofile-lra-participant` - The client library utilized in user deployments to participate in the distributed LRAs and define compensation and completition callbacks. + +=== Required extensions and subsystems configuration + +The LRA extensions are not included in the standard configurations included with WildFly application server. They need +to be explitcly enabled either in the configuration XML or by using CLI operations: + +[source,bash] +---- +[standalone@localhost:9990 /] /extension=org.wildfly.extension.microprofile.lra-coordinator:add +{"outcome" => "success"} + +[standalone@localhost:9990 /] /subsystem=microprofile-lra-coordinator:add +{ + "outcome" => "success", + "response-headers" => { + "operation-requires-reload" => true, + "process-state" => "reload-required" + } +} + +[standalone@localhost:9990 /] /extension=org.wildfly.extension.microprofile.lra-participant:add +{"outcome" => "success"} + +[standalone@localhost:9990 /] /subsystem=microprofile-lra-participant:add +{ + "outcome" => "success", + "response-headers" => { + "operation-requires-reload" => true, + "process-state" => "reload-required" + } +} + +[standalone@localhost:9990 /] reload +---- + +== Running LRA coordinator in a Docker container + +The LRA coordinator is also provided as a standalone Docker image that you can simply run with the following command: + +[source,bash] +---- +$ docker run -p 8080:8080 quay.io/jbosstm/lra-coordinator +---- + +== Using LRA in user deployments + +The `@LRA` annotation can be placed on any JAX-RS method to declare that the LRA should be started before the method is +entered and closed (finished successfully) when the method ends. By default, if the JAX-RS method returns any of the 4xx +or 5xx error HTTP status codes the LRA will be cancelled instead. + +[source,java] +---- +@LRA +@GET +@Path("/doInLRA") +public Response doInLRA(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) String lraId) { + LOG.info("Work LRA ID = " + lraId); + ... +---- + +When LRA closes successfully, the LRA coordinator calls the completion callback if the participant defined it: + +[source,java] +---- +@Complete +@PUT +@Path("/complete") +public Response complete(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) String lraId) { + LOG.info("Complete ID = " + lraId); + ... +---- + +Or, in the case of LRA cancel, the compensation callback will be invoked instead: + +[source,java] +---- +@Compensate +@PUT +@Path("/compensate") +public Response compensate(@HeaderParam(LRA.LRA_HTTP_CONTEXT_HEADER) String lraId) { + LOG.info("Compensate ID = " + lraId); + ... +---- + +The full example is available at https://github.com/xstefank/lra-wildfly-example. + +If you deploy this application to WildFly (28.0.0+) with both microprofile-lra-coordinator and +microprofile-lra-participant subsystems enabled, you can make the following HTTP invocation to see how the coordinator +invokes the complete callbacks or the compensation callbacks of the two defined participants: + +[source,bash] +---- +$ curl localhost:8080/lra-participant/lra-participant-1/doInLRA + +# in WFLY console log +15:14:50,128 INFO [io.xstefank.LRAParticipant1] (default task-1) Work LRA ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_14 +15:14:50,158 INFO [io.xstefank.LRAParticipant2] (default task-2) Work LRA ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_14 +15:14:50,183 INFO [io.xstefank.LRAParticipant1] (default task-3) Complete ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_14 +15:14:50,191 INFO [io.xstefank.LRAParticipant2] (default task-3) Complete ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_14 + + +$ curl "localhost:8080/lra-participant/lra-participant-1/doInLRA?fail=true" + +# in WFLY console log +15:15:33,516 INFO [io.xstefank.LRAParticipant1] (default task-1) Work LRA ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_1c +15:15:33,531 INFO [io.xstefank.LRAParticipant2] (default task-2) Work LRA ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_1c +15:15:33,543 INFO [io.xstefank.LRAParticipant1] (default task-3) Compensate ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_1c +15:15:33,550 INFO [io.xstefank.LRAParticipant2] (default task-3) Compensate ID = http://localhost:8080/lra-coordinator/lra-coordinator/0_ffff0aca8851_-3330598e_646cbc18_1c +---- + +You can also always check the currently active LRAs with a direct call to the coordinator API: + +[source,bash] +---- +$ curl localhost:8080/lra-coordinator/lra-coordinator +[]% +---- + +== Conclusion + +In this post, we showed you how to configure and use the MicroProfile LRA specification in your WildFly applications. +LRA provides a very broad feature set which we can't cover here. If you are interested in learning more, you can find +the full specification at https://download.eclipse.org/microprofile/microprofile-lra-2.0/microprofile-lra-spec-2.0.html. \ No newline at end of file From aee9212e0ca950eb8a98ec699d15c583fa81b87f Mon Sep 17 00:00:00 2001 From: Farah Juma Date: Mon, 18 Dec 2023 15:05:32 -0500 Subject: [PATCH 2/6] Add an initial set of security related guides --- _data/guides.yaml | 18 + guides/_includes/_attributes.adoc | 4 +- .../_includes/_proc-configure-keycloak.adoc | 30 ++ ...follow-build-and-deployment-openshift.adoc | 17 + .../_proc-install-or-update-helm.adoc | 14 + .../_proc-log-into-openshift-cluster.adoc | 25 ++ .../_proc-start-keycloak-openshift.adoc | 71 ++++ guides/security-oidc-auth0-openshift.adoc | 253 +++++++++++ .../security-oidc-identity-propagation.adoc | 400 ++++++++++++++++++ guides/security-oidc-management-console.adoc | 128 ++++++ guides/security-oidc-openshift.adoc | 227 ++++++++++ guides/security-saml-openshift.adoc | 276 ++++++++++++ 12 files changed, 1462 insertions(+), 1 deletion(-) create mode 100644 guides/_includes/_proc-configure-keycloak.adoc create mode 100644 guides/_includes/_proc-follow-build-and-deployment-openshift.adoc create mode 100644 guides/_includes/_proc-install-or-update-helm.adoc create mode 100644 guides/_includes/_proc-log-into-openshift-cluster.adoc create mode 100644 guides/_includes/_proc-start-keycloak-openshift.adoc create mode 100644 guides/security-oidc-auth0-openshift.adoc create mode 100644 guides/security-oidc-identity-propagation.adoc create mode 100644 guides/security-oidc-management-console.adoc create mode 100644 guides/security-oidc-openshift.adoc create mode 100644 guides/security-saml-openshift.adoc diff --git a/_data/guides.yaml b/_data/guides.yaml index 38b45a43..74b444cc 100644 --- a/_data/guides.yaml +++ b/_data/guides.yaml @@ -13,6 +13,24 @@ categories: - title: Configure Application Logging url: /guides/application-logging description: Learn how to setup and configure logging in WildFly. + - category: Security + cat-id: security + guides: + - title: Securing WildFly Apps with OpenID Connect on OpenShift + url: /guides/security-oidc-openshift + description: Learn how to secure applications deployed to WildFly on OpenShift with OpenID Connect. + - title: Identity Propagation with OpenID Connect + url: /guides/security-oidc-identity-propagation + description: Learn how to propagate identities within a deployment and across deployments when securing WildFly apps with OpenID Connect. + - title: Securing WildFly Apps with Auth0 on OpenShift + url: /guides/security-oidc-auth0-openshift + description: Learn how to secure applications deployed to WildFly on OpenShift with the Auth0 OpenID provider. + - title: Securing the WildFly Management Console with OpenID Connect + url: /guides/security-oidc-management-console + description: Learn how to secure the WildFly management console with the Keycloak OpenID provider. + - title: Securing WildFly Apps with SAML on OpenShift + url: /guides/security-saml-openshift + description: Learn how to secure applications deployed to WildFly on OpenShift with SAML. - category: Eclipse MicroProfile cat-id: microprofile guides: diff --git a/guides/_includes/_attributes.adoc b/guides/_includes/_attributes.adoc index e0ca4006..bbe2ac14 100644 --- a/guides/_includes/_attributes.adoc +++ b/guides/_includes/_attributes.adoc @@ -7,4 +7,6 @@ // . :toc: right // Default time to display in the prerequisites section -:prerequisites-time: 15 \ No newline at end of file +:prerequisites-time: 15 +// OpenShift Container Platform version +:ocp-version: 4.14 \ No newline at end of file diff --git a/guides/_includes/_proc-configure-keycloak.adoc b/guides/_includes/_proc-configure-keycloak.adoc new file mode 100644 index 00000000..4353297e --- /dev/null +++ b/guides/_includes/_proc-configure-keycloak.adoc @@ -0,0 +1,30 @@ +== Configure Keycloak + +. Log into the `Keycloak Admin Console`. + +. Create a new realm called `myrealm`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/getting-started/getting-started-openshift#_create_a_realm[create a realm]. + +ifdef::add-role[] +. Add a role called `User`. This role will be required to access our simple web application. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-using-roles-and-groups[create a role]. +endif::[] + +. Add a new user named `alice`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/getting-started/getting-started-openshift#_create_a_user[create a user]. + +. Once the new user has been created, set a password for this new user from the `Credentials` tab. + +ifdef::add-role[] +. From the `Role Mapping` tab, assign `alice` the `User` role. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#proc-assigning-role-mappings_server_administration_guide[assign a role] to a user. +endif::[] + +. Create a new client as follows: +* `General Settings`: +** *Client type* (or *Client Protocol*, depending on your Keycloak version): `OpenID Connect` +** *Client ID*: `myclient` +* `Capability config`: +** *Authentication flow*: `Standard flow`, `Direct access grants` +* `Login settings`: Leave the fields blank for now. + ++ +For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#_oidc_clients[Manage OpenID Connect clients]. + +. Click `Save` to save the client. diff --git a/guides/_includes/_proc-follow-build-and-deployment-openshift.adoc b/guides/_includes/_proc-follow-build-and-deployment-openshift.adoc new file mode 100644 index 00000000..e1d47d28 --- /dev/null +++ b/guides/_includes/_proc-follow-build-and-deployment-openshift.adoc @@ -0,0 +1,17 @@ +The application will now begin to build. This will take a couple of minutes. + +The build can be observed using: + +[source,bash] +---- +oc get build -w +---- + +Once complete, you can follow the deployment of the application using: + +[source,bash] +---- +oc get deployment oidc-app -w +---- + +Alternatively, you can check status directly from the OpenShift web console. diff --git a/guides/_includes/_proc-install-or-update-helm.adoc b/guides/_includes/_proc-install-or-update-helm.adoc new file mode 100644 index 00000000..a4ec2448 --- /dev/null +++ b/guides/_includes/_proc-install-or-update-helm.adoc @@ -0,0 +1,14 @@ +If you haven't already installed the WildFly Helm chart, install it: + +[source,bash] +---- +helm repo add wildfly https://docs.wildfly.org/wildfly-charts/ +---- + +If you've already installed the WildFly Helm Chart, be sure to update it to ensure you have the latest one: + +[source,bash] +---- +helm repo update +---- + diff --git a/guides/_includes/_proc-log-into-openshift-cluster.adoc b/guides/_includes/_proc-log-into-openshift-cluster.adoc new file mode 100644 index 00000000..56105820 --- /dev/null +++ b/guides/_includes/_proc-log-into-openshift-cluster.adoc @@ -0,0 +1,25 @@ +== Log Into the OpenShift Cluster + +Before we can deploy our application, we need to log in to an OpenShift cluster. You can log in via the https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI]: + +[source,bash] +---- +oc login -u myUserName +---- + +Alternatively, you can log in using an API token: + +[source,bash] +---- +oc login --token=myToken --server=myServerUrl +---- + +You can request the token via the `Copy Login Command` link in the OpenShift web console. + +If you don't already have a project created, you can create one using: + +[source,bash] +---- +oc new-project myProjectName +---- + diff --git a/guides/_includes/_proc-start-keycloak-openshift.adoc b/guides/_includes/_proc-start-keycloak-openshift.adoc new file mode 100644 index 00000000..22edc1bd --- /dev/null +++ b/guides/_includes/_proc-start-keycloak-openshift.adoc @@ -0,0 +1,71 @@ +== Start Keycloak + +ifndef::saml-auth-method[] +We will be using Keycloak as our OpenID provider. +endif::[] +ifdef::saml-auth-method[] +We will be using Keycloak as our SAML identity provider. +endif::[] + +To start a Keycloak server in your project on OpenShift, use the following command: + +[source,bash] +---- +oc process -f https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/openshift/keycloak.yaml \ + -p KEYCLOAK_ADMIN=admin \// <1> + -p KEYCLOAK_ADMIN_PASSWORD=admin \// <2> + -p NAMESPACE= \// <3> +| oc create -f - +---- +<1> Replace `admin` with the user name you would like to use when accessing the Keycloak Administration Console. +<2> Replace `admin` with the password you would like to use when accessing the Keycloak Administration Console. +<3> Replace `` with your project name. + +After running the above command, you should see the following output: + +[source,bash] +---- +service/keycloak created +route.route.openshift.io/keycloak created +Warning: apps.openshift.io/v1 DeploymentConfig is deprecated in v4.14+, unavailable in v4.10000+ +deploymentconfig.apps.openshift.io/keycloak created. +---- + +It will take a few minutes for OpenShift to provision the Keycloak pod and its related resources. + +You can use the OpenShift CLI or the OpenShift web console, depending on your preference, to check if your Keycloak server has been provisioned. + +=== OpenShift CLI + +To make sure your Keycloak server has been provisioned using the OpenShift CLI, run: + +[source,bash] +---- +oc get pods +---- + +After a little while, check for a message similar to the following message that indicates the pod is ready: + +[source,bash] +---- +NAME READY STATUS RESTARTS AGE +keycloak-1-deploy 0/1 Completed 0 1h +keycloak-1-l9kdx 1/1 Running 0 1h +---- + +Once the Keycloak server has been provisioned, use the following command to find the URL for your Keycloak instance's +Admin Console: + +[source,bash] +---- +KEYCLOAK_URL=https://$(oc get route keycloak --template='{{ .spec.host }}') && +echo "" && +echo "Keycloak Admin Console: $KEYCLOAK_URL/admin" && +echo "" +---- + +=== OpenShift Web Console + +To make sure your Keycloak server has been provisioned using the OpenShift web console, +navigate to the `Topology` view in the `Developer` perspective. You can click on your `keycloak` app +to check its status. Once it is running, you can click on `Open URL` and then access Keycloak's `Administration Console`. diff --git a/guides/security-oidc-auth0-openshift.adoc b/guides/security-oidc-auth0-openshift.adoc new file mode 100644 index 00000000..15f1e066 --- /dev/null +++ b/guides/security-oidc-auth0-openshift.adoc @@ -0,0 +1,253 @@ += Securing WildFly Apps with Auth0 on OpenShift +:summary: Learn how to secure applications deployed to WildFly on OpenShift with the Auth0 OpenID provider. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 15 + +You can secure your WildFly applications deployed on OpenShift with OpenID Connect (OIDC). By using OIDC to secure +applications, you delegate authentication to OIDC providers. This guide shows how to secure an example application +deployed to WildFly on OpenShift with OIDC using https://auth0.com/[Auth0] as the OpenID provider. + +If you prefer to watch a video, check out this 5-minute https://www.youtube.com/watch?v=uoQoCPGyAik[video] which also covers the steps +from this guide. + +include::{includedir}/_prerequisites.adoc[] +* Access to an OpenShift cluster (try the https://developers.redhat.com/developer-sandbox[Red Hat Developer Sandbox] for free) +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://helm.sh/docs/intro/install/[Helm Chart] +* Access to https://auth0.com/[Auth0] + +== Example Application + +We will use a simple web application in this guide that consists of a single https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-auth0/src/main/java/org/wildfly/security/examples/SecuredServlet.java[servlet]. We will secure this servlet using OIDC. + +We will use the example in the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/simple-webapp-auth0[simple-webapp-auth0] directory in the `elytron-examples` repo. + +To obtain this example, clone the `elytron-examples` repository to your local machine: + +[source,bash] +---- +git clone git@github.com:wildfly-security-incubator/elytron-examples.git +---- + +include::{includedir}/_proc-log-into-openshift-cluster.adoc[] + +== Configure Auth0 + +We will be using Auth0 as our OpenID provider. + +. Log into the *Auth0 Dashboard*. + +. Create an application called `OIDC App`. For the application type, select `Regular Web Applications` and then click on `Create`. For more information, see the Auth0 documentation on how to https://auth0.com/docs/get-started/auth0-overview/create-applications[create applications]. + +. Once the application has been created, we'll see the `Domain`, `Client ID`, and `Client Secret` in the `Basic Information` section. We'll make use of these values when we <> later on. + +. Using the sidebar menu on the left side of the *Dashboard*, navigate to the `APIs` page and copy the `API Audience` value. + +. Using the sidebar menu on the left side of the *Dashboard*, navigate to the `Settings` page and scroll down to the `API Authorization Settings`. Paste the `API Audience` value you just copied into the `Default Audience` field and then click on `Save`. + ++ +This will allow us to receive access tokens that are JWTs from Auth0. In the future, we're hoping to add the ability +to handle opaque access tokens as well to WildFly's Elytron OIDC Client subsystem. + +. Using the sidebar menu on the left side of the *Dashboard*, click on `User Management` and then `Users`. You can then +create a new user by clicking on `Create User`. You'll need to specify the new user's email, we'll use `user@example.com`. You'll also need to set a password for the user. ++ +Once the user has been created, you'll see the user's `user_id` at the top of the page. ++ +For more information, see Auth0's documentation on how to https://auth0.com/docs/manage-users/user-accounts/create-users[create users]. + +[[add-helm-configuration]] +== Add Helm Configuration + +. Switch to the `charts` directory in the `simple-webapp-auth0` example. ++ +[source,bash] +---- +cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-auth0/charts +---- ++ +Notice there's a `helm.yaml` file in this directory with the following content: ++ +[source,yaml] +---- +build: + uri: https://github.com/wildfly-security-incubator/elytron-examples.git + contextDir: simple-webapp-auth0 +deploy: + env: + - name: DOMAIN + value: <1> + - name: CLIENT_ID + value: <2> + - name: CLIENT_SECRET + value: <3> +---- +You need to update the environment variable values here using the information we saw earlier in the *Auth0 Dashboard*, +as described below. ++ +<1> Replace `` with the `Domain` value from your OIDC App's `Basic Information` section in the *Auth0 Dashboard*. +<2> Replace `` with the `Client ID` value from your OIDC App's `Basic Information` section in the *Auth0 Dashboard*. +<3> Replace `` with the `Client Secret` value from your OIDC App's `Basic Information` section in the *Auth0 Dashboard*. + +== Deploy the Example Application to WildFly on OpenShift + +include::{includedir}/_proc-install-or-update-helm.adoc[] + +We can deploy our example application to WildFly on OpenShift using the WildFly Helm Chart: + +[source,bash] +---- +helm install oidc-app -f /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-auth0/charts/helm.yaml wildfly/wildfly +---- + +Notice that this command specifies the file we updated, `helm.yaml`, that contains the values +needed to build and deploy our application. + +include::{includedir}/_proc-follow-build-and-deployment-openshift.adoc[] + +=== Behind the Scenes + +While our application is building, let's take a closer look at our application. + +* Examine the https://github.com/wildfly-security/elytron-examples/blob/main/simple-webapp-auth0/pom.xml[pom.xml] file. ++ +Notice that it contains an `openshift` profile. A profile in Maven lets you create a set of configuration values to customize your application build for different environments. The `openshift` profile in this example defines a configuration that will be used by the WildFly Helm Chart when provisioning the WildFly server on OpenShift. ++ +[source,xml] +---- + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.maven.plugin} + + + + org.wildfly:wildfly-galleon-pack:${version.wildfly} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly.cloud.galleon.pack} + + + + cloud-server + elytron-oidc-client + + simple-webapp-auth0.war + + + + + package + + + + + + + + +---- +<1> `wildfly-maven-plugin` provisions a WildFly server with the specified layers with our application deployed. +<2> `elytron-oidc-client` automatically adds the native OIDC client subsystem to our WildFly installation. + +* Examine the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-auth0/src/main/webapp/WEB-INF/web.xml[web.xml]. ++ +[source,xml] +---- +... + + OIDC <1> + +... +---- ++ +<1> When the `elytron-oidc-client` subsystem sees the `auth-method` is set to `OIDC`, it enables the OIDC authentication mechanism for the application. + +* Examine the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-auth0/src/main/webapp/WEB-INF/oidc.json[oidc.json] file. The `oidc.json` is used to configure the native OIDC client subsystem. ++ +[source,json] +---- +{ + "client-id" : "${env.CLIENT_ID}", <1> + "provider-url" : "https://${env.DOMAIN}", <2> + "ssl-required" : "EXTERNAL", <3> + "credentials" : { + "secret" : "${env.CLIENT_SECRET}" <4> + } +} +---- ++ +<1> The client ID, which is specified using the `CLIENT_ID` environment variable we defined in the Helm configuration. +<2> The provider URL, which is specified using the `DOMAIN` environment variable. We defined its value in the Helm configuration. +<3> When `ssl-required` is set to `EXTERNAL`, HTTPS is required by default for external requests. +<4> The client secret is needed to communicate with Auth0. This refers to the `CLIENT_SECRET` environment variable that we defined in the Helm configuration. + +== Get the Application URL + +Once the WildFly server has been provisioned, use the following command to find the URL for your example +application: + +[source,bash] +---- +SIMPLE_WEBAPP_AUTH0_URL=https://$(oc get route oidc-app --template='{{ .spec.host }}') && +echo "" && +echo "Application URL: $SIMPLE_WEBAPP_AUTH0_URL/simple-webapp-auth0" && +echo "Allowed Callback URL: $SIMPLE_WEBAPP_AUTH0_URL/simple-webapp-auth0/secured/*" && +echo "" +---- + +We'll make use of these URLs in the next two sections. + +== Finish Configuring Auth0 + +From your `OIDC App` in the Auth0 Dashboard, scroll down to the `Application URIs` section and set +`Allowed Callback URLs` to the `Allowed Callback URL` that was output in the previous section. Then click on `Save Changes`. + +== Access the Application + +From your browser, navigate to the `Application URL` that was output in the previous section. + +Click on `Access Secured Servlet`. + +You will be redirected to Auth0 to log in. + +Log in using the `user@example.com` user we created earlier. + +Upon successful authentication, you will be redirected back to the example application. + +The example application simply outputs the `user_id` of the logged in user. + +You should see output similar to the following: + +[source,text] +---- +Secured Servlet + +Current Principal 'auth0|6544f9aa427fb9f276240d55' +---- + +Notice the `user_id` for our `user@example.com` user is displayed. This indicates that we have successfully logged into our application! + +== Next Steps + +This guide has shown how to secure an application deployed to WildFly on OpenShift using the Auth0 OpenID provider. For additional +information, feel free to check out the resources linked below. To learn +more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] +documentation. + +[[references]] +== References + +* https://www.youtube.com/watch?v=uoQoCPGyAik[Vlog: Securing WildFly Apps with Auth0 on OpenShift] +* https://auth0.com/docs/get-started[Getting started with Auth0] +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OpenID Connect Client Subsystem Configuration] +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html[Getting Started with WildFly on OpenShift] +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html#helm-charts[WildFly Helm Chart] +* <> \ No newline at end of file diff --git a/guides/security-oidc-identity-propagation.adoc b/guides/security-oidc-identity-propagation.adoc new file mode 100644 index 00000000..1479f65d --- /dev/null +++ b/guides/security-oidc-identity-propagation.adoc @@ -0,0 +1,400 @@ += Identity Propagation with OpenID Connect +:summary: Learn how to propagate identities within a deployment and across deployments when securing WildFly apps with OpenID Connect. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 15 + +When securing an application with OpenID Connect (OIDC), WildFly https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#virtual-security-2[automatically] +creates and makes use of a virtual security domain across the deployment. If the application invokes an EJB, additional configuration +might be required in order to propagate the security identity from the virtual security domain. The configuration that's needed +depends on how the EJB that's being invoked is secured. This guide covers the different use cases for propagating an identity +from a virtual security domain. + +include::{includedir}/_prerequisites.adoc[] +* https://www.keycloak.org/guides#getting-started[Keycloak] + +== Overview of Identity Propagation with OIDC + +Additional configuration might be needed in order to propagate a security identity from a virtual security domain depending +on how the EJB that's being invoked is secured. + +=== Securing an EJB using the Same OIDC Virtual Security Domain + +==== Within the Same Deployment + +If a web application secured with OIDC invokes an EJB within the same deployment (e.g., within the same WAR or EAR) and you'd +like to secure the EJB using the same virtual security domain as the web application, no additional configuration is required. + +Both of examples that we'll be going through cover this use case. + +==== Across Deployments + +If a web application secured with OIDC invokes an EJB in a separate deployment (e.g., across EARs) and you'd like +to secure the EJB using the same virtual security domain as the web application, the following configuration is needed: + +* A `virtual-security-domain` resource needs to be added in the Elytron subsystem. +* The EJB being invoked needs to be updated with a `@SecurityDomain` annotation that references the `virtual-security-domain`. + +For a guided step by step example of how to configure this use case, see <>. + +[[different-security-domain]] +=== Securing an EJB using a Different Security Domain + +If a web application secured with OIDC invokes an EJB (either in the same deployment or in a separate deployment) and +you'd like to secure the EJB using a different security domain from the web application, the following configuration is +needed: + +* A `virtual-security-domain` resource needs to be added in the Elytron subsystem. +** This indicates the list of +security domains that a virtual security domain should automatically outflow its security identities to. +* A `trusted-virtual-security-domains` attribute needs to be configured for the `security-domain` that is being +used to secure the EJB being invoked. +** This indicates that the `security-domain` should trust any security identities +that have been established by the specified virtual security domains. + +For a guided step by step example of how to configure this use case, see <>. + +== Example Applications + +We will use some simple web applications in this guide that consist of a servlet secured using OIDC. The servlet will invoke an EJB +within the same deployment (i.e., invocation within the same EAR). This EJB will then invoke another EJB located in a different deployment +(i.e., invocation across EARs). + +We will use the `oidc-with-identity-propagation` and `oidc-with-identity-propagation-same-domain` examples from the `elytron-examples` repository: + +* https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation[oidc-with-identity-propagation] +* https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation-same-domain[oidc-with-identity-propagation-same-domain] + +To obtain the examples, clone the `elytron-examples` repository to your local machine: + +[source, shell] +---- +git clone git@github.com:wildfly-security-incubator/elytron-examples.git +---- + +== Start Keycloak + +This guide will be making use of Keycloak as our OpenID provider. + +To start a Keycloak server in your environment, follow the appropriate guide for your environment +from Keycloak’s https://www.keycloak.org/guides#getting-started[Getting Started] page. + +:add-role: +include::{includedir}/_proc-configure-keycloak.adoc[] + +== Secure an EJB Invoked by an OIDC App using a Different Security Domain + +For this use case, we'll be using the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation[oidc-with-identity-propagation] example. + +=== Inspect the Example Applications + +Let's take a closer look at our example. + +* This example consists of two EARs when built: `virtual-security-domain-to-domain.ear` and `ejb-basic.ear`. + +* Notice that `virtual-security-domain-to-domain.ear` contains a https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation/virtual-security-domain-to-domain/web/src/main/java/org/wildfly/security/examples/virtual_security_domain_to_domain/web/SecuredServlet.java[servlet] +that invokes an EJB, https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation/virtual-security-domain-to-domain/ejb/src/main/java/org/wildfly/security/examples/virtual_security_domain_to_domain/ejb/EntryBean.java[EntryBean], +that's also contained in the same EAR. This EJB doesn't have any explicit security domain configuration. Thus, this EJB will automatically be secured using the same virtual security domain as the servlet. + +* The `EntryBean` invokes another EJB, https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation/ejb-basic/ejb/src/main/java/org/wildfly/security/examples/ejb_basic/ejb/ManagementBean.java[ManagementBean], that's part of `ejb-basic.ear`. +Notice that `ManagementBean` has a `@SecurityDomain("BusinessDomain")` annotation. + +* Because the `ManagementBean` is being secured using a security domain that's different from the virtual security domain that's being +used to secure the web application, we'll need to add configuration to propagate security identities from the virtual security domain to +the `BusinessDomain`. + +=== Start WildFly + +First, we need to start our WildFly instance. We'll specify a port offset since our Keycloak instance is exposed on +port 8080: + +[source,bash] +---- +./bin/standalone.sh -Djboss.socket.binding.port-offset=10 +---- + +=== Configure the Security Domain that will be used to Secure the EJB (BusinessDomain) + +We're going to secure the EJB being invoked with a security domain called `BusinessDomain`. To create this security domain, +we'll connect to the WildFly CLI and execute the CLI commands shown below. + +[source,bash] +---- +./bin/jboss-cli.sh --connect --controller=localhost:10000 +---- + +[source,bash] +---- + +# Add a filesystem realm called BusinessRealm in the jboss.server.config directory +/subsystem=elytron/filesystem-realm=BusinessRealm:add(path=business-realm-users,relative-to=jboss.server.config.dir) + +# Add user alice with Admin role +/subsystem=elytron/filesystem-realm=BusinessRealm:add-identity(identity=alice) +/subsystem=elytron/filesystem-realm=BusinessRealm:add-identity-attribute(identity=alice, name=Roles, value=["Admin"]) + +# Add a security domain that references our newly created realm +/subsystem=elytron/security-domain=BusinessDomain:add(realms=[{realm=BusinessRealm}],default-realm=BusinessRealm,permission-mapper=default-permission-mapper) + +# Update the application security domain mapping in the EJB3 subsystem +/subsystem=ejb3/application-security-domain=BusinessDomain:add(security-domain=BusinessDomain) + +reload +---- + +=== Configure Identity Propagation + +First, let's configure a `virtual-security-domain` in the Elytron subsystem to specify that we want to automatically +outflow any security identities established by the virtual security domain to the `BusinessDomain`: + +[source,bash] +---- +/subsystem=elytron/virtual-security-domain=virtual-security-domain-to-domain.ear:add(outflow-security-domains=[BusinessDomain]) +---- + +Next, let's update the `BusinessDomain` to specify that we want to trust any security identities established by the virtual +security domain associated with `virtual-security-domain-to-domain.ear`: + +[source,bash] +---- +/subsystem=elytron/security-domain=BusinessDomain:write-attribute(name=trusted-virtual-security-domains, value=[virtual-security-domain-to-domain.ear]) +---- + +Finally, let's execute a reload: + +[source,bash] +---- +reload +---- + +=== Deploy the Example Application to WildFly + +We're now going to build and deploy our example. + +From the `elytron-examples` directory, run the following commands to build and deploy the `ejb-basic.ear` and `virtual-security-domain-to-domain.ear`: + +[source,bash] +---- +cd YOUR_PATH_TO_ELYTRON_EXAMPLES/oidc-with-identity-propagation/ejb-basic +mvn clean install wildfly:deploy -Dwildfly.port=10000 +---- + +[source,bash] +---- +cd YOUR_PATH_TO_ELYTRON_EXAMPLES/oidc-with-identity-propagation/virtual-security-domain-to-domain +mvn clean install wildfly:deploy -Dwildfly.port=10000 +---- + +=== Finish Configuring Keycloak + +From your `myclient` client in the Keycloak Administration Console, +in the client settings, set `Valid redirect URIs` to http://localhost:8090/virtual-security-domain-to-domain/secured and then click `Save`. + +=== Access the Application + +From your browser, navigate to http://localhost:8090/virtual-security-domain-to-domain. + +Click on `Access Secured Servlet`. + +You will be redirected to Keycloak to log in. + +Log in using the `alice` user we created earlier. + +Upon successful authentication, you will be redirected back to the example application. + +The example application outputs information about the user. + +You should see the following output: + +[source,text] +---- +Successfully logged into Secured Servlet with OIDC + +Identity as visible to servlet. + +Principal : alice + +Authentication Type : OIDC + +Caller Has Role 'User'=true + +Caller Has Role 'Admin'=false + +Identity as visible to EntryBean. + +Principal : alice + +Caller Has Role 'User'=true + +Caller Has Role 'Admin'=false + +Identity as visible to ManagementBean. + +Principal : alice + +Caller Has Role 'User'=false + +Caller Has Role 'Admin'=true +---- + +Notice the following things: + +* The identity as visible to the servlet and the EJB within `virtual-security-domain-to-domain.ear` is `alice` with `User` role. This +shows that the identity from the virtual security domain was successfully propagated to the EJB within the same EAR. + +* The identity as visible to the EJB within `ejb-basic.ear` is `alice` with `Admin` role. This shows that the identity +from the virtual security domain was successfully propagated to the `BusinessDomain` that's used to secure the EJB +in a separate deployment. + +[[same-virtual-domain]] +== Secure an EJB Invoked by an OIDC App using the Same Virtual Security Domain + +For this use case, we'll be using the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/oidc-with-identity-propagation-same-domain[oidc-with-identity-propagation-same-domain] example. + +=== Inspect the Example Applications + +Let's take a closer look at our example. + +* This example consists of two EARs when built: `same-virtual-domain.ear` and `ejb-same-domain.ear`. + +* Notice that `same-virtual-domain.ear` contains a https://github.com/wildfly-security-incubator/elytron-examples/blob/main/oidc-with-identity-propagation-same-domain/same-virtual-domain/web/src/main/java/org/wildfly/security/examples/same_virtual_domain/web/WhoAmIServlet.java[servlet] +that invokes an EJB, https://github.com/wildfly-security-incubator/elytron-examples/blob/main/oidc-with-identity-propagation-same-domain/same-virtual-domain/ejb/src/main/java/org/wildfly/security/examples/same_virtual_domain/ejb/EntryBean.java[EntryBean], +that's also contained in the same EAR. This EJB doesn't have any explicit security domain configuration. Thus, this EJB will automatically be secured using the same virtual security domain as the servlet. + +* The `EntryBean` invokes another EJB, https://github.com/wildfly-security-incubator/elytron-examples/blob/main/oidc-with-identity-propagation-same-domain/ejb-same-domain/ejb/src/main/java/org/wildfly/security/examples/ejb_same_domain/ejb/WhoAmIBean.java[WhoAmIBean], that's part of `ejb-same-domain.ear`. + +* Because we want to secure the `WhoAmIBean` with the same virtual security domain that's being +used to secure the web application, we'll need to add configuration to accomplish this. + +=== Start WildFly + +First, we need to start our WildFly instance. We'll specify a port offset since our Keycloak instance is exposed on +port 8080: + +[source,bash] +---- +./bin/standalone.sh -Djboss.socket.binding.port-offset=10 +---- + +=== Configure the Virtual Security Domain that will be used to Secure the EJB + +We're going to secure the EJB being invoked with the same virtual security domain that's being used +to secure the web application with OIDC. We first need to connect to the WildFly CLI and add a `virtual-security-domain` +resource in the Elytron subsystem as follows: + +[source,bash] +---- +./bin/jboss-cli.sh --connect --controller=localhost:10000 +---- + +[source,bash] +---- +# Add a virtual security domain resource for the same-virtual-domain.ear application +/subsystem=elytron/virtual-security-domain=same-virtual-domain.ear:add() +---- + +=== Configure Identity Propagation + +Next, let's update the `WhoAmIBean` to indicate that we want to secure it using the same virtual domain +that's being used to secure `same-virtual-domain.ear`: + +[source,java] +---- +@SecurityDomain("same-virtual-domain.ear") +public class WhoAmIBean implements WhoAmI { + ... +} +---- + +=== Deploy the Example Application to WildFly + +We're going to build and deploy our example. + +From the `elytron-examples` directory, run the following commands to build and deploy the `ejb-same-domain.ear` and `same-virtual-domain.ear`: + +[source,bash] +---- +cd YOUR_PATH_TO_ELYTRON_EXAMPLES/oidc-with-identity-propagation-same-domain/ejb-same-domain +mvn clean install wildfly:deploy -Dwildfly.port=10000 +---- + +[source,bash] +---- +cd YOUR_PATH_TO_ELYTRON_EXAMPLES/oidc-with-identity-propagation-same-domain/same-virtual-domain +mvn clean install wildfly:deploy -Dwildfly.port=10000 +---- + +=== Finish Configuring Keycloak + +From your `myclient` client in the Keycloak Administration Console, +in the client settings, set `Valid redirect URIs` to http://localhost:8090/same-virtual-domain/secured and then click `Save`. + +=== Access the Application + +From your browser, navigate to http://localhost:8090/same-virtual-domain. + +Click on `Access Secured Servlet`. + +You will be redirected to Keycloak to log in. + +Log in using the `alice` user we created earlier. + +Upon successful authentication, you will be redirected back to the example application. + +The example application outputs information about the user. + +You should see the following output: + +[source,text] +---- +Successfully logged into Secured Servlet with OIDC + +Identity as visible to servlet. + +Principal : alice + +Authentication Type : OIDC + +Caller Has Role 'User'=true + +Caller Has Role 'Admin'=false + +Identity as visible to EntryBean. + +Principal : alice + +Caller Has Role 'User'=true + +Caller Has Role 'Admin'=false + +Identity as visible to ManagementBean. + +Principal : alice + +Caller Has Role 'User'=true + +Caller Has Role 'Admin'=false +---- + +Notice the following things: + +* The identity as visible to the servlet and the EJB within `same-virutal-domain.ear` is `alice` with `User` role. This +shows that the identity from the virtual security domain was successfully propagated to the EJB within the same EAR. + +* The identity as visible to the EJB within `ejb-same-domain.ear` is `alice` with `User` role. This shows that the identity +from the virtual security domain was successfully propagated to the EJB in a separate deployment. + +== Next Steps + +This guide shown how to propagate security identities established by a virtual security domain within a deployment +and across deployments when securing a web application with OIDC. To learn +more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] +documentation. + +[[references]] +== References + +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#identity_propagation[OIDC Identity Propagation] +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OpenID Connect Client Subsystem Configuration] +* https://www.keycloak.org/docs/latest/server_admin/index.html[Keycloak Server Administration Guide] +* <> diff --git a/guides/security-oidc-management-console.adoc b/guides/security-oidc-management-console.adoc new file mode 100644 index 00000000..be8c305d --- /dev/null +++ b/guides/security-oidc-management-console.adoc @@ -0,0 +1,128 @@ += Securing the WildFly Management Console with OpenID Connect +:summary: Learn how to secure the WildFly management console with the Keycloak OpenID provider. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 15 + +You can secure the WildFly Management Console with OpenID Connect (OIDC) using the Keycloak +OpenID provider. When the WildFly Management Console is secured using OIDC, this means that when a user attempts to +access the console, they will be redirected to the Keycloak OpenID provider's login page. Upon successful +authentication, the user will then be redirected back to the WildFly Management Console. This guide +explains how to configure this. + +include::{includedir}/_prerequisites.adoc[] +* https://www.keycloak.org/guides#getting-started[Keycloak] + +== Start Keycloak + +This guide will be making use of Keycloak as our OpenID provider. + +To start a Keycloak server in your environment, follow the appropriate guide for your environment +from Keycloak’s https://www.keycloak.org/guides#getting-started[Getting Started] page. + +== Configure Keycloak + +. Log into the `Keycloak Admin Console`. + +. Create a new realm called `wildfly-infra`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-a-realm_server_administration_guide[create a realm]. + +. Create a new client as follows: +* `General Settings`: +** *Client type* (or *Client Protocol*, depending on your Keycloak version): `OpenID Connect` +** *Client ID*: `wildfly-console` +* `Capability config`: +** *Authentication flow*: `Standard flow`, `Direct access grants` +* `Login settings`: +** Set the *Valid redirect URIs* using the URI that will be used to access the WildFly Management Console. +Since we will use a port offset of 10 when starting WildFly in this guide, we will set the `Valid redirect URIs` to http://localhost:10000/console/*. +** Set the *Web Origins* using the management port for our WildFly instance, e.g., http://localhost:10000. + ++ +For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#_oidc_clients[Manage OpenID Connect clients]. + +. Click `Save` to save the client. + +. Create a second new client as follows: +* `General Settings`: +** *Client type* (or *Client Protocol*, depending on your Keycloak version): `OpenID Connect` +** *Client ID*: `wildfly-management` +* *Capability config*: +** *Authentication flow*: This client will be a bearer-only client, be sure to *uncheck* `Standard flow` and *uncheck* `Direct access grants`. +* *Login settings*: Leave the fields blank. + ++ +For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#_oidc_clients[Manage OpenID Connect clients]. + +. Click `Save` to save the client. + +. *[Optional]* If you want to configure WildFly to use https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#RBAC[Role Based Access Control], add a role called `Administrator`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-using-roles-and-groups[create a role]. + +. Add a new user named `alice`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#proc-creating-user_server_administration_guide[create a user]. + +. Once the new user has been created, set a password for this new user from the `Credentials` tab. + +. *[Optional]* If you want to configure WildFly to use https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#RBAC[Role Based Access Control], from the `Role Mapping` tab, assign `alice` the `Administrator` role. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#proc-assigning-role-mappings_server_administration_guide[assign a role] to a user. + +== Configure Elytron OIDC Client + +Now that we've configured our OpenID provider, there are a couple things that need to be configured in the +`elytron-oidc-client` subsystem to secure the WildFly Management Console with OIDC. + +First, we need to add a `secure-deployment` resource that references the `wildfly-management` client that was created in the previous section. + +A `secure-server` that references the `wildfly-console` client is also needed. + +We can use the following commands to add the required configuration: + +First, we need to start our WildFly server instance. Notice that we're specifying a port offset here +since our Keycloak instance is already exposed on port 8080: + +[source,bash] +---- +./bin/standalone.sh -Djboss.socket.binding.port-offset=10 +---- + +Next, we can connect to the WildFly CLI and then execute the commands below: + +[source,bash] +---- +./bin/jboss-cli.sh --connect --controller=localhost:10000 +---- + +[source,shell] +---- +# Configure the Keycloak provider +/subsystem=elytron-oidc-client/provider=keycloak:add(provider-url=http://localhost:8080/realms/wildfly-infra) + +# Create a secure-deployment in order to secure the management interface with bearer token authentication +/subsystem=elytron-oidc-client/secure-deployment=wildfly-management:add(provider=keycloak,client-id=wildfly-management,principal-attribute=preferred_username,bearer-only=true,ssl-required=EXTERNAL) + +# (Optional) Enable RBAC where roles are obtained from the identity +/core-service=management/access=authorization:write-attribute(name=provider,value=rbac) +/core-service=management/access=authorization:write-attribute(name=use-identity-roles,value=true) + +# Create a secure-server to ensure that the WildFly Management Console will redirect to the Keycloak OpenID provider for log in +/subsystem=elytron-oidc-client/secure-server=wildfly-console:add(provider=keycloak,client-id=wildfly-console,public-client=true) + +reload +---- + +== Accessing the WildFly Management Console + +With the above configuration now in place, let's access http://localhost:10000/console. We will be redirected to +the Keycloak login page. We can log in using the `alice` user that we created earlier. Upon successful authentication, +we will be redirected back to the WildFly Management Console. + +== Next Steps + +This guide has shown how to secure the WildFly Management Console with OIDC. To learn +more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] +documentation. + +[[references]] +== References + +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OpenID Connect Client Subsystem Configuration] +* https://www.keycloak.org/guides#getting-started[Getting Started with Keycloak] +* https://www.keycloak.org/docs/latest/server_admin/index.html[Keycloak Server Administration Guide] +* <> \ No newline at end of file diff --git a/guides/security-oidc-openshift.adoc b/guides/security-oidc-openshift.adoc new file mode 100644 index 00000000..d5297ab0 --- /dev/null +++ b/guides/security-oidc-openshift.adoc @@ -0,0 +1,227 @@ +[[security-oidc-openshift]] += Securing WildFly Apps with OIDC on OpenShift +:summary: Learn how to secure applications deployed to WildFly on OpenShift with OpenID Connect. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 15 + +You can secure your WildFly applications deployed on OpenShift with OpenID Connect (OIDC). By using OIDC +to secure applications, you delegate authentication to OIDC providers. This guide shows how to secure an +example application deployed to WildFly on OpenShift with OIDC using Keycloak as the OpenID provider. + +include::{includedir}/_prerequisites.adoc[] +* Access to an OpenShift cluster (try the https://developers.redhat.com/developer-sandbox[Red Hat Developer Sandbox] for free) +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://helm.sh/docs/intro/install/[Helm Chart] + +== Example Application + +We will use a simple web application in this guide that consists of a single https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-oidc/src/main/java/org/wildfly/security/examples/SecuredServlet.java[servlet]. We will secure this servlet using OIDC. + +We will use the example in the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/simple-webapp-oidc[simple-webapp-oidc] directory in the `elytron-examples` repo. + +To obtain this example, clone the `elytron-examples` repository to your local machine: + +[source,bash] +---- +git clone git@github.com:wildfly-security-incubator/elytron-examples.git +---- + +include::{includedir}/_proc-log-into-openshift-cluster.adoc[] + +include::{includedir}/_proc-start-keycloak-openshift.adoc[] + +include::{includedir}/_proc-configure-keycloak.adoc[] + +== Add Helm Configuration + +. Obtain the URL for Keycloak. ++ +[source,bash] +---- +KEYCLOAK_URL=https://$(oc get route keycloak --template='{{ .spec.host }}') && +echo "" && +echo "Keycloak URL: $KEYCLOAK_URL" && +echo "" +---- + +. Switch to the `charts` directory in the `simple-webapp-oidc` example. ++ +[source.bash] +---- +cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-oidc/charts +---- ++ +Notice there's a `helm.yaml` file in this directory with the following content: ++ +[source,yaml] +---- +build: + uri: https://github.com/wildfly-security-incubator/elytron-examples.git + contextDir: simple-webapp-oidc +deploy: + replicas: 1 + env: + - name: OIDC_PROVIDER_URL + value: <1> +---- +<1> Replace `` with the Keycloak URL obtained in the previous command. + +== Deploy the Example Application to WildFly on OpenShift + +include::{includedir}/_proc-install-or-update-helm.adoc[] + +We can deploy our example application to WildFly on OpenShift using the WildFly Helm Chart: + +[source,bash] +---- +helm install oidc-app -f /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-oidc/charts/helm.yaml wildfly/wildfly +---- + +Notice that this command specifies the file we updated, `helm.yaml`, that contains the values +needed to build and deploy our application. + +include::{includedir}/_proc-follow-build-and-deployment-openshift.adoc[] + +=== Behind the Scenes + +While our application is building, let's take a closer look at our application. + +* Examine the https://github.com/wildfly-security/elytron-examples/blob/main/simple-webapp-oidc/pom.xml[pom.xml] file. ++ +Notice that it contains an `openshift` profile. A profile in Maven lets you create a set of configuration values to customize your application build for different environments. +The `openshift` profile in this example defines a configuration that will be used by the WildFly Helm Chart when provisioning the WildFly server on OpenShift. ++ +[source,xml] +---- + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.maven.plugin} + + + + org.wildfly:wildfly-galleon-pack:${version.wildfly} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly.cloud.galleon.pack} + + + + cloud-server + elytron-oidc-client + + simple-webapp-oidc.war + + + + + package + + + + + + + + +---- +<1> `wildfly-maven-plugin` provisions a WildFly server with the specified layers with our application deployed. +<2> `elytron-oidc-client` automatically adds the native OIDC client subsystem to our WildFly installation. + +* Examine the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-oidc/src/main/webapp/WEB-INF/web.xml[web.xml]. ++ +[source,xml,options="nowrap"] +---- +... + + OIDC <1> + +... +---- +<1> When `elytron-oidc-client` subsystem sees `auth-method` is set to `OIDC`, it enables OIDC authentication mechanism for the application. + +* Examine the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-oidc/src/main/webapp/WEB-INF/oidc.json[oidc.json] file. The `oidc.json` is used to configure the native OIDC client subsystem. ++ +[source,json,options="nowrap"] +---- +{ + "client-id" : "myclient", <1> + "provider-url" : "${env.OIDC_PROVIDER_URL:http://localhost:8080}/realms/myrealm", <2> + "public-client" : "true", <3> + "principal-attribute" : "preferred_username", <4> + "ssl-required" : "EXTERNAL" <5> +} +---- +<1> This is the client we created in Keycloak. +<2> The provider URL, which is the URL for the realm `myrealm` that we created, is specified as an environment variable. We will set its value in the Helm configuration. +<3> When `public-client` is set to `true`, client credentials are not sent when communicating with the OpenID provider. +<4> We specify that the user name of the identity, which in our case is `alice`, is to be used as the principal for the identity. +<5> When `ssl-required` is set to `EXTERNAL`, HTTPS is required by default for external requests. + +== Get the Application URL + +Once the WildFly server has been provisioned, use the following command to find the URL for your example +application: + +[source,bash] +---- +SIMPLE_WEBAPP_OIDC_URL=https://$(oc get route oidc-app --template='{{ .spec.host }}') && +echo "" && +echo "Application URL: $SIMPLE_WEBAPP_OIDC_URL/simple-webapp-oidc" && +echo "Valid redirect URI: $SIMPLE_WEBAPP_OIDC_URL/simple-webapp-oidc/secured/*" && +echo "" +---- + +We'll make use of these URLs in the next two sections. + +== Finish Configuring Keycloak + +From your `myclient` client in the Keycloak Administration Console, +in the client settings, set `Valid redirect URIs` to the Valid redirect URI that was output in the previous section and then click `Save`. + +== Access the Application + +From your browser, navigate to the `Application URL` that was output in the previous section. + +Click on `Access Secured Servlet`. + +You will be redirected to Keycloak to log in. + +Log in using the `alice` user we created earlier. + +Upon successful authentication, you will be redirected back to the example application. + +The example application simply outputs the name of the logged in user. + +You should see the following output: + +[source,text] +---- +Secured Servlet + +Current Principal 'alice' +---- + +This indicates that we have successfully logged into our application! + +== Next Steps + +This guide has shown how to secure an application deployed to WildFly on OpenShift with OIDC. To learn +more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] +documentation. + +[[references]] +== References + +* https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OpenID Connect Client Subsystem Configuration] +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html[Getting Started with WildFly on OpenShift] +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html#helm-charts[WildFly Helm Chart] +* https://www.keycloak.org/getting-started/getting-started-openshift[Getting started with Keycloak on OpenShift] +* https://www.keycloak.org/docs/latest/server_admin/index.html[Keycloak Server Administration Guide] diff --git a/guides/security-saml-openshift.adoc b/guides/security-saml-openshift.adoc new file mode 100644 index 00000000..e19631ca --- /dev/null +++ b/guides/security-saml-openshift.adoc @@ -0,0 +1,276 @@ += Securing WildFly Apps with SAML on OpenShift +:summary: Learn how to secure applications deployed to WildFly on OpenShift with SAML. +:includedir: _includes +include::{includedir}/_attributes.adoc[] +:prerequisites-time: 15 + +You can secure your WildFly applications deployed on OpenShift with Security Assertion Markup Language (SAML). +By using SAML to secure applications, you delegate authentication to SAML identity providers (IdPs). This guide shows +how to secure an example application deployed to WildFly on OpenShift with SAML using Keycloak as the SAML IdP. + +include::{includedir}/_prerequisites.adoc[] +* Access to an OpenShift cluster (try the https://developers.redhat.com/developer-sandbox[Red Hat Developer Sandbox] for free) +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://helm.sh/docs/intro/install/[Helm Chart] + +== Example Application + +We will use a simple web application in this guide that consists of a single https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-saml/src/main/java/org/wildfly/security/examples/SecuredServlet.java[servlet]. We will secure this servlet using SAML. + +We will use the example in the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/simple-webapp-saml[simple-webapp-saml] directory in the `elytron-examples` repo. + +To obtain this example, clone the `elytron-examples` repository to your local machine: + +[source,bash] +---- +git clone git@github.com:wildfly-security-incubator/elytron-examples.git +---- + +include::{includedir}/_proc-log-into-openshift-cluster.adoc[] + +:saml-auth-method: +include::{includedir}/_proc-start-keycloak-openshift.adoc[] + +== Configure Keycloak + +. Log into the `Keycloak Admin Console`. + +. Create a new realm called `myrealm`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/getting-started/getting-started-openshift#_create_a_realm[create a realm]. + +. Add a role called `user`. This role will be required to access our simple web application. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-using-roles-and-groups[create a role]. + +. Add a new user named `alice`. Set an `email` address for this new user, we'll use `alice@example.org`. For more information, see the Keycloak documentation on how to https://www.keycloak.org/getting-started/getting-started-openshift#_create_a_user[create a user]. + +. Once the new user has been created, set a password for this new user from the `Credentials` tab. + +. From the `Role Mapping` tab, assign `alice` the `user` role. For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#proc-assigning-role-mappings_server_administration_guide[assign a role] to a user. + +. Create a new client as follows: +* `General Settings`: +** *Client type* (or *Client Protocol*, depending on your Keycloak version): `SAML` +** *Client ID*: `simple-webapp-saml` +* `Login settings`: Leave the fields blank for now. + ++ +For more information, see the Keycloak documentation on how to https://www.keycloak.org/docs/latest/server_admin/index.html#_client-saml-configuration[Create SAML clients]. + +. Click `Save` to save the client. + +. Once the new client has been created, in the `Settings` tab, scroll down to the `SAML capabilities` section and +set the `Name ID format` to `email`. When accessing +our servlet later on, we will see that this results in `HttpServletRequest.getUserPrincipal().getName()` returning +the logged in user's email address. + +. Then set `Force name ID format` to `On`. Then click on `Save`. + +== Download the SAML Keys + +. From your `simple-webapp-saml` client in the Keycloak Admin Console, click on the `Keys` tab. + +. Click on the `Export` button in the `Signing keys config` to export the SAML keys to a keystore. + +. Set the *Key alias* to `simple-webapp-saml`, the *Key password* to `password`, +the *Realm certificate alias* to `myrealm`, and the *Store password* to `password`. ++ +Take note of the aliases and passwords that you specify here since these will be used +when updating the `keycloak-saml.xml` file. + +. Click on `Export` to download the corresponding `keystore.jks` file. + +. Create an OpenShift secret using this keystore by running the following command: ++ +[source,bash] +---- +oc create secret generic simple-webapp-saml-secret --from-file=/PATH/TO/keystore.jks +---- + +== Download and Edit the Keycloak Adapter Configuration File + +. From your `simple-webapp-saml` client in the *Keycloak Admin Console*, click on the `Action` dropdown in the top right corner +and select `Download Adapter Config`. + +. For the `Format option`, select the `Keycloak SAML Adapter keycloak-saml.xml`, and download the file and place it in the example +application's `WEB-INF` directory, i.e., place the `keycloak-saml.xml` file in +`/PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml/src/main/webapp/WEB-INF`. + +. Update the `keycloak-saml.xml` file as follows: + +* Set the *SP* *entityID* to `"simple-webapp-saml"` +* Set the *SP* *logoutPage* to `"/simple-webapp-saml"` +* Replace the *SP* *Keys* configuration with the following configuration, being sure to use the aliases +and passwords you specified when exporting the SAML keys to the `keystore.jks` file: ++ +[source,xml] +---- + + + + + + + + +---- ++ +* Push this new file to the `simple-webapp-saml` directory in your `elytron-examples` fork, making +sure to push the changes to your fork's default branch. ++ +[source,bash] +---- +cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml +git add src/main/webapp/WEB-INF/keycloak-saml.xml +git commit -m "Added Keycloak adapter deployment descriptor file" +git push origin main +---- + +== Add Helm Configuration + +Let's switch to the `charts` directory in our `simple-webapp-saml` example: + +[source,bash] +---- +cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml/charts +---- + +Notice there's a `helm.yaml` file in this directory with the following content: + +[source,yaml] +---- +build: + uri: https://github.com/YOUR_GITHUB_USERNAME/elytron-examples <1> + contextDir: simple-webapp-saml +deploy: + volumes: + - name: saml-keystore-volume + secret: + secretName: simple-webapp-saml-secret + volumeMounts: + - name: saml-keystore-volume + mountPath: /etc/keycloak-saml-secret-volume + readOnly: true +---- +<1> Replace `YOUR_GITHUB_USERNAME` in the *build* *uri* with your own GitHub username. + +The `helm.yaml` file specifies the Git repository that contains our application's source code. + +Because we have modified the application's source code by adding a `keycloak-saml.xml` file, you need +to set the *build* *uri* in the `helm.yaml` file to point to your own fork. + +Notice that our `helm.yaml` file also refers to the OpenShift secret, `simple-webapp-saml-secret` we +created earlier. This will be used to mount the `keystore.jks` file on our WildFly server pod. + +== Deploy the Example Application to WildFly on OpenShift + +We can deploy our example application to WildFly on OpenShift using the WildFly Helm Chart: + +[source,bash] +---- +helm install saml-app -f /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml/charts/helm.yaml wildfly/wildfly +---- + +Notice that this command specifies the file we updated, `helm.yaml`, that contains the values +needed to build and deploy our application. + +include::{includedir}/_proc-follow-build-and-deployment-openshift.adoc[] + +=== Behind the Scenes + +While our application is building, let's take a closer look at our application's https://github.com/wildfly-security/elytron-examples/blob/main/simple-webapp-saml/pom.xml[pom.xml] file. +Notice that it contains the following `wildfly-maven-plugin` configuration: + +[source,xml] +---- + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.plugin} + + + + org.wildfly:wildfly-galleon-pack:${version.wildfly} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly.cloud.galleon.pack} + + + org.keycloak:keycloak-saml-adapter-galleon-pack:${version.keycloak} + + + + cloud-server + keycloak-client-saml + + + + + + package + + + + +---- + +This configuration is used to provision a WildFly server with the specified layers and with our application deployed. + +The `keycloak-client-saml` layer automatically adds the Keycloak SAML adapter to our WildFly installation. + +== Get the Application URL + +Once the WildFly server has been provisioned, use the following command to find the URL for your example +application: + +[source,bash] +---- +SIMPLE_WEBAPP_SAML_URL=https://$(oc get route saml-app --template='{{ .spec.host }}') && +echo "" && +echo "Application URL: $SIMPLE_WEBAPP_SAML_URL/simple-webapp-saml" && +echo "Master SAML Processing URL: $SIMPLE_WEBAPP_SAML_URL/simple-webapp-saml/saml" && +echo "" +---- + +We'll make use of these URLs in the next two sections. + +== Finish Configuring Keycloak + +From your `simple-webapp-saml` client in the *Keycloak Administration Console*, +In the client settings, set `Master SAML Processing URL` to the `Master SAML Processing URL` that was output +in the previous section and then click `Save`. + +== Access the Application + +From your browser, navigate to the `Application URL`. + +Click on `Access Secured Servlet`. + +You will be redirected to Keycloak to log in. + +Log in using the `alice` user we created earlier. + +Upon successful authentication, you will be redirected back to the example application. + +The example application simply outputs the email address associated with our logged in user. + +You should see the following output: + +[source,text] +---- +Current Principal 'alice@example.org' +---- + +This indicates that we have successfully logged into our application! + +== Next Steps + +This guide has shown how to secure an application deployed to WildFly on OpenShift with SAML. For additional +information, feel free to check out the resources linked below. + +[[references]] +== References + +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html[Getting Started with WildFly on OpenShift] +* https://docs.openshift.com/container-platform/{ocp-version}/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI] +* https://docs.wildfly.org/{wildfly-version}/Getting_Started_on_OpenShift.html#helm-charts[WildFly Helm Chart] +* https://www.keycloak.org/getting-started/getting-started-openshift[Getting started with Keycloak on OpenShift] +* https://www.keycloak.org/docs/latest/server_admin/index.html[Keycloak Server Administration Guide] +* https://www.keycloak.org/docs/latest/securing_apps/#using-saml-to-secure-applications-and-services[Using SAML to secure applications and services] From 49c35e64b9dd6367c5003ff56e03d7e3c0621e2e Mon Sep 17 00:00:00 2001 From: Harald Pehl Date: Thu, 25 Jan 2024 23:33:02 +0100 Subject: [PATCH 3/6] Common structure/wording, exclude MP LRA, fix typos --- _data/guides.yaml | 14 +++++----- getstarted.adoc | 2 +- guides/_includes/_attributes.adoc | 2 +- guides/_includes/_prerequisites.adoc | 1 - guides/application-logging.adoc | 28 ++++++++----------- guides/automate-with-ansible.adoc | 26 ++++++++--------- guides/security-oidc-auth0-openshift.adoc | 2 +- .../security-oidc-identity-propagation.adoc | 2 +- guides/security-oidc-management-console.adoc | 2 +- guides/security-oidc-openshift.adoc | 2 +- guides/security-saml-openshift.adoc | 2 +- guides/template.adoc | 11 ++------ guides/use-microprofile-config.adoc | 22 +++++++-------- guides/use-microprofile-lra.adoc | 25 +++++++++-------- 14 files changed, 66 insertions(+), 75 deletions(-) diff --git a/_data/guides.yaml b/_data/guides.yaml index 74b444cc..60fcb4ab 100644 --- a/_data/guides.yaml +++ b/_data/guides.yaml @@ -4,13 +4,13 @@ categories: - category: Get Started cat-id: get-started guides: - - title: Get Started With WildFly + - title: Getting Started with WildFly url: /get-started description: Build and run a Jakarta EE application with WildFly in a few minutes - category: Observability cat-id: observability guides: - - title: Configure Application Logging + - title: Configuring Logging for your Application url: /guides/application-logging description: Learn how to setup and configure logging in WildFly. - category: Security @@ -34,16 +34,16 @@ categories: - category: Eclipse MicroProfile cat-id: microprofile guides: - - title: Use MicroProfile Config With WildFly + - title: Using MicroProfile Config url: /guides/use-microprofile-config description: Discover how to use MicroProfile Config With WildFly. - - title: Use MicroProfile LRA With WildFly - url: /guides/use-microprofile-lra - description: Discover how to use MicroProfile LRA With WildFly. +# - title: Using MicroProfile LRA +# url: /guides/use-microprofile-lra +# description: Discover how to use MicroProfile LRA With WildFly. - category: Automation cat-id: automation guides: - - title: Deploy WildFly With Ansible + - title: Deploying WildFly using Ansible url: /guides/automate-with-ansible description: Learn how to automate WildFly deployments with Ansible. diff --git a/getstarted.adoc b/getstarted.adoc index 760e65d1..7ea4b815 100644 --- a/getstarted.adoc +++ b/getstarted.adoc @@ -1,6 +1,6 @@ --- layout: getstarted -title: Get Started with WildFly +title: Getting Started with WildFly permalink: /get-started/ --- :page-liquid: diff --git a/guides/_includes/_attributes.adoc b/guides/_includes/_attributes.adoc index bbe2ac14..3fbce8f3 100644 --- a/guides/_includes/_attributes.adoc +++ b/guides/_includes/_attributes.adoc @@ -1,5 +1,5 @@ // WildFly Major version to link to its documentation -:wildfly-version: 29 +:wildfly-version: 31 // Minimal version of Maven :maven-version: 3.9+ // Minimal Version of JDK diff --git a/guides/_includes/_prerequisites.adoc b/guides/_includes/_prerequisites.adoc index ec4baced..a48b9417 100644 --- a/guides/_includes/_prerequisites.adoc +++ b/guides/_includes/_prerequisites.adoc @@ -6,4 +6,3 @@ To complete this guide, you need: * Roughly {prerequisites-time} minutes * JDK {jdk-minimal-version} installed with `JAVA_HOME` configured appropriately * Apache Maven {maven-version} -* You have completed the https://wildfly.org/getstarted/[Get Started Guide]. diff --git a/guides/application-logging.adoc b/guides/application-logging.adoc index 97a5c4a9..eba1d295 100644 --- a/guides/application-logging.adoc +++ b/guides/application-logging.adoc @@ -1,26 +1,23 @@ -= Configure Logging for your Application += Configuring Logging for your Application :summary: Learn how to use logging in your application and configure WildFly to display them :includedir: _includes include::{includedir}/_attributes.adoc[] -// you can override any attributes eg to lengthen the +// you can override any attributes eg to lengthen the // time to complete the guide :prerequisites-time: 10 -TODO: Add a summary of what you achieve in this guide. -Something like: - In this guide, you will learn how to use logging in your application and configure WildFly to display the logs at the level you want. include::{includedir}/_prerequisites.adoc[] -To use logging in our application, we will add a dependency to `org.jboss.logging:jboss-logging` in the Maven `pom.xml` file. +To use logging in our application, we will add a dependency on `org.jboss.logging:jboss-logging` in the Maven `pom.xml` file. Then, we will add a few logs in our code at different levels. -Finally we will configure WildFly to change the log level of our application logs independently of WildFly own logs. +Finally, we will configure WildFly to change the log level of our application logs independently of WildFly own logs. -== Add Dependency to JBoss Logging +== Add Dependency on JBoss Logging -In order to use JBoss Logging in our application, we need to add a dependency to it in the `pom.xml`. +In order to use JBoss Logging in our application, we need to add a dependency on it in the `pom.xml`. The dependency is defined as: @@ -71,7 +68,7 @@ public class GettingStartedService { } ---- -You added a `log` Logger that can log message with the category correspondig to the class package `org.wildfly.examples`. +You added a `log` Logger that can log message with the category corresponding to the class package `org.wildfly.examples`. You also added two logging calls, one at the `TRACE` level and the other one at the `INFO` level. If you run the integration tests with `mvn clean verify`, you will only see the logs at the `INFO` level in the standard output: @@ -87,11 +84,11 @@ $ mvn clean verify By default, WildFly only displays `INFO` logs on the console. Let's now configure WildFly to display our application logs at the `TRACE` level. -== Configure Logging in WildFly Subsystem +== Configure Logging in the WildFly Subsystem The configuration of logging is done by WildFly in its `logging` subsystem. -There are different ways to modify WildFly configuration but as we used the `wildfly-maven-plugin` to provision WildFly, -we can pass a CLI script so that WildFly configuration will be modified whenever we invoke `mvn package`. +There are different ways to modify the WildFly configuration but as we used the `wildfly-maven-plugin` to provision WildFly, +we can pass a CLI script so the WildFly configuration will be modified whenever we invoke `mvn package`. First, we add a `configuration.cli` in the `src/main/scripts` directory: @@ -103,8 +100,7 @@ First, we add a `configuration.cli` in the `src/main/scripts` directory: /subsystem=logging/logger=org.wildfly.examples:add(level=TRACE) ---- -This script contains the management operations to change WildFly configuration. We could invoke any management operations but in this case, -we only modify the `/subsystem=logging` resources that control the logging aspects. +This script contains the management operations to change the WildFly configuration. We could invoke any management operations but, in this case, we only modify the `/subsystem=logging` resources that control the logging aspects. You then need to modify the `wildfly-maven-plugin` configuration in `pom.xml` to execute this: @@ -148,7 +144,7 @@ $ mvn clean verify ... ---- -== Next Steps +== What's next? WildFly provides extensive logging configuration. You can learn more by reading WildFly's https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Logging[Logging Subsystem Configuration Guide] and its https://docs.wildfly.org/{wildfly-version}/wildscribe/subsystem/logging/[model reference]. diff --git a/guides/automate-with-ansible.adoc b/guides/automate-with-ansible.adoc index d629adf0..c5ab5962 100644 --- a/guides/automate-with-ansible.adoc +++ b/guides/automate-with-ansible.adoc @@ -1,12 +1,12 @@ -= Deploy WildFly using Ansible += Deploying WildFly using Ansible :summary: Learn how to automate WildFly deployments with Ansible :includedir: _includes include::{includedir}/_attributes.adoc[] -// you can override any attributes eg to lengthen the +// you can override any attributes eg to lengthen the // time to complete the guide :prerequisites-time: 20 -In this brief demonstration, we’ll set up and run three instances of WildFly on the same machine (localhost). Together they will form a cluster. It’s a rather classic setup, where the appservers needs to synchronize the content of their application’s session to ensure fail over if one of the instances fails. This configuration guarantees that, if one instance fails while processing a request, another one can pick up the work without any data loss. Note that we’ll use a multicast to discover the members of the cluster and ensure that the cluster’s formation is fully automated and dynamic. +In this brief demonstration, we’ll set up and run three instances of WildFly on the same machine (localhost). Together they will form a cluster. It’s a rather classic setup, where the appservers need to synchronize the content of their application’s sessions to ensure fail over if one of the instances fails. This configuration guarantees that, if one instance fails while processing a request, another one can pick up the work without any data loss. Note that we’ll use a multicast to discover the members of the cluster and ensure that the cluster’s formation is fully automated and dynamic. include::{includedir}/_prerequisites.adoc[] @@ -58,12 +58,12 @@ community.general:6.1.0 was installed successfully == Set up the WildFly cluster -For simplicity’s sake and to allow you to reproduce this demonstration on a single machine (physical or virtual) or even a container, we opted to deploy our three instances on one target. We chose localhost as a target, so that the demonstration can even be performed without a remote host. +For simplicity’s sake and to allow you to reproduce this demonstration on a single machine (physical or virtual) or even a container, we opted to deploy our three instances on one target. We chose localhost as a target, so the demonstration can even be performed without a remote host. There are essentially two steps to set up the WildFly cluster: . Install WildFly on the targeted hosts (here just localhost). This means downloading the archive from this website and decompressing the archive in the appropriate directory (JBOSS_HOME). These tasks are handled by the wildfly_install role supplied by Ansible collection for WildFly. -. Create the configuration files to run several instances of WildFly. Because we’re running multiple instances on a single host, you also need to ensure that each instance has its own subdirectories and set of ports, so that the instances can coexist and communicate. Fortunately, this functionality is provided by a role within the Ansible collection called wildfly_systemd. +. Create the configuration files to run several instances of WildFly. Because we’re running multiple instances on a single host, you also need to ensure that each instance has its own subdirectories and set of ports, so the instances can coexist and communicate. Fortunately, this functionality is provided by a role within the Ansible collection called wildfly_systemd. === Ansible playbook to install WildFly @@ -121,7 +121,7 @@ Here is the playbook we'll use to deploy our clusters. Its content is relatively loop_var: port ---- -In short, this playbook uses the Ansible collection for WildFly to, first, install the appserver by using the wildfly_install role. This will download all the artifacts, create the required system groups and users, install dependency (unzip) and so on. At the end of its execution, all the tidbits required to run WildFly on the target host are installed, but the server is not yet running. That’s what happening in the next step. +In short, this playbook uses the Ansible collection for WildFly to, first, install the appserver by using the wildfly_install role. This will download all the artifacts, create the required system groups and users, install dependency (unzip) and so on. At the end of its execution, all the tidbits required to run WildFly on the target host are installed, but the server is not yet running. That is what's happening in the next step. In the tasks section of the playbook, we then call on another role provided by the collection: wildfly_systemd. This role will take care of integrating WildFly, as a regular system service, into the service manager. Here, we use a loop to ensure that we create not one, but three different services. Each one will have the same configuration (standalone-ha.xml) but runs on different ports, using a different set of directories to store its data. @@ -404,7 +404,7 @@ localhost : ok=70 changed=16 unreachable=0 failed=0 s Note that the playbook is not that long, but it does a lot for us. It performs almost 100 different tasks! Starting by automatically installing the dependencies, including the JVM required by WildFly, along with downloading its binaries. And the wildfly_systemd role does even more, effortlessly setting up three distinct services, each with its own set of ports and directory layout to store instance-specific data. -Even better, the WildFly installation is NOT duplicated. All of the binaries live under the /opt/wildfly-27.0.1 directory, but all the data files of each instance are stored in separate folders. This means that we just need to update the binaries, once, and then restart the instances, to deploy a patch or upgrade to a new version of WildFly. +Even better, the WildFly installation is NOT duplicated. All the binaries live under the /opt/wildfly-27.0.1 directory, but all the data files of each instance are stored in separate folders. This means that we just need to update the binaries, once, and then restart the instances, to deploy a patch or upgrade to a new version of WildFly. On top of everything, we configured the instances to use the standalone-ha.xml configuration as the baseline, so they are already set up for clustering. @@ -435,11 +435,11 @@ Jan 10 09:24:25 94aa1904876e standalone.sh[1001]: 09:24:25,914 INFO [org.jboss. ---- -=== Deploy an application to the Wildlfy cluster +=== Deploy an application to the WildFly cluster -Now, our three WildFly are running, but the cluster has yet to form. Indeed, with no apps there is no reason for the cluster to exist. Let's modify our Ansible playbook to deploy a simple application to all instances; this will allow us to check that the cluster is working as expected. To achieve this, we'll leverage another role provided by the WildFly collection: wildfly_utils. +Now, our three WildFly servers are running, but the cluster has yet to form. Indeed, with no apps there is no reason for the cluster to exist. Let's modify our Ansible playbook to deploy a simple application to all instances; this will allow us to check that the cluster is working as expected. To achieve this, we'll leverage another role provided by the WildFly collection: wildfly_utils. -In our case, we will use the jboss_cli.yml task file, which encapsulates the running of JBoss command-line interface (CLI) queries: +In our case, we will use the jboss_cli.yml task file, which encapsulates the running of JBoss command-line interface (CLI) commands: [source, yaml] ---- @@ -465,7 +465,7 @@ In our case, we will use the jboss_cli.yml task file, which encapsulates the run ---- -Now, we will once again execute our playbook so that the web application is deployed on all instances. Once the automation completes successfully, the deployment will trigger the formation of the cluster. +Now, we will once again execute our playbook so the web application is deployed on all instances. Once the automation completes successfully, the deployment will trigger the formation of the cluster. === Verify that the WildFly cluster is running and the app is deployed @@ -479,9 +479,9 @@ You can verify the cluster formation by looking at the log files of any of the t … ---- -=== Using the Ansible collection as an installer for Wildfly +=== Using the Ansible collection as an installer for WildFly -Last remark: while the collection is designed to be used inside a playbook, you can also use the provided playbook to directly install Wildfly: +Last remark: while the collection is designed to be used inside a playbook, you can also use the provided playbook to directly install WildFly: [source, bash] ---- diff --git a/guides/security-oidc-auth0-openshift.adoc b/guides/security-oidc-auth0-openshift.adoc index 15f1e066..ccc950b3 100644 --- a/guides/security-oidc-auth0-openshift.adoc +++ b/guides/security-oidc-auth0-openshift.adoc @@ -234,7 +234,7 @@ Current Principal 'auth0|6544f9aa427fb9f276240d55' Notice the `user_id` for our `user@example.com` user is displayed. This indicates that we have successfully logged into our application! -== Next Steps +== What's next? This guide has shown how to secure an application deployed to WildFly on OpenShift using the Auth0 OpenID provider. For additional information, feel free to check out the resources linked below. To learn diff --git a/guides/security-oidc-identity-propagation.adoc b/guides/security-oidc-identity-propagation.adoc index 1479f65d..cabe4ecf 100644 --- a/guides/security-oidc-identity-propagation.adoc +++ b/guides/security-oidc-identity-propagation.adoc @@ -384,7 +384,7 @@ shows that the identity from the virtual security domain was successfully propag * The identity as visible to the EJB within `ejb-same-domain.ear` is `alice` with `User` role. This shows that the identity from the virtual security domain was successfully propagated to the EJB in a separate deployment. -== Next Steps +== What's next? This guide shown how to propagate security identities established by a virtual security domain within a deployment and across deployments when securing a web application with OIDC. To learn diff --git a/guides/security-oidc-management-console.adoc b/guides/security-oidc-management-console.adoc index be8c305d..7996ce87 100644 --- a/guides/security-oidc-management-console.adoc +++ b/guides/security-oidc-management-console.adoc @@ -113,7 +113,7 @@ With the above configuration now in place, let's access http://localhost:10000/c the Keycloak login page. We can log in using the `alice` user that we created earlier. Upon successful authentication, we will be redirected back to the WildFly Management Console. -== Next Steps +== What's next? This guide has shown how to secure the WildFly Management Console with OIDC. To learn more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] diff --git a/guides/security-oidc-openshift.adoc b/guides/security-oidc-openshift.adoc index d5297ab0..a32b0775 100644 --- a/guides/security-oidc-openshift.adoc +++ b/guides/security-oidc-openshift.adoc @@ -210,7 +210,7 @@ Current Principal 'alice' This indicates that we have successfully logged into our application! -== Next Steps +== What's next? This guide has shown how to secure an application deployed to WildFly on OpenShift with OIDC. To learn more about OIDC configuration, check out the https://docs.wildfly.org/{wildfly-version}/Admin_Guide.html#Elytron_OIDC_Client[Elytron OIDC Client] diff --git a/guides/security-saml-openshift.adoc b/guides/security-saml-openshift.adoc index e19631ca..1c8197d7 100644 --- a/guides/security-saml-openshift.adoc +++ b/guides/security-saml-openshift.adoc @@ -260,7 +260,7 @@ Current Principal 'alice@example.org' This indicates that we have successfully logged into our application! -== Next Steps +== What's next? This guide has shown how to secure an application deployed to WildFly on OpenShift with SAML. For additional information, feel free to check out the resources linked below. diff --git a/guides/template.adoc b/guides/template.adoc index efe65a73..a748e461 100644 --- a/guides/template.adoc +++ b/guides/template.adoc @@ -2,7 +2,7 @@ :summary: ONELINE EXPLANATION OF THE GUIDE :includedir: _includes include::{includedir}/_attributes.adoc[] -// you can override any attributes eg to lengthen the +// you can override any attributes eg to lengthen the // time to complete the guide :prerequisites-time: 10 @@ -14,11 +14,6 @@ In this guide, you will learn how to setup and use Eclipse MicroProfile Config i include::{includedir}/_prerequisites.adoc[] * Any additional prerequisites specific to this guide (eg you have completed a previous guide) -[[requirements]] -== Requirements - -Lorem ipsum - == A section Lorem ipsum @@ -26,8 +21,8 @@ Lorem ipsum == Another section -// Always keep a next steps to let the user know what could be achieve next -== Next Steps +// Always keep a what's next? section to let the user know what could be achieved next +== What's next? Something like: diff --git a/guides/use-microprofile-config.adoc b/guides/use-microprofile-config.adoc index 9478e3ed..40e68d4c 100644 --- a/guides/use-microprofile-config.adoc +++ b/guides/use-microprofile-config.adoc @@ -1,4 +1,4 @@ -= Use Eclipse MicroProfile Config += Using MicroProfile Config :summary: Learn how to use MicroProfile Config With WildFly. :includedir: _includes include::{includedir}/_attributes.adoc[] @@ -9,18 +9,18 @@ In this guide, you will learn how to setup and use Eclipse MicroProfile Config i include::{includedir}/_prerequisites.adoc[] [[requirements]] -== Requirements +== Configure Your App to make use of MicroProfile Config In order to use MicroProfile Config in your application, you need to update the Maven `pom.xml` at different places: -1. Add a dependency to WildFly BOM for MicroProfile in the `` section -2. Add a dependency to the MicroProfile Config API in the `` section +1. Add a dependency on WildFly BOM for MicroProfile in the `` section +2. Add a dependency on the MicroProfile Config API in the `` section -Once these 2 steps will be achieved, you will be able to use MicroProfile Config in your application. +Once these 2 steps have been completed, you will be able to use MicroProfile Config in your application. -=== Add Dependency to WildFly MicroProfile BOM +=== Add Dependency on the WildFly MicroProfile BOM -You need to add a dependency to the WildFly MicroProfile BOM `org.wildfly.bom:wildfly-microprofile` in the `` section so that your application will use the correct version of the MicroProfile Config provided by WildFly. +You need to add a dependency on the WildFly MicroProfile BOM `org.wildfly.bom:wildfly-microprofile` in the `` section so your application will use the correct version of the MicroProfile Config provided by WildFly. The dependency is defined as: @@ -35,7 +35,7 @@ The dependency is defined as: ---- -It must be added to the `` of your pom.xml: +It must be added to the `` of your pom.xml: [source,xml] ---- @@ -54,7 +54,7 @@ WildFly BOMS are the only dependencies that must be added to the ` Date: Fri, 26 Jan 2024 00:38:13 +0100 Subject: [PATCH 4/6] More compact guides index page --- _includes/index-guides.html | 3 +-- _sass/layouts/guides.scss | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/_includes/index-guides.html b/_includes/index-guides.html index aad2221a..417c6dfb 100644 --- a/_includes/index-guides.html +++ b/_includes/index-guides.html @@ -10,9 +10,8 @@

    {{ item.category }}

    {{ guide.title}}

    +
    {{ guide.description | markdownify }}
    -
    {{ guide.description | markdownify }}
    - {% endfor %} {% endfor %} diff --git a/_sass/layouts/guides.scss b/_sass/layouts/guides.scss index 35eff77d..d9fa4d9e 100644 --- a/_sass/layouts/guides.scss +++ b/_sass/layouts/guides.scss @@ -1,3 +1,9 @@ .guide { padding-bottom: 3rem; } + +.guides { + .description { + margin: 0 1rem 1rem 1rem; + } +} \ No newline at end of file From a8ae90b85158b228e736103be6429bdc421d788d Mon Sep 17 00:00:00 2001 From: Harald Pehl Date: Fri, 26 Jan 2024 16:19:21 +0100 Subject: [PATCH 5/6] Remove 'Eclipse', and 'WildFly', fix typos --- _data/guides.yaml | 2 +- guides/automate-with-ansible.adoc | 4 ++-- guides/security-oidc-identity-propagation.adoc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_data/guides.yaml b/_data/guides.yaml index 60fcb4ab..52060453 100644 --- a/_data/guides.yaml +++ b/_data/guides.yaml @@ -31,7 +31,7 @@ categories: - title: Securing WildFly Apps with SAML on OpenShift url: /guides/security-saml-openshift description: Learn how to secure applications deployed to WildFly on OpenShift with SAML. - - category: Eclipse MicroProfile + - category: MicroProfile cat-id: microprofile guides: - title: Using MicroProfile Config diff --git a/guides/automate-with-ansible.adoc b/guides/automate-with-ansible.adoc index c5ab5962..2259f6c7 100644 --- a/guides/automate-with-ansible.adoc +++ b/guides/automate-with-ansible.adoc @@ -6,7 +6,7 @@ include::{includedir}/_attributes.adoc[] // time to complete the guide :prerequisites-time: 20 -In this brief demonstration, we’ll set up and run three instances of WildFly on the same machine (localhost). Together they will form a cluster. It’s a rather classic setup, where the appservers need to synchronize the content of their application’s sessions to ensure fail over if one of the instances fails. This configuration guarantees that, if one instance fails while processing a request, another one can pick up the work without any data loss. Note that we’ll use a multicast to discover the members of the cluster and ensure that the cluster’s formation is fully automated and dynamic. +In this brief guide, we’ll set up and run three instances of WildFly on the same machine (localhost). Together they will form a cluster. It’s a rather classic setup, where the appservers need to synchronize the content of their application’s sessions to ensure fail over if one of the instances fails. This configuration guarantees that, if one instance fails while processing a request, another one can pick up the work without any data loss. Note that we’ll use a multicast to discover the members of the cluster and ensure that the cluster’s formation is fully automated and dynamic. include::{includedir}/_prerequisites.adoc[] @@ -19,7 +19,7 @@ On a Linux system using a package manager, installing Ansible is pretty straight $ sudo dnf install ansible-core ---- -Please refer to the documentation available online for installation on other operating system. Note that this demonstration assumes you are running both the Ansible controller and the target (same machine in our case) on a Linux system. However, it should work on any other operating system with a few adjustements. +Please refer to the documentation available online for installation on other operating systems. Note that this guide assumes you are running both the Ansible controller and the target (same machine in our case) on a Linux system. However, it should work on any other operating system with a few adjustments. Before going further, double check that you are running a recent enough version of Ansible (2.12 or above will do, but 2.9 is the bare minimum): diff --git a/guides/security-oidc-identity-propagation.adoc b/guides/security-oidc-identity-propagation.adoc index cabe4ecf..1cca9fa5 100644 --- a/guides/security-oidc-identity-propagation.adoc +++ b/guides/security-oidc-identity-propagation.adoc @@ -1,5 +1,5 @@ = Identity Propagation with OpenID Connect -:summary: Learn how to propagate identities within a deployment and across deployments when securing WildFly apps with OpenID Connect. +:summary: Learn how to propagate identities within a deployment and across deployments when securing apps with OpenID Connect. :includedir: _includes include::{includedir}/_attributes.adoc[] :prerequisites-time: 15 From 05b97093c25cb9f5a57607b644a6496191626b8f Mon Sep 17 00:00:00 2001 From: Harald Pehl Date: Fri, 26 Jan 2024 16:24:52 +0100 Subject: [PATCH 6/6] Shorten long description in guides.yaml --- _data/guides.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/guides.yaml b/_data/guides.yaml index 52060453..0bbb1350 100644 --- a/_data/guides.yaml +++ b/_data/guides.yaml @@ -21,7 +21,7 @@ categories: description: Learn how to secure applications deployed to WildFly on OpenShift with OpenID Connect. - title: Identity Propagation with OpenID Connect url: /guides/security-oidc-identity-propagation - description: Learn how to propagate identities within a deployment and across deployments when securing WildFly apps with OpenID Connect. + description: Learn how to propagate identities within a deployment and across deployments when securing apps with OpenID Connect. - title: Securing WildFly Apps with Auth0 on OpenShift url: /guides/security-oidc-auth0-openshift description: Learn how to secure applications deployed to WildFly on OpenShift with the Auth0 OpenID provider.