From c8ad60441c90f141937a5b562dda3392d40e4f2d Mon Sep 17 00:00:00 2001 From: Cameron Durham Date: Sat, 24 Feb 2024 20:04:31 -0700 Subject: [PATCH 1/3] Log password requirement details in demo environment Signed-off-by: Cameron Durham --- .../security/support/ConfigConstants.java | 2 ++ .../SecuritySettingsConfigurer.java | 22 +++++++++++++------ .../SecuritySettingsConfigurerTests.java | 10 ++++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/opensearch/security/support/ConfigConstants.java b/src/main/java/org/opensearch/security/support/ConfigConstants.java index 3060e1b2dc..f336a41c56 100644 --- a/src/main/java/org/opensearch/security/support/ConfigConstants.java +++ b/src/main/java/org/opensearch/security/support/ConfigConstants.java @@ -273,9 +273,11 @@ public enum RolesMappingResolution { public static final String SECURITY_RESTAPI_ADMIN_ENABLED = "plugins.security.restapi.admin.enabled"; public static final String SECURITY_RESTAPI_ENDPOINTS_DISABLED = "plugins.security.restapi.endpoints_disabled"; public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX = "plugins.security.restapi.password_validation_regex"; + public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT = "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}"; public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_ERROR_MESSAGE = "plugins.security.restapi.password_validation_error_message"; public static final String SECURITY_RESTAPI_PASSWORD_MIN_LENGTH = "plugins.security.restapi.password_min_length"; + public static final Integer SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT = 8; public static final String SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH = "plugins.security.restapi.password_score_based_validation_strength"; // Illegal Opcodes from here on diff --git a/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java b/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java index a68c93f03f..f788f6a6a3 100644 --- a/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java +++ b/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java @@ -39,7 +39,9 @@ import org.yaml.snakeyaml.Yaml; import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH; +import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT; import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX; +import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT; /** * This class updates the security related configuration, as needed. @@ -130,8 +132,8 @@ void updateAdminPassword() { try { final PasswordValidator passwordValidator = PasswordValidator.of( Settings.builder() - .put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") - .put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, 8) + .put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT) + .put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT) .build() ); @@ -142,11 +144,17 @@ void updateAdminPassword() { } // If script execution environment is set to demo, validate custom password, else if set to test, skip validation - if (shouldValidatePassword - && !ADMIN_PASSWORD.isEmpty() - && passwordValidator.validate(ADMIN_USERNAME, ADMIN_PASSWORD) != RequestContentValidator.ValidationError.NONE) { - System.out.println("Password " + ADMIN_PASSWORD + " is weak. Please re-try with a stronger password."); - System.exit(-1); + if (shouldValidatePassword && !ADMIN_PASSWORD.isEmpty()) { + RequestContentValidator.ValidationError response = passwordValidator.validate(ADMIN_USERNAME, ADMIN_PASSWORD); + if (!RequestContentValidator.ValidationError.NONE.equals(response)) { + System.out.println( + String.format( + "Password %s failed validation: \"%s\". Please re-try with a minimum %d character password that is strong per zxcvbn validation." + , ADMIN_PASSWORD, response.message(), SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT + ) + ); + System.exit(-1); + } } // if ADMIN_PASSWORD is still an empty string, it implies no custom password was provided. We exit the setup. diff --git a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java index 280d704fb8..4653b43f3b 100644 --- a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java +++ b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java @@ -37,6 +37,8 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.opensearch.security.dlic.rest.validation.RequestContentValidator.ValidationError.INVALID_PASSWORD_INVALID_REGEX; +import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.REST_ENABLED_ROLES; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.SYSTEM_INDICES; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.isKeyPresentInYMLFile; @@ -125,7 +127,13 @@ public void testUpdateAdminPasswordWithWeakPassword() throws NoSuchFieldExceptio System.setSecurityManager(null); } - verifyStdOutContainsString("Password weakpassword is weak. Please re-try with a stronger password."); + verifyStdOutContainsString( + String.format( + "Password weakpassword failed validation: \"%s\". Please re-try with a minimum %d character password that is strong per zxcvbn validation.", + INVALID_PASSWORD_INVALID_REGEX.message(), + SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT + ) + ); } @Test From 09dcdc9293de21b1144ace0dccd810e22dd5b02b Mon Sep 17 00:00:00 2001 From: Cameron Durham Date: Mon, 26 Feb 2024 19:26:14 -0700 Subject: [PATCH 2/3] Move *_DEFAULTs and add password length test Signed-off-by: Cameron Durham --- .../security/support/ConfigConstants.java | 2 -- .../SecuritySettingsConfigurer.java | 17 ++++----- .../SecuritySettingsConfigurerTests.java | 35 +++++++++++++++---- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/opensearch/security/support/ConfigConstants.java b/src/main/java/org/opensearch/security/support/ConfigConstants.java index f336a41c56..3060e1b2dc 100644 --- a/src/main/java/org/opensearch/security/support/ConfigConstants.java +++ b/src/main/java/org/opensearch/security/support/ConfigConstants.java @@ -273,11 +273,9 @@ public enum RolesMappingResolution { public static final String SECURITY_RESTAPI_ADMIN_ENABLED = "plugins.security.restapi.admin.enabled"; public static final String SECURITY_RESTAPI_ENDPOINTS_DISABLED = "plugins.security.restapi.endpoints_disabled"; public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX = "plugins.security.restapi.password_validation_regex"; - public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT = "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}"; public static final String SECURITY_RESTAPI_PASSWORD_VALIDATION_ERROR_MESSAGE = "plugins.security.restapi.password_validation_error_message"; public static final String SECURITY_RESTAPI_PASSWORD_MIN_LENGTH = "plugins.security.restapi.password_min_length"; - public static final Integer SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT = 8; public static final String SECURITY_RESTAPI_PASSWORD_SCORE_BASED_VALIDATION_STRENGTH = "plugins.security.restapi.password_score_based_validation_strength"; // Illegal Opcodes from here on diff --git a/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java b/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java index f788f6a6a3..5b497d0f20 100644 --- a/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java +++ b/src/main/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurer.java @@ -39,9 +39,7 @@ import org.yaml.snakeyaml.Yaml; import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH; -import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT; import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX; -import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT; /** * This class updates the security related configuration, as needed. @@ -78,6 +76,7 @@ public class SecuritySettingsConfigurer { ".plugins-flow-framework-templates", ".plugins-flow-framework-state" ); + static final Integer DEFAULT_PASSWORD_MIN_LENGTH = 8; static String ADMIN_PASSWORD = ""; static String ADMIN_USERNAME = "admin"; @@ -132,8 +131,8 @@ void updateAdminPassword() { try { final PasswordValidator passwordValidator = PasswordValidator.of( Settings.builder() - .put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX_DEFAULT) - .put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT) + .put(SECURITY_RESTAPI_PASSWORD_VALIDATION_REGEX, "(?=.*[A-Z])(?=.*[^a-zA-Z\\\\d])(?=.*[0-9])(?=.*[a-z]).{8,}") + .put(SECURITY_RESTAPI_PASSWORD_MIN_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH) .build() ); @@ -148,10 +147,12 @@ void updateAdminPassword() { RequestContentValidator.ValidationError response = passwordValidator.validate(ADMIN_USERNAME, ADMIN_PASSWORD); if (!RequestContentValidator.ValidationError.NONE.equals(response)) { System.out.println( - String.format( - "Password %s failed validation: \"%s\". Please re-try with a minimum %d character password that is strong per zxcvbn validation." - , ADMIN_PASSWORD, response.message(), SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT - ) + String.format( + "Password %s failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn", + ADMIN_PASSWORD, + response.message(), + DEFAULT_PASSWORD_MIN_LENGTH + ) ); System.exit(-1); } diff --git a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java index 4653b43f3b..38e55d42b1 100644 --- a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java +++ b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java @@ -38,7 +38,8 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.opensearch.security.dlic.rest.validation.RequestContentValidator.ValidationError.INVALID_PASSWORD_INVALID_REGEX; -import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT; +import static org.opensearch.security.dlic.rest.validation.RequestContentValidator.ValidationError.INVALID_PASSWORD_TOO_SHORT; +import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.DEFAULT_PASSWORD_MIN_LENGTH; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.REST_ENABLED_ROLES; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.SYSTEM_INDICES; import static org.opensearch.security.tools.democonfig.SecuritySettingsConfigurer.isKeyPresentInYMLFile; @@ -128,11 +129,33 @@ public void testUpdateAdminPasswordWithWeakPassword() throws NoSuchFieldExceptio } verifyStdOutContainsString( - String.format( - "Password weakpassword failed validation: \"%s\". Please re-try with a minimum %d character password that is strong per zxcvbn validation.", - INVALID_PASSWORD_INVALID_REGEX.message(), - SECURITY_RESTAPI_PASSWORD_MIN_LENGTH_DEFAULT - ) + String.format( + "Password weakpassword failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn", + INVALID_PASSWORD_INVALID_REGEX.message(), + DEFAULT_PASSWORD_MIN_LENGTH + ) + ); + } + + @Test + public void testUpdateAdminPasswordWithShortPassword() throws NoSuchFieldException, IllegalAccessException { + + setEnv(adminPasswordKey, "short"); + try { + System.setSecurityManager(new NoExitSecurityManager()); + securitySettingsConfigurer.updateAdminPassword(); + } catch (SecurityException e) { + assertThat(e.getMessage(), equalTo("System.exit(-1) blocked to allow print statement testing.")); + } finally { + System.setSecurityManager(null); + } + + verifyStdOutContainsString( + String.format( + "Password short failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn", + INVALID_PASSWORD_TOO_SHORT.message(), + DEFAULT_PASSWORD_MIN_LENGTH + ) ); } From ae6177a8087b8748d5aaab40b7192493364ed2e2 Mon Sep 17 00:00:00 2001 From: Cameron Durham Date: Tue, 27 Feb 2024 12:12:24 -0700 Subject: [PATCH 3/3] Consolidate password validation in test Signed-off-by: Cameron Durham --- .../democonfig/SecuritySettingsConfigurerTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java index 38e55d42b1..50a65e7fa2 100644 --- a/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java +++ b/src/test/java/org/opensearch/security/tools/democonfig/SecuritySettingsConfigurerTests.java @@ -58,6 +58,9 @@ public class SecuritySettingsConfigurerTests { private final String adminPasswordKey = ConfigConstants.OPENSEARCH_INITIAL_ADMIN_PASSWORD; + private static final String PASSWORD_VALIDATION_FAILURE_MESSAGE = + "Password %s failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn"; + private static SecuritySettingsConfigurer securitySettingsConfigurer; private static Installer installer; @@ -130,7 +133,8 @@ public void testUpdateAdminPasswordWithWeakPassword() throws NoSuchFieldExceptio verifyStdOutContainsString( String.format( - "Password weakpassword failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn", + PASSWORD_VALIDATION_FAILURE_MESSAGE, + "weakpassword", INVALID_PASSWORD_INVALID_REGEX.message(), DEFAULT_PASSWORD_MIN_LENGTH ) @@ -151,11 +155,7 @@ public void testUpdateAdminPasswordWithShortPassword() throws NoSuchFieldExcepti } verifyStdOutContainsString( - String.format( - "Password short failed validation: \"%s\". Please re-try with a minimum %d character password and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character that is strong. Password strength can be tested here: https://lowe.github.io/tryzxcvbn", - INVALID_PASSWORD_TOO_SHORT.message(), - DEFAULT_PASSWORD_MIN_LENGTH - ) + String.format(PASSWORD_VALIDATION_FAILURE_MESSAGE, "short", INVALID_PASSWORD_TOO_SHORT.message(), DEFAULT_PASSWORD_MIN_LENGTH) ); }