Limit token expiration to application credential expiration

If a token is issued with an application credential we need to check
the expiration of the application credential to ensure that the token
does not outlive the application credential. This ensures that if the
token expiration is greaten than that of the application credential it
is reset to the expiration of the application credential and a warning
is logged. Please see CVE-2022-2447 for more information.

Closes-Bug: 1992183
Change-Id: If6f9f72cf25769d022a970fac36cead17b2030f2
This commit is contained in:
Dave Wilde (d34dh0r53) 2022-10-13 15:37:53 -05:00
parent 02db926396
commit 8f999d1c1f
3 changed files with 42 additions and 0 deletions

View File

@ -5577,6 +5577,21 @@ class ApplicationCredentialAuth(test_v3.RestfulTestCase):
self.v3_create_token(auth_data, self.v3_create_token(auth_data,
expected_status=http.client.UNAUTHORIZED) expected_status=http.client.UNAUTHORIZED)
def test_application_credential_expiration_limits_token_expiration(self):
expires_at = datetime.datetime.utcnow() + datetime.timedelta(minutes=1)
app_cred = self._make_app_cred(expires=expires_at)
app_cred_ref = self.app_cred_api.create_application_credential(
app_cred)
auth_data = self.build_authentication_request(
app_cred_id=app_cred_ref['id'], secret=app_cred_ref['secret'])
resp = self.v3_create_token(auth_data,
expected_status=http.client.CREATED)
token = resp.headers.get('X-Subject-Token')
future = datetime.datetime.utcnow() + datetime.timedelta(minutes=2)
with freezegun.freeze_time(future):
self._validate_token(token,
expected_status=http.client.UNAUTHORIZED)
def test_application_credential_fails_when_user_deleted(self): def test_application_credential_fails_when_user_deleted(self):
app_cred = self._make_app_cred() app_cred = self._make_app_cred()
app_cred_ref = self.app_cred_api.create_application_credential( app_cred_ref = self.app_cred_api.create_application_credential(

View File

@ -267,6 +267,23 @@ class Manager(manager.Manager):
default_expire_time(), subsecond=True default_expire_time(), subsecond=True
) )
# NOTE(d34dh0r53): If this token is being issued with an application
# credential and the application credential expires before the token
# we need to set the token expiration to be the same as the application
# credential. See CVE-2022-2447 for more information.
if app_cred_id is not None:
app_cred_api = PROVIDERS.application_credential_api
app_cred = app_cred_api.get_application_credential(
token.application_credential_id)
token_time = timeutils.normalize_time(
timeutils.parse_isotime(token.expires_at))
if (app_cred['expires_at'] is not None) and (
token_time > app_cred['expires_at']):
token.expires_at = app_cred['expires_at'].isoformat()
LOG.debug('Resetting token expiration to the application'
' credential expiration: %s',
app_cred['expires_at'].isoformat())
token_id, issued_at = self.driver.generate_id_and_issued_at(token) token_id, issued_at = self.driver.generate_id_and_issued_at(token)
token.mint(token_id, issued_at) token.mint(token_id, issued_at)

View File

@ -0,0 +1,10 @@
---
security:
- |
[`bug 1992183 <https://bugs.launchpad.net/keystone/+bug/1992183>`_]
[`CVE-2022-2447 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-2447>`_]
Tokens issued with application credentials will now have their expiration
validated against that of the application credential. If the application
credential expires before the token the token's expiration will be set to
the same expiration as the application credential. Otherwise the token
will use the configured value.