Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions keystone/api/_shared/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,10 @@ def authenticate_for_token(auth=None):
'after authenticating with application credentials'
)
raise exception.Unauthorized(
_('Cannot reauthenticate with a token issued with '
'application credentials')
_(
'Cannot reauthenticate with a token issued with '
'application credentials'
)
)

# Do MFA Rule Validation for the user
Expand Down
3 changes: 2 additions & 1 deletion keystone/api/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ def get(self):
# requested; otherwise all domains are getting filtered out
try:
is_domain_requested = utils.attr_as_boolean(
flask.request.args['is_domain'])
flask.request.args['is_domain']
)
except KeyError:
is_domain_requested = False

Expand Down
2 changes: 1 addition & 1 deletion keystone/cmd/doctor/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ def symptom_unreasonable_max_token_size():
"""
# return 'fernet' in CONF.token.provider and CONF.max_token_size > 255
# CCloud: we are using ldap, hence the max_token_size needs to go up.
return ('fernet' in CONF.token.provider and CONF.max_token_size > 268)
return 'fernet' in CONF.token.provider and CONF.max_token_size > 268
11 changes: 7 additions & 4 deletions keystone/common/render_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,14 @@ def render_token_response_from_model(token, include_catalog=True):
# ccloud: additional bootstrap project support
bootstrap_name = CONF.resource.bootstrap_project_name
bootstrap_domain_name = CONF.resource.bootstrap_project_domain_name
if bootstrap_name and bootstrap_domain_name and \
not token_reference['token'].get('is_admin_project', False):
if (
bootstrap_name
and bootstrap_domain_name
and not token_reference['token'].get('is_admin_project', False)
):
is_ap = (
token.project['name'] == bootstrap_name and
bootstrap_domain_name == token.project_domain['name']
token.project['name'] == bootstrap_name
and bootstrap_domain_name == token.project_domain['name']
)
token_reference['token']['is_admin_project'] = is_ap
if include_catalog and not token.unscoped:
Expand Down
3 changes: 2 additions & 1 deletion keystone/conf/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@
order to set multiple default tags, for example:
default_tag=tag_0
default_tag=tag_1
"""))
"""),
)

notification_format = cfg.StrOpt(
'notification_format',
Expand Down
4 changes: 2 additions & 2 deletions keystone/conf/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
Name of the domain that owns the `bootstrap_project_name`. If left unset, then
there is no admin project. `[resource] bootstrap_project_name` must also be set
to use this option.
""")
"""),
)

bootstrap_project_name = cfg.StrOpt(
Expand All @@ -105,7 +105,7 @@
If left unset, then there is no admin project, and thus no explicit means of
cross-project role assignments. `[resource] bootstrap_project_domain_name` must
also be set to use this option.
""")
"""),
)

project_name_url_safe = cfg.StrOpt(
Expand Down
9 changes: 8 additions & 1 deletion keystone/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,14 @@ class _CatalogHelperObj(provider_api.ProviderAPIMixin):


def _send_audit_notification(
action, initiator, outcome, target, event_type, reason=None, attachments=None, **kwargs
action,
initiator,
outcome,
target,
event_type,
reason=None,
attachments=None,
**kwargs,
):
"""Send CADF notification to inform observers about the affected resource.

Expand Down
2 changes: 1 addition & 1 deletion keystone/oauth1/backends/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def authorize_request_token(self, request_token_id, user_id, role_ids):
token_dict['authorizing_user_id'] = user_id
token_dict['verifier'] = ''.join(
random.sample(base.VERIFIER_CHARS, 8)
) # nosec
) # nosec
token_dict['role_ids'] = jsonutils.dumps(role_ids)

new_token = RequestToken.from_dict(token_dict)
Expand Down
42 changes: 27 additions & 15 deletions keystone/server/flask/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,18 @@
# AuthContextMiddleware
_CC_MIDDLEWARE = (
# CCloud: add watcher middleware
_Middleware(namespace='watcher.middleware',
ep='watcher',
conf={'service_type': 'identity',
'config_file': '/etc/keystone/watcher.yaml',
'include_initiator_user_id_in_metric': 'true',
'include_target_project_id_in_metric': 'false'}),
_Middleware(
namespace='watcher.middleware',
ep='watcher',
conf={
'service_type': 'identity',
'config_file': '/etc/keystone/watcher.yaml',
'include_initiator_user_id_in_metric': 'true',
'include_target_project_id_in_metric': 'false',
},
),
# CCloud: add lifesaver middleware
_Middleware(namespace='lifesaver.middleware',
ep='lifesaver',
conf={}),
_Middleware(namespace='lifesaver.middleware', ep='lifesaver', conf={}),
# CCloud: add rate_limit middleware
# _Middleware(namespace='rate_limit.middleware',
# ep='rate-limit',
Expand Down Expand Up @@ -152,8 +154,9 @@ def setup_app_middleware(app):
if mw.ep == 'watcher' and os.environ.get('WATCHER_DISABLED', None):
continue

loaded = stevedore.DriverManager(mw.namespace, mw.ep,
invoke_on_load=False)
loaded = stevedore.DriverManager(
mw.namespace, mw.ep, invoke_on_load=False
)
factory_func = loaded.driver.factory({}, **mw.conf)
app.wsgi_app = factory_func(app.wsgi_app)

Expand Down Expand Up @@ -196,11 +199,20 @@ def setup_app_middleware(app):
'raven.processors.RemovePostDataProcessor',
)
sanitize_keys = [
'old_password', 'new_password', 'password', 'cred', 'secret',
'passwd', 'credentials']
'old_password',
'new_password',
'password',
'cred',
'secret',
'passwd',
'credentials',
]
app.config['SENTRY_CONFIG'] = {
'ignore_exceptions': [exception.NotFound, exception.Unauthorized,
'INVALID_CREDENTIALS'],
'ignore_exceptions': [
exception.NotFound,
exception.Unauthorized,
'INVALID_CREDENTIALS',
],
'processors': processors,
'sanitize_keys': sanitize_keys,
}
Expand Down
8 changes: 7 additions & 1 deletion keystone/tests/unit/common/test_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,13 @@ def _assert_last_note(
self.assertEqual(actor_operation, note['actor_operation'])

def _assert_last_audit(
self, resource_id, operation, resource_type, target_uri, reason=None, attachments=None
self,
resource_id,
operation,
resource_type,
target_uri,
reason=None,
attachments=None,
):
# NOTE(stevemar): If 'cadf' format is not used, then simply
# return since this assertion is not valid.
Expand Down
1 change: 1 addition & 0 deletions keystone/tests/unit/common/test_password_hashing.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def test_pbkdf2_sha512(self):
hashed = password_hashing.hash_password(password)
self.assertTrue(password_hashing.check_password(password, hashed))


class TestGeneratePartialPasswordHash(unit.BaseTestCase):
def setUp(self):
super().setUp()
Expand Down
54 changes: 31 additions & 23 deletions keystone/tests/unit/test_v3_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,12 +863,9 @@ def _create_project_and_tags(self, num_of_tags=1, with_default_tag=False):
tags.pop()
# add default tag instead
tags += _DEFAULT_TAG
ref = unit.new_project_ref(
domain_id=self.domain_id,
tags=tags)
ref = unit.new_project_ref(domain_id=self.domain_id, tags=tags)
else:
ref = unit.new_project_without_tags_ref(
domain_id=self.domain_id)
ref = unit.new_project_without_tags_ref(domain_id=self.domain_id)
resp = self.post('/projects', body={'project': ref})
return resp.result['project'], tags

Expand Down Expand Up @@ -1400,36 +1397,46 @@ def test_list_project_is_domain_filter(self):
def test_list_projects_is_domain_filter_domain_scoped_token(self):
"""Call ``GET /projects?is_domain=True/False`` with domain scope."""
# grant the domain role to user
path = '/domains/%s/users/%s/roles/%s' % (
self.domain_id, self.user['id'], self.role['id'])
path = '/domains/{}/users/{}/roles/{}'.format(
self.domain_id, self.user['id'], self.role['id']
)
self.put(path=path)

auth = self.build_authentication_request(
user_id=self.user['id'],
password=self.user['password'],
domain_id=self.domain_id)
domain_id=self.domain_id,
)

# Check that listing the domains does not result in an empty list
new_is_domain_project = unit.new_project_ref(is_domain=True)
new_is_domain_project = PROVIDERS.resource_api.create_project(
new_is_domain_project['id'], new_is_domain_project)
new_is_domain_project['id'], new_is_domain_project
)

r = self.get('/projects?is_domain=True', auth=auth,
expected_status=200)
self.assertIn(new_is_domain_project['id'],
[p['id'] for p in r.result['projects']])
r = self.get(
'/projects?is_domain=True', auth=auth, expected_status=200
)
self.assertIn(
new_is_domain_project['id'],
[p['id'] for p in r.result['projects']],
)

# Check that the projects are still being filtered
# The previously created is_domain project is a domain, so
# we can reuse it for the project
new_regular_project = unit.new_project_ref(
is_domain=False, domain_id=new_is_domain_project['id'])
is_domain=False, domain_id=new_is_domain_project['id']
)
new_regular_project = PROVIDERS.resource_api.create_project(
new_regular_project['id'], new_regular_project)
r = self.get('/projects?is_domain=False', auth=auth,
expected_status=200)
self.assertNotIn(new_regular_project['id'],
[p['id'] for p in r.result['projects']])
new_regular_project['id'], new_regular_project
)
r = self.get(
'/projects?is_domain=False', auth=auth, expected_status=200
)
self.assertNotIn(
new_regular_project['id'], [p['id'] for p in r.result['projects']]
)

def test_list_project_is_domain_filter_default(self):
"""Default project list should not see projects acting as domains."""
Expand Down Expand Up @@ -1814,11 +1821,12 @@ def test_create_project_with_tags(self):
self.config_fixture.config(default_tag=config_setting)
for tag_number in [0, 10]:
project, tags = self._create_project_and_tags(
num_of_tags=tag_number, with_default_tag=True)
num_of_tags=tag_number, with_default_tag=True
)
ref = self.get(
'/projects/%(project_id)s' % {
'project_id': project['id']},
expected_status=http.client.OK)
'/projects/{project_id}'.format(project_id=project['id']),
expected_status=http.client.OK,
)
self.assertIn('tags', ref.result['project'])
for tag in tags:
self.assertIn(tag, ref.result['project']['tags'])
Expand Down