Ricky's Hodgepodge
https://blogs.nologin.es/rickyepoderi/
···A little of everything···enhttps://blogs.nologin.es/rickyepoderi/templates/default/img/s9y_banner_small.pngRSS: Ricky's Hodgepodge - ···A little of everything···
https://blogs.nologin.es/rickyepoderi/
10021Using jakartaee 10 security OIDC with wildfly 27 preview
https://blogs.nologin.es/rickyepoderi/index.php?/archives/198-Using-jakartaee-10-security-OIDC-with-wildfly-27-preview.html
<p>Today a very quick entry about the jakarta security OpenID Connect is going to be presented. The <a href="https://jakarta.ee/specifications/security/3.0/jakarta-security-spec-3.0.html#openid-connect-annotation">new version 3.0 of the jakarta security spec allows as to configure an OpenID Connect authentication mechanism</a>. The idea of this entry is testing the mechanism using <a href="https://www.keycloak.org/">keycloak</a> as the authentication server and <a href="https://www.wildfly.org/">wildfly</a> 27 preview (current alpha5 version) as the jakartaee 10 compatible server. This <a href="https://github.com/hantsy/jakartaee10-sandbox">repository developed by <em>hantsy</em></a> will be used as the test application, specifically the folder called <em>security-oidc</em> which is a sample OIDC application.</p>
<p>The application defines a <a href="https://github.com/rickyepoderi/jakartaee10-sandbox/blob/master/security-oidc/src/main/java/com/example/ProtectedServlet.java#L16-L23">ProtectedServlet.java</a> which has the <em>OpenIdAuthenticationMechanismDefinition</em> defined in it.</p>
<pre><code class="java">
@OpenIdAuthenticationMechanismDefinition(
providerURI = "${openIdConfig.issuerUri}",
clientId = "${openIdConfig.clientId}",
clientSecret = "${openIdConfig.clientSecret}",
redirectURI = "${baseURL}/callback"
)
</code></pre>
<p>The configuration is loaded from a CDI Named (openIdConfig) bean which is defined in the class <a href="https://github.com/rickyepoderi/jakartaee10-sandbox/blob/master/security-oidc/src/main/java/com/example/Auth0OpenIdConfig.java">Auth0OpenIdConfig.java</a>. This class in turn loads the final data from a file <em>openid.properties</em> located in the classpath. The file should be configured to specify the OpenID Connect server information (which will be the local <em>keycloak</em> installation).</p>
<p>Once the demo app has been explained (thanks <em>hantsy</em>!) all the detailed steps to make it run in the commented setup are presented. </p>
<ol>
<li><p>Install <em>keycloak</em> and start it in dev mode.</p>
<pre><code class="bash">
wget https://github.com/keycloak/keycloak/releases/download/19.0.2/keycloak-19.0.2.zip
unzip keycloak-19.0.2.zip
cd keycloak-19.0.2/bin/
./kc.sh start-dev
</code></pre>
</li>
<li><p>Go to the console (<em>http://localhost:8080</em>) and create the initial <em>admin</em> user. Then login with that user to the console.</p>
<li><p>Create a client in <em>keycloak</em> called <em>wildfly</em> in the master realm. Go to the <em>Clients</em> menu option and click <em>Create client</em>. Fill first form in the following way.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/client1.png" alt="Create client 1st screen"/>
</div>
<p>Click next and continue with the second form.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/client2.png" alt="Create client 2nd screen"/>
</div>
<p>Click <em>Save</em>. In the <em>Settings</em> tab add the valid redirect URIs for the client (the <em>wildfly</em> server will run in port 8081 to not collide with <em>keycloak</em>).</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/client-uris.png" alt="Set valid redirect URIs"/>
</div>
<o>And take note of the client secret which is displayed in the <em>Credentials</em> tab (this information will be needed to configure the <em>openid.properties</em> file in the application).
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/client-secret.png" alt="View client secret"/>
</div>
</li>
<li><p>The sample app requires a user called <em>user</em>. So let's create it. In the <em>Users</em> menu click the <em>Add User</em> button and fill the information.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/user1.png" alt="Create user"/>
</div>
</li>
<p>Click <em>Create</em>. In the <em>Credentials</em> tab set a password using <em>Set password</em>.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Using-jakartaee-10-security-OIDC-with-wildfly-27-preview/user-password.png" alt="Set user password"/>
</div>
<p>Click <em>Save</em> and <em>Set password</em>.</p>
</li>
<li><p>Time to install the <em>wildfly</em> server. As previously commented it is started with an offset of 1 to use port 8081 (and avoid collision with <em>keycloak</em>).</p>
<pre><code class="bash">
wget https://github.com/wildfly/wildfly/releases/download/27.0.0.Alpha5/wildfly-preview-27.0.0.Alpha5.zip
unzip wildfly-preview-27.0.0.Alpha5.zip
cd wildfly-preview-27.0.0.Alpha5/bin/
./add-user.sh -u admin -p admin
./standalone.sh -Djboss.socket.binding.port-offset=1
</code></pre>
</li>
<li><p>In order to build the application clone the repository and go to the <em>security-oidc</em> project.<p>
<pre><code class="bash">
git clone https://github.com/hantsy/jakartaee10-sandbox.git
cd jakartaee10-sandbox/security-oidc
</code></pre>
<p>At this point we need to configure the file <em>src/main/resources/openid.properties</em> with our keycloak information. Note the secret was taken from a previous step.</p>
<pre><code class="bash">
domain=localhost:8080/realms/master
clientId=wildfly
clientSecret=4R9Akb1bCYc7TkW9up0cYUgBB9h4u5Mv
</code></pre>
<p>And finally I did some little modifications to fully set my environment for the application. Check this diff.</p>
<pre><code class="diff">
git diff
diff --git a/pom.xml b/pom.xml
index 2c53f21..28940ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <maven.compiler.release>17</maven.compiler.release>
+ <maven.compiler.release>11</maven.compiler.release>
<!-- Official Maven Plugins -->
vmaven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
diff --git a/security-oidc/src/main/java/com/example/Auth0OpenIdConfig.java b/security-oidc/src/main/java/com/example/Auth0OpenIdConfig.java
index 3326125..2c1da58 100644
--- a/security-oidc/src/main/java/com/example/Auth0OpenIdConfig.java
+++ b/security-oidc/src/main/java/com/example/Auth0OpenIdConfig.java
@@ -28,7 +28,7 @@ public class Auth0OpenIdConfig {
domain = properties.getProperty("domain");
clientId = properties.getProperty("clientId");
clientSecret = properties.getProperty("clientSecret");
- issuerUri = "https://" + this.domain + "/";
+ issuerUri = "http://" + this.domain + "/";
LOGGER.log(
Level.INFO,
"domain: {0}, clientId: {1}, clientSecret:{2}, issuerUri: {3}",
diff --git a/security-oidc/src/main/java/com/example/CallbackServlet.java b/security-oidc/src/main/java/com/example/CallbackServlet.java
index c739173..57dd4a2 100644
--- a/security-oidc/src/main/java/com/example/CallbackServlet.java
+++ b/security-oidc/src/main/java/com/example/CallbackServlet.java
@@ -23,7 +23,7 @@ public class CallbackServlet extends HttpServlet {
LOGGER.log(Level.FINEST, "Enter callback servlet");
// response.getWriter().println(context.getAccessToken());
String referer = (String) request.getSession().getAttribute("Referer");
- String redirectTo = referer != null ? referer : "/protected";
+ String redirectTo = referer != null ? referer : "/security-oidc-examples/protected";
LOGGER.log(Level.FINEST, "In /callback, redirect to: {0}", redirectTo);
response.sendRedirect(redirectTo);
</code></pre>
<p>Java 11 (which is my default java) is used instead of 17, the <em>issuerUri</em> is http and not https (because <em>keycloak</em> was started in dev mode to not complicate the demo with certificates) and finally the application will be deployed normally from the war, so the context will be <em>/security-oidc-examples</em> (not deployed as the ROOT app).</p>
</li>
<li><p>One tricky point is that by default the elytron subsystem enforces the logged user to be in the default <em>other</em> domain (by default application users are placed in the <em>application-users.properties</em> file in <em>wildfly</em>). The <em>integrated-jaspi</em> option was set to false to avoid that. Now the logged users via jakartaee security will not be mapped to local elytron users.</p>
<pre><code class="bash">
./jboss-cli.sh --connect --controller=remote+http://localhost:9991
/subsystem=undertow/application-security-domain=other:write-attribute(name=integrated-jaspi, value=false)
reload
</code></pre>
</li>
<li><p>Everything is OK to compile the sample app and deploy it to the server.</p>
<pre><code class="bash">
cd jakartaee10-sandbox/security-oidc
mvn clean package
cd ${JBOSS_HOME}/bin
./jboss-cli.sh --connect --controller=remote+http://localhost:9991
deploy /path/to/jakartaee10-sandbox/security-oidc/target/security-oidc-examples.war
</code></pre>
</li>
<li><p>You can now go the protected servlet <em>http://localhost:8081/security-oidc-examples/protected</em> and check performing a login into the app. The browser will be redirected to the keycloak login screen and, after a successful login with <em>user</em>, it will be redirected back to the app. The token information is displayed by the protected page in this application. I was about to record a video but it seems that <a href="https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2461">my fedora laptop is not in the mood</a>. So no video this time.</p>
</li>
</ol>
<p>That's all folks! Today's entry is a quick review of the steps needed to configure jakartaee 10 OIDC security with <em>keycloak</em> and <em>wildfly</em> 27 preview. All these specs are very new so there will be issues for sure (note wildfly is a preview in alpha state, beta will be reached soon) but seeing it working is nice.</p>
<p>Brest regards!</p>
Ricky's Hodgepodgenospam@example.com (rickyepoderi)
Java, Security, 2022-09-15T10:01:00Zhttps://blogs.nologin.es/rickyepoderi/wfwcomment.php?cid=1981https://blogs.nologin.es/rickyepoderi/rss.php?version=1.0&type=comments&cid=198Creating a custom credential store for wildfly
https://blogs.nologin.es/rickyepoderi/index.php?/archives/197-Creating-a-custom-credential-store-for-wildfly.html
Today an entry about custom credential stores in <a href="https://www.wildfly.org">wildfly</a> is going to be presented. With the new <em>elytron</em> subsystem the way of securely manage passwords inside the configuration is using a <a href="http://www.mastertheboss.com/jbossas/jboss-security/using-credential-stores-to-store-your-passwords-in-wildfly-11">credential store</a>. But what happen if a custom implementation is needed for any reason, is it possible to develop a custom credential store? Yes, it is, and that is the goal of the current post. <img src="https://blogs.nologin.es/rickyepoderi/templates/default/img/emoticons/smile.png" alt=":-)" class="emoticon" />
<ol>
<li><p>The first step is downloading, installing and starting the last <em>wildfly</em> server. </p>
<pre><code class="bash">
wget https://github.com/wildfly/wildfly/releases/download/26.1.1.Final/wildfly-26.1.1.Final.zip
unzip wildfly-26.1.1.Final.zip
cd wildfly-26.1.1.Final/bin
./add-user.sh -u admin -p admin
./standalone.sh
</code></pre>
</li>
<li><p>The credential stores are just provided by a standard JavaSE <a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/security/Provider.html">Provider</a>. So in order to create a custom implementation two classes should be developed.<p>
<ul>
<li><p>The one that extends the <a href="https://github.com/rmartinc/wildfly-elytron/blob/1.11.3.Final/credential/store/src/main/java/org/wildfly/security/credential/store/CredentialStoreSpi.java">CredentialStoreSpi</a>. This class is the real implementation of the store, with methods like <em>store</em>, <em>retrieve</em> or <em>getAliases</em> to manage the secret values. The standard implementations are placed in this <a href="https://github.com/rmartinc/wildfly-elytron/tree/1.11.3.Final/credential/store/src/main/java/org/wildfly/security/credential/store/impl">folder</a> and, for example, the <em>MapCredentialStore</em> is a simple <em>Map</em> implementation which is a useful starting point.</p></li>
<li><p>But the <em>Provider</em> is also needed to register the previous implementation. Inside elytron the provider class is <a href="https://github.com/rmartinc/wildfly-elytron/blob/1.11.3.Final/credential/store/src/main/java/org/wildfly/security/credential/store/WildFlyElytronCredentialStoreProvider.java">WildFlyElytronCredentialStoreProvider</a>. It adds the services for the standard stores with the correct types, algorithms and implementation classes.</p></li>
</ul>
</li>
<li><p>For the entry a simple credential store that saves the secrets in a properties file is going to be developed. But to make it a bit more interesting the values in the file are going to be encrypted using a PBE algorithm. The PBE key will be derived from the password passed to the credential store. This point is a bit weak and maybe it was better to use a hardcoded key, but I think that this way the entry is more educational. As always, the implementation is just an example you can extend, improve and adapt to your needs. The full maven project can be downloaded from <a href="https://blogs.nologin.es/rickyepoderi/uploads/Creating-a-custom-credential-store-for-wildfly/custom-credential-store.zip">here</a> and it is also in <a href="https://github.com/rickyepoderi/custom-credential-store">my personal github account</a>.</p>
<p>For details in the implementation just check <a href="https://github.com/rickyepoderi/custom-credential-store/blob/main/src/main/java/es/rickyepoderi/ccs/CustomCredentialStore.java">the store class</a> but let's show the provider constructor.</p>
<pre><code class="java">
public CustomCredentialStoreProvider() {
super("CustomCredentialStoreProvider", "0.1", "Custom CredentialStore Provider");
putService(new Service(this, "CredentialStore", "CustomCredentialStoreProvider",
"es.rickyepoderi.ccs.CustomCredentialStore", Collections.<String>emptyList(),
Collections.<String, String>emptyMap()));
}
</code></pre>
<p>The class registers the implementation putting the service with type <em>CredentialStore</em> (it should be this value), algorithm is <em>CustomCredentialStoreProvider</em> (this name will be used later to configure the store inside <em>wildfly</em>) and the implementation class is <em>es.rickyepoderi.ccs.CustomCredentialStore</em>. No aliases or attributes are defined.</p>
</li>
<li><p>The final part of the coding process is adding a <em>META-INF/services/java.security.Provider</em> file that will make the JDK automatically detect the provider (<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html">ServiceLoader</a> technique).
<pre><code class="bash">
cat src/main/resources/META-INF/services/java.security.Provider
es.rickyepoderi.ccs.CustomCredentialStoreProvider
</code></pre>
</li>
<li><p>So we have our custom credential store implementation ready. Just compile it and create the jar.</p>
<pre><code class="bash">
cd custom-credential-store
mvn clean package
</code></pre>
<p>The final file will be place in the <em>target</em> directory.</p>
</li>
<li><p>Now the interesting part, using CLI add the library as a module inside <em>wildfly</em>.</p>
<pre><code class="bash">
module add --name=es.rickyepoderi.ccs --resources=/path/to/custom-credential-store/target/custom-credential-store-0.0.1.jar --dependencies=org.wildfly.security.elytron
</code></pre>
</li>
<li><p>The provider should be loaded into <em>elytron</em> to make it available to the server (if you remember I did the same with <a href="https://blogs.nologin.es/rickyepoderi/index.php?/archives/190-Configuring-BCFIPS-in-wildfly-via-elytron.html">the Bouncy Castle FIPS jars in a previous entry</a>).</p>
<pre><code class="bash">
/subsystem=elytron/provider-loader=ccs:add(module=es.rickyepoderi.ccs)
</code></pre>
<p>As the provider was defined in the service file no more arguments are needed. The provider class will be located automatically.</p>
</li>
<li><p>The custom credential can be configured at this point.</p>
<pre><code class="bash">
/subsystem=elytron/credential-store=ccs:add(providers=ccs, credential-reference={clear-text=XXXXXX}, location=custom.properties, relative-to=jboss.server.config.dir, type=CustomCredentialStoreProvider, create=true)
</code></pre>
<p>The <em>type</em> should be <em>CustomCredentialStoreProvider</em> (the algorithm registered inside the provider). The store will use the provided password (please here it is provided in plain which is a nonsense, as I commented this is just an example) to create a PBE key and the values will be encrypted with it. The underlying file is specified using <em>location</em> and <em>relative-to</em> options and placed inside the configuration folder of the server. By default the implementation encrypts values using <em>PBEWithHmacSHA512AndAES_256</em> algorithm but it can be changed using the <em>implementation-properties</em> option. In general that option can pass custom attributes to the implementation and the example manages several of them you can try and play with.</p>
</li>
<li><p>Finally a secret is created inside the store ready to be used.</p>
<pre><code class="bash">
/subsystem=elytron/credential-store=ccs:add-alias(alias=alias1, secret-value=sa)
</code></pre>
<p>And if you check the properties file the alias will be there with the value encrypted.</p>
<pre><code class="bash">
grep alias1 ../standalone/configuration/custom.properties
alias1=oDaesxvoSWLkiwWo89sjzA\=\=\:MFkwOAYJKoZIhvcNAQUMMCsEFGTaNHH+6TJiT6PrGPC/tByEaGIWAgIQAAIBIDAMBggqhkiG9w0CCwUAMB0GCWCGSAFlAwQBKgQQDzqM6mftjvjqCg49J2td7Q\=\=
</code></pre>
</li>
<li><p>That secret will be used to connect to the default H2 datasource that is defined in the <em>wildfly</em> server (that is why the secret value was <em>sa</em>).</p>
<pre><code class="bash">
batch
/subsystem=datasources/data-source=ExampleDS:undefine-attribute(name=password)
/subsystem=datasources/data-source=ExampleDS:write-attribute(name=credential-reference, value={store=ccs, alias=alias1})
run-batch
reload
</code></pre>
<p>The server should be reloaded OK and the datasource should be able to connect to the H2 database.</p>
<pre><code class="bash">
/subsystem=datasources/data-source=ExampleDS:test-connection-in-pool
{
"outcome" => "success",
"result" => [true]
}
</code></pre>
<p>It works successfully!</p>
</li>
</ol>
<p>That is all. The entry is a simple example to develop your own credential store. This is usually not needed and standard stores provided by <em>wildfly</em> should be enough for you. But, if for whatever reason, there is a specific requirement that forces you to implement a custom credential store, here you have an example. Remember my implementation uses the password provided to the store to derive a PBE key and encrypt values with it (it was done to show how to recover that password but maybe using a hadcoded key was a better idea). It is just a proof of concept. The entry details the implementation and the configuration of the store inside the server. Links to the maven project were available before, please use it with care.</p>
<p>Best regards!</p>
Ricky's Hodgepodgenospam@example.com (rickyepoderi)
Java, 2022-07-23T09:31:00Zhttps://blogs.nologin.es/rickyepoderi/wfwcomment.php?cid=1970https://blogs.nologin.es/rickyepoderi/rss.php?version=1.0&type=comments&cid=197Installing magisk in my lineage phone
https://blogs.nologin.es/rickyepoderi/index.php?/archives/196-Installing-magisk-in-my-lineage-phone.html
<p>A very quick personal entry to summarize how to install <a href="https://github.com/topjohnwu/Magisk">magisk</a> in my <a href="https://lineageos.org/">lineage</a> device. It seems that now every time the OS is upgraded <em>magisk</em> should also be re-installed on it. The procedure is described in the project <a href="https://topjohnwu.github.io/Magisk/">documentation</a> but I prefer my usual detailed steps.</p>
<ol>
<li><p>Download and install/upgrade <a href="https://github.com/topjohnwu/Magisk/releases/">the latest magisk app</a> on the phone once it is upgraded.</p></li>
<li><p>Magisk need to patch the <em>boot.img</em> of the lineage distribution. Download the used <a href="https://download.lineageos.org">lineage bundle</a> for your phone.</p></li>
<li><p>Install python and the protobuf package on your laptop in order to extract the zip.</p>
<pre><code class="bash">
dnf install python python-protobuf
</code></pre>
</li>
<li><p>Download <a href="https://github.com/cyxx/extract_android_ota_payload">extract_android_ota_payload</a> tool and execute it over the zip file.</p>
<pre><code class="bash">
wget https://raw.githubusercontent.com/cyxx/extract_android_ota_payload/master/extract_android_ota_payload.py
wget https://raw.githubusercontent.com/cyxx/extract_android_ota_payload/master/update_metadata_pb2.py
python extract_android_ota_payload.py lineage-18.1-YYYYMMDD-nightly-XXX-signed.zip .
Extracting 'payload.bin' from OTA file...
Extracting 'boot.img'
Extracting 'system.img'
</code></pre>
</li>
<li><p>Use <em>adb</em> to push the image to the phone:</p>
<pre><code class="bash">
adb push boot.img /sdcard/Download/
</code></pre>
</li>
<li><p>Open the application on the phone, click <em>install</em>, <em>Select and patch File</em> and locate the image. Click <em>Let's go</em>. A patched <em>magisk_patched-XXXXX_XXXXX.img</em> is generated. Copy it to your laptop.</p>
<pre><code class="bash">
adb pull /sdcard/Download/magisk_patched-XXXXX_XXXXX.img
</code></pre>
</li>
<li><p>Now just flash the new boot image to your phone.</p>
<pre><code class="bash">
adb reboot-bootloader
fastboot devices
fastboot flash boot magisk_patched-XXXXX_XXXXX.img
</code></pre>
</li>
</ol>
<p>And that is all. Magisk is installed and now my firewall can be configured again.</p>
<p>Regards!</p>
Ricky's Hodgepodgenospam@example.com (rickyepoderi)
Android, Me, 2022-05-15T12:15:00Zhttps://blogs.nologin.es/rickyepoderi/wfwcomment.php?cid=1960https://blogs.nologin.es/rickyepoderi/rss.php?version=1.0&type=comments&cid=196Using test-containers for Java with podman
https://blogs.nologin.es/rickyepoderi/index.php?/archives/195-Using-test-containers-for-Java-with-podman.html
<p>A very quick entry for today. Sometimes the <a href="https://github.com/testcontainers/testcontainers-java">test-containers</a> project (in its java version) is used to add some tests that involve <a href="https://en.wikipedia.org/wiki/Docker_(software)">docker</a> in my daily job. The idea is using containers for complicated tests which cannot be easily mocked up and therefore need the full software image. But I have a fedora laptop now and it incorporated <a href="https://podman.io/">podman</a> instead of <em>docker</em>. They are two different container engines, and, although the former was implemented having <em>docker</em> in mind, they are similar but not exactly the same. Therefore the <em>test-containers</em> project needs some tweaks to make it work in my box. Here I am going to summarize the steps that are more or less explained in this <a href="https://github.com/testcontainers/testcontainers-java/issues/2088">issue report</a>.</p>
<ol>
<li><p>Start the <em>podman</em> service. One of the main difference of <em>podman</em> is that it is daemonless, so we need to start the service in order to have something the <em>test-containers</em> project can talk to.</p>
<pre><code class="bash">
podman system service -t 0 &
</code></pre>
</li>
<li><p>After that just export some environmental variables to the java project. The unix socket depends on our user (it is not root based) and some features should be disabled from the <em>test-containers</em> because they do not work under <em>podman</em>.
<pre><code class="bash">
export DOCKER_HOST=unix:///run/user/${UID}/podman/podman.sock
export TESTCONTAINERS_CHECKS_DISABLE=true
export TESTCONTAINERS_RYUK_DISABLED=true
</code></pre>
</li>
<li><p>Usually the previous two steps are enough but remember you can specify several things under <em>~/.config/containers</em> directory. For example the registries you want search images from by default.</p>
<pre><code class="bash">
cat ~/.config/containers/registries.conf
unqualified-search-registries=["docker.io", "quay.io"]
</code></pre>
</li>
</ol>
<p>That is all. A very short post that I wanted to have in the blog. I am going to need this from time to time. And my memory is very bad for these random things. This way I can always look to this entry and just copy the commands without thinking what they do or why I need them. Sadly the entry will be obsolete soon, but until that moment it will save me a lot of time.</p>
<p>Best regards!</p>
Ricky's Hodgepodgenospam@example.com (rickyepoderi)2022-01-15T11:11:00Zhttps://blogs.nologin.es/rickyepoderi/wfwcomment.php?cid=1950https://blogs.nologin.es/rickyepoderi/rss.php?version=1.0&type=comments&cid=195Wildfly bootable jar inside the OpenShift sandbox
https://blogs.nologin.es/rickyepoderi/index.php?/archives/194-Wildfly-bootable-jar-inside-the-OpenShift-sandbox.html
<p>Today's entry is going to continue <a href="https://blogs.nologin.es/rickyepoderi/index.php?/archives/187-Testing-bootable-JAR-in-wildfly.html">the bootable jar series</a> that was started some time ago. Red Hat currently offers the <a href="https://developers.redhat.com/developer-sandbox">Developer Sandbox for OpenShift</a> as a preconfigured environment of its cloud product which you can use for training or learning purposes. The sandbox needs a free Red Hat login and also requests your phone number to avoid resources overexploiting. Throughout the entry the same application that was initially used for the bootable jar solution will be adapted for the sandbox or, more generically, for <em>OpenShift</em>. My starting point was <a href="https://www.wildfly.org/news/2021/02/01/Bootable-jar-jkube-clustering-openshift/">this good article about the <em>maven</em> <em>OpenShift</em> plugin</a>, it explains how to use <em>maven</em> to deploy a <em>wildfly</em> application to <em>OpenShift</em>. As usual the full process is going to be detailed step by step.</p>
<h3>Preparation for the sandbox</h3>
<p>Once the sandbox is ready, log into the <em>OpenShift</em> console. The <em>oc</em> command tool needs to be downloaded and added to the system path. Click the question mark icon next to your login name and then the option <em>Command line tools</em>.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/command-line-tools.png" alt="Command line tools"/>
</div>
<p>Download the command for your architecture, in my case the linux x86_64 option. Uncompress the file and put the <em>oc</em> binary in the path.</p>
<pre><code class="bash">
tar xvf oc.tar
mv oc ~/bin/
oc help
</code></pre>
<p>Now, again inside the console, click the option <em>Copy login command</em> and in the new page click on the <em>DevSandbox</em> button and then the <em>Display Token Link</em>. An <em>oc login</em> command is displayed that can be used to start working via terminal. That is more my style and now the command tool can also be used by the <em>maven</em> plugin.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/copy-login-command.png" alt="Copy login command"/>
</div>
<pre><code class="bash">
oc login --token=xxx --server=https://api.sandbox-m2.xxxx.p1.openshiftapps.com:6443
oc whoami
rickyepoderi
oc project
Using project "rickyepoderi-dev" on server "https://api.sandbox-m2.xxxx.p1.openshiftapps.com:6443".
</code></pre>
<h3>Keycloak/RH-SSO installation</h3>
<p>The sample application was a <em>jax-rs</em> web services endpoint that used the <em>keycloak</em> plugin for security and <em>swagger</em> to document the API. So a <em>keycloak</em> server is needed in the deployment. As the sandbox is already provisioned with the Red Hat products the Red Hat Single Sign-On (<em>RH-SSO</em>, productivized version of the upstream <em>keycloak</em> project) can be directly installed.</p>
<p>There is a template called <em>sso74-ocp4-x509-https</em> which performs re-encryption to the https port and therefore no special certificates are needed for the configuration.</p>
<pre><code class="bash">
oc get templates -n openshift -o name | grep sso74-ocp4-x509-https
template.template.openshift.io/sso74-ocp4-x509-https
</code></pre>
<p>The server can be installed just passing the realm name and the admin username and password.</p>
<pre><code class="bash">
oc new-app --template=sso74-ocp4-x509-https -p SSO_REALM="ocp" -p SSO_ADMIN_USERNAME="admin" -p SSO_ADMIN_PASSWORD="xxxxx"
</code></pre>
<p>Wait the app to start and ask for the route used for the application. You can access the <em>keycloak</em> console in that https URL.</p>
<pre><code class="bash">
oc get route
NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD
sso sso-rickyepoderi-dev.apps.sandbox-m2.xxxx.p1.openshiftapps.com sso <all> reencrypt None
</code></pre>
<h3>Preparing keycloak</h3>
<p>The application will need several elements inside <em>keycloak</em>.</p>
<ol>
<li><p>Once you are logged in the <em>keycloak</em> console, select the <em>ocp</em> realm and go to the roles tab.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-role-1.png" alt="Create role"/>
</div>
<p>Click <em>Add</em> to create the <em>Users</em> role.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-role-2.png" alt="Create role Users"/>
</div>
<p>That role is required to call the hello application endpoint because an authorization filter was developed to check for it.</p>
</li>
<li><p>Now time to create the sample user. Go to the users tab.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-user-1.png" alt="Create user"/>
</div>
<p>Fill the data for your user, in my case user <em>ricky</em> is created.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-user-2.png" alt="Create user ricky"/>
</div>
<p>Set a password.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/set-user-password.png" alt="Set password"/>
</div>
<p>And assign the <em>Users</em> role to the created user.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/assign-role-to-user.png" alt="Assign role to user"/>
</div>
<li><p>Finally go to the clients tab and create one for the application.</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-client-1.png" alt="Create client"/>
</div>
<p>Just a public client is needed named <em>bootable-jar-sample</em> and with the correct URL in the sandbox (you can change it later if the URL is not correct).</p>
<div class="picture">
<img src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/create-client-2.png" alt="Create client bootable-jar-sample"/>
</div>
</li></ol>
<h3>Application changes</h3>
<p>The application is already implemented, but it needs to be modified to be deployed in the cloud.</p>
<ol>
<li><p>First the <em>keycloak</em> configuration files should be modified to point to the new realm and URL in the sandbox. If you remember there are two <em>keycloak.json</em> files (one for the JavaScript part and another one for the Java/REST application, I used that trick for the app before).</p>
<ul>
<li>src/main/webapp/WEB-INF/keycloak.json</li>
<li>src/main/webapp/keycloak.json</li>
</ul>
</li>
<li><p>In the <em>index.html</em> the <em>keycloak</em> adapter is updated to download the JS source file from the sandbox URL.</p>
</li>
<li><p>And finally the interesting part, the <em>pom.xml</em>. All the versions were updated to the last one available, among them <em>wildfly</em> to 25.0.1 and the <em>keycloak</em> plugin to 15.0.2. In order to deploy on <em>OpenShift</em>, adding the <em><cloud/></em> tag to the <em>wildfly-jar-maven-plugin</em> is a must. That tag prepares the deployment to be cloud aware (adds microprofile health layer for checks, configure KUBE_PING if using clustering, assigns the pod name to the <em>jboss.node.name</em>,...).</p>
<pre><code class="xml">
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-jar-maven-plugin</artifactId>
<version>6.1.1.Final</version>
<configuration>
<feature-packs>
<feature-pack>
<location>wildfly@maven(org.jboss.universe:community-universe)#25.0.1.Final</location>
</feature-pack>
<feature-pack>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-galleon-pack</artifactId>
<version>15.0.2</version>
</feature-pack>
</feature-packs>
<layers>
<layer>base-server</layer>
<layer>logging</layer>
<layer>jaxrs</layer>
<layer>keycloak-client-oidc</layer>
</layers>
<cloud/> <!-- Remember this!!! -->
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</code></pre>
<p>Now the <a href="https://www.eclipse.org/jkube/docs/openshift-maven-plugin">openshift-maven-plugin</a> is needed to create the build image, all the required <em>kubernetes</em> resources and deploy everything to the sandbox. This plugin is the other important piece that needs to be added to your application. The following configuration will use a <em>NodePort</em> service, and the route is configured to default <em>edge</em> (<em>OpenShift</em> will expose https externally but the pods will internally use plain 8080 port) and <em>Redirect</em> (external <em>http</em> will be redirected to <em>https</em>).</p>
<pre><code class="xml">
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>openshift-maven-plugin</artifactId>
<version>1.5.1</version>
<executions>
<execution>
<goals>
<goal>resource</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<enricher>
<config>
<jkube-service>
<type>NodePort</type>
</jkube-service>
<jkube-openshift-route>
<generateRoute>true</generateRoute>
<tlsInsecureEdgeTerminationPolicy>Redirect</tlsInsecureEdgeTerminationPolicy>
<tlsTermination>edge</tlsTermination>
</jkube-openshift-route>
</config>
</enricher>
</configuration>
</plugin>
</code></pre>
<p>The only missing part is what image we start with, and that information is added using a global configuration property.</p>
<pre><code class="xml">
<properties>
<jkube.generator.from>registry.redhat.io/ubi8/openjdk-11:latest</jkube.generator.from>
</properties>
</code></pre>
<p>In the end the real work is performed by this plugin. Once the bootable jar is ready the <em>openshift-maven-plugin</em> adds the bootable jar to a <em>openjdk-11</em> base and creates the final image for the application. Besides it creates the service, the deployment-config and the route resources for kubernetes. All the elements that are needed to incorporate that image to the cloud.</p>
<p>At this point we are one <em>maven</em> command away of running the application inside the sandbox. Just execute the following.</p>
<pre><code class="bash">
mvn oc:deploy
</code></pre>
</li></ol>
<h3>Demo</h3>
<p>It is just one command, but it does a lot of things: first it compiles the sources; bundles the app into a war; creates the bootable jar file; then the new <em>OpenShift</em> plugin constructs the image with the application and all the resources; finally everything is uploaded and deployed into the sandbox. The following video shows exactly that. <em>OpenShift</em> is initially only running the <em>keycloak</em> server inside it. The <em>maven</em> command is executed and all the steps are performed. After waiting the deploy to finish and the pod is fully started, the route is accessed. The browser is redirected to log in the <em>keycloak</em> realm. After that the hello endpoint is executed successfully.</p>
<p><video src="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/out.webm" autobuffer controls>
<img src="https://blogs.nologin.es/rickyepoderi/uploads/categories/error.png" alt="Error!" />
Your browser doesn't support the video tag. See this <a href="https://blogs.nologin.es/rickyepoderi/index.php?/archives/41-Videos-Are-About-to-Change-Second-Time-Lucky.html">entry</a> for more information about how to see the videos in this blog. You can <a href="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/out.webm">download the file</a> instead.
</video></p>
<h3>Summary</h3>
<p>Today's entry explains how to adapt the bootable jar idea and use it in an <em>OpenShift</em> environment. The two main points are adding the <em>cloud</em> tag to the <em>wildfly-jar-maven-plugin</em> (it prepares the bootable jar for <em>OpenShift</em>) and incorporating the <em>openshift-maven-plugin</em> (it performs all the interaction with the sandbox, creating the image and resources and deploying them). The first part is simple, the second one is not so easy. The <em>OpenShift</em> plugin has lots of options that can be tweaked. The post used the most common ones, the application is deployed and exposed using https in the new route. The complete <em>maven</em> project for the demo app can be downloaded from <a href="https://blogs.nologin.es/rickyepoderi/uploads/Wildfly-bootable-jar-inside-the-OpenShift-sandbox/bootable-jar.zip">here</a>. It can be used and/or extended to explore more complex scenarios.</p>
<p>Regards from the cloud!</p>
Ricky's Hodgepodgenospam@example.com (rickyepoderi)
Java, 2021-12-11T14:53:00Zhttps://blogs.nologin.es/rickyepoderi/wfwcomment.php?cid=1940https://blogs.nologin.es/rickyepoderi/rss.php?version=1.0&type=comments&cid=194