Skip to content

Conversation

@andsel
Copy link
Contributor

@andsel andsel commented Sep 18, 2025

Release notes

[rn:skip]

What does this PR do?

Translates ValidatedPassword setting class into plain Java. This PR copies the Rspec test also to JUnit, plus removed a log validation test, because mocking of the ValidatedPasswordSetting Java class seems to do not work in Rspec.

Why is it important/What is the impact to the user?

N/A

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • [ ] I have made corresponding changes to the documentation
  • [ ] I have made corresponding change to the default configuration files (and/or docker env variables)
  • I have added tests that prove my fix is effective or that my feature works

Author's Checklist

  • [ ]

How to test this PR locally

On config/logstash.yml enable basic authetication on HTTP API with an invalid password and configure password_policy.mode to warn a log message:

api.auth.type: basic
api.auth.basic.username: "logstash-user"
api.auth.basic.password: "invalid"
api.auth.basic.password_policy.mode: WARN 

run Logstash:

bin/logstash -e "input{stdin{}} output{stdout{codec=>rubydebug}}"

and verify that in log appears:

[WARN ][org.logstash.settings.ValidatedPasswordSetting] Password must contain at least one upper case, must contain at least one digit between 0 and 9.

and doesn't crash.

Then switch api.auth.basic.password_policy.mode to ERROR

and check in logs appears a stacktrace:

[2025-12-03T16:03:19,849][FATAL][logstash.runner          ] An unexpected error occurred! {:error=>#<Java::JavaLang::IllegalArgumentException: Password must be length of between 8 and 1024, must contain at least one digit between 0 and 9, must contain at least one upper case.>,

Related issues

@andsel andsel self-assigned this Sep 18, 2025
@github-actions
Copy link
Contributor

🤖 GitHub comments

Expand to view the GitHub comments

Just comment with:

  • run docs-build : Re-trigger the docs validation. (use unformatted text in the comment!)

@mergify
Copy link
Contributor

mergify bot commented Sep 18, 2025

This pull request does not have a backport label. Could you fix it @andsel? 🙏
To fixup this pull request, you need to add the backport labels for the needed
branches, such as:

  • backport-8./d is the label to automatically backport to the 8./d branch. /d is the digit.
  • If no backport is necessary, please add the backport-skip label

@andsel andsel force-pushed the feature/validated_password_setting_to_java branch from 6ca07fb to fc2e9aa Compare September 18, 2025 15:37
@elastic-sonarqube
Copy link

@andsel andsel force-pushed the feature/validated_password_setting_to_java branch from fc2e9aa to 37653a5 Compare October 2, 2025 14:49
@andsel andsel changed the title Feature/validated password setting to java Moved Ruby ValidatedPassword setting to Java implementation Oct 3, 2025
@andsel andsel force-pushed the feature/validated_password_setting_to_java branch from 37653a5 to 42bd8bc Compare December 1, 2025 15:35
@andsel
Copy link
Contributor Author

andsel commented Dec 3, 2025

run exhaustive tests

@andsel andsel marked this pull request as ready for review December 3, 2025 16:09
Copy link
Member

@donoghuc donoghuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. One question about log level for one of the messages, but not a blocking review.

if (value instanceof Map) {
value = convertKeyRubyLabelsToStrings((Map<Object, Object>) value);
}
// TODO handle lists if needed ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont see how lists would be used in practice with this setting. Symbols, maybe? Should we convert symbol to string somewhere?

Copy link
Contributor Author

@andsel andsel Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the places this setting is used (only LogStash::WebServer) and how the options tree is created

options = {}
options[:http_host] = settings.get('api.http.host') # may be overridden later if API configured securely
options[:http_ports] = settings.get('api.http.port')
options[:http_environment] = settings.get('api.environment')
if settings.get('api.ssl.enabled')
ssl_params = {}
ssl_params[:keystore_path] = required_setting(settings, 'api.ssl.keystore.path', "api.ssl.enabled")
ssl_params[:keystore_password] = required_setting(settings, 'api.ssl.keystore.password', "api.ssl.enabled")
ssl_params[:supported_protocols] = settings.get('api.ssl.supported_protocols')
options[:ssl_params] = ssl_params.freeze
else
warn_ignored(logger, settings, "api.ssl.", "api.ssl.enabled")
end
if settings.get('api.auth.type') == 'basic'
auth_basic = {}
auth_basic[:username] = required_setting(settings, 'api.auth.basic.username', "api.auth.type")
auth_basic[:password] = required_setting(settings, 'api.auth.basic.password', "api.auth.type")
password_policies = {}
password_policies[:mode] = required_setting_with_changing_default(settings, 'api.auth.basic.password_policy.mode', "api.auth.type", "ERROR")
password_policies[:length] = {}
password_policies[:length][:minimum] = required_setting(settings, 'api.auth.basic.password_policy.length.minimum', "api.auth.type")
if !password_policies[:length][:minimum].between?(8, 1024)
fail(ArgumentError, "api.auth.basic.password_policy.length.minimum has to be between 8 and 1024.")
end
password_policies[:include] = {}
password_policies[:include][:upper] = required_setting(settings, 'api.auth.basic.password_policy.include.upper', "api.auth.type")
password_policies[:include][:lower] = required_setting(settings, 'api.auth.basic.password_policy.include.lower', "api.auth.type")
password_policies[:include][:digit] = required_setting(settings, 'api.auth.basic.password_policy.include.digit', "api.auth.type")
password_policies[:include][:symbol] = required_setting(settings, 'api.auth.basic.password_policy.include.symbol', "api.auth.type")
auth_basic[:password_policies] = password_policies
options[:auth_basic] = auth_basic.freeze
, as nested maps where the keys are symbols and values are other maps or strings, I think we could:

  1. if a List or Array is encountered throw a type error
    ~~2. convert the value to string
    2a. or using explicit casting if (value instanceof RubySymbol) { ((RubySymbol) value).asJavaString(); }
    2b. or use value.toString() ~~

We can't convert because the value is handled in https://github.com/elastic/logstash/pull/18185/files#diff-8e93bdd2987d82a339de8febcd961849e191bc2ce9f5aab2a4a7b68afc1e9be3R87-R91 and we have to grant that if it's nil it's decoded as "" empty string, plus the toString() is already invoked there.

So RubySymbol shouldn't happen and neither List or Array.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Thanks for the extra details.

@andsel andsel requested a review from donoghuc December 4, 2025 08:47
Copy link
Member

@donoghuc donoghuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjustments look good! One question about a new import but other than that its all good. #18185 (comment)

…abelsToStrings method needs to work on other collection values.
@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

cc @andsel

@andsel andsel merged commit 3659b6f into elastic:main Dec 4, 2025
11 checks passed
@andsel andsel added the backport-active-all Automated backport with mergify to all the active branches label Dec 4, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

@Mergifyio backport 8.19 9.1 9.2

@mergify
Copy link
Contributor

mergify bot commented Dec 4, 2025

backport 8.19 9.1 9.2

✅ Backports have been created

mergify bot pushed a commit that referenced this pull request Dec 4, 2025
Translates ValidatedPassword setting class into plain Java. This PR copies the Rspec test also to JUnit, plus removed a log validation test, because mocking of the ValidatedPasswordSetting Java class seems to do not work in Rspec.

Co-authored-by: Cas Donoghue <[email protected]>
(cherry picked from commit 3659b6f)

# Conflicts:
#	logstash-core/lib/logstash/settings.rb
#	logstash-core/spec/logstash/settings_spec.rb
#	logstash-core/src/test/java/org/logstash/settings/PasswordSettingTest.java
mergify bot pushed a commit that referenced this pull request Dec 4, 2025
Translates ValidatedPassword setting class into plain Java. This PR copies the Rspec test also to JUnit, plus removed a log validation test, because mocking of the ValidatedPasswordSetting Java class seems to do not work in Rspec.

Co-authored-by: Cas Donoghue <[email protected]>
(cherry picked from commit 3659b6f)

# Conflicts:
#	logstash-core/lib/logstash/settings.rb
#	logstash-core/spec/logstash/settings_spec.rb
#	logstash-core/src/test/java/org/logstash/settings/PasswordSettingTest.java
mergify bot pushed a commit that referenced this pull request Dec 4, 2025
Translates ValidatedPassword setting class into plain Java. This PR copies the Rspec test also to JUnit, plus removed a log validation test, because mocking of the ValidatedPasswordSetting Java class seems to do not work in Rspec.

Co-authored-by: Cas Donoghue <[email protected]>
(cherry picked from commit 3659b6f)

# Conflicts:
#	logstash-core/lib/logstash/settings.rb
#	logstash-core/spec/logstash/settings_spec.rb
#	logstash-core/src/test/java/org/logstash/settings/PasswordSettingTest.java
@andsel andsel removed the backport-active-all Automated backport with mergify to all the active branches label Dec 5, 2025
@mergify
Copy link
Contributor

mergify bot commented Dec 5, 2025

This pull request does not have a backport label. Could you fix it @andsel? 🙏
To fixup this pull request, you need to add the backport labels for the needed
branches, such as:

  • backport-8./d is the label to automatically backport to the 8./d branch. /d is the digit.
  • If no backport is necessary, please add the backport-skip label

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reimplement LogStash::Setting::ValidatedPassword to Java

3 participants