Deploying custom Keycloak theme with Operator (v15.1.1 & v16.0.0) - keycloak

I have a theme with a size >1MB (which precludes the configmap-solution provided as an answer to this question).
This theme has been been packaged according to the Server Development Guide - its folder structure is
META-INF/keycloak-themes.json
themes/[themeName]/login/login.ftl
themes/[themeName]/login/login-reset-password.ftl
themes/[themeName]/login/template.ftl
themes/[themeName]/login/template.html
themes/[themeName]/login/theme.properties
themes/[themeName]/login/messages/messages_de.properties
themes/[themeName]/login/messages/messages_en.properties
themes/[themeName]/login/resources/[...]
The contents of keycloak-themes.json are
{
"themes": [{
"name" : "[themeName]",
"types": [ "login" ]
}]
}
where [themeName] is my theme name.
Keycloak is running with 3 instances, its resource spec includes:
extensions:
- [URL-to-jar]
Deployment was successful according to the logs of each pod - each log contains a message containing
Deployed "[jar-name].jar" (runtime-name : "[jar-name].jar")
However, in the admin console, I cannot select the theme from the extension for the login-theme. Creating a new realm via crd with a preconfigured login-theme via spec-entry
loginTheme: [themeName]
also does not work - in the admin-console, the selected entry for the login-theme is empty.
I may be missing something basic, but it seems like this ought to work according to this answer if I am not mistaken.

As is so often the case, an uncaught typo was the source of the error.
The directory-structure must not be
META-INF/keycloak-themes.json
themes/[theme-name]/[theme-role]/theme.properties
[...]
But instead
META-INF/keycloak-themes.json
theme/[theme-name]/[theme-role]/theme.properties
[...]
Given a correct structure, keycloak-operator can successfully deploy and load custom-themes as jar-extensions.

Related

JPAM Configuration for Apache Drill

I'm trying to configure PLAIN authentification based on JPAM 1.1 and am going crazy since it doesnt work after x times checking my syntax and settings. When I start drill with cluster-id and zk-connect only, it works, but with both options of PLAIN authentification it fails. Since I started with pam4j and tried JPAM later on, I kept JPAM for this post. In general I don't have any preferences. I just want to get it done. I'm running Drill on CentOS in embedded mode.
I've done anything required due to the official documentation:
I downloaded JPAM 1.1, uncompressed it and put libjpam.so into a specific folder (/opt/pamfile/)
I've edited drill-env.sh with:
export DRILLBIT_JAVA_OPTS="-Djava.library.path=/opt/pamfile/"
I edited drill-override.conf with:
drill.exec: {
cluster-id: "drillbits1",
zk.connect: "local",
impersonation: {
enabled: true,
max_chained_user_hops: 3
},
security: {
auth.mechanisms: ["PLAIN"],
},
security.user.auth: {
enabled: true,
packages += "org.apache.drill.exec.rpc.user.security",
impl: "pam",
pam_profiles: [ "sudo", "login" ]
}
}
It throws the subsequent error:
Error: Failure in starting embedded Drillbit: org.apache.drill.exec.exception.DrillbitStartupException: Problem in finding the native library of JPAM (Pluggable Authenticator Module API). Make sure to set Drillbit JVM option 'java.library.path' to point to the directory where the native JPAM exists.:no jpam in java.library.path (state=,code=0)
I've run that *.sh file by hand to make sure that the necessary path is exported since I don't know if Drill is expecting that. The path to libjpam should be know known. I've started Sqlline with sudo et cetera. No chance. Documentation doesn't help. I don't get it why it's so bad and imo incomplete. Sadly there is 0 explanation how to troubleshoot or configure basic user authentification in detail.
Or do I have to do something which is not told but expected? Are there any Prerequsites concerning PLAIN authentification which aren't mentioned by Apache Drill itself?
Try change:
export DRILLBIT_JAVA_OPTS="-Djava.library.path=/opt/pamfile/"
to:
export DRILL_JAVA_OPTS="$DRILL_JAVA_OPTS -Djava.library.path=/opt/pamfile/"
It works for me.

IBM Content Navigator ICN Plugin returns an error when configured but works fine

I am using ICN 3.0.3 IF7. I have a custom plugin that writes the following error to the console when I initially configure it into ICN.
The plugin itself works fine once configured.
Uncaught TypeError: cls is not a constructor
at Object.eval (ecm/widget/layout/AdminPane.js:9845)
at dojo.js.jgz:22442
at runFactory (dojo.js.jgz:611)
at execModule (dojo.js.jgz:691)
at dojo.js.jgz:397
at guardCheckComplete (dojo.js.jgz:699)
at contextRequire (dojo.js.jgz:396)
at req (dojo.js.jgz:32)
at Object._displayPluginConfig (ecm/widget/layout/AdminPane.js:9844)
at Object._pluginRequestCompleted (ecm/widget/layout/AdminPane.js:9759)
In addition, once it is configured, I cannot get the details on it like I can for the included AFP Viewer plugin:
Name: AFP Viewer
Version: 2.0.3.5
Repository types: None
Actions: None
Open Actions: None
Viewers: AFP Viewer
Features: None
Layouts: None
It seems like something is wrong with the plugin structure that doesn't affect its ability to run. I am worried because I just don't like seeing errors. Has anyone seen this before?
Looking at the error it seems like the module you specified in the plugin.java#getConfigurationDijitClass is either failing to instantiate, or isn't specified at all.
If you have a configuration dijit class configured, then ensure it's actually a widget and that it's constructor and postCreate method (if provided) don't throw an error :).
If you don't have one configured, set it to null to prevent instantiation

How to implement a serviceworker in SFCC (Demandware)

I was wondering if anyone here has experience with implementing a service worker in SFCC/Demandware.
I generate a service worker with Webpack with sw-precache-webpack-plugin
The problem is: a service worker should be available from the root of the domain. so site.com/sw.js.
JS files will come normally in the static/ folder.
Anyone an idea how to serve this JS file from the root of the project in Demandware/SFCC?
Unfortunately, registering a service worker under an scope that is in an upper path than the service worker file itself does not work (as stated in MDN):
The service worker will only catch requests from clients under the service worker's scope.
The max scope for a service worker is the location of the worker.
(Source: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers)
Solution
Here is a suggestion for a working approach for serving "/sw.js" in Demandware (Sales Force):
Create a new controller (or pipeline), e.g. "ServiceWorker-GetFile"; the response should be a file content, which can be read from whatever source you wish:
Content asset (dw.content.ContentMgr.getContent());
Library file (dw.content.ContentMgr.getContent() or directly reading a file with dw.io.File / dw.io.FileReader);
even Site preference (although I wouldn't recommend it);
Create an entry in Business Manager / Merchant Tools / SEO / Aliases to route "/sw.js" to "ServiceWorker-GetFile", i.e. use something along:
{
...
"your-host" : [
...,
{
"if-site-path": "/sw.js",
"pipeline": "ServiceWorker-GetFile"
}
]
}
This may seem like an unnecessary overhead, but it was the only way I could findfor serving files with root path in the URI.
Serving other root files as well
By expanding the controller (renaming it to, say, "Content-GetFile" and adding GET/POST parameters like "name" and/or "source") this could be conveniently used for other files as well ("/manifest.json", "/.well-known/assetlinks.json" etc.). In the next example of Business Manager / ... / Aliases, let Content-GetFile accept two parameters: "name" (which would be a file name in the content library or a content asset ID) and "source" (which would be "file" or "asset"):
...
{
"if-site-path": "/sw.js",
"pipeline": "Content-GetFile",
"params": {
"name": "/ServiceWorker/sw.js",
"source": "file"
}
},
{
"if-site-path": "/manifest.json",
"pipeline": "Content-GetFile",
"params": {
"name": "MANIFEST_JSON",
"source": "asset"
}
}
Note that your code should handle appropriately the base paths of the resources (e.g. "/ServiceWorker/sw.js" from the above example does not speak much; you should know whether this is a path in a content library or a path relative to "cartridges//static/default/js/").
Dynamic content
Since the suggested approach uses a controller, you can dynamically process the content before serving it to the user (e.g. if you need to add/remove the "/v12435145145/" part from DMW links). Sky is your limits. :)
I'm currently messing around with the service workers on DW as well.
In my case I have directly added the script inside a footer.isml file like this:
<script>
//init service worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register("${URLUtils.staticURL('/lib/sw/sw.js')}")
.then(registration => {
console.log(
`Service Worker registered! Scope: ${registration.scope}`
);
})
.catch(err => {
console.log(`Service Worker registration failed: ${err}`);
});
});
}
</script>
This works for me, well at least I can see the Service Worker registered message.
I also had some issues due to the SSL certificate since my development environment doesn't have a proper SSL but it's using HTTPs routes, so chrome was complaining about it, I needed to run chrome via terminal using this command:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=[YOUR DOMAIN]
Unfortunately I'm not able to make work any line of code inside that service worker file, even I tried on Safari, since it has a Service Workers option in the develop menu, but it's not showing any service worker running.
I Hope it will helps you.

i am trying to configure Lexik JWT Bundle but i am getting error which is given below

There is no extension able to load the configuration for "jwt_private_key_path" (in /var/www/html/EduboldPortalApp/eduboldportal/app/config/parameters.yml). Looked for namespace "jwt_private_key_path", found "framework", "security", "twig", "monolog", "swiftmailer", "doctrine", "sensio_framework_extra", "doctrine_mongodb", "lexik_jwt_authentication", "fos_rest", "debug", "web_profiler", "sensio_distribution" in /var/www/html/EduboldPortalApp/eduboldportal/app/config/parameters.yml (which is being imported from "/var/www/html/EduboldPortalApp/eduboldportal/app/config/config.yml").
There is no extension able to load the configuration for "jwt_private_key_path" (in /var/www/html/EduboldPortalApp/eduboldportal/app/config/parameters.yml). Looked for namespace "jwt_private_key_path", found "framework", "security", "twig", "monolog", "swiftmailer", "doctrine", "sensio_framework_extra", "doctrine_mongodb", "lexik_jwt_authentication", "fos_rest", "debug", "web_profiler", "sensio_distribution"
Are you sure the bundle has been added to the app/AppKernel.php ?
From the error it seems like symfony is not loading the bundle.

Extended application descriptor file and invalid datasource

I have two applications:
hrportalcore: The core application with BaseController, ...
hrportalrequestleave: A sample application extended from the hrportalcore application
The hrportalcore has the namespace de.example.core and there are the dataSources also maintained. (sap.app.dataSources in manifest.json). The datasource is:
[...]
"HRPOJavaLeave": {
"uri": "<path>",
"type": "OData",
"settings": {
"annotations": [],
"odataVersion": "2.0",
"localUri": ""
}
}
[...]
The datasources can be used without any problems in the extended application but the console brings the following errors:
It says the datasource contains errors, but it can be used (strange?).
Another thing is, that the Component-preload.js file is loaded from a wrong place once a time. The application works without problems, but it is - as said - loaded once from a wrong location?
My manifest.json of the hrportalrequestleave looks like in the extension part (sap.ui5.extends):
[...]
"extends": {
"component": "de.example.core",
"extensions": {}
},
[...]
The parent is defined rightly in the neo-app.json as /parent to show to hrportalcore.
jQuery.sap.declare("de.example.request.leave.Component");
// use the load function for getting the optimized preload file if present
if (!jQuery.sap.isDeclared("de.example.core.Component")) {
sap.ui.component.load({
name: "de.example.core",
// Use the below URL to run the extended application when SAP-delivered application is deployed on cloud
url: jQuery.sap.getModulePath("de.example.request.leave") + "/parent"
// we use a URL relative to our own component
// extension application is deployed with customer namespace
});
}
this.de.example.core.Component.extend("de.example.request.leave.Component", {
metadata: {
manifest: "json"
}
});
This all happens in the Fiori Launchpad of HANA Cloud Platform
Solution
manifest.json of hrportalcore: Always use the up-to-date version which you have deployed on your HCP in the applicationVersion property:
{
"_version": "1.2.0",
"sap.app": {
"_version": "1.2.0",
"applicationVersion": {
"version": "1.6.2"
},
...
manifest.json of hrportalrequestleave (Extension project): As above, always use the up-to-date version which you have deployed on your HCP in the applicationVersion property.
DataSource not found?!
If you have a extension project (like hrportalrequestleave < hrportalcore), then the manifest.json of both applications are merged like jQuery.extend(...). All properties, expect the sap.app tree, because it describes really the application and can not be copied from parent extension.
Now, when you use a dataSource from the parent extension, it will not be found. That means for you, you must define the sap.app.dataSources in the extension project manifest.json.
The error in the log
"Error in application dependency de.example.core.Component: No descriptor was found"
suggests that the manifest.json contains a dependency to "de.example.core.Component" instead of "de.example.core". According to your code snippets, the "extends" dependency is correct. Do you have other dependencies?
The AppIndex in the backend calculates the transitive closure of dependencies and if it can't find an installation with that ID, the above error is created and logged on the client side.
If your manifest.json looks okay but might have contained a wrong dependency in the past, then it might be necessary to re-run the AppIndex (or schedule it for a regular run).
The fact that the app works despite the config error is caused by the code that you've shown above. It explicitly loads the de.example.core component from an explicitly calculated URL. But before that step, the framework already tries to load it, based on the information in the manifest.json and there the information about the explicit URL is missing.
BTW: the code that calculates the URL suggests that even after fixing the manifest.json, the AppIndex might not find the component as it seems to be stored in a sub package of the de.example.request.leave app. Not sure if the AppIndex can handle this (it can handle nested components if they are listed as embedded components in the top level manifest.json, but I'm not sure if it recognizes such embedded components in the dependencies section. As a result it might try to load the embedded component although it has been loaded together with the enclosing component already.