Merge "New config option 'user_limit' in credentials"
This commit is contained in:
commit
e3bd1d747d
@ -69,6 +69,15 @@ The length of time in minutes for which a signed EC2 or S3 token request is
|
||||
valid from the timestamp contained in the token request.
|
||||
"""))
|
||||
|
||||
user_limit = cfg.IntOpt(
|
||||
'user_limit',
|
||||
default=-1,
|
||||
help=utils.fmt("""
|
||||
Maximum number of credentials a user is permitted to create. A value of
|
||||
-1 means unlimited. If a limit is not set, users are permitted to create
|
||||
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 = [
|
||||
@ -77,7 +86,8 @@ ALL_OPTS = [
|
||||
key_repository,
|
||||
caching,
|
||||
cache_time,
|
||||
auth_ttl
|
||||
auth_ttl,
|
||||
user_limit,
|
||||
]
|
||||
|
||||
|
||||
|
@ -86,6 +86,14 @@ class Manager(manager.Manager):
|
||||
credential_copy.pop('blob', None)
|
||||
return credential_copy
|
||||
|
||||
def _assert_limit_not_exceeded(self, user_id):
|
||||
user_limit = CONF.credential.user_limit
|
||||
if user_limit >= 0:
|
||||
cred_count = len(self.list_credentials_for_user(user_id))
|
||||
if cred_count >= user_limit:
|
||||
raise exception.CredentialLimitExceeded(
|
||||
limit=user_limit)
|
||||
|
||||
@manager.response_truncated
|
||||
def list_credentials(self, hints=None):
|
||||
credentials = self.driver.list_credentials(
|
||||
@ -119,6 +127,8 @@ class Manager(manager.Manager):
|
||||
initiator=None):
|
||||
"""Create a credential."""
|
||||
credential_copy = self._encrypt_credential(credential)
|
||||
user_id = credential_copy['user_id']
|
||||
self._assert_limit_not_exceeded(user_id)
|
||||
ref = self.driver.create_credential(credential_id, credential_copy)
|
||||
if MEMOIZE.should_cache(ref):
|
||||
self._get_credential.set(ref,
|
||||
|
@ -222,6 +222,11 @@ class ApplicationCredentialLimitExceeded(ForbiddenNotSecurity):
|
||||
"maximum of %(limit)d already exceeded for user.")
|
||||
|
||||
|
||||
class CredentialLimitExceeded(ForbiddenNotSecurity):
|
||||
message_format = _("Unable to create additional credentials, maximum "
|
||||
"of %(limit)d already exceeded for user.")
|
||||
|
||||
|
||||
class SecurityError(Error):
|
||||
"""Security error exception.
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
import uuid
|
||||
|
||||
from oslo_config import fixture as config_fixture
|
||||
|
||||
from keystone.common import provider_api
|
||||
from keystone.credential.providers import fernet as credential_provider
|
||||
from keystone.tests import unit
|
||||
@ -20,6 +22,7 @@ from keystone.tests.unit import ksfixtures
|
||||
from keystone.tests.unit.ksfixtures import database
|
||||
|
||||
from keystone.credential.backends import sql as credential_sql
|
||||
from keystone import exception
|
||||
|
||||
PROVIDERS = provider_api.ProviderAPIs
|
||||
|
||||
@ -102,3 +105,11 @@ class SqlCredential(SqlTests):
|
||||
# Make sure CredentialModel is handing over a text string
|
||||
# to the database. To avoid encoding issues
|
||||
self.assertIsInstance(ref.encrypted_blob, str)
|
||||
|
||||
def test_credential_limits(self):
|
||||
config_fixture_ = self.user = self.useFixture(config_fixture.Config())
|
||||
config_fixture_.config(group='credential', user_limit=4)
|
||||
self._create_credential_with_user_id(self.user_foo['id'])
|
||||
self.assertRaises(exception.CredentialLimitExceeded,
|
||||
self._create_credential_with_user_id,
|
||||
self.user_foo['id'])
|
||||
|
6
releasenotes/notes/bug-1872732-7261816d0b170008.yaml
Normal file
6
releasenotes/notes/bug-1872732-7261816d0b170008.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- >
|
||||
[`bug 1872732 <https://bugs.launchpad.net/keystone/+bug/1872732>`_]
|
||||
'user_limit' is added to config file of credentials that allows user to set
|
||||
maximum number of credentials a user is permitted to create.
|
Loading…
Reference in New Issue
Block a user