This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 2894a9e7b21275bf9ba48a58d8d694b42b341eaa
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Sep 8 14:39:48 2026 +0200

    [SYNCOPE-1996] Security production mode
---
 .../core/logic/UserSelfLogicPasswordResetTest.java |  1 +
 .../persistence/jpa/PersistenceTestContext.java    |  4 +-
 .../persistence/neo4j/PersistenceTestContext.java  |  4 +-
 .../src/test/resources/core-test.properties        |  1 +
 .../spring/security/DefaultCredentialChecker.java  | 63 ++++++++++++++++++----
 .../core/spring/security/DefaultEncryptor.java     | 49 +++++++++--------
 .../spring/security/DefaultEncryptorManager.java   | 14 ++++-
 .../core/spring/security/SecurityContext.java      | 59 +++++++++++++-------
 .../core/spring/security/SecurityProperties.java   | 10 ++++
 .../core/spring/SpringTestConfiguration.java       |  3 +-
 .../core/spring/security/DefaultEncryptorTest.java | 11 +++-
 core/starter/src/main/resources/core.properties    |  1 +
 .../src/main/resources/core-embedded.properties    |  1 +
 .../org/apache/syncope/fit/AbstractITCase.java     |  5 +-
 14 files changed, 167 insertions(+), 59 deletions(-)

diff --git 
a/core/idrepo/logic/src/test/java/org/apache/syncope/core/logic/UserSelfLogicPasswordResetTest.java
 
b/core/idrepo/logic/src/test/java/org/apache/syncope/core/logic/UserSelfLogicPasswordResetTest.java
index 78fadb0577..94d9d979de 100644
--- 
a/core/idrepo/logic/src/test/java/org/apache/syncope/core/logic/UserSelfLogicPasswordResetTest.java
+++ 
b/core/idrepo/logic/src/test/java/org/apache/syncope/core/logic/UserSelfLogicPasswordResetTest.java
@@ -66,6 +66,7 @@ public class UserSelfLogicPasswordResetTest {
         ConfParamOps confParamOps = mock(ConfParamOps.class);
         userDAO = mock(UserDAO.class);
         securityProperties = new SecurityProperties();
+        securityProperties.setProductionMode(false);
 
         when(confParamOps.get(any(), 
eq(StandardConfParams.PASSWORD_RESET_ALLOWED), eq(false), eq(boolean.class))).
                 thenReturn(true);
diff --git 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
 
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
index a8995b97ab..9f9aec48be 100644
--- 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
+++ 
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/PersistenceTestContext.java
@@ -34,6 +34,7 @@ import 
org.apache.syncope.core.persistence.jpa.spring.CommonEntityManagerFactory
 import 
org.apache.syncope.core.persistence.jpa.spring.DomainRoutingEntityManagerFactory;
 import org.apache.syncope.core.provisioning.api.ConnectorManager;
 import org.apache.syncope.core.provisioning.api.ImplementationLookup;
+import org.apache.syncope.core.spring.security.DefaultCredentialChecker;
 import org.apache.syncope.core.spring.security.DefaultEncryptorManager;
 import org.apache.syncope.core.spring.security.DefaultPasswordGenerator;
 import org.apache.syncope.core.spring.security.PasswordGenerator;
@@ -120,7 +121,8 @@ public class PersistenceTestContext {
     public EncryptorManager encryptorManager() {
         SecurityProperties securityProperties = new SecurityProperties();
         securityProperties.setAesSecretKey(StringUtils.EMPTY);
-        return new DefaultEncryptorManager(securityProperties);
+        securityProperties.setProductionMode(false);
+        return new DefaultEncryptorManager(new DefaultCredentialChecker("", 
"", "", "", false), securityProperties);
     }
 
     @Bean
diff --git 
a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/PersistenceTestContext.java
 
b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/PersistenceTestContext.java
index 29cb7fe845..dd26b09595 100644
--- 
a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/PersistenceTestContext.java
+++ 
b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/PersistenceTestContext.java
@@ -32,6 +32,7 @@ import 
org.apache.syncope.core.persistence.api.content.ContentLoader;
 import org.apache.syncope.core.persistence.neo4j.spring.DomainRoutingDriver;
 import org.apache.syncope.core.provisioning.api.ConnectorManager;
 import org.apache.syncope.core.provisioning.api.ImplementationLookup;
+import org.apache.syncope.core.spring.security.DefaultCredentialChecker;
 import org.apache.syncope.core.spring.security.DefaultEncryptorManager;
 import org.apache.syncope.core.spring.security.DefaultPasswordGenerator;
 import org.apache.syncope.core.spring.security.PasswordGenerator;
@@ -110,7 +111,8 @@ public class PersistenceTestContext {
     public EncryptorManager encryptorManager() {
         SecurityProperties securityProperties = new SecurityProperties();
         securityProperties.setAesSecretKey(StringUtils.EMPTY);
-        return new DefaultEncryptorManager(securityProperties);
+        securityProperties.setProductionMode(false);
+        return new DefaultEncryptorManager(new DefaultCredentialChecker("", 
"", "", "", false), securityProperties);
     }
 
     @Bean
diff --git a/core/provisioning-java/src/test/resources/core-test.properties 
b/core/provisioning-java/src/test/resources/core-test.properties
index 10da9c173c..c3e75041a9 100644
--- a/core/provisioning-java/src/test/resources/core-test.properties
+++ b/core/provisioning-java/src/test/resources/core-test.properties
@@ -15,6 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
+security.productionMode=false
 security.adminUser=${adminUser}
 security.anonymousUser=${anonymousUser}
 security.jwsKey=${jwsKey}
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
index eef5fcb677..84e4732a59 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultCredentialChecker.java
@@ -28,43 +28,88 @@ public class DefaultCredentialChecker {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(DefaultCredentialChecker.class);
 
+    private static final String DEFAULT_AES_KEY_ERROR_MESSAGE =
+            "The default AES key property is being used. "
+            + "This must be changed to avoid a security breach!";
+
+    private static final String DEFAULT_AES_KEY = "1abcdefghilmnopqrstuvz2!";
+
+    private static final String DEFAULT_JWS_KEY_ERROR_MESSAGE =
+            "The default JWKS key property is being used. "
+            + "This must be changed to avoid a security breach!";
+
     private static final String DEFAULT_JWS_KEY = 
"ZW7pRixehFuNUtnY5Se47IemgMryTzazPPJ9CGX5LTCmsOJpOgHAQEuPQeV9A28f";
 
+    private static final String DEFAULT_ADMIN_PASSWORD_ERROR_MESSAGE =
+            "The default adminPassword property is being used. "
+            + "This must be changed to avoid a security breach!";
+
     private static final String DEFAULT_ADMIN_PASSWORD =
-        
"DE088591C00CC98B36F5ADAAF7DA2B004CF7F2FE7BBB45B766B6409876E2F3DB13C7905C6AA59464";
+            
"DE088591C00CC98B36F5ADAAF7DA2B004CF7F2FE7BBB45B766B6409876E2F3DB13C7905C6AA59464";
+
+    private static final String DEFAULT_ANON_KEY_ERROR_MESSAGE =
+            "The default anonymousKey property is being used. "
+            + "This must be changed to avoid a security breach!";
 
     private static final String DEFAULT_ANON_KEY = "anonymousKey";
 
-    private final boolean defaultAdminPasswordInUse;
+    private final boolean defaultAesKeyInUse;
 
     private final boolean defaultJwsKeyInUse;
 
+    private final boolean defaultAdminPasswordInUse;
+
     private final boolean defaultAnonymousKeyInUse;
 
-    public DefaultCredentialChecker(final String jwsKey, final String 
adminPassword, final String anonymousKey) {
+    private final boolean productionMode;
+
+    public DefaultCredentialChecker(
+            final String aesKey,
+            final String jwsKey,
+            final String adminPassword,
+            final String anonymousKey,
+            final boolean productionMode) {
+
+        defaultAesKeyInUse = DEFAULT_AES_KEY.equals(aesKey);
         defaultJwsKeyInUse = DEFAULT_JWS_KEY.equals(jwsKey);
         defaultAdminPasswordInUse = 
DEFAULT_ADMIN_PASSWORD.equals(adminPassword);
         defaultAnonymousKeyInUse = DEFAULT_ANON_KEY.equals(anonymousKey);
+        this.productionMode = productionMode;
+    }
+
+    public void checkIsDefaultAESKeyInUse() {
+        if (defaultAesKeyInUse) {
+            if (productionMode) {
+                throw new IllegalStateException(DEFAULT_AES_KEY_ERROR_MESSAGE);
+            }
+            LOG.warn(DEFAULT_AES_KEY_ERROR_MESSAGE);
+        }
     }
 
     public void checkIsDefaultJWSKeyInUse() {
         if (defaultJwsKeyInUse) {
-            LOG.warn("The default jwsKey property is being used. "
-                    + "This must be changed to avoid a security breach!");
+            if (productionMode) {
+                throw new IllegalStateException(DEFAULT_JWS_KEY_ERROR_MESSAGE);
+            }
+            LOG.warn(DEFAULT_JWS_KEY_ERROR_MESSAGE);
         }
     }
 
     public void checkIsDefaultAdminPasswordInUse() {
         if (defaultAdminPasswordInUse) {
-            LOG.warn("The default adminPassword property is being used. "
-                    + "This must be changed to avoid a security breach!");
+            if (productionMode) {
+                throw new 
IllegalStateException(DEFAULT_ADMIN_PASSWORD_ERROR_MESSAGE);
+            }
+            LOG.warn(DEFAULT_ADMIN_PASSWORD_ERROR_MESSAGE);
         }
     }
 
     public void checkIsDefaultAnonymousKeyInUse() {
         if (defaultAnonymousKeyInUse) {
-            LOG.warn("The default anonymousKey property is being used. "
-                    + "This must be changed to avoid a security breach!");
+            if (productionMode) {
+                throw new 
IllegalStateException(DEFAULT_ANON_KEY_ERROR_MESSAGE);
+            }
+            LOG.warn(DEFAULT_ANON_KEY_ERROR_MESSAGE);
         }
     }
 }
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptor.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptor.java
index 7b0824ba87..e415306134 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptor.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptor.java
@@ -51,6 +51,7 @@ public class DefaultEncryptor implements Encryptor {
 
     protected DefaultEncryptor(
             final String aesSecretKey,
+            final boolean productionMode,
             final SecurityProperties.DigesterProperties digesterProperties) {
 
         this.digesterProperties = digesterProperties;
@@ -60,30 +61,34 @@ public class DefaultEncryptor implements Encryptor {
         if (StringUtils.isNotBlank(aesSecretKey)) {
             String actualKey = aesSecretKey;
 
-            Integer pad = null;
-            boolean truncate = false;
-            if (actualKey.length() < 16) {
-                pad = 16 - actualKey.length();
-            } else if (actualKey.length() > 16 && actualKey.length() < 24) {
-                pad = 24 - actualKey.length();
-            } else if (actualKey.length() > 24 && actualKey.length() < 32) {
-                pad = 32 - actualKey.length();
-            } else if (actualKey.length() > 32) {
-                truncate = true;
-            }
+            if (!productionMode) {
+                Integer pad = null;
+                boolean truncate = false;
+                if (actualKey.length() < 16) {
+                    pad = 16 - actualKey.length();
+                } else if (actualKey.length() > 16 && actualKey.length() < 24) 
{
+                    pad = 24 - actualKey.length();
+                } else if (actualKey.length() > 24 && actualKey.length() < 32) 
{
+                    pad = 32 - actualKey.length();
+                } else if (actualKey.length() > 32) {
+                    truncate = true;
+                }
 
-            if (pad != null) {
-                StringBuilder actualKeyPadding = new StringBuilder(actualKey);
-                String randomChars = 
SecureRandomUtils.generateRandomPassword(pad);
+                if (pad != null) {
+                    StringBuilder actualKeyPadding = new 
StringBuilder(actualKey);
+                    String randomChars = 
SecureRandomUtils.generateRandomPassword(pad);
 
-                actualKeyPadding.append(randomChars);
-                actualKey = actualKeyPadding.toString();
-                LOG.warn("The configured AES secret key is too short (< {}), 
padding with random chars: {}",
-                        actualKey.length(), actualKey);
-            }
-            if (truncate) {
-                actualKey = actualKey.substring(0, 32);
-                LOG.warn("The configured AES secret key is too long (> 32), 
truncating: {}", actualKey);
+                    actualKeyPadding.append(randomChars);
+                    actualKey = actualKeyPadding.toString();
+                    LOG.warn("The configured AES secret key is too short (< 
{}), padding with random chars",
+                            actualKey.length());
+                    LOG.debug("Using\nsecurity.aesSecretKey={}", actualKey);
+                }
+                if (truncate) {
+                    actualKey = actualKey.substring(0, 32);
+                    LOG.warn("The configured AES secret key is too long (> 
32), truncating");
+                    LOG.debug("Using\nsecurity.aesSecretKey={}", actualKey);
+                }
             }
 
             try {
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptorManager.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptorManager.java
index f0d5776f78..1cee4bdeaf 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptorManager.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultEncryptorManager.java
@@ -26,11 +26,17 @@ import 
org.apache.syncope.core.persistence.api.EncryptorManager;
 
 public class DefaultEncryptorManager implements EncryptorManager {
 
+    protected final DefaultCredentialChecker credentialChecker;
+
     protected final SecurityProperties securityProperties;
 
     protected final Map<String, DefaultEncryptor> instances = new 
ConcurrentHashMap<>();
 
-    public DefaultEncryptorManager(final SecurityProperties 
securityProperties) {
+    public DefaultEncryptorManager(
+            final DefaultCredentialChecker credentialChecker,
+            final SecurityProperties securityProperties) {
+
+        this.credentialChecker = credentialChecker;
         this.securityProperties = securityProperties;
     }
 
@@ -41,7 +47,11 @@ public class DefaultEncryptorManager implements 
EncryptorManager {
 
     @Override
     public Encryptor getInstance(final String aesSecretKey) {
+        credentialChecker.checkIsDefaultAESKeyInUse();
+
         String actualKey = StringUtils.isBlank(aesSecretKey) ? 
securityProperties.getAesSecretKey() : aesSecretKey;
-        return instances.computeIfAbsent(actualKey, k -> new 
DefaultEncryptor(k, securityProperties.getDigester()));
+        return instances.computeIfAbsent(
+                actualKey,
+                k -> new DefaultEncryptor(k, 
securityProperties.isProductionMode(), securityProperties.getDigester()));
     }
 }
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityContext.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityContext.java
index cc0bd75b71..7c41140def 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityContext.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityContext.java
@@ -65,31 +65,45 @@ public class SecurityContext {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(SecurityContext.class);
 
+    private static String JWS_KEY = null;
+
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
     @Bean
     public static GrantedAuthorityDefaults grantedAuthorityDefaults() {
         return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
     }
 
-    protected static String jwsKey(final JWSAlgorithm jwsAlgorithm, final 
SecurityProperties props) {
-        String jwsKey = Optional.ofNullable(props.getJwsKey()).
-                orElseThrow(() -> new IllegalArgumentException("No JWS key 
provided"));
-
-        if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
-            int minLength = jwsAlgorithm.equals(JWSAlgorithm.HS256)
-                    ? 256 / 8
-                    : jwsAlgorithm.equals(JWSAlgorithm.HS384)
-                    ? 384 / 8
-                    : 512 / 8;
-            if (jwsKey.length() < minLength) {
-                jwsKey = SecureRandomUtils.generateRandomPassword(minLength);
-                props.setJwsKey(jwsKey);
-                LOG.warn("The configured key for {} must be at least {} bits, 
generating random: {}",
-                        jwsAlgorithm, minLength * 8, jwsKey);
+    private static String jwsKey(final JWSAlgorithm jwsAlgorithm, final 
SecurityProperties props) {
+        synchronized (LOG) {
+            if (JWS_KEY == null) {
+                String jwsKey = Optional.ofNullable(props.getJwsKey()).
+                        orElseThrow(() -> new IllegalArgumentException("No JWS 
key provided"));
+
+                if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
+                    int minLength = jwsAlgorithm.equals(JWSAlgorithm.HS256)
+                            ? 256 / 8
+                            : jwsAlgorithm.equals(JWSAlgorithm.HS384)
+                            ? 384 / 8
+                            : 512 / 8;
+                    if (jwsKey.length() < minLength) {
+                        if (props.isProductionMode()) {
+                            throw new IllegalArgumentException(
+                                    "The configured key for %s must be at 
least %d characters".
+                                            formatted(jwsAlgorithm, 
minLength));
+                        }
+
+                        jwsKey = 
SecureRandomUtils.generateRandomPassword(minLength);
+                        props.setJwsKey(jwsKey);
+                        LOG.warn("The configured key for {} must be at least 
{} characters, generating random",
+                                jwsAlgorithm, minLength);
+                        LOG.debug("Using\nsecurity.jwsKey={}", jwsKey);
+                    }
+                }
+
+                JWS_KEY = jwsKey;
             }
         }
-
-        return jwsKey;
+        return JWS_KEY;
     }
 
     @Bean
@@ -109,9 +123,11 @@ public class SecurityContext {
             final JWSAlgorithm jwsAlgorithm) {
 
         return new DefaultCredentialChecker(
+                props.getAesSecretKey(),
                 jwsKey(jwsAlgorithm, props),
                 props.getAdminPassword(),
-                props.getAnonymousKey());
+                props.getAnonymousKey(),
+                props.isProductionMode());
     }
 
     @ConditionalOnMissingBean
@@ -164,8 +180,11 @@ public class SecurityContext {
     }
 
     @Bean
-    public EncryptorManager encryptorManager(final SecurityProperties 
securityProperties) {
-        return new DefaultEncryptorManager(securityProperties);
+    public EncryptorManager encryptorManager(
+            final DefaultCredentialChecker credentialChecker,
+            final SecurityProperties securityProperties) {
+
+        return new DefaultEncryptorManager(credentialChecker, 
securityProperties);
     }
 
     @ConditionalOnMissingBean
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java
index f444717a3e..d41b3e0923 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecurityProperties.java
@@ -150,6 +150,8 @@ public class SecurityProperties {
         }
     }
 
+    private boolean productionMode = true;
+
     private String adminUser;
 
     private String adminPassword;
@@ -182,6 +184,14 @@ public class SecurityProperties {
 
     private final DigesterProperties digester = new DigesterProperties();
 
+    public boolean isProductionMode() {
+        return productionMode;
+    }
+
+    public void setProductionMode(final boolean productionMode) {
+        this.productionMode = productionMode;
+    }
+
     public String getAdminUser() {
         return adminUser;
     }
diff --git 
a/core/spring/src/test/java/org/apache/syncope/core/spring/SpringTestConfiguration.java
 
b/core/spring/src/test/java/org/apache/syncope/core/spring/SpringTestConfiguration.java
index 82313849c4..7d6d2d2757 100644
--- 
a/core/spring/src/test/java/org/apache/syncope/core/spring/SpringTestConfiguration.java
+++ 
b/core/spring/src/test/java/org/apache/syncope/core/spring/SpringTestConfiguration.java
@@ -25,6 +25,7 @@ import java.io.Reader;
 import org.apache.syncope.core.persistence.api.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.EncryptorManager;
 import org.apache.syncope.core.provisioning.api.ImplementationLookup;
+import org.apache.syncope.core.spring.security.DefaultCredentialChecker;
 import org.apache.syncope.core.spring.security.DefaultEncryptorManager;
 import org.apache.syncope.core.spring.security.DummyImplementationLookup;
 import org.apache.syncope.core.spring.security.SecurityProperties;
@@ -49,7 +50,7 @@ public class SpringTestConfiguration {
     public EncryptorManager encryptorManager() {
         SecurityProperties securityProperties = new SecurityProperties();
         securityProperties.setAesSecretKey(AES_SECRET_KEY);
-        return new DefaultEncryptorManager(securityProperties);
+        return new DefaultEncryptorManager(new DefaultCredentialChecker("", 
"", "", "", false), securityProperties);
     }
 
     @Primary
diff --git 
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/DefaultEncryptorTest.java
 
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/DefaultEncryptorTest.java
index bba0d18cf9..1ff092f3ca 100644
--- 
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/DefaultEncryptorTest.java
+++ 
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/DefaultEncryptorTest.java
@@ -21,8 +21,10 @@ package org.apache.syncope.core.spring.security;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.security.InvalidKeyException;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.Encryptor;
@@ -44,7 +46,9 @@ public class DefaultEncryptorTest {
 
         SecurityProperties securityProperties = new SecurityProperties();
         
securityProperties.setAesSecretKey(SpringTestConfiguration.AES_SECRET_KEY);
-        ENCRYPTOR = new 
DefaultEncryptorManager(securityProperties).getInstance();
+
+        ENCRYPTOR = new DefaultEncryptorManager(
+                new DefaultCredentialChecker("", "", "", "", false), 
securityProperties).getInstance();
     }
 
     @Test
@@ -74,7 +78,10 @@ public class DefaultEncryptorTest {
 
     @Test
     public void smallKey() throws Exception {
-        DefaultEncryptor smallKeyEncryptor = new DefaultEncryptor("123", new 
SecurityProperties().getDigester());
+        DefaultEncryptor prodModeEncryptor = new DefaultEncryptor("123", true, 
new SecurityProperties().getDigester());
+        assertThrows(InvalidKeyException.class, () -> 
prodModeEncryptor.encode(PASSWORD_VALUE, CipherAlgorithm.AES));
+
+        DefaultEncryptor smallKeyEncryptor = new DefaultEncryptor("123", 
false, new SecurityProperties().getDigester());
         String encPassword = smallKeyEncryptor.encode(PASSWORD_VALUE, 
CipherAlgorithm.AES);
         String decPassword = smallKeyEncryptor.decode(encPassword, 
CipherAlgorithm.AES);
         assertEquals(PASSWORD_VALUE, decPassword);
diff --git a/core/starter/src/main/resources/core.properties 
b/core/starter/src/main/resources/core.properties
index e9dfe4650b..c3638aa1d9 100644
--- a/core/starter/src/main/resources/core.properties
+++ b/core/starter/src/main/resources/core.properties
@@ -80,6 +80,7 @@ spring.mail.properties.mail.smtp.starttls.enable=false
 # Security #
 ############
 
+security.productionMode=true
 security.adminUser=${adminUser}
 security.adminPassword=${adminPassword}
 security.adminPasswordAlgorithm=SSHA256
diff --git a/fit/core-reference/src/main/resources/core-embedded.properties 
b/fit/core-reference/src/main/resources/core-embedded.properties
index 243f8c42dc..e030e8d2f0 100644
--- a/fit/core-reference/src/main/resources/core-embedded.properties
+++ b/fit/core-reference/src/main/resources/core-embedded.properties
@@ -27,6 +27,7 @@ service.discovery.address=http://localhost:9080/syncope/rest/
 spring.devtools.livereload.enabled=false
 spring.devtools.restart.enabled=false
 
+security.productionMode=false
 security.adminUser=${adminUser}
 security.anonymousUser=${anonymousUser}
 security.jwsKey=${jwsKey}
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 3c1f5912a5..d22ce6c0ae 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -175,6 +175,7 @@ import 
org.apache.syncope.common.rest.api.service.wa.MfaTrustStorageService;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
 import 
org.apache.syncope.common.rest.api.service.wa.WebAuthnRegistrationService;
 import org.apache.syncope.core.persistence.api.EncryptorManager;
+import org.apache.syncope.core.spring.security.DefaultCredentialChecker;
 import org.apache.syncope.core.spring.security.DefaultEncryptorManager;
 import org.apache.syncope.core.spring.security.SecurityProperties;
 import org.apache.syncope.fit.AbstractITCase.KeymasterInitializer;
@@ -1189,6 +1190,8 @@ public abstract class AbstractITCase {
     protected AbstractITCase() {
         SecurityProperties securityProperties = new SecurityProperties();
         securityProperties.setAesSecretKey(StringUtils.EMPTY);
-        encryptorManager = new DefaultEncryptorManager(securityProperties);
+        securityProperties.setProductionMode(false);
+        encryptorManager = new DefaultEncryptorManager(
+                new DefaultCredentialChecker("", "", "", "", false), 
securityProperties);
     }
 }

Reply via email to