diff --git a/tomcat-password-encryption/pom.xml b/tomcat-password-encryption/pom.xml
new file mode 100644
index 00000000000..26f53154277
--- /dev/null
+++ b/tomcat-password-encryption/pom.xml
@@ -0,0 +1,71 @@
+
+ 4.0.0
+ it.eng.knowage
+ tomcat-password-encryption
+ 9.0.0-SNAPSHOT
+ Archetype - tomcat-password-encryption
+ http://maven.apache.org
+
+
+ UTF-8
+ UTF-8
+ 17
+
+
+
+
+ org.apache.tomcat
+ tomcat-jdbc
+ 9.0.83
+ compile
+
+
+ org.jasypt
+ jasypt
+ 1.9.3
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ ${maven.compiler.release}
+ ${project.build.sourceEncoding}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.0
+
+
+ package
+
+ shade
+
+
+ true
+
+
+ org.jasypt:jasypt
+
+
+
+
+
+ org.jasypt
+ shade.org.jasypt
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/KnowageTomcatEncryptedPasswordDatasource.java b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/KnowageTomcatEncryptedPasswordDatasource.java
new file mode 100644
index 00000000000..406834b5b7a
--- /dev/null
+++ b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/KnowageTomcatEncryptedPasswordDatasource.java
@@ -0,0 +1,56 @@
+package it.eng.knowage.tomcatpasswordencryption;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+
+import it.eng.knowage.tomcatpasswordencryption.helper.EncryptedPasswordUtils;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+public class KnowageTomcatEncryptedPasswordDatasource extends org.apache.tomcat.jdbc.pool.DataSourceFactory {
+
+ private static final Log log = LogFactory.getLog(KnowageTomcatEncryptedPasswordDatasource.class);
+
+ @Override
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable, ?> environment) throws Exception {
+ try {
+ if (obj instanceof Reference ref) {
+ StringRefAddr passwordRefAddr = (StringRefAddr) ref.get(PROP_PASSWORD);
+ if (passwordRefAddr != null) {
+ String encryptedPwd = (String) passwordRefAddr.getContent();
+ String cleartextPwd = decrypt(encryptedPwd);
+ int index = find(ref);
+ if (index >= 0) {
+ ref.remove(index);
+ ref.add(index, new StringRefAddr(PROP_PASSWORD, cleartextPwd));
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("Failed to decrypt password. Please check DataSource definition.");
+ throw e;
+ }
+ return super.getObjectInstance(obj, name, nameCtx, environment);
+ }
+
+ private int find(Reference ref) {
+ Enumeration enu = ref.getAll();
+ for (int i = 0; enu.hasMoreElements(); i++) {
+ RefAddr addr = enu.nextElement();
+ if (addr.getType().equals(PROP_PASSWORD))
+ return i;
+ }
+ return -1;
+ }
+
+ public static String decrypt(String encryptSource) {
+ return EncryptedPasswordUtils.decrypt(encryptSource);
+ }
+
+}
diff --git a/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptOnce.java b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptOnce.java
new file mode 100644
index 00000000000..a8bdfcfdb57
--- /dev/null
+++ b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptOnce.java
@@ -0,0 +1,31 @@
+package it.eng.knowage.tomcatpasswordencryption.helper;
+import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
+import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
+
+public class EncryptOnce {
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ System.err.println("Usage: java -Dknowage.enc.password= [-Dknowage.enc.algorithm=PBEWithMD5AndDES] "
+ + "[-Dknowage.enc.keyObtentionIterations=1000] EncryptOnce ");
+ System.exit(1);
+ }
+ String clear = args[0];
+ String key = EncryptedPasswordUtils.resolveKey();
+ if (key == null || key.isEmpty()) {
+ System.err.println("Missing -Dknowage.enc.password.file");
+ System.exit(2);
+ }
+
+ SimpleStringPBEConfig cfg = new SimpleStringPBEConfig();
+ cfg.setPassword(key);
+ cfg.setPoolSize("1");
+ cfg.setStringOutputType("base64");
+
+ StandardPBEStringEncryptor enc = new StandardPBEStringEncryptor();
+ enc.setConfig(cfg);
+
+ String cipher = enc.encrypt(clear);
+ System.out.println("#encr#" + cipher);
+ }
+}
\ No newline at end of file
diff --git a/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptedPasswordUtils.java b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptedPasswordUtils.java
new file mode 100644
index 00000000000..57afd3f8999
--- /dev/null
+++ b/tomcat-password-encryption/src/main/java/it/eng/knowage/tomcatpasswordencryption/helper/EncryptedPasswordUtils.java
@@ -0,0 +1,74 @@
+package it.eng.knowage.tomcatpasswordencryption.helper;
+
+import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
+import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public final class EncryptedPasswordUtils {
+ private static final String ENCRYPTED_PREFIX = "#encr#";
+
+ private EncryptedPasswordUtils() {}
+
+ public static String decrypt(String value) {
+ if (value == null || value.isEmpty()) return value;
+ if (!value.startsWith(ENCRYPTED_PREFIX)) {
+ return value;
+ }
+ String cipherText = value.substring(ENCRYPTED_PREFIX.length());
+ String password = resolveKey();
+ if (password == null || password.isEmpty()) {
+ throw new IllegalStateException("""
+ Missing decryption key. Provide it via system property knowage.enc.password, " +
+ "environment variable KNOWAGE_ENC_PASSWORD, or a file at ${catalina.base}/conf/knowageTomcatEncryptedPasswordDatasource " +
+ "or -Dknowage.enc.password.file=/secure/path
+ """);
+ }
+
+ SimpleStringPBEConfig cfg = new SimpleStringPBEConfig();
+ cfg.setPassword(password);
+ cfg.setPoolSize("1");
+ cfg.setStringOutputType("base64");
+
+ StandardPBEStringEncryptor enc = new StandardPBEStringEncryptor();
+ enc.setConfig(cfg);
+ return enc.decrypt(cipherText);
+ }
+
+ public static String resolveKey() {
+ // Prefer explicit file path via system property
+ String fileProp = System.getProperty("knowage.enc.password.file");
+ if (fileProp != null && !fileProp.isEmpty()) {
+ String fromFile = readFirstLineTrimmed(Path.of(fileProp));
+ if (fromFile != null && !fromFile.isEmpty()) return fromFile;
+ }
+
+ // Default file under Tomcat conf: ${catalina.base}/conf/passwordEncryptionSecret
+ String catalinaBase = System.getProperty("catalina.base");
+ if (catalinaBase != null && !catalinaBase.isEmpty()) {
+ Path defaultPath = Path.of(catalinaBase, "conf", "knowageTomcatEncryptedPasswordDatasource");
+ String fromFile = readFirstLineTrimmed(defaultPath);
+ if (fromFile != null && !fromFile.isEmpty()) return fromFile;
+ }
+
+ return null;
+ }
+
+ private static String readFirstLineTrimmed(Path path) {
+ try {
+ if (Files.isRegularFile(path)) {
+ for (String line : Files.readAllLines(path, StandardCharsets.UTF_8)) {
+ String trimmed = line.trim();
+ if (!trimmed.isEmpty()) return trimmed;
+ }
+ }
+ } catch (IOException ignored) {
+ }
+ return null;
+ }
+
+
+}
\ No newline at end of file