comparison roundup/configuration.py @ 7809:be6cb2e0d471

feat: add support for rotating jwt keys This allows jwt_secret to have multiple ',' separated secrets. The first/leftmost should be used to sign new JWTs. All of them are used (starting from left/newest) to try to verify a JWT. If the first secret is < 32 chars in length JWTs are disabled. If any of the other secrets are < 32 chars, the configuration code causes the software to exit. This prevents insecure (too short) secrets from being used. Updated doc examples and tests.
author John Rouillard <rouilj@ieee.org>
date Thu, 14 Mar 2024 19:04:19 -0400
parents 6f66d74d37f3
children 890097bc4cd0
comparison
equal deleted inserted replaced
7808:6c5f8da9fca7 7809:be6cb2e0d471
824 class SecretNullableOption(NullableOption, SecretOption): 824 class SecretNullableOption(NullableOption, SecretOption):
825 # use get from SecretOption and rest from NullableOption 825 # use get from SecretOption and rest from NullableOption
826 get = SecretOption.get 826 get = SecretOption.get
827 class_description = SecretOption.class_description 827 class_description = SecretOption.class_description
828 828
829 class ListSecretOption(SecretOption):
830 # use get from SecretOption
831 def get(self):
832 value = SecretOption.get(self)
833 return [x.lstrip() for x in value.split(',')]
834
835 class_description = SecretOption.class_description
836
837 def validate(self, options):
838 if self.name == "WEB_JWT_SECRET":
839 secrets = self.get()
840 invalid_secrets = [ x for x in secrets[1:] if len(x) < 32]
841 if invalid_secrets:
842 raise OptionValueError(
843 self, ", ".join(secrets),
844 "One or more secrets less then 32 characters in length\n"
845 "found: %s" % ', '.join(invalid_secrets))
846 else:
847 self.get()
829 848
830 class RedisUrlOption(SecretNullableOption): 849 class RedisUrlOption(SecretNullableOption):
831 """Do required check to make sure known bad parameters are not 850 """Do required check to make sure known bad parameters are not
832 put in the url. 851 put in the url.
833 852
1435 "Changing this changes the etag and invalidates updates by\n" 1454 "Changing this changes the etag and invalidates updates by\n"
1436 "clients. It must be persistent across application restarts.\n" 1455 "clients. It must be persistent across application restarts.\n"
1437 "(Note the default value changes every time\n" 1456 "(Note the default value changes every time\n"
1438 " roundup-admin updateconfig\n" 1457 " roundup-admin updateconfig\n"
1439 "is run, so it must be explicitly set to a non-empty string.\n"), 1458 "is run, so it must be explicitly set to a non-empty string.\n"),
1440 (SecretNullableOption, "jwt_secret", "disabled", 1459 (ListSecretOption, "jwt_secret", "disabled",
1441 "This is used to generate/validate json web tokens (jwt).\n" 1460 "This is used to sign/validate json web tokens\n"
1442 "Even if you don't use jwts it must not be empty.\n" 1461 "(JWT). Even if you don't use JWTs it must not be\n"
1443 "If less than 256 bits (32 characters) in length it will\n" 1462 "empty. You can use multiple secrets separated by a\n"
1444 "disable use of jwt. Changing this invalidates all jwts\n" 1463 "comma ','. This allows for secret rotation. The newest\n"
1445 "issued by the roundup instance requiring *all* users to\n" 1464 "secret should be placed first and used for signing. The\n"
1446 "generate new jwts. This is experimental and disabled by\n" 1465 "rest of the secrets are used for validating an old JWT.\n"
1447 "default. It must be persistent across application restarts.\n"), 1466 "If the first secret is less than 256 bits (32\n"
1467 "characters) in length JWTs are disabled. If other secrets\n"
1468 "are less than 32 chars, the application will exit. Removing\n"
1469 "a secret from this list invalidates all JWTs signed with\n"
1470 "the secret. JWT support is experimental and disabled by\n"
1471 "default. The secrets must be persistent across\n"
1472 "application restarts.\n"),
1448 )), 1473 )),
1449 ("rdbms", ( 1474 ("rdbms", (
1450 (DatabaseBackend, 'backend', NODEFAULT, 1475 (DatabaseBackend, 'backend', NODEFAULT,
1451 "Database backend."), 1476 "Database backend."),
1452 (Option, 'name', 'roundup', 1477 (Option, 'name', 'roundup',

Roundup Issue Tracker: http://roundup-tracker.org/