-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add symmetric key monitoring #324
Changes from 2 commits
b819f72
e6f923c
08ab689
2ddf6a5
700832c
21551ab
d96580f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
""" edx Django REST Framework extensions. """ | ||
|
||
__version__ = '8.5.3' # pragma: no cover | ||
__version__ = '8.6.0' # pragma: no cover |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -173,18 +173,73 @@ def _set_filters(token): | |
|
||
|
||
def _verify_jwt_signature(token, jwt_issuer, decode_symmetric_token): | ||
""" | ||
Verifies the JWT signature. Raises InvalidTokenError in the event of an error. | ||
|
||
Arguments: | ||
token (str): JWT to be decoded. | ||
jwt_issuer (dict): A dict of JWT issuer related settings, containing the symmetric key. | ||
decode_symmetric_token (bool): Whether to decode symmetric tokens or not. Pass False for asymmetric tokens only | ||
""" | ||
# .. custom_attribute_name: jwt_auth_decode_symmetric_token | ||
# .. custom_attribute_description: True if symmetric keys will also be used for checking | ||
# the JWT signature, and False if only asymmetric keys will be used. | ||
set_custom_attribute('jwt_auth_decode_symmetric_token', decode_symmetric_token) | ||
|
||
# For observability purposes, we will first try asymmetric keys only to verify | ||
# that we no longer need the symmetric key. However, if this fails, we will | ||
# continue on to the original code path and try all keys (including symmetric) | ||
# and add monitoring to let us know. This is meant to be temporary, until we | ||
# can fully retire code paths for symmetric keys, as part of | ||
# DEPR: Symmetric JWTs: https://github.com/openedx/public-engineering/issues/83 | ||
|
||
# Use add_symmetric_keys=False to only include asymmetric keys at first | ||
key_set = _get_signing_jwk_key_set(jwt_issuer, add_symmetric_keys=False) | ||
# .. custom_attribute_name: jwt_auth_verify_asymmetric_keys_count | ||
# .. custom_attribute_description: Number of JWT verification keys in use for this | ||
# verification. Should be same as number of asymmetric public keys. This is | ||
# intended to aid in key rotations; once the average count stabilizes at a | ||
# higher number after adding a public key, it should be safe to change the secret key. | ||
set_custom_attribute('jwt_auth_verify_asymmetric_keys_count', len(key_set)) | ||
|
||
try: | ||
_ = JWS().verify_compact(token, key_set) | ||
# .. custom_attribute_name: jwt_auth_asymmetric_verified | ||
# .. custom_attribute_description: The count of JWTs successfully verified | ||
# using an asymmetric key. | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
set_custom_attribute('jwt_auth_asymmetric_verified', True) | ||
return | ||
except Exception: # pylint: disable=broad-except | ||
# Continue to the old code path of trying all keys | ||
pass | ||
|
||
# The following is the original code that includes both the symmetric and asymmetric keys | ||
# as requested with the decode_symmetric_token argument. Note that the check against | ||
# the asymmetric keys here is redundant and unnecessary, but this code is temporary and | ||
# will be simplified once symmetric keys have been fully retired. | ||
|
||
key_set = _get_signing_jwk_key_set(jwt_issuer, add_symmetric_keys=decode_symmetric_token) | ||
# .. custom_attribute_name: jwt_auth_verify_keys_count | ||
# .. custom_attribute_name: jwt_auth_verify_all_keys_count | ||
# .. custom_attribute_description: Number of JWT verification keys in use for this | ||
# verification. Should be same as number of asymmetric public keys, plus one if | ||
# a symmetric key secret is set. This is intended to aid in key rotations; once | ||
# the average count stabilizes at a higher number after adding a public key, it | ||
# should be safe to change the secret key. | ||
set_custom_attribute('jwt_auth_verify_keys_count', len(key_set)) | ||
set_custom_attribute('jwt_auth_verify_all_keys_count', len(key_set)) | ||
|
||
try: | ||
_ = JWS().verify_compact(token, key_set) | ||
# .. custom_attribute_name: jwt_auth_symmetric_verified | ||
# .. custom_attribute_description: The count of JWTs successfully verified | ||
# using a symmetric key. | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Note: A separate custom attribute is used in case there are different JWTs decoded | ||
# in the same request. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having trouble understanding this comment. What other attribute is this being contrasted to? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried a longer version. You can let me know if it is more clear. |
||
set_custom_attribute('jwt_auth_symmetric_verified', True) | ||
return | ||
except Exception as token_error: | ||
# .. custom_attribute_name: jwt_auth_verification_failed | ||
# .. custom_attribute_description: True if the JWT token verification failed. | ||
set_custom_attribute('jwt_auth_verification_failed', True) | ||
logger.exception('Token verification failed.') | ||
exc_info = sys.exc_info() | ||
raise jwt.InvalidTokenError(exc_info[2]) from token_error | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This reads a little misleadingly to me; I would expect it to mean that the token was decoded using a symmetric key, not that the symmetric key is allowed to be used. (Non-blocking.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to
jwt_auth_check_symmetric_key
.