Repository: StackStorm/st2

Issue:
Special characters in st2admin account causing st2 key failure
Just upgraded to version 3.4 and my keyvault is having problems. I believe it's due to my st2admin password containing special characters.

```
[root@stackstorm workflows]# st2 key list --scope=all
Traceback (most recent call last):
  File "/bin/st2", line 10, in <module>
    sys.exit(main())
  File "/opt/stackstorm/st2/lib/python3.6/site-packages/st2client/shell.py", line 470, in main
    return Shell().run(argv)
  File "/opt/stackstorm/st2/lib/python3.6/site-packages/st2client/shell.py", line 385, in run
    config = self._parse_config_file(args=args, validate_config_permissions=False)
  File "/opt/stackstorm/st2/lib/python3.6/site-packages/st2client/base.py", line 183, in _parse_config_file
    result = parser.parse()
  File "/opt/stackstorm/st2/lib/python3.6/site-packages/st2client/config_parser.py", line 197, in parse
    value = get_func(section, key)
  File "/usr/lib64/python3.6/configparser.py", line 800, in get
    d)
  File "/usr/lib64/python3.6/configparser.py", line 394, in before_get
    self._interpolate_some(parser, option, L, value, section, defaults, 1)
  File "/usr/lib64/python3.6/configparser.py", line 444, in _interpolate_some
    "found: %r" % (rest,))
configparser.InterpolationSyntaxError: '%' must be followed by '%' or '(', found: '%3C#V~Bvg%3E3t+'
```

This password above is what I used to install stackstorm. Or at least part of it. I've since changed the password via the documented htpasswd method, but the issue persists. Any tips? Left the password in for research purposes.

curl -sSL https://stackstorm.com/packages/install.sh | bash -s -- --user=st2admin --password='q7j/t%3C#V~Bvg%3E3t+'


Discussion:

Resolving patch:
diff --git a/st2client/st2client/config_parser.py b/st2client/st2client/config_parser.py
--- a/st2client/st2client/config_parser.py
+++ b/st2client/st2client/config_parser.py
@@ -152,7 +152,7 @@ def parse(self):
                         msg = 'Invalid type "%s" for option "%s"' % (key_type, key)
                         raise ValueError(msg)
 
-                    value = get_func(section, key)
+                    value = get_func(section, key, raw=True)
                     result[section][key] = value
                 else:
                     result[section][key] = key_default_value


Test patch:
diff --git a/st2client/tests/fixtures/test_unicode.ini b/st2client/tests/fixtures/test_unicode.ini
--- a/st2client/tests/fixtures/test_unicode.ini
+++ b/st2client/tests/fixtures/test_unicode.ini
@@ -8,7 +8,7 @@ debug = True
 
 [credentials]
 username = test1
-password = 密码
+password = 密码%
 
 [api]
 url = http://127.0.0.1:9101/v1
diff --git a/st2client/tests/unit/test_config_parser.py b/st2client/tests/unit/test_config_parser.py
--- a/st2client/tests/unit/test_config_parser.py
+++ b/st2client/tests/unit/test_config_parser.py
@@ -83,15 +83,18 @@ def test_parse(self):
         self.assertTrue(result["cli"]["cache_token"], True)
 
     def test_get_config_for_unicode_char(self):
+        # this test tests for config parameters with unicode characters and the % sign
+        # the % sign interpolation is disabled since values are read with raw=True; See:
+        # https://docs.python.org/3.8/library/configparser.html#configparser.ConfigParser
         parser = CLIConfigParser(
             config_file_path=CONFIG_FILE_PATH_UNICODE, validate_config_exists=False
         )
         config = parser.parse()
 
         if six.PY3:
-            self.assertEqual(config["credentials"]["password"], "密码")
+            self.assertEqual(config["credentials"]["password"], "密码%")
         else:
-            self.assertEqual(config["credentials"]["password"], "\u5bc6\u7801")
+            self.assertEqual(config["credentials"]["password"], "\u5bc6\u7801\u0025")
 
 
 class CLIConfigPermissionsTestCase(unittest2.TestCase):