Impose limits on application credentials
In order to protect against possible abuse or bloat, add a config option to set a limit on the number of application credentials a user may have. bp application-credentials Change-Id: Ieab33c3265fa0c0b1b1c6d586e5ea8a9a39edfb1
This commit is contained in:
parent
5e97f2d052
commit
d827e6e3ab
@ -91,6 +91,14 @@ class Manager(manager.Manager):
|
||||
actor_id=user_id,
|
||||
target_id=project_id)
|
||||
|
||||
def _assert_limit_not_exceeded(self, user_id):
|
||||
user_limit = CONF.application_credential.user_limit
|
||||
if user_limit >= 0:
|
||||
app_cred_count = len(self.list_application_credentials(user_id))
|
||||
if app_cred_count >= user_limit:
|
||||
raise exception.ApplicationCredentialLimitExceeded(
|
||||
limit=user_limit)
|
||||
|
||||
def _get_role_list(self, app_cred_roles):
|
||||
roles = []
|
||||
for role in app_cred_roles:
|
||||
@ -126,6 +134,8 @@ class Manager(manager.Manager):
|
||||
user_id = application_credential['user_id']
|
||||
project_id = application_credential['project_id']
|
||||
roles = application_credential.pop('roles', [])
|
||||
|
||||
self._assert_limit_not_exceeded(user_id)
|
||||
self._require_user_has_role_in_project(roles, user_id, project_id)
|
||||
unhashed_secret = application_credential['secret']
|
||||
ref = self.driver.create_application_credential(
|
||||
|
@ -40,12 +40,23 @@ Time to cache application credential data in seconds. This has no effect
|
||||
unless global caching is enabled.
|
||||
"""))
|
||||
|
||||
user_limit = cfg.IntOpt(
|
||||
'user_limit',
|
||||
default=-1,
|
||||
help=utils.fmt("""
|
||||
Maximum number of application credentials a user is permitted to create. A
|
||||
value of -1 means unlimited. If a limit is not set, users are permitted to
|
||||
create application credentials at will, which could lead to bloat in the
|
||||
keystone database or open keystone to a DoS attack.
|
||||
"""))
|
||||
|
||||
|
||||
GROUP_NAME = __name__.split('.')[-1]
|
||||
ALL_OPTS = [
|
||||
driver,
|
||||
caching,
|
||||
cache_time,
|
||||
user_limit,
|
||||
]
|
||||
|
||||
|
||||
|
@ -205,6 +205,11 @@ class RegionDeletionError(ForbiddenNotSecurity):
|
||||
"its child regions have associated endpoints.")
|
||||
|
||||
|
||||
class ApplicationCredentialLimitExceeded(ForbiddenNotSecurity):
|
||||
message_format = _("Unable to create additional application credentials, "
|
||||
"maximum of %(limit)d already exceeded for user.")
|
||||
|
||||
|
||||
class SecurityError(Error):
|
||||
"""Security error exception.
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from oslo_config import fixture as config_fixture
|
||||
|
||||
from keystone.common import driver_hints
|
||||
from keystone.common import provider_api
|
||||
import keystone.conf
|
||||
@ -92,6 +94,19 @@ class ApplicationCredentialTests(object):
|
||||
app_cred.pop('roles')
|
||||
self.assertDictEqual(app_cred, resp)
|
||||
|
||||
def test_application_credential_limits(self):
|
||||
config_fixture_ = self.user = self.useFixture(config_fixture.Config())
|
||||
config_fixture_.config(group='application_credential', user_limit=2)
|
||||
app_cred = self._new_app_cred_data(self.user_foo['id'],
|
||||
self.tenant_bar['id'])
|
||||
self.app_cred_api.create_application_credential(app_cred)
|
||||
app_cred['name'] = 'two'
|
||||
self.app_cred_api.create_application_credential(app_cred)
|
||||
app_cred['name'] = 'three'
|
||||
self.assertRaises(exception.ApplicationCredentialLimitExceeded,
|
||||
self.app_cred_api.create_application_credential,
|
||||
app_cred)
|
||||
|
||||
def test_get_application_credential(self):
|
||||
app_cred = self._new_app_cred_data(self.user_foo['id'],
|
||||
project_id=self.tenant_bar['id'])
|
||||
|
Loading…
Reference in New Issue
Block a user