diff --git a/keystone/api/credentials.py b/keystone/api/credentials.py index 2b81000e09..90b53dd686 100644 --- a/keystone/api/credentials.py +++ b/keystone/api/credentials.py @@ -176,7 +176,8 @@ class CredentialResource(ks_flask.ResourceBase): if isinstance(old_blob, str): old_blob = jsonutils.loads(old_blob) # if there was a scope set, prevent changing it or unsetting it - for key in ['trust_id', 'app_cred_id', 'access_token_id']: + for key in ['trust_id', 'app_cred_id', 'access_token_id', + 'access_id']: if old_blob.get(key) != new_blob.get(key): message = _('%s can not be updated for credential') % key raise exception.ValidationError(message=message) diff --git a/keystone/tests/unit/test_v3_credential.py b/keystone/tests/unit/test_v3_credential.py index 4cce2d1bf8..6573f4402a 100644 --- a/keystone/tests/unit/test_v3_credential.py +++ b/keystone/tests/unit/test_v3_credential.py @@ -407,6 +407,34 @@ class CredentialTestCase(CredentialBaseTestCase): body={'credential': update_ref}, expected_status=http.client.BAD_REQUEST) + def test_update_ec2_credential_change_access_id(self): + """Call ``PATCH /credentials/{credential_id}``.""" + blob, ref = unit.new_ec2_credential(user_id=self.user['id'], + project_id=self.project_id) + blob['access_id'] = uuid.uuid4().hex + ref['blob'] = json.dumps(blob) + r = self.post( + '/credentials', + body={'credential': ref}) + self.assertValidCredentialResponse(r, ref) + credential_id = r.result.get('credential')['id'] + # Try changing to a different access_id + blob['access_id'] = uuid.uuid4().hex + update_ref = {'blob': json.dumps(blob)} + self.patch( + '/credentials/%(credential_id)s' % { + 'credential_id': credential_id}, + body={'credential': update_ref}, + expected_status=http.client.BAD_REQUEST) + # Try removing the access_id + del blob['access_id'] + update_ref = {'blob': json.dumps(blob)} + self.patch( + '/credentials/%(credential_id)s' % { + 'credential_id': credential_id}, + body={'credential': update_ref}, + expected_status=http.client.BAD_REQUEST) + def test_delete_credential(self): """Call ``DELETE /credentials/{credential_id}``.""" self.delete( diff --git a/releasenotes/notes/bug-1872753-e2a934eac919ccde.yaml b/releasenotes/notes/bug-1872753-e2a934eac919ccde.yaml new file mode 100644 index 0000000000..5f8790537e --- /dev/null +++ b/releasenotes/notes/bug-1872753-e2a934eac919ccde.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - > + [`bug 1872753 `_] + Added validation to the EC2 credential API to prevent altering the ``access_id`` + field in the blob attribute. This prevents accidentally orphaning an EC2 credential + resource when an altered ``access_id`` no longer resolves to the credential's + resource ID.