ActionView::Template::Error (bad password component) error with non-encoded elasticsearch passwords

Summary

When enabling Advanced Search with a password or username that contains characters that are invalid for the User Information section of the URI section - trying to visit the /admin/application_settings/advanced_search page will result in a 500 error viewing the settings - with either a:

URI::InvalidComponentError (bad component(expected userinfo component or user component)

or more likely, given the password is going to have a URI-invalid character:

URI::InvalidComponentError (bad password component)

The error may also manifest as:

ActionView::Template::Error (bad password component)

Steps to reproduce

  1. Enable Advanced Search
  2. Enter a username or password with invalid characters for a URI - e.g. (#1234#)
  3. 500 error when viewing the settings

Backtrace:

 "exception.class": "ActionView::Template::Error",
  "exception.message": "bad password component",
  "exception.backtrace": [
    "ee/app/models/ee/application_setting.rb:319:in `block in elasticsearch_url_with_credentials'",
    "ee/app/models/ee/application_setting.rb:315:in `map'",
    "ee/app/models/ee/application_setting.rb:315:in `elasticsearch_url_with_credentials'",
    "ee/app/models/ee/application_setting.rb:326:in `elasticsearch_config'",
[...]

Possible fixes

The elasticsearch_username/elasticsearch_password strings likely need to be URI encoded with URI.encode_www_form_component when setting URI.user and URI.password when building the elasticsearch_url_with_credentials

Workaround

To get back into the settings - the password and/or username can be cleared out using the GitLab Rails Console by running:

ApplicationSetting.last.update(elasticsearch_password: nil)
ApplicationSetting.last.update(elasticsearch_username: nil)

Alternatively - you can encode the current value(s) by doing:

ApplicationSetting.last.update(elasticsearch_password: URI.encode_www_form_component(ApplicationSetting.last.elasticsearch_password))
ApplicationSetting.last.update(elasticsearch_username: URI.encode_www_form_component(ApplicationSetting.last.elasticsearch_username))

Release Notes

This will be added to the Bug Release Post in 14.6

CC: @changzhengliu

Edited by John McGuire