Ruff the code
Switch from black to ruff similarly to keystoneauth. Change-Id: Ieee72e8598ae182d9f6cc40d7f4c20e955a69b2d
This commit is contained in:
parent
f7ffacb7ad
commit
ae7b3a0534
@ -22,16 +22,12 @@ repos:
|
|||||||
# rev: v1.1.1
|
# rev: v1.1.1
|
||||||
# hooks:
|
# hooks:
|
||||||
# - id: doc8
|
# - id: doc8
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v3.15.2
|
rev: v0.6.9
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: ruff
|
||||||
args: ['--py38-plus']
|
args: ['--fix', '--unsafe-fixes']
|
||||||
- repo: https://github.com/psf/black
|
- id: ruff-format
|
||||||
rev: 24.4.0
|
|
||||||
hooks:
|
|
||||||
- id: black
|
|
||||||
args: ['-S', '-l', '79']
|
|
||||||
- repo: https://github.com/PyCQA/bandit
|
- repo: https://github.com/PyCQA/bandit
|
||||||
rev: '1.7.9'
|
rev: '1.7.9'
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -23,15 +23,9 @@
|
|||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
html_theme = 'openstackdocs'
|
html_theme = 'openstackdocs'
|
||||||
html_theme_options = {
|
html_theme_options = {"sidebar_dropdown": "api_ref", "sidebar_mode": "toc"}
|
||||||
"sidebar_dropdown": "api_ref",
|
|
||||||
"sidebar_mode": "toc",
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions = [
|
extensions = ['os_api_ref', 'openstackdocstheme']
|
||||||
'os_api_ref',
|
|
||||||
'openstackdocstheme',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
@ -29,7 +29,7 @@ class KeycloakClient:
|
|||||||
}
|
}
|
||||||
r = requests.post(self.token_endpoint(realm), data=params).json()
|
r = requests.post(self.token_endpoint(realm), data=params).json()
|
||||||
headers = {
|
headers = {
|
||||||
'Authorization': ("Bearer %s" % r['access_token']),
|
'Authorization': f"Bearer {r['access_token']}",
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
self.session.headers.update(headers)
|
self.session.headers.update(headers)
|
||||||
|
@ -285,7 +285,7 @@ texinfo_documents = [
|
|||||||
'keystone',
|
'keystone',
|
||||||
'One line description of project.',
|
'One line description of project.',
|
||||||
'Miscellaneous',
|
'Miscellaneous',
|
||||||
),
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Documents to append as an appendix to all manuals.
|
# Documents to append as an appendix to all manuals.
|
||||||
|
@ -110,15 +110,15 @@ class ResourceBase(ks_flask.ResourceBase):
|
|||||||
loaded = cred['blob']
|
loaded = cred['blob']
|
||||||
|
|
||||||
# Convert to the legacy format
|
# Convert to the legacy format
|
||||||
cred_data = dict(
|
cred_data = {
|
||||||
user_id=cred.get('user_id'),
|
'user_id': cred.get('user_id'),
|
||||||
project_id=cred.get('project_id'),
|
'project_id': cred.get('project_id'),
|
||||||
access=loaded.get('access'),
|
'access': loaded.get('access'),
|
||||||
secret=loaded.get('secret'),
|
'secret': loaded.get('secret'),
|
||||||
trust_id=loaded.get('trust_id'),
|
'trust_id': loaded.get('trust_id'),
|
||||||
app_cred_id=loaded.get('app_cred_id'),
|
'app_cred_id': loaded.get('app_cred_id'),
|
||||||
access_token_id=loaded.get('access_token_id'),
|
'access_token_id': loaded.get('access_token_id'),
|
||||||
)
|
}
|
||||||
|
|
||||||
# validate the signature
|
# validate the signature
|
||||||
self._check_signature(cred_data, credentials)
|
self._check_signature(cred_data, credentials)
|
||||||
|
@ -24,7 +24,7 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
def build_prior_role_response_data(prior_role_id, prior_role_name):
|
def build_prior_role_response_data(prior_role_id, prior_role_name):
|
||||||
return {
|
return {
|
||||||
'id': prior_role_id,
|
'id': prior_role_id,
|
||||||
'links': {'self': ks_flask.base_url(path='/roles/%s' % prior_role_id)},
|
'links': {'self': ks_flask.base_url(path=f'/roles/{prior_role_id}')},
|
||||||
'name': prior_role_name,
|
'name': prior_role_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,9 @@ def build_implied_role_response_data(implied_role):
|
|||||||
return {
|
return {
|
||||||
'id': implied_role['id'],
|
'id': implied_role['id'],
|
||||||
'links': {
|
'links': {
|
||||||
'self': ks_flask.base_url(path='/roles/%s' % implied_role['id'])
|
'self': ks_flask.base_url(
|
||||||
|
path='/roles/{}'.format(implied_role['id'])
|
||||||
|
)
|
||||||
},
|
},
|
||||||
'name': implied_role['name'],
|
'name': implied_role['name'],
|
||||||
}
|
}
|
||||||
|
@ -466,15 +466,15 @@ class AuthAPI(ks_flask.APIBase):
|
|||||||
resource=AuthProjectsResource,
|
resource=AuthProjectsResource,
|
||||||
url='/auth/projects',
|
url='/auth/projects',
|
||||||
alternate_urls=[
|
alternate_urls=[
|
||||||
dict(
|
{
|
||||||
url='/OS-FEDERATION/projects',
|
'url': '/OS-FEDERATION/projects',
|
||||||
json_home=ks_flask.construct_json_home_data(
|
'json_home': ks_flask.construct_json_home_data(
|
||||||
rel='projects',
|
rel='projects',
|
||||||
resource_relation_func=(
|
resource_relation_func=(
|
||||||
json_home_relations.os_federation_resource_rel_func
|
json_home_relations.os_federation_resource_rel_func
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
}
|
||||||
],
|
],
|
||||||
rel='auth_projects',
|
rel='auth_projects',
|
||||||
resource_kwargs={},
|
resource_kwargs={},
|
||||||
@ -483,15 +483,15 @@ class AuthAPI(ks_flask.APIBase):
|
|||||||
resource=AuthDomainsResource,
|
resource=AuthDomainsResource,
|
||||||
url='/auth/domains',
|
url='/auth/domains',
|
||||||
alternate_urls=[
|
alternate_urls=[
|
||||||
dict(
|
{
|
||||||
url='/OS-FEDERATION/domains',
|
'url': '/OS-FEDERATION/domains',
|
||||||
json_home=ks_flask.construct_json_home_data(
|
'json_home': ks_flask.construct_json_home_data(
|
||||||
rel='domains',
|
rel='domains',
|
||||||
resource_relation_func=(
|
resource_relation_func=(
|
||||||
json_home_relations.os_federation_resource_rel_func
|
json_home_relations.os_federation_resource_rel_func
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
}
|
||||||
],
|
],
|
||||||
rel='auth_domains',
|
rel='auth_domains',
|
||||||
resource_kwargs={},
|
resource_kwargs={},
|
||||||
@ -590,7 +590,4 @@ class AuthFederationAPI(ks_flask.APIBase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
APIs = (
|
APIs = (AuthAPI, AuthFederationAPI)
|
||||||
AuthAPI,
|
|
||||||
AuthFederationAPI,
|
|
||||||
)
|
|
||||||
|
@ -286,7 +286,6 @@ class CredentialResource(ks_flask.ResourceBase):
|
|||||||
|
|
||||||
|
|
||||||
class CredentialAPI(ks_flask.APIBase):
|
class CredentialAPI(ks_flask.APIBase):
|
||||||
|
|
||||||
_name = 'credentials'
|
_name = 'credentials'
|
||||||
_import_name = __name__
|
_import_name = __name__
|
||||||
resource_mapping = [
|
resource_mapping = [
|
||||||
|
@ -31,12 +31,7 @@ def _get_versions_list(identity_url):
|
|||||||
'id': 'v3.14',
|
'id': 'v3.14',
|
||||||
'status': 'stable',
|
'status': 'stable',
|
||||||
'updated': '2020-04-07T00:00:00Z',
|
'updated': '2020-04-07T00:00:00Z',
|
||||||
'links': [
|
'links': [{'rel': 'self', 'href': identity_url}],
|
||||||
{
|
|
||||||
'rel': 'self',
|
|
||||||
'href': identity_url,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'media-types': [
|
'media-types': [
|
||||||
{'base': 'application/json', 'type': MEDIA_TYPE_JSON % 'v3'}
|
{'base': 'application/json', 'type': MEDIA_TYPE_JSON % 'v3'}
|
||||||
],
|
],
|
||||||
@ -70,7 +65,7 @@ def get_versions():
|
|||||||
mimetype=MimeTypes.JSON_HOME,
|
mimetype=MimeTypes.JSON_HOME,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
identity_url = '%s/' % ks_flask.base_url()
|
identity_url = f'{ks_flask.base_url()}/'
|
||||||
versions = _get_versions_list(identity_url)
|
versions = _get_versions_list(identity_url)
|
||||||
# Set the preferred version to the latest "stable" version.
|
# Set the preferred version to the latest "stable" version.
|
||||||
# TODO(morgan): If we ever have more API versions find the latest
|
# TODO(morgan): If we ever have more API versions find the latest
|
||||||
@ -99,7 +94,7 @@ def get_version_v3():
|
|||||||
response=jsonutils.dumps(content), mimetype=MimeTypes.JSON_HOME
|
response=jsonutils.dumps(content), mimetype=MimeTypes.JSON_HOME
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
identity_url = '%s/' % ks_flask.base_url()
|
identity_url = f'{ks_flask.base_url()}/'
|
||||||
versions = _get_versions_list(identity_url)
|
versions = _get_versions_list(identity_url)
|
||||||
return flask.Response(
|
return flask.Response(
|
||||||
response=jsonutils.dumps({'version': versions['v3']}),
|
response=jsonutils.dumps({'version': versions['v3']}),
|
||||||
|
@ -67,7 +67,7 @@ class EndpointResource(ks_flask.ResourceBase):
|
|||||||
try:
|
try:
|
||||||
PROVIDERS.catalog_api.get_region(endpoint['region_id'])
|
PROVIDERS.catalog_api.get_region(endpoint['region_id'])
|
||||||
except exception.RegionNotFound:
|
except exception.RegionNotFound:
|
||||||
region = dict(id=endpoint['region_id'])
|
region = {'id': endpoint['region_id']}
|
||||||
PROVIDERS.catalog_api.create_region(
|
PROVIDERS.catalog_api.create_region(
|
||||||
region, initiator=notifications.build_audit_initiator()
|
region, initiator=notifications.build_audit_initiator()
|
||||||
)
|
)
|
||||||
|
@ -235,12 +235,11 @@ class EPFilterGroupsProjectsResource(ks_flask.ResourceBase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _add_self_referential_link(cls, ref, collection_name=None):
|
def _add_self_referential_link(cls, ref, collection_name=None):
|
||||||
url = (
|
url = (
|
||||||
'/OS-EP-FILTER/endpoint_groups/%(endpoint_group_id)s'
|
'/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}'
|
||||||
'/projects/%(project_id)s'
|
'/projects/{project_id}'.format(
|
||||||
% {
|
endpoint_group_id=ref['endpoint_group_id'],
|
||||||
'endpoint_group_id': ref['endpoint_group_id'],
|
project_id=ref['project_id'],
|
||||||
'project_id': ref['project_id'],
|
)
|
||||||
}
|
|
||||||
)
|
)
|
||||||
ref.setdefault('links', {})
|
ref.setdefault('links', {})
|
||||||
ref['links']['self'] = url
|
ref['links']['self'] = url
|
||||||
|
@ -99,7 +99,9 @@ class IdentityProvidersResource(_ResourceBase):
|
|||||||
"""
|
"""
|
||||||
base_path = ref['links'].get('self')
|
base_path = ref['links'].get('self')
|
||||||
if base_path is None:
|
if base_path is None:
|
||||||
base_path = '/'.join(ks_flask.base_url(path='/%s' % ref['id']))
|
base_path = '/'.join(
|
||||||
|
ks_flask.base_url(path='/{}'.format(ref['id']))
|
||||||
|
)
|
||||||
|
|
||||||
for name in ['protocols']:
|
for name in ['protocols']:
|
||||||
ref['links'][name] = '/'.join([base_path, name])
|
ref['links'][name] = '/'.join([base_path, name])
|
||||||
@ -188,7 +190,6 @@ class _IdentityProvidersProtocolsResourceBase(_ResourceBase):
|
|||||||
|
|
||||||
|
|
||||||
class IDPProtocolsListResource(_IdentityProvidersProtocolsResourceBase):
|
class IDPProtocolsListResource(_IdentityProvidersProtocolsResourceBase):
|
||||||
|
|
||||||
def get(self, idp_id):
|
def get(self, idp_id):
|
||||||
"""List protocols for an IDP.
|
"""List protocols for an IDP.
|
||||||
|
|
||||||
@ -205,7 +206,6 @@ class IDPProtocolsListResource(_IdentityProvidersProtocolsResourceBase):
|
|||||||
|
|
||||||
|
|
||||||
class IDPProtocolsCRUDResource(_IdentityProvidersProtocolsResourceBase):
|
class IDPProtocolsCRUDResource(_IdentityProvidersProtocolsResourceBase):
|
||||||
|
|
||||||
def get(self, idp_id, protocol_id):
|
def get(self, idp_id, protocol_id):
|
||||||
"""Get protocols for an IDP.
|
"""Get protocols for an IDP.
|
||||||
|
|
||||||
@ -448,7 +448,6 @@ class SAML2MetadataResource(flask_restful.Resource):
|
|||||||
|
|
||||||
|
|
||||||
class OSFederationAuthResource(flask_restful.Resource):
|
class OSFederationAuthResource(flask_restful.Resource):
|
||||||
|
|
||||||
@ks_flask.unenforced_api
|
@ks_flask.unenforced_api
|
||||||
def get(self, idp_id, protocol_id):
|
def get(self, idp_id, protocol_id):
|
||||||
"""Authenticate from dedicated uri endpoint.
|
"""Authenticate from dedicated uri endpoint.
|
||||||
|
@ -117,10 +117,10 @@ class ConsumerResource(ks_flask.ResourceBase):
|
|||||||
def delete(self, consumer_id):
|
def delete(self, consumer_id):
|
||||||
ENFORCER.enforce_call(action='identity:delete_consumer')
|
ENFORCER.enforce_call(action='identity:delete_consumer')
|
||||||
reason = (
|
reason = (
|
||||||
'Invalidating token cache because consumer %(consumer_id)s has '
|
f'Invalidating token cache because consumer {consumer_id} has '
|
||||||
'been deleted. Authorization for users with OAuth tokens will be '
|
'been deleted. Authorization for users with OAuth tokens will be '
|
||||||
'recalculated and enforced accordingly the next time they '
|
'recalculated and enforced accordingly the next time they '
|
||||||
'authenticate or validate a token.' % {'consumer_id': consumer_id}
|
'authenticate or validate a token.'
|
||||||
)
|
)
|
||||||
notifications.invalidate_token_cache_notification(reason)
|
notifications.invalidate_token_cache_notification(reason)
|
||||||
PROVIDERS.oauth_api.delete_consumer(
|
PROVIDERS.oauth_api.delete_consumer(
|
||||||
@ -191,12 +191,11 @@ class RequestTokenResource(_OAuth1ResourceBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
result = 'oauth_token={key}&oauth_token_secret={secret}'.format(
|
result = 'oauth_token={key}&oauth_token_secret={secret}'.format(
|
||||||
key=token_ref['id'],
|
key=token_ref['id'], secret=token_ref['request_secret']
|
||||||
secret=token_ref['request_secret'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF.oauth1.request_token_duration > 0:
|
if CONF.oauth1.request_token_duration > 0:
|
||||||
expiry_bit = '&oauth_expires_at=%s' % token_ref['expires_at']
|
expiry_bit = '&oauth_expires_at={}'.format(token_ref['expires_at'])
|
||||||
result += expiry_bit
|
result += expiry_bit
|
||||||
|
|
||||||
resp = flask.make_response(result, http.client.CREATED)
|
resp = flask.make_response(result, http.client.CREATED)
|
||||||
@ -294,12 +293,11 @@ class AccessTokenResource(_OAuth1ResourceBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
result = 'oauth_token={key}&oauth_token_secret={secret}'.format(
|
result = 'oauth_token={key}&oauth_token_secret={secret}'.format(
|
||||||
key=token_ref['id'],
|
key=token_ref['id'], secret=token_ref['access_secret']
|
||||||
secret=token_ref['access_secret'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF.oauth1.access_token_duration > 0:
|
if CONF.oauth1.access_token_duration > 0:
|
||||||
expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at'])
|
expiry_bit = '&oauth_expires_at={}'.format(token_ref['expires_at'])
|
||||||
result += expiry_bit
|
result += expiry_bit
|
||||||
|
|
||||||
resp = flask.make_response(result, http.client.CREATED)
|
resp = flask.make_response(result, http.client.CREATED)
|
||||||
|
@ -37,7 +37,6 @@ _build_resource_relation = json_home_relations.os_oauth2_resource_rel_func
|
|||||||
|
|
||||||
|
|
||||||
class AccessTokenResource(ks_flask.ResourceBase):
|
class AccessTokenResource(ks_flask.ResourceBase):
|
||||||
|
|
||||||
def _method_not_allowed(self):
|
def _method_not_allowed(self):
|
||||||
"""Raise a method not allowed error."""
|
"""Raise a method not allowed error."""
|
||||||
raise exception.OAuth2OtherError(
|
raise exception.OAuth2OtherError(
|
||||||
@ -361,11 +360,11 @@ class AccessTokenResource(ks_flask.ResourceBase):
|
|||||||
raise error
|
raise error
|
||||||
client_cert_dn = {}
|
client_cert_dn = {}
|
||||||
for key in cert_subject_dn:
|
for key in cert_subject_dn:
|
||||||
client_cert_dn['SSL_CLIENT_SUBJECT_DN_%s' % key.upper()] = (
|
client_cert_dn[f'SSL_CLIENT_SUBJECT_DN_{key.upper()}'] = (
|
||||||
cert_subject_dn.get(key)
|
cert_subject_dn.get(key)
|
||||||
)
|
)
|
||||||
for key in cert_issuer_dn:
|
for key in cert_issuer_dn:
|
||||||
client_cert_dn['SSL_CLIENT_ISSUER_DN_%s' % key.upper()] = (
|
client_cert_dn[f'SSL_CLIENT_ISSUER_DN_{key.upper()}'] = (
|
||||||
cert_issuer_dn.get(key)
|
cert_issuer_dn.get(key)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,7 +102,6 @@ class PolicyResource(ks_flask.ResourceBase):
|
|||||||
|
|
||||||
|
|
||||||
class EndpointPolicyResource(flask_restful.Resource):
|
class EndpointPolicyResource(flask_restful.Resource):
|
||||||
|
|
||||||
def get(self, policy_id):
|
def get(self, policy_id):
|
||||||
ENFORCER.enforce_call(action='identity:list_endpoints_for_policy')
|
ENFORCER.enforce_call(action='identity:list_endpoints_for_policy')
|
||||||
PROVIDERS.policy_api.get_policy(policy_id)
|
PROVIDERS.policy_api.get_policy(policy_id)
|
||||||
@ -120,7 +119,6 @@ class EndpointPolicyResource(flask_restful.Resource):
|
|||||||
|
|
||||||
|
|
||||||
class EndpointPolicyAssociations(flask_restful.Resource):
|
class EndpointPolicyAssociations(flask_restful.Resource):
|
||||||
|
|
||||||
def get(self, policy_id, endpoint_id):
|
def get(self, policy_id, endpoint_id):
|
||||||
action = 'identity:check_policy_association_for_endpoint'
|
action = 'identity:check_policy_association_for_endpoint'
|
||||||
ENFORCER.enforce_call(action=action)
|
ENFORCER.enforce_call(action=action)
|
||||||
@ -153,7 +151,6 @@ class EndpointPolicyAssociations(flask_restful.Resource):
|
|||||||
|
|
||||||
|
|
||||||
class ServicePolicyAssociations(flask_restful.Resource):
|
class ServicePolicyAssociations(flask_restful.Resource):
|
||||||
|
|
||||||
def get(self, policy_id, service_id):
|
def get(self, policy_id, service_id):
|
||||||
action = 'identity:check_policy_association_for_service'
|
action = 'identity:check_policy_association_for_service'
|
||||||
ENFORCER.enforce_call(action=action)
|
ENFORCER.enforce_call(action=action)
|
||||||
@ -186,7 +183,6 @@ class ServicePolicyAssociations(flask_restful.Resource):
|
|||||||
|
|
||||||
|
|
||||||
class ServiceRegionPolicyAssociations(flask_restful.Resource):
|
class ServiceRegionPolicyAssociations(flask_restful.Resource):
|
||||||
|
|
||||||
def get(self, policy_id, service_id, region_id):
|
def get(self, policy_id, service_id, region_id):
|
||||||
action = 'identity:check_policy_association_for_region_and_service'
|
action = 'identity:check_policy_association_for_region_and_service'
|
||||||
ENFORCER.enforce_call(action=action)
|
ENFORCER.enforce_call(action=action)
|
||||||
|
@ -315,16 +315,16 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
|
|||||||
|
|
||||||
if 'domain_id' in entity.get('indirect', {}):
|
if 'domain_id' in entity.get('indirect', {}):
|
||||||
inherited_assignment = True
|
inherited_assignment = True
|
||||||
formatted_link = (
|
formatted_link = '/domains/{}'.format(
|
||||||
'/domains/%s' % entity['indirect']['domain_id']
|
entity['indirect']['domain_id']
|
||||||
)
|
)
|
||||||
elif 'project_id' in entity.get('indirect', {}):
|
elif 'project_id' in entity.get('indirect', {}):
|
||||||
inherited_assignment = True
|
inherited_assignment = True
|
||||||
formatted_link = (
|
formatted_link = '/projects/{}'.format(
|
||||||
'/projects/%s' % entity['indirect']['project_id']
|
entity['indirect']['project_id']
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
formatted_link = '/projects/%s' % entity['project_id']
|
formatted_link = '/projects/{}'.format(entity['project_id'])
|
||||||
elif 'domain_id' in entity:
|
elif 'domain_id' in entity:
|
||||||
if 'domain_name' in entity:
|
if 'domain_name' in entity:
|
||||||
formatted_entity['scope'] = {
|
formatted_entity['scope'] = {
|
||||||
@ -337,7 +337,7 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
|
|||||||
formatted_entity['scope'] = {
|
formatted_entity['scope'] = {
|
||||||
'domain': {'id': entity['domain_id']}
|
'domain': {'id': entity['domain_id']}
|
||||||
}
|
}
|
||||||
formatted_link = '/domains/%s' % entity['domain_id']
|
formatted_link = '/domains/{}'.format(entity['domain_id'])
|
||||||
elif 'system' in entity:
|
elif 'system' in entity:
|
||||||
formatted_link = '/system'
|
formatted_link = '/system'
|
||||||
formatted_entity['scope'] = {'system': entity['system']}
|
formatted_entity['scope'] = {'system': entity['system']}
|
||||||
@ -356,13 +356,16 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
|
|||||||
formatted_entity['user'] = {'id': entity['user_id']}
|
formatted_entity['user'] = {'id': entity['user_id']}
|
||||||
if 'group_id' in entity.get('indirect', {}):
|
if 'group_id' in entity.get('indirect', {}):
|
||||||
membership_url = ks_flask.base_url(
|
membership_url = ks_flask.base_url(
|
||||||
path='/groups/%s/users/%s'
|
path='/groups/{}/users/{}'.format(
|
||||||
% (entity['indirect']['group_id'], entity['user_id'])
|
entity['indirect']['group_id'], entity['user_id']
|
||||||
|
)
|
||||||
)
|
)
|
||||||
formatted_entity['links']['membership'] = membership_url
|
formatted_entity['links']['membership'] = membership_url
|
||||||
formatted_link += '/groups/%s' % entity['indirect']['group_id']
|
formatted_link += '/groups/{}'.format(
|
||||||
|
entity['indirect']['group_id']
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
formatted_link += '/users/%s' % entity['user_id']
|
formatted_link += '/users/{}'.format(entity['user_id'])
|
||||||
elif 'group_id' in entity:
|
elif 'group_id' in entity:
|
||||||
if 'group_name' in entity:
|
if 'group_name' in entity:
|
||||||
formatted_entity['group'] = {
|
formatted_entity['group'] = {
|
||||||
@ -375,7 +378,7 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
formatted_entity['group'] = {'id': entity['group_id']}
|
formatted_entity['group'] = {'id': entity['group_id']}
|
||||||
formatted_link += '/groups/%s' % entity['group_id']
|
formatted_link += '/groups/{}'.format(entity['group_id'])
|
||||||
|
|
||||||
if 'role_name' in entity:
|
if 'role_name' in entity:
|
||||||
formatted_entity['role'] = {
|
formatted_entity['role'] = {
|
||||||
@ -395,18 +398,17 @@ class RoleAssignmentsResource(ks_flask.ResourceBase):
|
|||||||
formatted_entity['role'] = {'id': entity['role_id']}
|
formatted_entity['role'] = {'id': entity['role_id']}
|
||||||
prior_role_link = ''
|
prior_role_link = ''
|
||||||
if 'role_id' in entity.get('indirect', {}):
|
if 'role_id' in entity.get('indirect', {}):
|
||||||
formatted_link += '/roles/%s' % entity['indirect']['role_id']
|
formatted_link += '/roles/{}'.format(entity['indirect']['role_id'])
|
||||||
prior_role_link = '/prior_role/{prior}/implies/{implied}'.format(
|
prior_role_link = '/prior_role/{prior}/implies/{implied}'.format(
|
||||||
prior=entity['role_id'],
|
prior=entity['role_id'], implied=entity['indirect']['role_id']
|
||||||
implied=entity['indirect']['role_id'],
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
formatted_link += '/roles/%s' % entity['role_id']
|
formatted_link += '/roles/{}'.format(entity['role_id'])
|
||||||
|
|
||||||
if inherited_assignment:
|
if inherited_assignment:
|
||||||
formatted_entity['scope']['OS-INHERIT:inherited_to'] = 'projects'
|
formatted_entity['scope']['OS-INHERIT:inherited_to'] = 'projects'
|
||||||
formatted_link = (
|
formatted_link = (
|
||||||
'/OS-INHERIT%s/inherited_to_projects' % formatted_link
|
f'/OS-INHERIT{formatted_link}/inherited_to_projects'
|
||||||
)
|
)
|
||||||
|
|
||||||
formatted_entity['links']['assignment'] = ks_flask.base_url(
|
formatted_entity['links']['assignment'] = ks_flask.base_url(
|
||||||
|
@ -36,7 +36,7 @@ class RoleInferencesResource(flask_restful.Resource):
|
|||||||
for role_ref in PROVIDERS.role_api.list_roles()
|
for role_ref in PROVIDERS.role_api.list_roles()
|
||||||
}
|
}
|
||||||
|
|
||||||
rules = dict()
|
rules = {}
|
||||||
for ref in refs:
|
for ref in refs:
|
||||||
implied_role_id = ref['implied_role_id']
|
implied_role_id = ref['implied_role_id']
|
||||||
prior_role_id = ref['prior_role_id']
|
prior_role_id = ref['prior_role_id']
|
||||||
@ -49,10 +49,7 @@ class RoleInferencesResource(flask_restful.Resource):
|
|||||||
rules[prior_role_id] = implied
|
rules[prior_role_id] = implied
|
||||||
|
|
||||||
inferences = []
|
inferences = []
|
||||||
for (
|
for prior_id, implied in rules.items():
|
||||||
prior_id,
|
|
||||||
implied,
|
|
||||||
) in rules.items():
|
|
||||||
prior_response = shared.build_prior_role_response_data(
|
prior_response = shared.build_prior_role_response_data(
|
||||||
prior_id, role_dict[prior_id]['name']
|
prior_id, role_dict[prior_id]['name']
|
||||||
)
|
)
|
||||||
|
@ -220,13 +220,12 @@ class RoleImplicationListResource(flask_restful.Resource):
|
|||||||
shared.build_implied_role_response_data(implied_role)
|
shared.build_implied_role_response_data(implied_role)
|
||||||
)
|
)
|
||||||
response_json['links'] = {
|
response_json['links'] = {
|
||||||
'self': ks_flask.base_url(path='/roles/%s/implies' % prior_role_id)
|
'self': ks_flask.base_url(path=f'/roles/{prior_role_id}/implies')
|
||||||
}
|
}
|
||||||
return response_json
|
return response_json
|
||||||
|
|
||||||
|
|
||||||
class RoleImplicationResource(flask_restful.Resource):
|
class RoleImplicationResource(flask_restful.Resource):
|
||||||
|
|
||||||
def head(self, prior_role_id, implied_role_id=None):
|
def head(self, prior_role_id, implied_role_id=None):
|
||||||
# TODO(morgan): deprecate "check_implied_role" policy, as a user must
|
# TODO(morgan): deprecate "check_implied_role" policy, as a user must
|
||||||
# have both check_implied_role and get_implied_role to use the head
|
# have both check_implied_role and get_implied_role to use the head
|
||||||
@ -266,8 +265,7 @@ class RoleImplicationResource(flask_restful.Resource):
|
|||||||
)
|
)
|
||||||
response_json['links'] = {
|
response_json['links'] = {
|
||||||
'self': ks_flask.base_url(
|
'self': ks_flask.base_url(
|
||||||
path='/roles/%(prior)s/implies/%(implies)s'
|
path=f'/roles/{prior_role_id}/implies/{implied_role_id}'
|
||||||
% {'prior': prior_role_id, 'implies': implied_role_id}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return response_json
|
return response_json
|
||||||
|
@ -94,7 +94,7 @@ def _normalize_trust_roles(trust):
|
|||||||
|
|
||||||
trust['roles'] = trust_full_roles
|
trust['roles'] = trust_full_roles
|
||||||
trust['roles_links'] = {
|
trust['roles_links'] = {
|
||||||
'self': ks_flask.base_url(path='/%s/roles' % trust['id']),
|
'self': ks_flask.base_url(path='/{}/roles'.format(trust['id'])),
|
||||||
'next': None,
|
'next': None,
|
||||||
'previous': None,
|
'previous': None,
|
||||||
}
|
}
|
||||||
@ -374,7 +374,6 @@ class TrustResource(ks_flask.ResourceBase):
|
|||||||
# URL additions and does not have a collection key/member_key, we use
|
# URL additions and does not have a collection key/member_key, we use
|
||||||
# the flask-restful Resource, not the keystone ResourceBase
|
# the flask-restful Resource, not the keystone ResourceBase
|
||||||
class RolesForTrustListResource(flask_restful.Resource):
|
class RolesForTrustListResource(flask_restful.Resource):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def oslo_context(self):
|
def oslo_context(self):
|
||||||
return flask.request.environ.get(context.REQUEST_CONTEXT_ENV, None)
|
return flask.request.environ.get(context.REQUEST_CONTEXT_ENV, None)
|
||||||
@ -429,7 +428,6 @@ class RolesForTrustListResource(flask_restful.Resource):
|
|||||||
# URL additions and does not have a collection key/member_key, we use
|
# URL additions and does not have a collection key/member_key, we use
|
||||||
# the flask-restful Resource, not the keystone ResourceBase
|
# the flask-restful Resource, not the keystone ResourceBase
|
||||||
class RoleForTrustResource(flask_restful.Resource):
|
class RoleForTrustResource(flask_restful.Resource):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def oslo_context(self):
|
def oslo_context(self):
|
||||||
return flask.request.environ.get(context.REQUEST_CONTEXT_ENV, None)
|
return flask.request.environ.get(context.REQUEST_CONTEXT_ENV, None)
|
||||||
|
@ -66,7 +66,6 @@ def _convert_v3_to_ec2_credential(credential):
|
|||||||
|
|
||||||
|
|
||||||
def _format_token_entity(entity):
|
def _format_token_entity(entity):
|
||||||
|
|
||||||
formatted_entity = entity.copy()
|
formatted_entity = entity.copy()
|
||||||
access_token_id = formatted_entity['id']
|
access_token_id = formatted_entity['id']
|
||||||
user_id = formatted_entity.get('authorizing_user_id', '')
|
user_id = formatted_entity.get('authorizing_user_id', '')
|
||||||
@ -76,8 +75,7 @@ def _format_token_entity(entity):
|
|||||||
formatted_entity.pop('access_secret')
|
formatted_entity.pop('access_secret')
|
||||||
|
|
||||||
url = (
|
url = (
|
||||||
'/users/%(user_id)s/OS-OAUTH1/access_tokens/%(access_token_id)s'
|
f'/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}' '/roles'
|
||||||
'/roles' % {'user_id': user_id, 'access_token_id': access_token_id}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
formatted_entity.setdefault('links', {})
|
formatted_entity.setdefault('links', {})
|
||||||
@ -418,19 +416,19 @@ class UserOSEC2CredentialsResourceListCreate(_UserOSEC2CredBaseResource):
|
|||||||
PROVIDERS.identity_api.get_user(user_id)
|
PROVIDERS.identity_api.get_user(user_id)
|
||||||
tenant_id = self.request_body_json.get('tenant_id')
|
tenant_id = self.request_body_json.get('tenant_id')
|
||||||
PROVIDERS.resource_api.get_project(tenant_id)
|
PROVIDERS.resource_api.get_project(tenant_id)
|
||||||
blob = dict(
|
blob = {
|
||||||
access=uuid.uuid4().hex,
|
'access': uuid.uuid4().hex,
|
||||||
secret=uuid.uuid4().hex,
|
'secret': uuid.uuid4().hex,
|
||||||
trust_id=self.oslo_context.trust_id,
|
'trust_id': self.oslo_context.trust_id,
|
||||||
)
|
}
|
||||||
credential_id = utils.hash_access_key(blob['access'])
|
credential_id = utils.hash_access_key(blob['access'])
|
||||||
cred_data = dict(
|
cred_data = {
|
||||||
user_id=user_id,
|
'user_id': user_id,
|
||||||
project_id=tenant_id,
|
'project_id': tenant_id,
|
||||||
blob=jsonutils.dumps(blob),
|
'blob': jsonutils.dumps(blob),
|
||||||
id=credential_id,
|
'id': credential_id,
|
||||||
type=CRED_TYPE_EC2,
|
'type': CRED_TYPE_EC2,
|
||||||
)
|
}
|
||||||
PROVIDERS.credential_api.create_credential(credential_id, cred_data)
|
PROVIDERS.credential_api.create_credential(credential_id, cred_data)
|
||||||
ref = _convert_v3_to_ec2_credential(cred_data)
|
ref = _convert_v3_to_ec2_credential(cred_data)
|
||||||
return self.wrap_member(ref), http.client.CREATED
|
return self.wrap_member(ref), http.client.CREATED
|
||||||
@ -537,10 +535,10 @@ class OAuth1AccessTokenCRUDResource(_OAuth1ResourceBase):
|
|||||||
access_token = PROVIDERS.oauth_api.get_access_token(access_token_id)
|
access_token = PROVIDERS.oauth_api.get_access_token(access_token_id)
|
||||||
reason = (
|
reason = (
|
||||||
'Invalidating the token cache because an access token for '
|
'Invalidating the token cache because an access token for '
|
||||||
'consumer %(consumer_id)s has been deleted. Authorization for '
|
'consumer {consumer_id} has been deleted. Authorization for '
|
||||||
'users with OAuth tokens will be recalculated and enforced '
|
'users with OAuth tokens will be recalculated and enforced '
|
||||||
'accordingly the next time they authenticate or validate a '
|
'accordingly the next time they authenticate or validate a '
|
||||||
'token.' % {'consumer_id': access_token['consumer_id']}
|
'token.'.format(consumer_id=access_token['consumer_id'])
|
||||||
)
|
)
|
||||||
notifications.invalidate_token_cache_notification(reason)
|
notifications.invalidate_token_cache_notification(reason)
|
||||||
PROVIDERS.oauth_api.delete_access_token(
|
PROVIDERS.oauth_api.delete_access_token(
|
||||||
@ -752,8 +750,7 @@ class UserAppCredGetDeleteResource(ks_flask.ResourceBase):
|
|||||||
"""
|
"""
|
||||||
target = _update_request_user_id_attribute()
|
target = _update_request_user_id_attribute()
|
||||||
ENFORCER.enforce_call(
|
ENFORCER.enforce_call(
|
||||||
action='identity:get_application_credential',
|
action='identity:get_application_credential', target_attr=target
|
||||||
target_attr=target,
|
|
||||||
)
|
)
|
||||||
ref = PROVIDERS.application_credential_api.get_application_credential(
|
ref = PROVIDERS.application_credential_api.get_application_credential(
|
||||||
application_credential_id
|
application_credential_id
|
||||||
@ -787,11 +784,7 @@ class UserAccessRuleListResource(ks_flask.ResourceBase):
|
|||||||
|
|
||||||
GET/HEAD /v3/users/{user_id}/access_rules
|
GET/HEAD /v3/users/{user_id}/access_rules
|
||||||
"""
|
"""
|
||||||
filters = (
|
filters = ('service', 'path', 'method')
|
||||||
'service',
|
|
||||||
'path',
|
|
||||||
'method',
|
|
||||||
)
|
|
||||||
ENFORCER.enforce_call(
|
ENFORCER.enforce_call(
|
||||||
action='identity:list_access_rules',
|
action='identity:list_access_rules',
|
||||||
filters=filters,
|
filters=filters,
|
||||||
|
@ -52,9 +52,7 @@ def _schema_validator(
|
|||||||
schema_validator.validate(target)
|
schema_validator.validate(target)
|
||||||
|
|
||||||
|
|
||||||
def request_body_schema(
|
def request_body_schema(schema: ty.Optional[ty.Dict[str, ty.Any]] = None):
|
||||||
schema: ty.Optional[ty.Dict[str, ty.Any]] = None,
|
|
||||||
):
|
|
||||||
"""Register a schema to validate request body.
|
"""Register a schema to validate request body.
|
||||||
|
|
||||||
``schema`` will be used for validating the request body just before the API
|
``schema`` will be used for validating the request body just before the API
|
||||||
@ -88,9 +86,7 @@ def request_body_schema(
|
|||||||
return add_validator
|
return add_validator
|
||||||
|
|
||||||
|
|
||||||
def request_query_schema(
|
def request_query_schema(schema: ty.Optional[ty.Dict[str, ty.Any]] = None):
|
||||||
schema: ty.Optional[ty.Dict[str, ty.Any]] = None,
|
|
||||||
):
|
|
||||||
"""Register a schema to validate request query string parameters.
|
"""Register a schema to validate request query string parameters.
|
||||||
|
|
||||||
``schema`` will be used for validating request query strings just before
|
``schema`` will be used for validating request query strings just before
|
||||||
@ -113,13 +109,7 @@ def request_query_schema(
|
|||||||
else:
|
else:
|
||||||
req = flask.request.args
|
req = flask.request.args
|
||||||
|
|
||||||
_schema_validator(
|
_schema_validator(schema, req, args, kwargs, is_body=True)
|
||||||
schema,
|
|
||||||
req,
|
|
||||||
args,
|
|
||||||
kwargs,
|
|
||||||
is_body=True,
|
|
||||||
)
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
wrapper._request_query_schema = schema
|
wrapper._request_query_schema = schema
|
||||||
@ -129,9 +119,7 @@ def request_query_schema(
|
|||||||
return add_validator
|
return add_validator
|
||||||
|
|
||||||
|
|
||||||
def response_body_schema(
|
def response_body_schema(schema: ty.Optional[ty.Dict[str, ty.Any]] = None):
|
||||||
schema: ty.Optional[ty.Dict[str, ty.Any]] = None,
|
|
||||||
):
|
|
||||||
"""Register a schema to validate response body.
|
"""Register a schema to validate response body.
|
||||||
|
|
||||||
``schema`` will be used for validating the response body just after the API
|
``schema`` will be used for validating the response body just after the API
|
||||||
@ -169,13 +157,7 @@ def response_body_schema(
|
|||||||
else:
|
else:
|
||||||
body = jsonutils.loads(_body)
|
body = jsonutils.loads(_body)
|
||||||
|
|
||||||
_schema_validator(
|
_schema_validator(schema, body, args, kwargs, is_body=True)
|
||||||
schema,
|
|
||||||
body,
|
|
||||||
args,
|
|
||||||
kwargs,
|
|
||||||
is_body=True,
|
|
||||||
)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
wrapper._response_body_schema = schema
|
wrapper._response_body_schema = schema
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""Common parameter types for validating API requests."""
|
"""Common parameter types for validating API requests."""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
empty: dict[str, Any] = {"type": "null"}
|
empty: dict[str, Any] = {"type": "null"}
|
||||||
@ -24,22 +25,11 @@ name: dict[str, Any] = {
|
|||||||
|
|
||||||
boolean = {
|
boolean = {
|
||||||
"type": ["boolean", "string"],
|
"type": ["boolean", "string"],
|
||||||
"enum": [
|
"enum": [True, "True", "TRUE", "true", False, "False", "FALSE", "false"],
|
||||||
True,
|
|
||||||
"True",
|
|
||||||
"TRUE",
|
|
||||||
"true",
|
|
||||||
False,
|
|
||||||
"False",
|
|
||||||
"FALSE",
|
|
||||||
"false",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
domain_id: dict[str, str] = {
|
domain_id: dict[str, str] = {"type": "string"}
|
||||||
"type": "string",
|
|
||||||
}
|
|
||||||
|
|
||||||
parent_id: dict[str, str] = {"type": "string", "format": "uuid"}
|
parent_id: dict[str, str] = {"type": "string", "format": "uuid"}
|
||||||
|
|
||||||
@ -60,10 +50,7 @@ tags: dict[str, Any] = {
|
|||||||
# As OpenAPI request parameters this is an array of string serialized
|
# As OpenAPI request parameters this is an array of string serialized
|
||||||
# as csv
|
# as csv
|
||||||
"openapi": {
|
"openapi": {
|
||||||
"schema": {
|
"schema": {"type": "array", "items": _tag_name_property},
|
||||||
"type": "array",
|
|
||||||
"items": _tag_name_property,
|
|
||||||
},
|
|
||||||
"style": "form",
|
"style": "form",
|
||||||
"explode": False,
|
"explode": False,
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""Common field types for validating API responses."""
|
"""Common field types for validating API responses."""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
# Common schema for resource `link` attribute
|
# Common schema for resource `link` attribute
|
||||||
|
@ -26,10 +26,7 @@ from keystone.i18n import _
|
|||||||
|
|
||||||
|
|
||||||
def _soft_validate_additional_properties(
|
def _soft_validate_additional_properties(
|
||||||
validator,
|
validator, additional_properties_value, param_value, schema
|
||||||
additional_properties_value,
|
|
||||||
param_value,
|
|
||||||
schema,
|
|
||||||
):
|
):
|
||||||
"""Validator function.
|
"""Validator function.
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ from keystone import exception
|
|||||||
|
|
||||||
|
|
||||||
class ApplicationCredentialDriverBase(metaclass=abc.ABCMeta):
|
class ApplicationCredentialDriverBase(metaclass=abc.ABCMeta):
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def authenticate(self, application_credential_id, secret):
|
def authenticate(self, application_credential_id, secret):
|
||||||
"""Validate an application credential.
|
"""Validate an application credential.
|
||||||
|
@ -125,7 +125,6 @@ class ApplicationCredentialAccessRuleModel(sql.ModelBase, sql.ModelDictMixin):
|
|||||||
|
|
||||||
|
|
||||||
class ApplicationCredential(base.ApplicationCredentialDriverBase):
|
class ApplicationCredential(base.ApplicationCredentialDriverBase):
|
||||||
|
|
||||||
def _check_secret(self, secret, app_cred_ref):
|
def _check_secret(self, secret, app_cred_ref):
|
||||||
secret_hash = app_cred_ref['secret_hash']
|
secret_hash = app_cred_ref['secret_hash']
|
||||||
return password_hashing.check_password(secret, secret_hash)
|
return password_hashing.check_password(secret, secret_hash)
|
||||||
|
@ -21,7 +21,6 @@ CONF = keystone.conf.CONF
|
|||||||
|
|
||||||
|
|
||||||
class AssignmentDriverBase(metaclass=abc.ABCMeta):
|
class AssignmentDriverBase(metaclass=abc.ABCMeta):
|
||||||
|
|
||||||
def _get_list_limit(self):
|
def _get_list_limit(self):
|
||||||
return CONF.assignment.list_limit or CONF.list_limit
|
return CONF.assignment.list_limit or CONF.list_limit
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ class AssignmentType:
|
|||||||
|
|
||||||
|
|
||||||
class Assignment(base.AssignmentDriverBase):
|
class Assignment(base.AssignmentDriverBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_role_driver(cls):
|
def default_role_driver(cls):
|
||||||
return 'sql'
|
return 'sql'
|
||||||
@ -55,7 +54,6 @@ class Assignment(base.AssignmentDriverBase):
|
|||||||
project_id=None,
|
project_id=None,
|
||||||
inherited_to_projects=False,
|
inherited_to_projects=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
assignment_type = AssignmentType.calculate_type(
|
assignment_type = AssignmentType.calculate_type(
|
||||||
user_id, group_id, project_id, domain_id
|
user_id, group_id, project_id, domain_id
|
||||||
)
|
)
|
||||||
@ -182,11 +180,7 @@ class Assignment(base.AssignmentDriverBase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
except sql.DBDuplicateEntry:
|
except sql.DBDuplicateEntry:
|
||||||
msg = 'User {} already has role {} in tenant {}'.format(
|
msg = f'User {user_id} already has role {role_id} in tenant {project_id}'
|
||||||
user_id,
|
|
||||||
role_id,
|
|
||||||
project_id,
|
|
||||||
)
|
|
||||||
raise exception.Conflict(type='role grant', details=msg)
|
raise exception.Conflict(type='role grant', details=msg)
|
||||||
|
|
||||||
def remove_role_from_user_and_project(self, user_id, project_id, role_id):
|
def remove_role_from_user_and_project(self, user_id, project_id, role_id):
|
||||||
@ -264,7 +258,6 @@ class Assignment(base.AssignmentDriverBase):
|
|||||||
project_ids=None,
|
project_ids=None,
|
||||||
inherited_to_projects=None,
|
inherited_to_projects=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
def denormalize_role(ref):
|
def denormalize_role(ref):
|
||||||
assignment = {}
|
assignment = {}
|
||||||
if ref.type == AssignmentType.USER_PROJECT:
|
if ref.type == AssignmentType.USER_PROJECT:
|
||||||
|
@ -71,8 +71,8 @@ class Manager(manager.Manager):
|
|||||||
|
|
||||||
self.event_callbacks = {
|
self.event_callbacks = {
|
||||||
notifications.ACTIONS.deleted: {
|
notifications.ACTIONS.deleted: {
|
||||||
'domain': [self._delete_domain_assignments],
|
'domain': [self._delete_domain_assignments]
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def _delete_domain_assignments(
|
def _delete_domain_assignments(
|
||||||
@ -209,7 +209,6 @@ class Manager(manager.Manager):
|
|||||||
inherited_to_projects=False,
|
inherited_to_projects=False,
|
||||||
context=None,
|
context=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
# The parameters for this method must match the parameters for
|
# The parameters for this method must match the parameters for
|
||||||
# create_grant so that the notifications.role_assignment decorator
|
# create_grant so that the notifications.role_assignment decorator
|
||||||
# will work.
|
# will work.
|
||||||
@ -286,7 +285,6 @@ class Manager(manager.Manager):
|
|||||||
inherited_to_projects=False,
|
inherited_to_projects=False,
|
||||||
context=None,
|
context=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
# The parameters for this method must match the parameters for
|
# The parameters for this method must match the parameters for
|
||||||
# delete_grant so that the notifications.role_assignment decorator
|
# delete_grant so that the notifications.role_assignment decorator
|
||||||
# will work.
|
# will work.
|
||||||
@ -326,16 +324,9 @@ class Manager(manager.Manager):
|
|||||||
target_id = project_id
|
target_id = project_id
|
||||||
|
|
||||||
reason = (
|
reason = (
|
||||||
'Invalidating the token cache because role %(role_id)s was '
|
f'Invalidating the token cache because role {role_id} was '
|
||||||
'removed from %(actor_type)s %(actor_id)s on %(target_type)s '
|
f'removed from {actor_type} {actor_id} on {target_type} '
|
||||||
'%(target_id)s.'
|
f'{target_id}.'
|
||||||
% {
|
|
||||||
'role_id': role_id,
|
|
||||||
'actor_type': actor_type,
|
|
||||||
'actor_id': actor_id,
|
|
||||||
'target_type': target_type,
|
|
||||||
'target_id': target_id,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
notifications.invalidate_token_cache_notification(reason)
|
notifications.invalidate_token_cache_notification(reason)
|
||||||
|
|
||||||
@ -429,7 +420,6 @@ class Manager(manager.Manager):
|
|||||||
inherited_to_projects=False,
|
inherited_to_projects=False,
|
||||||
initiator=None,
|
initiator=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
# check if role exist before any processing
|
# check if role exist before any processing
|
||||||
PROVIDERS.role_api.get_role(role_id)
|
PROVIDERS.role_api.get_role(role_id)
|
||||||
|
|
||||||
@ -760,7 +750,7 @@ class Manager(manager.Manager):
|
|||||||
implied_roles_cache = {}
|
implied_roles_cache = {}
|
||||||
role_refs_to_check = list(role_refs)
|
role_refs_to_check = list(role_refs)
|
||||||
ref_results = list(role_refs)
|
ref_results = list(role_refs)
|
||||||
checked_role_refs = list()
|
checked_role_refs = []
|
||||||
while role_refs_to_check:
|
while role_refs_to_check:
|
||||||
next_ref = role_refs_to_check.pop()
|
next_ref = role_refs_to_check.pop()
|
||||||
checked_role_refs.append(next_ref)
|
checked_role_refs.append(next_ref)
|
||||||
@ -1348,9 +1338,8 @@ class Manager(manager.Manager):
|
|||||||
role = PROVIDERS.role_api.get_role(role_id)
|
role = PROVIDERS.role_api.get_role(role_id)
|
||||||
if role.get('domain_id'):
|
if role.get('domain_id'):
|
||||||
raise exception.ValidationError(
|
raise exception.ValidationError(
|
||||||
'Role %(role_id)s is a domain-specific role. Unable to use '
|
f'Role {role_id} is a domain-specific role. Unable to use '
|
||||||
'a domain-specific role in a system assignment.'
|
'a domain-specific role in a system assignment.'
|
||||||
% {'role_id': role_id}
|
|
||||||
)
|
)
|
||||||
target_id = self._SYSTEM_SCOPE_TOKEN
|
target_id = self._SYSTEM_SCOPE_TOKEN
|
||||||
assignment_type = self._USER_SYSTEM
|
assignment_type = self._USER_SYSTEM
|
||||||
@ -1420,9 +1409,8 @@ class Manager(manager.Manager):
|
|||||||
role = PROVIDERS.role_api.get_role(role_id)
|
role = PROVIDERS.role_api.get_role(role_id)
|
||||||
if role.get('domain_id'):
|
if role.get('domain_id'):
|
||||||
raise exception.ValidationError(
|
raise exception.ValidationError(
|
||||||
'Role %(role_id)s is a domain-specific role. Unable to use '
|
f'Role {role_id} is a domain-specific role. Unable to use '
|
||||||
'a domain-specific role in a system assignment.'
|
'a domain-specific role in a system assignment.'
|
||||||
% {'role_id': role_id}
|
|
||||||
)
|
)
|
||||||
target_id = self._SYSTEM_SCOPE_TOKEN
|
target_id = self._SYSTEM_SCOPE_TOKEN
|
||||||
assignment_type = self._GROUP_SYSTEM
|
assignment_type = self._GROUP_SYSTEM
|
||||||
@ -1556,10 +1544,10 @@ class RoleManager(manager.Manager):
|
|||||||
notifications.Audit.deleted(self._ROLE, role_id, initiator)
|
notifications.Audit.deleted(self._ROLE, role_id, initiator)
|
||||||
self.get_role.invalidate(self, role_id)
|
self.get_role.invalidate(self, role_id)
|
||||||
reason = (
|
reason = (
|
||||||
'Invalidating the token cache because role %(role_id)s has been '
|
f'Invalidating the token cache because role {role_id} has been '
|
||||||
'removed. Role assignments for users will be recalculated and '
|
'removed. Role assignments for users will be recalculated and '
|
||||||
'enforced accordingly the next time they authenticate or validate '
|
'enforced accordingly the next time they authenticate or validate '
|
||||||
'a token' % {'role_id': role_id}
|
'a token'
|
||||||
)
|
)
|
||||||
notifications.invalidate_token_cache_notification(reason)
|
notifications.invalidate_token_cache_notification(reason)
|
||||||
COMPUTED_ASSIGNMENTS_REGION.invalidate()
|
COMPUTED_ASSIGNMENTS_REGION.invalidate()
|
||||||
|
@ -29,7 +29,6 @@ CONF = keystone.conf.CONF
|
|||||||
|
|
||||||
|
|
||||||
class RoleDriverBase(metaclass=abc.ABCMeta):
|
class RoleDriverBase(metaclass=abc.ABCMeta):
|
||||||
|
|
||||||
def _get_list_limit(self):
|
def _get_list_limit(self):
|
||||||
return CONF.role.list_limit or CONF.list_limit
|
return CONF.role.list_limit or CONF.list_limit
|
||||||
|
|
||||||
|
@ -19,9 +19,7 @@ ROLE_OPTIONS_REGISTRY = resource_options.ResourceOptionRegistry('ROLE')
|
|||||||
# NOTE(morgan): wrap this in a function for testing purposes.
|
# NOTE(morgan): wrap this in a function for testing purposes.
|
||||||
# This is called on import by design.
|
# This is called on import by design.
|
||||||
def register_role_options():
|
def register_role_options():
|
||||||
for opt in [
|
for opt in [ro_opt.IMMUTABLE_OPT]:
|
||||||
ro_opt.IMMUTABLE_OPT,
|
|
||||||
]:
|
|
||||||
ROLE_OPTIONS_REGISTRY.register_option(opt)
|
ROLE_OPTIONS_REGISTRY.register_option(opt)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ from keystone import exception
|
|||||||
|
|
||||||
|
|
||||||
class Role(base.RoleDriverBase):
|
class Role(base.RoleDriverBase):
|
||||||
|
|
||||||
@sql.handle_conflicts(conflict_type='role')
|
@sql.handle_conflicts(conflict_type='role')
|
||||||
def create_role(self, role_id, role):
|
def create_role(self, role_id, role):
|
||||||
with sql.session_for_write() as session:
|
with sql.session_for_write() as session:
|
||||||
|
@ -19,7 +19,6 @@ from keystone.common import sql
|
|||||||
|
|
||||||
|
|
||||||
class RoleTable(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
class RoleTable(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
|
|
||||||
def to_dict(self, include_extra_dict=False):
|
def to_dict(self, include_extra_dict=False):
|
||||||
d = super().to_dict(include_extra_dict=include_extra_dict)
|
d = super().to_dict(include_extra_dict=include_extra_dict)
|
||||||
if d['domain_id'] == base.NULL_DOMAIN_ID:
|
if d['domain_id'] == base.NULL_DOMAIN_ID:
|
||||||
@ -96,7 +95,7 @@ class ImpliedRoleTable(sql.ModelBase, sql.ModelDictMixin):
|
|||||||
overrides the `to_dict` function from the base class
|
overrides the `to_dict` function from the base class
|
||||||
to avoid having an `extra` field.
|
to avoid having an `extra` field.
|
||||||
"""
|
"""
|
||||||
d = dict()
|
d = {}
|
||||||
for attr in self.__class__.attributes:
|
for attr in self.__class__.attributes:
|
||||||
d[attr] = getattr(self, attr)
|
d[attr] = getattr(self, attr)
|
||||||
return d
|
return d
|
||||||
|
@ -38,7 +38,7 @@ def _get_auth_driver_manager(namespace, plugin_name):
|
|||||||
|
|
||||||
def load_auth_method(method):
|
def load_auth_method(method):
|
||||||
plugin_name = CONF.auth.get(method) or 'default'
|
plugin_name = CONF.auth.get(method) or 'default'
|
||||||
namespace = 'keystone.auth.%s' % method
|
namespace = f'keystone.auth.{method}'
|
||||||
driver_manager = _get_auth_driver_manager(namespace, plugin_name)
|
driver_manager = _get_auth_driver_manager(namespace, plugin_name)
|
||||||
return driver_manager.driver
|
return driver_manager.driver
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ class AuthInfo(provider_api.ProviderAPIMixin):
|
|||||||
app_cred_api = PROVIDERS.application_credential_api
|
app_cred_api = PROVIDERS.application_credential_api
|
||||||
app_creds = app_cred_api.list_application_credentials(user_id, hints)
|
app_creds = app_cred_api.list_application_credentials(user_id, hints)
|
||||||
if len(app_creds) != 1:
|
if len(app_creds) != 1:
|
||||||
message = "Could not find application credential: %s" % name
|
message = f"Could not find application credential: {name}"
|
||||||
tr_message = _("Could not find application credential: %s") % name
|
tr_message = _("Could not find application credential: %s") % name
|
||||||
LOG.warning(message)
|
LOG.warning(message)
|
||||||
raise exception.Unauthorized(tr_message)
|
raise exception.Unauthorized(tr_message)
|
||||||
|
@ -45,13 +45,7 @@ class AuthMethodHandler(provider_api.ProviderAPIMixin, metaclass=abc.ABCMeta):
|
|||||||
to the re-scope type action. Here's an example of ``response_data`` on
|
to the re-scope type action. Here's an example of ``response_data`` on
|
||||||
successful authentication::
|
successful authentication::
|
||||||
|
|
||||||
{
|
{"methods": ["password", "token"], "user_id": "abc123"}
|
||||||
"methods": [
|
|
||||||
"password",
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"user_id": "abc123"
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugins are invoked in the order in which they are specified in the
|
Plugins are invoked in the order in which they are specified in the
|
||||||
``methods`` attribute of the ``identity`` object. For example,
|
``methods`` attribute of the ``identity`` object. For example,
|
||||||
@ -61,23 +55,12 @@ class AuthMethodHandler(provider_api.ProviderAPIMixin, metaclass=abc.ABCMeta):
|
|||||||
{
|
{
|
||||||
"auth": {
|
"auth": {
|
||||||
"identity": {
|
"identity": {
|
||||||
"custom-plugin": {
|
"custom-plugin": {"custom-data": "sdfdfsfsfsdfsf"},
|
||||||
"custom-data": "sdfdfsfsfsdfsf"
|
"methods": ["custom-plugin", "password", "token"],
|
||||||
},
|
|
||||||
"methods": [
|
|
||||||
"custom-plugin",
|
|
||||||
"password",
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"password": {
|
"password": {
|
||||||
"user": {
|
"user": {"id": "s23sfad1", "password": "secret"}
|
||||||
"id": "s23sfad1",
|
|
||||||
"password": "secret"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {"id": "sdfafasdfsfasfasdfds"},
|
||||||
"id": "sdfafasdfsfasfasdfds"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ CONF = keystone.conf.CONF
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
PROVIDERS = provider_api.ProviderAPIs
|
PROVIDERS = provider_api.ProviderAPIs
|
||||||
_NOTIFY_OP = 'authenticate'
|
_NOTIFY_OP = 'authenticate'
|
||||||
_NOTIFY_EVENT = '{service}.{event}'.format(
|
_NOTIFY_EVENT = f'{notifications.SERVICE}.{_NOTIFY_OP}'
|
||||||
service=notifications.SERVICE, event=_NOTIFY_OP
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def construct_method_map_from_config():
|
def construct_method_map_from_config():
|
||||||
@ -38,7 +36,7 @@ def construct_method_map_from_config():
|
|||||||
:returns: a dictionary containing the methods and their indexes
|
:returns: a dictionary containing the methods and their indexes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
method_map = dict()
|
method_map = {}
|
||||||
method_index = 1
|
method_index = 1
|
||||||
for method in CONF.auth.methods:
|
for method in CONF.auth.methods:
|
||||||
method_map[method_index] = method
|
method_map[method_index] = method
|
||||||
@ -99,7 +97,6 @@ def convert_integer_to_method_list(method_int):
|
|||||||
|
|
||||||
|
|
||||||
class BaseUserInfo(provider_api.ProviderAPIMixin):
|
class BaseUserInfo(provider_api.ProviderAPIMixin):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, auth_payload, method_name):
|
def create(cls, auth_payload, method_name):
|
||||||
user_auth_info = cls()
|
user_auth_info = cls()
|
||||||
@ -213,7 +210,6 @@ class BaseUserInfo(provider_api.ProviderAPIMixin):
|
|||||||
|
|
||||||
|
|
||||||
class UserAuthInfo(BaseUserInfo):
|
class UserAuthInfo(BaseUserInfo):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.password = None
|
self.password = None
|
||||||
@ -225,7 +221,6 @@ class UserAuthInfo(BaseUserInfo):
|
|||||||
|
|
||||||
|
|
||||||
class TOTPUserInfo(BaseUserInfo):
|
class TOTPUserInfo(BaseUserInfo):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.passcode = None
|
self.passcode = None
|
||||||
|
@ -34,7 +34,6 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
|
|
||||||
|
|
||||||
class Mapped(base.AuthMethodHandler):
|
class Mapped(base.AuthMethodHandler):
|
||||||
|
|
||||||
def _get_token_ref(self, auth_payload):
|
def _get_token_ref(self, auth_payload):
|
||||||
token_id = auth_payload['id']
|
token_id = auth_payload['id']
|
||||||
return PROVIDERS.token_provider_api.validate_token(token_id)
|
return PROVIDERS.token_provider_api.validate_token(token_id)
|
||||||
@ -184,7 +183,6 @@ def handle_unscoped_token(
|
|||||||
assignment_api,
|
assignment_api,
|
||||||
role_api,
|
role_api,
|
||||||
):
|
):
|
||||||
|
|
||||||
def validate_shadow_mapping(
|
def validate_shadow_mapping(
|
||||||
shadow_projects, existing_roles, user_domain_id, idp_id
|
shadow_projects, existing_roles, user_domain_id, idp_id
|
||||||
):
|
):
|
||||||
@ -300,7 +298,6 @@ def handle_unscoped_token(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if 'projects' in mapped_properties:
|
if 'projects' in mapped_properties:
|
||||||
|
|
||||||
existing_roles = {
|
existing_roles = {
|
||||||
role['name']: role for role in role_api.list_roles()
|
role['name']: role for role in role_api.list_roles()
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
|
|
||||||
|
|
||||||
class Password(base.AuthMethodHandler):
|
class Password(base.AuthMethodHandler):
|
||||||
|
|
||||||
def authenticate(self, auth_payload):
|
def authenticate(self, auth_payload):
|
||||||
"""Try to authenticate against the identity backend."""
|
"""Try to authenticate against the identity backend."""
|
||||||
response_data = {}
|
response_data = {}
|
||||||
|
@ -29,7 +29,6 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
|
|
||||||
|
|
||||||
class Token(base.AuthMethodHandler):
|
class Token(base.AuthMethodHandler):
|
||||||
|
|
||||||
def _get_token_ref(self, auth_payload):
|
def _get_token_ref(self, auth_payload):
|
||||||
token_id = auth_payload['id']
|
token_id = auth_payload['id']
|
||||||
return PROVIDERS.token_provider_api.validate_token(token_id)
|
return PROVIDERS.token_provider_api.validate_token(token_id)
|
||||||
@ -59,7 +58,6 @@ class Token(base.AuthMethodHandler):
|
|||||||
def token_authenticate(token):
|
def token_authenticate(token):
|
||||||
response_data = {}
|
response_data = {}
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# Do not allow tokens used for delegation to
|
# Do not allow tokens used for delegation to
|
||||||
# create another token, or perform any changes of
|
# create another token, or perform any changes of
|
||||||
# state in Keystone. To do so is to invite elevation of
|
# state in Keystone. To do so is to invite elevation of
|
||||||
|
@ -90,7 +90,6 @@ def _generate_totp_passcodes(secret, included_previous_windows=0):
|
|||||||
|
|
||||||
|
|
||||||
class TOTP(base.AuthMethodHandler):
|
class TOTP(base.AuthMethodHandler):
|
||||||
|
|
||||||
def authenticate(self, auth_payload):
|
def authenticate(self, auth_payload):
|
||||||
"""Try to authenticate using TOTP."""
|
"""Try to authenticate using TOTP."""
|
||||||
response_data = {}
|
response_data = {}
|
||||||
|
@ -21,57 +21,34 @@ token_issue = {
|
|||||||
'identity': {
|
'identity': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'methods': {
|
'methods': {'type': 'array', 'items': {'type': 'string'}},
|
||||||
'type': 'array',
|
|
||||||
'items': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'password': {
|
'password': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'user': {
|
'user': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'id': {
|
'id': {'type': 'string'},
|
||||||
'type': 'string',
|
'name': {'type': 'string'},
|
||||||
},
|
'password': {'type': 'string'},
|
||||||
'name': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
'password': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
'domain': {
|
'domain': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'id': {
|
'id': {'type': 'string'},
|
||||||
'type': 'string',
|
'name': {'type': 'string'},
|
||||||
},
|
|
||||||
'name': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'token': {
|
'token': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {'id': {'type': 'string'}},
|
||||||
'id': {
|
'required': ['id'],
|
||||||
'type': 'string',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'required': [
|
'required': ['methods'],
|
||||||
'id',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'required': [
|
|
||||||
'methods',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
'scope': {
|
'scope': {
|
||||||
# For explicit unscoped authentication the type should not be
|
# For explicit unscoped authentication the type should not be
|
||||||
@ -85,21 +62,13 @@ token_issue = {
|
|||||||
'project': {
|
'project': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'name': {
|
'name': {'type': 'string'},
|
||||||
'type': 'string',
|
'id': {'type': 'string'},
|
||||||
},
|
|
||||||
'id': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
'domain': {
|
'domain': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'id': {
|
'id': {'type': 'string'},
|
||||||
'type': 'string',
|
'name': {'type': 'string'},
|
||||||
},
|
|
||||||
'name': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -107,21 +76,13 @@ token_issue = {
|
|||||||
'domain': {
|
'domain': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'id': {
|
'id': {'type': 'string'},
|
||||||
'type': 'string',
|
'name': {'type': 'string'},
|
||||||
},
|
|
||||||
'name': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'OS-TRUST:trust': {
|
'OS-TRUST:trust': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {'id': {'type': 'string'}},
|
||||||
'id': {
|
|
||||||
'type': 'string',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'system': {
|
'system': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
@ -130,9 +91,7 @@ token_issue = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'required': [
|
'required': ['identity'],
|
||||||
'identity',
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,17 +246,19 @@ class CatalogDriverBase(provider_api.ProviderAPIMixin, metaclass=abc.ABCMeta):
|
|||||||
"interface": "public",
|
"interface": "public",
|
||||||
"id": "--endpoint-id--",
|
"id": "--endpoint-id--",
|
||||||
"region": "RegionOne",
|
"region": "RegionOne",
|
||||||
"url": "http://external:8776/v1/--project-id--"
|
"url": "http://external:8776/v1/--project-id--",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"interface": "internal",
|
"interface": "internal",
|
||||||
"id": "--endpoint-id--",
|
"id": "--endpoint-id--",
|
||||||
"region": "RegionOne",
|
"region": "RegionOne",
|
||||||
"url": "http://internal:8776/v1/--project-id--"
|
"url": "http://internal:8776/v1/--project-id--",
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
"id": "--service-id--",
|
"id": "--service-id--",
|
||||||
"type": "volume"
|
"type": "volume",
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
|
|
||||||
:returns: A list representing the service catalog or an empty list
|
:returns: A list representing the service catalog or an empty list
|
||||||
:raises keystone.exception.NotFound: If the endpoint doesn't exist.
|
:raises keystone.exception.NotFound: If the endpoint doesn't exist.
|
||||||
|
@ -333,7 +333,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
}
|
}
|
||||||
catalog.setdefault(region, {})
|
catalog.setdefault(region, {})
|
||||||
catalog[region].setdefault(service_type, default_service)
|
catalog[region].setdefault(service_type, default_service)
|
||||||
interface_url = '%sURL' % endpoint['interface']
|
interface_url = '{}URL'.format(endpoint['interface'])
|
||||||
catalog[region][service_type][interface_url] = url
|
catalog[region][service_type][interface_url] = url
|
||||||
|
|
||||||
return catalog
|
return catalog
|
||||||
@ -355,12 +355,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
d.update({'user_id': user_id})
|
d.update({'user_id': user_id})
|
||||||
silent_keyerror_failures = []
|
silent_keyerror_failures = []
|
||||||
if project_id:
|
if project_id:
|
||||||
d.update(
|
d.update({'tenant_id': project_id, 'project_id': project_id})
|
||||||
{
|
|
||||||
'tenant_id': project_id,
|
|
||||||
'project_id': project_id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
silent_keyerror_failures = ['tenant_id', 'project_id']
|
silent_keyerror_failures = ['tenant_id', 'project_id']
|
||||||
|
|
||||||
@ -463,8 +458,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
|
|
||||||
def _get_project_endpoint_ref(self, session, endpoint_id, project_id):
|
def _get_project_endpoint_ref(self, session, endpoint_id, project_id):
|
||||||
endpoint_filter_ref = session.get(
|
endpoint_filter_ref = session.get(
|
||||||
ProjectEndpoint,
|
ProjectEndpoint, (endpoint_id, project_id)
|
||||||
(endpoint_id, project_id),
|
|
||||||
)
|
)
|
||||||
if endpoint_filter_ref is None:
|
if endpoint_filter_ref is None:
|
||||||
msg = _(
|
msg = _(
|
||||||
@ -576,8 +570,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
self, session, endpoint_group_id, project_id
|
self, session, endpoint_group_id, project_id
|
||||||
):
|
):
|
||||||
endpoint_group_project_ref = session.get(
|
endpoint_group_project_ref = session.get(
|
||||||
ProjectEndpointGroupMembership,
|
ProjectEndpointGroupMembership, (endpoint_group_id, project_id)
|
||||||
(endpoint_group_id, project_id),
|
|
||||||
)
|
)
|
||||||
if endpoint_group_project_ref is None:
|
if endpoint_group_project_ref is None:
|
||||||
msg = _('Endpoint Group Project Association not found')
|
msg = _('Endpoint Group Project Association not found')
|
||||||
|
@ -166,11 +166,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
for key in service_ref:
|
for key in service_ref:
|
||||||
if key.endswith('URL'):
|
if key.endswith('URL'):
|
||||||
interface = key[:-3]
|
interface = key[:-3]
|
||||||
endpoint_id = '{}-{}-{}'.format(
|
endpoint_id = f'{region_id}-{service_type}-{interface}'
|
||||||
region_id,
|
|
||||||
service_type,
|
|
||||||
interface,
|
|
||||||
)
|
|
||||||
yield {
|
yield {
|
||||||
'id': endpoint_id,
|
'id': endpoint_id,
|
||||||
'service_id': service_type,
|
'service_id': service_type,
|
||||||
@ -215,16 +211,10 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
silent_keyerror_failures = []
|
silent_keyerror_failures = []
|
||||||
if project_id:
|
if project_id:
|
||||||
substitutions.update(
|
substitutions.update(
|
||||||
{
|
{'tenant_id': project_id, 'project_id': project_id}
|
||||||
'tenant_id': project_id,
|
|
||||||
'project_id': project_id,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
silent_keyerror_failures = [
|
silent_keyerror_failures = ['tenant_id', 'project_id']
|
||||||
'tenant_id',
|
|
||||||
'project_id',
|
|
||||||
]
|
|
||||||
|
|
||||||
catalog = {}
|
catalog = {}
|
||||||
# TODO(davechen): If there is service with no endpoints, we should
|
# TODO(davechen): If there is service with no endpoints, we should
|
||||||
|
@ -26,7 +26,6 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
|
|
||||||
|
|
||||||
class Bootstrapper:
|
class Bootstrapper:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
backends.load_backends()
|
backends.load_backends()
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ LOG = log.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class BaseApp:
|
class BaseApp:
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -536,8 +535,7 @@ class ResetLastActive(BaseApp):
|
|||||||
raise SystemExit('reset_last_active aborted.')
|
raise SystemExit('reset_last_active aborted.')
|
||||||
|
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
"Resetting null values to current time %s",
|
"Resetting null values to current time %s", timeutils.utcnow()
|
||||||
timeutils.utcnow(),
|
|
||||||
)
|
)
|
||||||
drivers = backends.load_backends()
|
drivers = backends.load_backends()
|
||||||
identity_api = drivers['identity_api']
|
identity_api = drivers['identity_api']
|
||||||
@ -565,14 +563,14 @@ class BasePermissionsSetup(BaseApp):
|
|||||||
if a:
|
if a:
|
||||||
keystone_user_id = utils.get_unix_user(a)[0]
|
keystone_user_id = utils.get_unix_user(a)[0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError("Unknown user '%s' in --keystone-user" % a)
|
raise ValueError(f"Unknown user '{a}' in --keystone-user")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a = CONF.command.keystone_group
|
a = CONF.command.keystone_group
|
||||||
if a:
|
if a:
|
||||||
keystone_group_id = utils.get_unix_group(a)[0]
|
keystone_group_id = utils.get_unix_group(a)[0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError("Unknown group '%s' in --keystone-group" % a)
|
raise ValueError(f"Unknown group '{a}' in --keystone-group")
|
||||||
|
|
||||||
return keystone_user_id, keystone_group_id
|
return keystone_user_id, keystone_group_id
|
||||||
|
|
||||||
@ -1180,7 +1178,6 @@ def _domain_config_finder(conf_dir):
|
|||||||
|
|
||||||
|
|
||||||
class DomainConfigUploadFiles:
|
class DomainConfigUploadFiles:
|
||||||
|
|
||||||
def __init__(self, domain_config_finder=_domain_config_finder):
|
def __init__(self, domain_config_finder=_domain_config_finder):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.load_backends()
|
self.load_backends()
|
||||||
@ -1518,12 +1515,9 @@ class MappingEngineTester(BaseApp):
|
|||||||
tester.normalize_assertion()
|
tester.normalize_assertion()
|
||||||
|
|
||||||
if CONF.command.engine_debug:
|
if CONF.command.engine_debug:
|
||||||
|
print(f"Using Rules:\n{jsonutils.dumps(tester.rules, indent=2)}")
|
||||||
print(
|
print(
|
||||||
"Using Rules:\n%s" % (jsonutils.dumps(tester.rules, indent=2))
|
f"Using Assertion:\n{jsonutils.dumps(tester.assertion, indent=2)}"
|
||||||
)
|
|
||||||
print(
|
|
||||||
"Using Assertion:\n%s"
|
|
||||||
% (jsonutils.dumps(tester.assertion, indent=2))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
rp = mapping_engine.RuleProcessor(
|
rp = mapping_engine.RuleProcessor(
|
||||||
|
@ -50,8 +50,9 @@ def diagnose():
|
|||||||
# Some symptoms may take a long time to check, so let's keep
|
# Some symptoms may take a long time to check, so let's keep
|
||||||
# curious users posted on our progress as we go.
|
# curious users posted on our progress as we go.
|
||||||
print(
|
print(
|
||||||
'Checking for %s...'
|
'Checking for {}...'.format(
|
||||||
% symptom.__name__[len(SYMPTOM_PREFIX) :].replace('_', ' ')
|
symptom.__name__[len(SYMPTOM_PREFIX) :].replace('_', ' ')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# All symptoms are just callables that return true when they match the
|
# All symptoms are just callables that return true when they match the
|
||||||
@ -65,9 +66,7 @@ def diagnose():
|
|||||||
# passing a string here. Also, we include a line break here to
|
# passing a string here. Also, we include a line break here to
|
||||||
# visually separate the symptom's description from any other
|
# visually separate the symptom's description from any other
|
||||||
# checks -- it provides a better user experience.
|
# checks -- it provides a better user experience.
|
||||||
print(
|
print(_('\nWARNING: %s') % _(symptom.__doc__)) # noqa: See comment above.
|
||||||
_('\nWARNING: %s') % _(symptom.__doc__)
|
|
||||||
) # noqa: See comment above.
|
|
||||||
|
|
||||||
return symptoms_found
|
return symptoms_found
|
||||||
|
|
||||||
|
@ -85,10 +85,10 @@ def symptom_LDAP_file_based_domain_specific_configs():
|
|||||||
if invalid_files:
|
if invalid_files:
|
||||||
invalid_str = ', '.join(invalid_files)
|
invalid_str = ', '.join(invalid_files)
|
||||||
print(
|
print(
|
||||||
'Warning: The following non-config files were found: %s\n'
|
f'Warning: The following non-config files were found: {invalid_str}\n'
|
||||||
'If they are intended to be config files then rename them '
|
'If they are intended to be config files then rename them '
|
||||||
'to the form of `keystone.<domain_name>.conf`. '
|
'to the form of `keystone.<domain_name>.conf`. '
|
||||||
'Otherwise, ignore this warning' % invalid_str
|
'Otherwise, ignore this warning'
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -28,7 +28,6 @@ PROVIDERS = provider_api.ProviderAPIs
|
|||||||
|
|
||||||
|
|
||||||
class Identity:
|
class Identity:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
backends.load_backends()
|
backends.load_backends()
|
||||||
|
|
||||||
|
@ -54,13 +54,14 @@ class Checks(upgradecheck.UpgradeCommands):
|
|||||||
if any(failed_rules):
|
if any(failed_rules):
|
||||||
return upgradecheck.Result(
|
return upgradecheck.Result(
|
||||||
upgradecheck.Code.FAILURE,
|
upgradecheck.Code.FAILURE,
|
||||||
"Policy check string for rules \"%s\" are overridden to "
|
"Policy check string for rules \"{}\" are overridden to "
|
||||||
"\"\", \"@\", or []. In the next release, this will cause "
|
"\"\", \"@\", or []. In the next release, this will cause "
|
||||||
"these rules to be fully permissive as hardcoded enforcement "
|
"these rules to be fully permissive as hardcoded enforcement "
|
||||||
"will be removed. To correct this issue, either stop "
|
"will be removed. To correct this issue, either stop "
|
||||||
"overriding these rules in config to accept the defaults, or "
|
"overriding these rules in config to accept the defaults, or "
|
||||||
"explicitly set check strings that are not empty."
|
"explicitly set check strings that are not empty.".format(
|
||||||
% "\", \"".join(failed_rules),
|
"\", \"".join(failed_rules)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return upgradecheck.Result(
|
return upgradecheck.Result(
|
||||||
upgradecheck.Code.SUCCESS, 'Trust policies are safe.'
|
upgradecheck.Code.SUCCESS, 'Trust policies are safe.'
|
||||||
@ -70,11 +71,7 @@ class Checks(upgradecheck.UpgradeCommands):
|
|||||||
hints = driver_hints.Hints()
|
hints = driver_hints.Hints()
|
||||||
hints.add_filter('domain_id', None) # Only check global roles
|
hints.add_filter('domain_id', None) # Only check global roles
|
||||||
roles = PROVIDERS.role_api.list_roles(hints=hints)
|
roles = PROVIDERS.role_api.list_roles(hints=hints)
|
||||||
default_roles = (
|
default_roles = ('admin', 'member', 'reader')
|
||||||
'admin',
|
|
||||||
'member',
|
|
||||||
'reader',
|
|
||||||
)
|
|
||||||
failed_roles = []
|
failed_roles = []
|
||||||
for role in [r for r in roles if r['name'] in default_roles]:
|
for role in [r for r in roles if r['name'] in default_roles]:
|
||||||
if not role.get('options', {}).get('immutable'):
|
if not role.get('options', {}).get('immutable'):
|
||||||
@ -82,7 +79,7 @@ class Checks(upgradecheck.UpgradeCommands):
|
|||||||
if any(failed_roles):
|
if any(failed_roles):
|
||||||
return upgradecheck.Result(
|
return upgradecheck.Result(
|
||||||
upgradecheck.Code.FAILURE,
|
upgradecheck.Code.FAILURE,
|
||||||
"Roles are not immutable: %s" % ", ".join(failed_roles),
|
"Roles are not immutable: {}".format(", ".join(failed_roles)),
|
||||||
)
|
)
|
||||||
return upgradecheck.Result(
|
return upgradecheck.Result(
|
||||||
upgradecheck.Code.SUCCESS, "Default roles are immutable."
|
upgradecheck.Code.SUCCESS, "Default roles are immutable."
|
||||||
|
2
keystone/common/cache/_context_cache.py
vendored
2
keystone/common/cache/_context_cache.py
vendored
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""A dogpile.cache proxy that caches objects in the request local cache."""
|
"""A dogpile.cache proxy that caches objects in the request local cache."""
|
||||||
|
|
||||||
from dogpile.cache import api
|
from dogpile.cache import api
|
||||||
from dogpile.cache import proxy
|
from dogpile.cache import proxy
|
||||||
from oslo_context import context as oslo_context
|
from oslo_context import context as oslo_context
|
||||||
@ -28,7 +29,6 @@ def _register_model_handler(handler_class):
|
|||||||
|
|
||||||
|
|
||||||
class _ResponseCacheProxy(proxy.ProxyBackend):
|
class _ResponseCacheProxy(proxy.ProxyBackend):
|
||||||
|
|
||||||
__key_pfx = '_request_cache_%s'
|
__key_pfx = '_request_cache_%s'
|
||||||
|
|
||||||
def _get_request_context(self):
|
def _get_request_context(self):
|
||||||
|
4
keystone/common/cache/core.py
vendored
4
keystone/common/cache/core.py
vendored
@ -27,7 +27,6 @@ CONF = keystone.conf.CONF
|
|||||||
|
|
||||||
|
|
||||||
class RegionInvalidationManager:
|
class RegionInvalidationManager:
|
||||||
|
|
||||||
REGION_KEY_PREFIX = '<<<region>>>:'
|
REGION_KEY_PREFIX = '<<<region>>>:'
|
||||||
|
|
||||||
def __init__(self, invalidation_region, region_name):
|
def __init__(self, invalidation_region, region_name):
|
||||||
@ -53,7 +52,6 @@ class RegionInvalidationManager:
|
|||||||
|
|
||||||
|
|
||||||
class DistributedInvalidationStrategy(region.RegionInvalidationStrategy):
|
class DistributedInvalidationStrategy(region.RegionInvalidationStrategy):
|
||||||
|
|
||||||
def __init__(self, region_manager):
|
def __init__(self, region_manager):
|
||||||
self._region_manager = region_manager
|
self._region_manager = region_manager
|
||||||
|
|
||||||
@ -165,7 +163,7 @@ def configure_invalidation_region():
|
|||||||
config_dict['expiration_time'] = None # we don't want an expiration
|
config_dict['expiration_time'] = None # we don't want an expiration
|
||||||
|
|
||||||
CACHE_INVALIDATION_REGION.configure_from_config(
|
CACHE_INVALIDATION_REGION.configure_from_config(
|
||||||
config_dict, '%s.' % CONF.cache.config_prefix
|
config_dict, f'{CONF.cache.config_prefix}.'
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE(breton): Wrap the cache invalidation region to avoid excessive
|
# NOTE(breton): Wrap the cache invalidation region to avoid excessive
|
||||||
|
@ -22,7 +22,6 @@ def _prop(name):
|
|||||||
|
|
||||||
|
|
||||||
class RequestContext(oslo_context.RequestContext):
|
class RequestContext(oslo_context.RequestContext):
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.username = kwargs.pop('username', None)
|
self.username = kwargs.pop('username', None)
|
||||||
self.project_tag_name = kwargs.pop('project_tag_name', None)
|
self.project_tag_name = kwargs.pop('project_tag_name', None)
|
||||||
|
@ -96,7 +96,7 @@ class Hints:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.limit = None
|
self.limit = None
|
||||||
self.filters = list()
|
self.filters = []
|
||||||
self.cannot_match = False
|
self.cannot_match = False
|
||||||
|
|
||||||
def add_filter(
|
def add_filter(
|
||||||
|
@ -34,7 +34,6 @@ NULL_KEY = base64.urlsafe_b64encode(b'\x00' * 32)
|
|||||||
|
|
||||||
|
|
||||||
class FernetUtils:
|
class FernetUtils:
|
||||||
|
|
||||||
def __init__(self, key_repository, max_active_keys, config_group):
|
def __init__(self, key_repository, max_active_keys, config_group):
|
||||||
self.key_repository = key_repository
|
self.key_repository = key_repository
|
||||||
self.max_active_keys = max_active_keys
|
self.max_active_keys = max_active_keys
|
||||||
@ -157,8 +156,8 @@ class FernetUtils:
|
|||||||
LOG.info('Become a valid new key: %s', valid_key_file)
|
LOG.info('Become a valid new key: %s', valid_key_file)
|
||||||
|
|
||||||
def _get_key_files(self, key_repo):
|
def _get_key_files(self, key_repo):
|
||||||
key_files = dict()
|
key_files = {}
|
||||||
keys = dict()
|
keys = {}
|
||||||
for filename in os.listdir(key_repo):
|
for filename in os.listdir(key_repo):
|
||||||
path = os.path.join(key_repo, str(filename))
|
path = os.path.join(key_repo, str(filename))
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
|
@ -20,34 +20,28 @@ from keystone.i18n import _
|
|||||||
|
|
||||||
|
|
||||||
def build_v3_resource_relation(resource_name):
|
def build_v3_resource_relation(resource_name):
|
||||||
return (
|
return f'https://docs.openstack.org/api/openstack-identity/3/rel/{resource_name}'
|
||||||
'https://docs.openstack.org/api/openstack-identity/3/rel/%s'
|
|
||||||
% resource_name
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_v3_extension_resource_relation(
|
def build_v3_extension_resource_relation(
|
||||||
extension_name, extension_version, resource_name
|
extension_name, extension_version, resource_name
|
||||||
):
|
):
|
||||||
return (
|
return (
|
||||||
'https://docs.openstack.org/api/openstack-identity/3/ext/%s/%s/rel/'
|
f'https://docs.openstack.org/api/openstack-identity/3/ext/{extension_name}/{extension_version}/rel/'
|
||||||
'%s' % (extension_name, extension_version, resource_name)
|
f'{resource_name}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_v3_parameter_relation(parameter_name):
|
def build_v3_parameter_relation(parameter_name):
|
||||||
return (
|
return f'https://docs.openstack.org/api/openstack-identity/3/param/{parameter_name}'
|
||||||
'https://docs.openstack.org/api/openstack-identity/3/param/%s'
|
|
||||||
% parameter_name
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_v3_extension_parameter_relation(
|
def build_v3_extension_parameter_relation(
|
||||||
extension_name, extension_version, parameter_name
|
extension_name, extension_version, parameter_name
|
||||||
):
|
):
|
||||||
return (
|
return (
|
||||||
'https://docs.openstack.org/api/openstack-identity/3/ext/%s/%s/param/'
|
f'https://docs.openstack.org/api/openstack-identity/3/ext/{extension_name}/{extension_version}/param/'
|
||||||
'%s' % (extension_name, extension_version, parameter_name)
|
f'{parameter_name}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,10 +86,8 @@ class _TraceMeta(type):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def wrapper(__f, __classname):
|
def wrapper(__f, __classname):
|
||||||
__argspec = inspect.getfullargspec(__f)
|
__argspec = inspect.getfullargspec(__f)
|
||||||
__fn_info = '{module}.{classname}.{funcname}'.format(
|
__fn_info = (
|
||||||
module=inspect.getmodule(__f).__name__,
|
f'{inspect.getmodule(__f).__name__}.{__classname}.{__f.__name__}'
|
||||||
classname=__classname,
|
|
||||||
funcname=__f.__name__,
|
|
||||||
)
|
)
|
||||||
# NOTE(morganfainberg): Omit "cls" and "self" when printing trace logs
|
# NOTE(morganfainberg): Omit "cls" and "self" when printing trace logs
|
||||||
# the index can be calculated at wrap time rather than at runtime.
|
# the index can be calculated at wrap time rather than at runtime.
|
||||||
|
@ -26,11 +26,7 @@ class Bcrypt(password_hashers.PasswordHasher):
|
|||||||
ident_values: set[str] = {"$2$", "$2a$", "$2b$", "$2x$", "$2y$"}
|
ident_values: set[str] = {"$2$", "$2a$", "$2b$", "$2x$", "$2y$"}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hash(
|
def hash(password: bytes, rounds: int = 12, **kwargs) -> str:
|
||||||
password: bytes,
|
|
||||||
rounds: int = 12,
|
|
||||||
**kwargs,
|
|
||||||
) -> str:
|
|
||||||
"""Generate password hash string with ident and params
|
"""Generate password hash string with ident and params
|
||||||
|
|
||||||
https://pypi.org/project/bcrypt/
|
https://pypi.org/project/bcrypt/
|
||||||
@ -66,11 +62,7 @@ class Bcrypt_sha256(password_hashers.PasswordHasher):
|
|||||||
prefix: str = "$bcrypt-sha256$"
|
prefix: str = "$bcrypt-sha256$"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hash(
|
def hash(password: bytes, rounds: int = 12, **kwargs) -> str:
|
||||||
password: bytes,
|
|
||||||
rounds: int = 12,
|
|
||||||
**kwargs,
|
|
||||||
) -> str:
|
|
||||||
"""Generate password hash string with ident and params
|
"""Generate password hash string with ident and params
|
||||||
|
|
||||||
https://pypi.org/project/bcrypt/
|
https://pypi.org/project/bcrypt/
|
||||||
|
@ -29,11 +29,7 @@ class Sha512(password_hashers.PasswordHasher):
|
|||||||
hash_algo = hashes.SHA512()
|
hash_algo = hashes.SHA512()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hash(
|
def hash(password: bytes, salt_size: int = 16, rounds: int = 25000) -> str:
|
||||||
password: bytes,
|
|
||||||
salt_size: int = 16,
|
|
||||||
rounds: int = 25000,
|
|
||||||
) -> str:
|
|
||||||
"""Generate password hash string with ident and params
|
"""Generate password hash string with ident and params
|
||||||
|
|
||||||
https://cryptography.io/en/stable/hazmat/primitives/key-derivation-functions/#pbkdf2
|
https://cryptography.io/en/stable/hazmat/primitives/key-derivation-functions/#pbkdf2
|
||||||
@ -49,10 +45,7 @@ class Sha512(password_hashers.PasswordHasher):
|
|||||||
|
|
||||||
# Prepave the kdf function with params
|
# Prepave the kdf function with params
|
||||||
kdf = PBKDF2HMAC(
|
kdf = PBKDF2HMAC(
|
||||||
algorithm=Sha512.hash_algo,
|
algorithm=Sha512.hash_algo, length=64, salt=salt, iterations=rounds
|
||||||
length=64,
|
|
||||||
salt=salt,
|
|
||||||
iterations=rounds,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# derive - create a digest
|
# derive - create a digest
|
||||||
@ -101,10 +94,7 @@ class Sha512(password_hashers.PasswordHasher):
|
|||||||
|
|
||||||
# Prepave the kdf function with params
|
# Prepave the kdf function with params
|
||||||
kdf = PBKDF2HMAC(
|
kdf = PBKDF2HMAC(
|
||||||
algorithm=Sha512.hash_algo,
|
algorithm=Sha512.hash_algo, length=64, salt=salt, iterations=rounds
|
||||||
length=64,
|
|
||||||
salt=salt,
|
|
||||||
iterations=rounds,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify the key.
|
# Verify the key.
|
||||||
|
@ -28,9 +28,7 @@ RULE_ADMIN_OR_TARGET_PROJECT = (
|
|||||||
)
|
)
|
||||||
RULE_ADMIN_OR_TOKEN_SUBJECT = 'rule:admin_or_token_subject' # nosec
|
RULE_ADMIN_OR_TOKEN_SUBJECT = 'rule:admin_or_token_subject' # nosec
|
||||||
RULE_REVOKE_EVENT_OR_ADMIN = 'rule:revoke_event_or_admin'
|
RULE_REVOKE_EVENT_OR_ADMIN = 'rule:revoke_event_or_admin'
|
||||||
RULE_SERVICE_ADMIN_OR_TOKEN_SUBJECT = (
|
RULE_SERVICE_ADMIN_OR_TOKEN_SUBJECT = 'rule:service_admin_or_token_subject' # nosec
|
||||||
'rule:service_admin_or_token_subject' # nosec
|
|
||||||
)
|
|
||||||
RULE_SERVICE_OR_ADMIN = 'rule:service_or_admin'
|
RULE_SERVICE_OR_ADMIN = 'rule:service_or_admin'
|
||||||
RULE_TRUST_OWNER = 'user_id:%(trust.trustor_user_id)s'
|
RULE_TRUST_OWNER = 'user_id:%(trust.trustor_user_id)s'
|
||||||
|
|
||||||
|
@ -40,9 +40,7 @@ SYSTEM_ADMIN_OR_DOMAIN_ADMIN_OR_PROJECT_ADMIN = (
|
|||||||
# /v3/users/{user_id}/project path.
|
# /v3/users/{user_id}/project path.
|
||||||
SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER = (
|
SYSTEM_READER_OR_DOMAIN_READER_OR_OWNER = (
|
||||||
# System reader policy
|
# System reader policy
|
||||||
'('
|
'(' + base.SYSTEM_READER + ') or '
|
||||||
+ base.SYSTEM_READER
|
|
||||||
+ ') or '
|
|
||||||
# Domain reader policy
|
# Domain reader policy
|
||||||
'(role:reader and domain_id:%(target.user.domain_id)s) or '
|
'(role:reader and domain_id:%(target.user.domain_id)s) or '
|
||||||
# User accessing the API with a token they've obtained, matching
|
# User accessing the API with a token they've obtained, matching
|
||||||
|
@ -35,7 +35,7 @@ class ProviderAPIRegistry:
|
|||||||
try:
|
try:
|
||||||
return self.__registry[item]
|
return self.__registry[item]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError("'ProviderAPIs' has no attribute %s" % item)
|
raise AttributeError(f"'ProviderAPIs' has no attribute {item}")
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
def __setattr__(self, key, value):
|
||||||
"""Do not allow setting values on the registry object."""
|
"""Do not allow setting values on the registry object."""
|
||||||
@ -58,9 +58,8 @@ class ProviderAPIRegistry:
|
|||||||
|
|
||||||
if name in self.__registry:
|
if name in self.__registry:
|
||||||
raise DuplicateProviderError(
|
raise DuplicateProviderError(
|
||||||
'`%(name)s` has already been registered as an api '
|
f'`{name}` has already been registered as an api '
|
||||||
'provider by `%(prov)r`'
|
f'provider by `{self.__registry[name]!r}`'
|
||||||
% {'name': name, 'prov': self.__registry[name]}
|
|
||||||
)
|
)
|
||||||
self.__registry[name] = obj
|
self.__registry[name] = obj
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ class RBACEnforcer:
|
|||||||
member_name = None
|
member_name = None
|
||||||
func = getattr(resource, 'get_member_from_driver', None)
|
func = getattr(resource, 'get_member_from_driver', None)
|
||||||
if member_name is not None and callable(func):
|
if member_name is not None and callable(func):
|
||||||
key = '%s_id' % member_name
|
key = f'{member_name}_id'
|
||||||
if key in (flask.request.view_args or {}):
|
if key in (flask.request.view_args or {}):
|
||||||
# NOTE(morgan): For most correct setup, instantiate the
|
# NOTE(morgan): For most correct setup, instantiate the
|
||||||
# view_class. There is no current support for passing
|
# view_class. There is no current support for passing
|
||||||
|
@ -107,11 +107,11 @@ def render_token_response_from_model(token, include_catalog=True):
|
|||||||
token_reference['token']['service_providers'] = sps
|
token_reference['token']['service_providers'] = sps
|
||||||
if token.is_federated:
|
if token.is_federated:
|
||||||
PROVIDERS.federation_api.get_idp(token.identity_provider_id)
|
PROVIDERS.federation_api.get_idp(token.identity_provider_id)
|
||||||
federated_dict = dict(
|
federated_dict = {
|
||||||
groups=token.federated_groups,
|
'groups': token.federated_groups,
|
||||||
identity_provider={'id': token.identity_provider_id},
|
'identity_provider': {'id': token.identity_provider_id},
|
||||||
protocol={'id': token.protocol_id},
|
'protocol': {'id': token.protocol_id},
|
||||||
)
|
}
|
||||||
token_reference['token']['user']['OS-FEDERATION'] = federated_dict
|
token_reference['token']['user']['OS-FEDERATION'] = federated_dict
|
||||||
del token_reference['token']['user']['password_expires_at']
|
del token_reference['token']['user']['password_expires_at']
|
||||||
if token.access_token_id:
|
if token.access_token_id:
|
||||||
|
@ -183,7 +183,6 @@ class ResourceOptionRegistry:
|
|||||||
|
|
||||||
|
|
||||||
class ResourceOption:
|
class ResourceOption:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
option_id,
|
option_id,
|
||||||
|
@ -18,6 +18,7 @@ Before using this module, call initialize(). This has to be done before
|
|||||||
CONF() because it sets up configuration options.
|
CONF() because it sets up configuration options.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
@ -117,7 +118,6 @@ ModelBase.__init__ = initialize_decorator(ModelBase.__init__)
|
|||||||
|
|
||||||
# Special Fields
|
# Special Fields
|
||||||
class JsonBlob(sql_types.TypeDecorator):
|
class JsonBlob(sql_types.TypeDecorator):
|
||||||
|
|
||||||
impl = sql.Text
|
impl = sql.Text
|
||||||
# NOTE(ralonsoh): set to True as any other TypeDecorator in SQLAlchemy
|
# NOTE(ralonsoh): set to True as any other TypeDecorator in SQLAlchemy
|
||||||
# https://docs.sqlalchemy.org/en/14/core/custom_types.html# \
|
# https://docs.sqlalchemy.org/en/14/core/custom_types.html# \
|
||||||
@ -256,7 +256,6 @@ class ModelDictMixinWithExtras(models.ModelBase):
|
|||||||
|
|
||||||
|
|
||||||
class ModelDictMixin(models.ModelBase):
|
class ModelDictMixin(models.ModelBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, d):
|
def from_dict(cls, d):
|
||||||
"""Return a model instance from a dictionary."""
|
"""Return a model instance from a dictionary."""
|
||||||
@ -413,13 +412,13 @@ def _filter(model, query, hints):
|
|||||||
|
|
||||||
if filter_['comparator'] == 'contains':
|
if filter_['comparator'] == 'contains':
|
||||||
_WontMatch.check(filter_['value'], column_attr)
|
_WontMatch.check(filter_['value'], column_attr)
|
||||||
query_term = column_attr.ilike('%%%s%%' % filter_['value'])
|
query_term = column_attr.ilike('%{}%'.format(filter_['value']))
|
||||||
elif filter_['comparator'] == 'startswith':
|
elif filter_['comparator'] == 'startswith':
|
||||||
_WontMatch.check(filter_['value'], column_attr)
|
_WontMatch.check(filter_['value'], column_attr)
|
||||||
query_term = column_attr.ilike('%s%%' % filter_['value'])
|
query_term = column_attr.ilike('{}%'.format(filter_['value']))
|
||||||
elif filter_['comparator'] == 'endswith':
|
elif filter_['comparator'] == 'endswith':
|
||||||
_WontMatch.check(filter_['value'], column_attr)
|
_WontMatch.check(filter_['value'], column_attr)
|
||||||
query_term = column_attr.ilike('%%%s' % filter_['value'])
|
query_term = column_attr.ilike('%{}'.format(filter_['value']))
|
||||||
else:
|
else:
|
||||||
# It's a filter we don't understand, so let the caller
|
# It's a filter we don't understand, so let the caller
|
||||||
# work out if they need to do something with it.
|
# work out if they need to do something with it.
|
||||||
|
@ -51,8 +51,7 @@ def _migration_script_ops(context, directive, phase):
|
|||||||
"""
|
"""
|
||||||
autogen_kwargs = {}
|
autogen_kwargs = {}
|
||||||
version_path = upgrades.get_version_branch_path(
|
version_path = upgrades.get_version_branch_path(
|
||||||
release=upgrades.CURRENT_RELEASE,
|
release=upgrades.CURRENT_RELEASE, branch=phase
|
||||||
branch=phase,
|
|
||||||
)
|
)
|
||||||
upgrades.check_bootstrap_new_branch(phase, version_path, autogen_kwargs)
|
upgrades.check_bootstrap_new_branch(phase, version_path, autogen_kwargs)
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ def _migration_script_ops(context, directive, phase):
|
|||||||
),
|
),
|
||||||
ops.DowngradeOps(ops=[]),
|
ops.DowngradeOps(ops=[]),
|
||||||
message=directive.message,
|
message=directive.message,
|
||||||
**autogen_kwargs
|
**autogen_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not op.upgrade_ops.is_empty():
|
if not op.upgrade_ops.is_empty():
|
||||||
|
@ -134,14 +134,10 @@ def do_upgrade(config, cmd):
|
|||||||
|
|
||||||
if revision in upgrades.MILESTONES:
|
if revision in upgrades.MILESTONES:
|
||||||
expand_revisions = _find_milestone_revisions(
|
expand_revisions = _find_milestone_revisions(
|
||||||
config,
|
config, revision, upgrades.EXPAND_BRANCH
|
||||||
revision,
|
|
||||||
upgrades.EXPAND_BRANCH,
|
|
||||||
)
|
)
|
||||||
contract_revisions = _find_milestone_revisions(
|
contract_revisions = _find_milestone_revisions(
|
||||||
config,
|
config, revision, upgrades.CONTRACT_BRANCH
|
||||||
revision,
|
|
||||||
upgrades.CONTRACT_BRANCH,
|
|
||||||
)
|
)
|
||||||
# Expand revisions must be run before contract revisions
|
# Expand revisions must be run before contract revisions
|
||||||
revisions = expand_revisions + contract_revisions
|
revisions = expand_revisions + contract_revisions
|
||||||
@ -152,10 +148,7 @@ def do_upgrade(config, cmd):
|
|||||||
# if not CONF.command.sql:
|
# if not CONF.command.sql:
|
||||||
# run_sanity_checks(config, revision)
|
# run_sanity_checks(config, revision)
|
||||||
do_alembic_command(
|
do_alembic_command(
|
||||||
config,
|
config, cmd, revision=revision, sql=CONF.command.sql
|
||||||
cmd,
|
|
||||||
revision=revision,
|
|
||||||
sql=CONF.command.sql,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -179,8 +172,7 @@ def do_revision(config, cmd):
|
|||||||
for branch in branches:
|
for branch in branches:
|
||||||
args = copy.copy(kwargs)
|
args = copy.copy(kwargs)
|
||||||
version_path = upgrades.get_version_branch_path(
|
version_path = upgrades.get_version_branch_path(
|
||||||
release=upgrades.CURRENT_RELEASE,
|
release=upgrades.CURRENT_RELEASE, branch=branch
|
||||||
branch=branch,
|
|
||||||
)
|
)
|
||||||
upgrades.check_bootstrap_new_branch(branch, version_path, args)
|
upgrades.check_bootstrap_new_branch(branch, version_path, args)
|
||||||
do_alembic_command(config, cmd, **args)
|
do_alembic_command(config, cmd, **args)
|
||||||
|
@ -46,8 +46,7 @@ def upgrade():
|
|||||||
if bind.engine.name == 'mysql':
|
if bind.engine.name == 'mysql':
|
||||||
# Set default DB charset to UTF8.
|
# Set default DB charset to UTF8.
|
||||||
op.execute(
|
op.execute(
|
||||||
'ALTER DATABASE %s DEFAULT CHARACTER SET utf8'
|
f'ALTER DATABASE {bind.engine.url.database} DEFAULT CHARACTER SET utf8'
|
||||||
% bind.engine.url.database
|
|
||||||
)
|
)
|
||||||
|
|
||||||
op.create_table(
|
op.create_table(
|
||||||
@ -89,11 +88,7 @@ def upgrade():
|
|||||||
sql.Column('role_id', sql.String(64), nullable=False),
|
sql.Column('role_id', sql.String(64), nullable=False),
|
||||||
sql.Column('inherited', sql.Boolean, default=False, nullable=False),
|
sql.Column('inherited', sql.Boolean, default=False, nullable=False),
|
||||||
sql.PrimaryKeyConstraint(
|
sql.PrimaryKeyConstraint(
|
||||||
'type',
|
'type', 'actor_id', 'target_id', 'role_id', 'inherited'
|
||||||
'actor_id',
|
|
||||||
'target_id',
|
|
||||||
'role_id',
|
|
||||||
'inherited',
|
|
||||||
),
|
),
|
||||||
sql.Index('ix_actor_id', 'actor_id'),
|
sql.Index('ix_actor_id', 'actor_id'),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
@ -109,8 +104,7 @@ def upgrade():
|
|||||||
sql.Column('external_id', sql.String(64)),
|
sql.Column('external_id', sql.String(64)),
|
||||||
sql.Column('user_id', sql.String(64)),
|
sql.Column('user_id', sql.String(64)),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'external_id',
|
'external_id', name='access_rule_external_id_key'
|
||||||
name='access_rule_external_id_key',
|
|
||||||
),
|
),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'user_id',
|
'user_id',
|
||||||
@ -149,11 +143,7 @@ def upgrade():
|
|||||||
sql.Column('type', sql.String(length=255), nullable=False),
|
sql.Column('type', sql.String(length=255), nullable=False),
|
||||||
sql.Column('extra', ks_sql.JsonBlob.impl),
|
sql.Column('extra', ks_sql.JsonBlob.impl),
|
||||||
sql.Column('key_hash', sql.String(64), nullable=False),
|
sql.Column('key_hash', sql.String(64), nullable=False),
|
||||||
sql.Column(
|
sql.Column('encrypted_blob', ks_sql.Text, nullable=False),
|
||||||
'encrypted_blob',
|
|
||||||
ks_sql.Text,
|
|
||||||
nullable=False,
|
|
||||||
),
|
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
)
|
)
|
||||||
@ -166,9 +156,7 @@ def upgrade():
|
|||||||
sql.Column('description', sql.Text),
|
sql.Column('description', sql.Text),
|
||||||
sql.Column('extra', ks_sql.JsonBlob.impl),
|
sql.Column('extra', ks_sql.JsonBlob.impl),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'domain_id',
|
'domain_id', 'name', name='ixu_group_name_domain_id'
|
||||||
'name',
|
|
||||||
name='ixu_group_name_domain_id',
|
|
||||||
),
|
),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
@ -189,10 +177,7 @@ def upgrade():
|
|||||||
nullable=False,
|
nullable=False,
|
||||||
),
|
),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'domain_id',
|
'domain_id', 'local_id', 'entity_type', name='domain_id'
|
||||||
'local_id',
|
|
||||||
'entity_type',
|
|
||||||
name='domain_id',
|
|
||||||
),
|
),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
@ -261,19 +246,13 @@ def upgrade():
|
|||||||
sql.Column(
|
sql.Column(
|
||||||
'domain_id',
|
'domain_id',
|
||||||
sql.String(length=64),
|
sql.String(length=64),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey('project.id', name='project_domain_id_fkey'),
|
||||||
'project.id',
|
|
||||||
name='project_domain_id_fkey',
|
|
||||||
),
|
|
||||||
nullable=False,
|
nullable=False,
|
||||||
),
|
),
|
||||||
sql.Column(
|
sql.Column(
|
||||||
'parent_id',
|
'parent_id',
|
||||||
sql.String(64),
|
sql.String(64),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey('project.id', name='project_parent_id_fkey'),
|
||||||
'project.id',
|
|
||||||
name='project_parent_id_fkey',
|
|
||||||
),
|
|
||||||
nullable=True,
|
nullable=True,
|
||||||
),
|
),
|
||||||
sql.Column(
|
sql.Column(
|
||||||
@ -284,9 +263,7 @@ def upgrade():
|
|||||||
default=False,
|
default=False,
|
||||||
),
|
),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'domain_id',
|
'domain_id', 'name', name='ixu_project_name_domain_id'
|
||||||
'name',
|
|
||||||
name='ixu_project_name_domain_id',
|
|
||||||
),
|
),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
@ -439,9 +416,7 @@ def upgrade():
|
|||||||
),
|
),
|
||||||
sql.Column('description', sql.String(255), nullable=True),
|
sql.Column('description', sql.String(255), nullable=True),
|
||||||
sql.UniqueConstraint(
|
sql.UniqueConstraint(
|
||||||
'name',
|
'name', 'domain_id', name='ixu_role_name_domain_id'
|
||||||
'domain_id',
|
|
||||||
name='ixu_role_name_domain_id',
|
|
||||||
),
|
),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
@ -558,16 +533,8 @@ def upgrade():
|
|||||||
'expires_at_int',
|
'expires_at_int',
|
||||||
name='duplicate_trust_constraint_expanded',
|
name='duplicate_trust_constraint_expanded',
|
||||||
),
|
),
|
||||||
sql.Column(
|
sql.Column('redelegated_trust_id', sql.String(64), nullable=True),
|
||||||
'redelegated_trust_id',
|
sql.Column('redelegation_count', sql.Integer, nullable=True),
|
||||||
sql.String(64),
|
|
||||||
nullable=True,
|
|
||||||
),
|
|
||||||
sql.Column(
|
|
||||||
'redelegation_count',
|
|
||||||
sql.Integer,
|
|
||||||
nullable=True,
|
|
||||||
),
|
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8',
|
mysql_charset='utf8',
|
||||||
)
|
)
|
||||||
@ -604,18 +571,14 @@ def upgrade():
|
|||||||
sql.Column(
|
sql.Column(
|
||||||
'user_id',
|
'user_id',
|
||||||
sql.String(length=64),
|
sql.String(length=64),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey('user.id', name='fk_user_group_membership_user_id'),
|
||||||
'user.id',
|
|
||||||
name='fk_user_group_membership_user_id',
|
|
||||||
),
|
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
),
|
),
|
||||||
sql.Column(
|
sql.Column(
|
||||||
'group_id',
|
'group_id',
|
||||||
sql.String(length=64),
|
sql.String(length=64),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey(
|
||||||
'group.id',
|
'group.id', name='fk_user_group_membership_group_id'
|
||||||
name='fk_user_group_membership_group_id',
|
|
||||||
),
|
),
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
),
|
),
|
||||||
@ -720,10 +683,7 @@ def upgrade():
|
|||||||
sql.Column(
|
sql.Column(
|
||||||
'service_id',
|
'service_id',
|
||||||
sql.String(length=64),
|
sql.String(length=64),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey('service.id', name='endpoint_service_id_fkey'),
|
||||||
'service.id',
|
|
||||||
name='endpoint_service_id_fkey',
|
|
||||||
),
|
|
||||||
nullable=False,
|
nullable=False,
|
||||||
),
|
),
|
||||||
sql.Column('url', sql.Text, nullable=False),
|
sql.Column('url', sql.Text, nullable=False),
|
||||||
@ -738,10 +698,7 @@ def upgrade():
|
|||||||
sql.Column(
|
sql.Column(
|
||||||
'region_id',
|
'region_id',
|
||||||
sql.String(length=255),
|
sql.String(length=255),
|
||||||
sql.ForeignKey(
|
sql.ForeignKey('region.id', name='fk_endpoint_region_id'),
|
||||||
'region.id',
|
|
||||||
name='fk_endpoint_region_id',
|
|
||||||
),
|
|
||||||
nullable=True,
|
nullable=True,
|
||||||
),
|
),
|
||||||
# NOTE(stevemar): The index was named 'service_id' in
|
# NOTE(stevemar): The index was named 'service_id' in
|
||||||
@ -835,10 +792,7 @@ def upgrade():
|
|||||||
# FIXME(stephenfin): This should have a foreign key constraint on
|
# FIXME(stephenfin): This should have a foreign key constraint on
|
||||||
# registered_limit.id, but sqlalchemy-migrate clearly didn't handle
|
# registered_limit.id, but sqlalchemy-migrate clearly didn't handle
|
||||||
# creating a column with embedded FK info as was attempted in 048
|
# creating a column with embedded FK info as was attempted in 048
|
||||||
sql.Column(
|
sql.Column('registered_limit_id', sql.String(64)),
|
||||||
'registered_limit_id',
|
|
||||||
sql.String(64),
|
|
||||||
),
|
|
||||||
sql.Column('domain_id', sql.String(64), nullable=True),
|
sql.Column('domain_id', sql.String(64), nullable=True),
|
||||||
# NOTE(stephenfin): Name chosen to preserve backwards compatibility
|
# NOTE(stephenfin): Name chosen to preserve backwards compatibility
|
||||||
# with names used for primary key unique constraints
|
# with names used for primary key unique constraints
|
||||||
@ -850,12 +804,7 @@ def upgrade():
|
|||||||
op.create_table(
|
op.create_table(
|
||||||
'local_user',
|
'local_user',
|
||||||
sql.Column('id', sql.Integer, primary_key=True, nullable=False),
|
sql.Column('id', sql.Integer, primary_key=True, nullable=False),
|
||||||
sql.Column(
|
sql.Column('user_id', sql.String(64), nullable=False, unique=True),
|
||||||
'user_id',
|
|
||||||
sql.String(64),
|
|
||||||
nullable=False,
|
|
||||||
unique=True,
|
|
||||||
),
|
|
||||||
sql.Column('domain_id', sql.String(64), nullable=False),
|
sql.Column('domain_id', sql.String(64), nullable=False),
|
||||||
sql.Column('name', sql.String(255), nullable=False),
|
sql.Column('name', sql.String(255), nullable=False),
|
||||||
sql.Column('failed_auth_count', sql.Integer, nullable=True),
|
sql.Column('failed_auth_count', sql.Integer, nullable=True),
|
||||||
@ -874,11 +823,7 @@ def upgrade():
|
|||||||
'nonlocal_user',
|
'nonlocal_user',
|
||||||
sql.Column('domain_id', sql.String(64), primary_key=True),
|
sql.Column('domain_id', sql.String(64), primary_key=True),
|
||||||
sql.Column('name', sql.String(255), primary_key=True),
|
sql.Column('name', sql.String(255), primary_key=True),
|
||||||
sql.Column(
|
sql.Column('user_id', sql.String(64), nullable=False),
|
||||||
'user_id',
|
|
||||||
sql.String(64),
|
|
||||||
nullable=False,
|
|
||||||
),
|
|
||||||
sql.ForeignKeyConstraint(
|
sql.ForeignKeyConstraint(
|
||||||
['user_id', 'domain_id'],
|
['user_id', 'domain_id'],
|
||||||
['user.id', 'user.domain_id'],
|
['user.id', 'user.domain_id'],
|
||||||
@ -974,10 +919,7 @@ def upgrade():
|
|||||||
# only for sqlite, once we collapse 073 we can remove this constraint
|
# only for sqlite, once we collapse 073 we can remove this constraint
|
||||||
with op.batch_alter_table('assignment') as batch_op:
|
with op.batch_alter_table('assignment') as batch_op:
|
||||||
batch_op.create_foreign_key(
|
batch_op.create_foreign_key(
|
||||||
'fk_assignment_role_id',
|
'fk_assignment_role_id', 'role', ['role_id'], ['id']
|
||||||
'role',
|
|
||||||
['role_id'],
|
|
||||||
['id'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO(stephenfin): Remove these procedures in a future contract migration
|
# TODO(stephenfin): Remove these procedures in a future contract migration
|
||||||
@ -1064,9 +1006,7 @@ def upgrade():
|
|||||||
# FIXME(stephenfin): This should be dropped when we add the FK
|
# FIXME(stephenfin): This should be dropped when we add the FK
|
||||||
# constraint to this column
|
# constraint to this column
|
||||||
op.create_index(
|
op.create_index(
|
||||||
'registered_limit_id',
|
'registered_limit_id', 'limit', ['registered_limit_id']
|
||||||
'limit',
|
|
||||||
['registered_limit_id'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIXME(stephenfin): These are leftover from when we removed a FK
|
# FIXME(stephenfin): These are leftover from when we removed a FK
|
||||||
|
@ -28,7 +28,4 @@ depends_on = None
|
|||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
with op.batch_alter_table('service_provider', schema=None) as batch_op:
|
with op.batch_alter_table('service_provider', schema=None) as batch_op:
|
||||||
batch_op.alter_column(
|
batch_op.alter_column('relay_state_prefix', server_default=None)
|
||||||
'relay_state_prefix',
|
|
||||||
server_default=None,
|
|
||||||
)
|
|
||||||
|
@ -36,11 +36,7 @@ EXPAND_BRANCH = 'expand'
|
|||||||
DATA_MIGRATION_BRANCH = 'data_migration'
|
DATA_MIGRATION_BRANCH = 'data_migration'
|
||||||
CONTRACT_BRANCH = 'contract'
|
CONTRACT_BRANCH = 'contract'
|
||||||
|
|
||||||
RELEASES = (
|
RELEASES = ('yoga', 'bobcat', '2024.01')
|
||||||
'yoga',
|
|
||||||
'bobcat',
|
|
||||||
'2024.01',
|
|
||||||
)
|
|
||||||
MILESTONES = (
|
MILESTONES = (
|
||||||
'yoga',
|
'yoga',
|
||||||
# Do not add the milestone until the end of the release
|
# Do not add the milestone until the end of the release
|
||||||
@ -48,9 +44,7 @@ MILESTONES = (
|
|||||||
CURRENT_RELEASE = RELEASES[-1]
|
CURRENT_RELEASE = RELEASES[-1]
|
||||||
MIGRATION_BRANCHES = (EXPAND_BRANCH, CONTRACT_BRANCH)
|
MIGRATION_BRANCHES = (EXPAND_BRANCH, CONTRACT_BRANCH)
|
||||||
VERSIONS_PATH = os.path.join(
|
VERSIONS_PATH = os.path.join(
|
||||||
os.path.dirname(sql.__file__),
|
os.path.dirname(sql.__file__), 'migrations', 'versions'
|
||||||
'migrations',
|
|
||||||
'versions',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -77,8 +71,7 @@ def _find_alembic_conf():
|
|||||||
:returns: An instance of ``alembic.config.Config``
|
:returns: An instance of ``alembic.config.Config``
|
||||||
"""
|
"""
|
||||||
path = os.path.join(
|
path = os.path.join(
|
||||||
os.path.abspath(os.path.dirname(__file__)),
|
os.path.abspath(os.path.dirname(__file__)), 'alembic.ini'
|
||||||
'alembic.ini',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
config = alembic_config.Config(os.path.abspath(path))
|
config = alembic_config.Config(os.path.abspath(path))
|
||||||
|
@ -66,9 +66,7 @@ check_password = password_hashing.check_password
|
|||||||
# NOTE(hiromu): This dict defines alternative DN string for X.509. When
|
# NOTE(hiromu): This dict defines alternative DN string for X.509. When
|
||||||
# retriving DN from X.509, converting attributes types that are not listed
|
# retriving DN from X.509, converting attributes types that are not listed
|
||||||
# in the RFC4514 to a corresponding alternative DN string.
|
# in the RFC4514 to a corresponding alternative DN string.
|
||||||
ATTR_NAME_OVERRIDES = {
|
ATTR_NAME_OVERRIDES = {x509.NameOID.EMAIL_ADDRESS: "emailAddress"}
|
||||||
x509.NameOID.EMAIL_ADDRESS: "emailAddress",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def resource_uuid(value):
|
def resource_uuid(value):
|
||||||
@ -217,7 +215,7 @@ def get_unix_user(user=None):
|
|||||||
try:
|
try:
|
||||||
i = int(user)
|
i = int(user)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise KeyError("user name '%s' not found" % user)
|
raise KeyError(f"user name '{user}' not found")
|
||||||
try:
|
try:
|
||||||
user_info = pwd.getpwuid(i)
|
user_info = pwd.getpwuid(i)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -232,8 +230,7 @@ def get_unix_user(user=None):
|
|||||||
else:
|
else:
|
||||||
user_cls_name = reflection.get_class_name(user, fully_qualified=False)
|
user_cls_name = reflection.get_class_name(user, fully_qualified=False)
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
'user must be string, int or None; not %s (%r)'
|
f'user must be string, int or None; not {user_cls_name} ({user!r})'
|
||||||
% (user_cls_name, user)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return user_info.pw_uid, user_info.pw_name
|
return user_info.pw_uid, user_info.pw_name
|
||||||
@ -278,7 +275,7 @@ def get_unix_group(group=None):
|
|||||||
try:
|
try:
|
||||||
i = int(group)
|
i = int(group)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise KeyError("group name '%s' not found" % group)
|
raise KeyError(f"group name '{group}' not found")
|
||||||
try:
|
try:
|
||||||
group_info = grp.getgrgid(i)
|
group_info = grp.getgrgid(i)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -295,15 +292,13 @@ def get_unix_group(group=None):
|
|||||||
group, fully_qualified=False
|
group, fully_qualified=False
|
||||||
)
|
)
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
'group must be string, int or None; not %s (%r)'
|
f'group must be string, int or None; not {group_cls_name} ({group!r})'
|
||||||
% (group_cls_name, group)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return group_info.gr_gid, group_info.gr_name
|
return group_info.gr_gid, group_info.gr_name
|
||||||
|
|
||||||
|
|
||||||
class WhiteListedItemFilter:
|
class WhiteListedItemFilter:
|
||||||
|
|
||||||
def __init__(self, whitelist, data):
|
def __init__(self, whitelist, data):
|
||||||
self._whitelist = set(whitelist or [])
|
self._whitelist = set(whitelist or [])
|
||||||
self._data = data
|
self._data = data
|
||||||
|
@ -105,10 +105,7 @@ def set_default_for_default_log_levels():
|
|||||||
This function needs to be called before CONF().
|
This function needs to be called before CONF().
|
||||||
|
|
||||||
"""
|
"""
|
||||||
extra_log_level_defaults = [
|
extra_log_level_defaults = ['dogpile=INFO', 'routes=INFO']
|
||||||
'dogpile=INFO',
|
|
||||||
'routes=INFO',
|
|
||||||
]
|
|
||||||
|
|
||||||
log.register_options(CONF)
|
log.register_options(CONF)
|
||||||
log.set_defaults(
|
log.set_defaults(
|
||||||
|
@ -63,12 +63,7 @@ keystone database or open keystone to a DoS attack.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, caching, cache_time, user_limit]
|
||||||
driver,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
user_limit,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -75,13 +75,7 @@ have enough services or endpoints to exceed a reasonable limit.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [template_file, driver, caching, cache_time, list_limit]
|
||||||
template_file,
|
|
||||||
driver,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
list_limit,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -16,7 +16,6 @@ package.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
_DEFAULT_AUTH_METHODS = [
|
_DEFAULT_AUTH_METHODS = [
|
||||||
'external',
|
'external',
|
||||||
'password',
|
'password',
|
||||||
|
@ -42,10 +42,7 @@ catalog. If set to false, keystone will return an empty service catalog.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, return_all_endpoints_if_no_filter]
|
||||||
driver,
|
|
||||||
return_all_endpoints_if_no_filter,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -28,9 +28,7 @@ to set this unless you are providing a custom entry point.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver]
|
||||||
driver,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -62,10 +62,7 @@ this value means that additional secondary keys will be kept in the rotation.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [key_repository, max_active_keys]
|
||||||
key_repository,
|
|
||||||
max_active_keys,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -60,10 +60,7 @@ this value means that additional secondary keys will be kept in the rotation.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [key_repository, max_active_keys]
|
||||||
key_repository,
|
|
||||||
max_active_keys,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -67,11 +67,7 @@ recommended value.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, generator, backward_compatible_ids]
|
||||||
driver,
|
|
||||||
generator,
|
|
||||||
backward_compatible_ids,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -55,11 +55,7 @@ means that access tokens will last forever.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, request_token_duration, access_token_duration]
|
||||||
driver,
|
|
||||||
request_token_duration,
|
|
||||||
access_token_duration,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -47,7 +47,7 @@ def list_opts():
|
|||||||
|
|
||||||
def _tupleize(d):
|
def _tupleize(d):
|
||||||
"""Convert a dict of options to the 2-tuple format."""
|
"""Convert a dict of options to the 2-tuple format."""
|
||||||
return [(key, value) for key, value in d.items()]
|
return list(d.items())
|
||||||
|
|
||||||
|
|
||||||
def _list_module_names():
|
def _list_module_names():
|
||||||
@ -69,9 +69,8 @@ def _import_modules(module_names):
|
|||||||
module = importlib.import_module(full_module_path)
|
module = importlib.import_module(full_module_path)
|
||||||
if not hasattr(module, LIST_OPTS_FUNC_NAME):
|
if not hasattr(module, LIST_OPTS_FUNC_NAME):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"The module '%s' should have a '%s' function which "
|
f"The module '{full_module_path}' should have a '{LIST_OPTS_FUNC_NAME}' function which "
|
||||||
"returns the config options."
|
"returns the config options."
|
||||||
% (full_module_path, LIST_OPTS_FUNC_NAME)
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
imported_modules.append(module)
|
imported_modules.append(module)
|
||||||
|
@ -38,10 +38,7 @@ Maximum number of entities that will be returned in a policy collection.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, list_limit]
|
||||||
driver,
|
|
||||||
list_limit,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -83,13 +83,7 @@ has no effect unless global caching and receipt caching are enabled.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [expiration, provider, caching, cache_time, cache_on_issue]
|
||||||
expiration,
|
|
||||||
provider,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
cache_on_issue,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -65,12 +65,7 @@ has no effect unless global and `[revoke] caching` are both enabled.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, expiration_buffer, caching, cache_time]
|
||||||
driver,
|
|
||||||
expiration_buffer,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -61,12 +61,7 @@ deployment.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, caching, cache_time, list_limit]
|
||||||
driver,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
list_limit,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -30,9 +30,7 @@ this option unless you are providing a custom entry point.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver]
|
||||||
driver,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -61,11 +61,7 @@ this value.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [trusted_issuer, protocol, issuer_attribute]
|
||||||
trusted_issuer,
|
|
||||||
protocol,
|
|
||||||
issuer_attribute,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -28,9 +28,7 @@ The number of previous windows to check when processing TOTP passcodes.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [included_previous_windows]
|
||||||
included_previous_windows,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -52,11 +52,7 @@ unless you are providing a custom entry point.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [allow_redelegation, max_redelegation_count, driver]
|
||||||
allow_redelegation,
|
|
||||||
max_redelegation_count,
|
|
||||||
driver,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -74,13 +74,7 @@ running deployment.
|
|||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [driver, caching, cache_time, list_limit, enforcement_model]
|
||||||
driver,
|
|
||||||
caching,
|
|
||||||
cache_time,
|
|
||||||
list_limit,
|
|
||||||
enforcement_model,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -39,9 +39,7 @@ SENSITIVE/PRIVILEGED DATA.
|
|||||||
)
|
)
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
GROUP_NAME = __name__.split('.')[-1]
|
||||||
ALL_OPTS = [
|
ALL_OPTS = [debug_middleware]
|
||||||
debug_middleware,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
def register_opts(conf):
|
||||||
|
@ -54,7 +54,6 @@ class CredentialModel(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
|||||||
|
|
||||||
|
|
||||||
class Credential(base.CredentialDriverBase):
|
class Credential(base.CredentialDriverBase):
|
||||||
|
|
||||||
# credential crud
|
# credential crud
|
||||||
|
|
||||||
@sql.handle_conflicts(conflict_type='credential')
|
@sql.handle_conflicts(conflict_type='credential')
|
||||||
|
@ -50,7 +50,7 @@ class Manager(manager.Manager):
|
|||||||
if credential['type'] == 'ec2':
|
if credential['type'] == 'ec2':
|
||||||
decrypted_blob = json.loads(
|
decrypted_blob = json.loads(
|
||||||
PROVIDERS.credential_provider_api.decrypt(
|
PROVIDERS.credential_provider_api.decrypt(
|
||||||
credential['encrypted_blob'],
|
credential['encrypted_blob']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -17,7 +17,6 @@ CONF = keystone.conf.CONF
|
|||||||
|
|
||||||
|
|
||||||
class Manager(manager.Manager):
|
class Manager(manager.Manager):
|
||||||
|
|
||||||
driver_namespace = 'keystone.credential.provider'
|
driver_namespace = 'keystone.credential.provider'
|
||||||
_provides_api = 'credential_provider_api'
|
_provides_api = 'credential_provider_api'
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ class Provider(core.Provider):
|
|||||||
primary_key_hash(keys),
|
primary_key_hash(keys),
|
||||||
)
|
)
|
||||||
except (TypeError, ValueError) as e:
|
except (TypeError, ValueError) as e:
|
||||||
msg = 'Credential could not be encrypted: %s' % str(e)
|
msg = f'Credential could not be encrypted: {str(e)}'
|
||||||
tr_msg = _('Credential could not be encrypted: %s') % str(e)
|
tr_msg = _('Credential could not be encrypted: %s') % str(e)
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.CredentialEncryptionError(tr_msg)
|
raise exception.CredentialEncryptionError(tr_msg)
|
||||||
|
@ -135,7 +135,7 @@ update_request_body: dict[str, Any] = {
|
|||||||
"properties": _credential_properties,
|
"properties": _credential_properties,
|
||||||
"additionalProperties": True,
|
"additionalProperties": True,
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
"required": ["credential"],
|
"required": ["credential"],
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,6 @@ class PolicyAssociation(sql.ModelBase, sql.ModelDictMixin):
|
|||||||
|
|
||||||
|
|
||||||
class EndpointPolicy(base.EndpointPolicyDriverBase):
|
class EndpointPolicy(base.EndpointPolicyDriverBase):
|
||||||
|
|
||||||
def create_policy_association(
|
def create_policy_association(
|
||||||
self, policy_id, endpoint_id=None, service_id=None, region_id=None
|
self, policy_id, endpoint_id=None, service_id=None, region_id=None
|
||||||
):
|
):
|
||||||
|
@ -97,7 +97,6 @@ class Manager(manager.Manager):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def list_endpoints_for_policy(self, policy_id):
|
def list_endpoints_for_policy(self, policy_id):
|
||||||
|
|
||||||
def _get_endpoint(endpoint_id, policy_id):
|
def _get_endpoint(endpoint_id, policy_id):
|
||||||
try:
|
try:
|
||||||
return PROVIDERS.catalog_api.get_endpoint(endpoint_id)
|
return PROVIDERS.catalog_api.get_endpoint(endpoint_id)
|
||||||
@ -235,7 +234,6 @@ class Manager(manager.Manager):
|
|||||||
return matching_endpoints
|
return matching_endpoints
|
||||||
|
|
||||||
def get_policy_for_endpoint(self, endpoint_id):
|
def get_policy_for_endpoint(self, endpoint_id):
|
||||||
|
|
||||||
def _get_policy(policy_id, endpoint_id):
|
def _get_policy(policy_id, endpoint_id):
|
||||||
try:
|
try:
|
||||||
return PROVIDERS.policy_api.get_policy(policy_id)
|
return PROVIDERS.policy_api.get_policy(policy_id)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user