From b449d86ee56960adacfcf2086f07b57324f51d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Douglas=20Mendiz=C3=A1bal?= Date: Wed, 27 Mar 2024 08:55:54 -0500 Subject: [PATCH] Allow admin to access tokens and credentials This patch modifies a few policies to allow users with the "admin" role to access /v3/auth/tokens and /v3/credentials. These policies were missed when we implemented Phase 1 of Secure RBAC. Change-Id: Id789c09121f1405f7ba5e4926498dab4ad98e057 (cherry picked from commit b31007e1b2ecbea5e1268d3e28d6230d0f5d09b2) (cherry picked from commit 0dcc423a2621943ab9188cff3edb9bc488339fe0) (cherry picked from commit 570c19e91bc3212f748221bdab5f2976f479fa13) --- .../common/policies/application_credential.py | 6 +++--- keystone/common/policies/base.py | 12 ++++++++---- keystone/common/policies/credential.py | 10 +++++----- keystone/common/policies/ec2_credential.py | 8 ++++---- keystone/common/policies/token.py | 16 +++++++++------- keystone/tests/protection/v3/test_credentials.py | 12 +++++++----- .../tests/protection/v3/test_ec2_credential.py | 4 ++-- 7 files changed, 38 insertions(+), 30 deletions(-) diff --git a/keystone/common/policies/application_credential.py b/keystone/common/policies/application_credential.py index bae998a397..12958d8cd2 100644 --- a/keystone/common/policies/application_credential.py +++ b/keystone/common/policies/application_credential.py @@ -46,7 +46,7 @@ deprecated_delete_application_credentials_for_user = policy.DeprecatedRule( application_credential_policies = [ policy.DocumentedRuleDefault( name=base.IDENTITY % 'get_application_credential', - check_str=base.RULE_SYSTEM_READER_OR_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_OWNER, scope_types=['system', 'project'], description='Show application credential details.', operations=[{'path': resource_path, @@ -56,7 +56,7 @@ application_credential_policies = [ deprecated_rule=deprecated_get_application_credentials_for_user), policy.DocumentedRuleDefault( name=base.IDENTITY % 'list_application_credentials', - check_str=base.RULE_SYSTEM_READER_OR_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_OWNER, scope_types=['system', 'project'], description='List application credentials for a user.', operations=[{'path': collection_path, @@ -73,7 +73,7 @@ application_credential_policies = [ 'method': 'POST'}]), policy.DocumentedRuleDefault( name=base.IDENTITY % 'delete_application_credential', - check_str=base.RULE_SYSTEM_ADMIN_OR_OWNER, + check_str=base.RULE_ADMIN_OR_OWNER, scope_types=['system', 'project'], description='Delete an application credential.', operations=[{'path': resource_path, diff --git a/keystone/common/policies/base.py b/keystone/common/policies/base.py index 5b323f5615..39df9eaa28 100644 --- a/keystone/common/policies/base.py +++ b/keystone/common/policies/base.py @@ -48,16 +48,20 @@ SYSTEM_READER = 'role:reader and system_scope:all' SYSTEM_ADMIN = 'role:admin and system_scope:all' DOMAIN_READER = 'role:reader and domain_id:%(target.domain_id)s' RULE_SYSTEM_ADMIN_OR_OWNER = '(' + SYSTEM_ADMIN + ') or rule:owner' -RULE_SYSTEM_READER_OR_OWNER = '(' + SYSTEM_READER + ') or rule:owner' +ADMIN_OR_SYSTEM_READER_OR_OWNER = ( + '(' + RULE_ADMIN_REQUIRED + ') or ' + '(' + SYSTEM_READER + ') or rule:owner' +) RULE_ADMIN_OR_SYSTEM_READER = 'rule:admin_required or (' + SYSTEM_READER + ')' # Credential and EC2 Credential policies -SYSTEM_READER_OR_CRED_OWNER = ( +ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER = ( + '(' + RULE_ADMIN_REQUIRED + ') or ' '(' + SYSTEM_READER + ') ' 'or user_id:%(target.credential.user_id)s' ) -SYSTEM_ADMIN_OR_CRED_OWNER = ( - '(' + SYSTEM_ADMIN + ') ' +ADMIN_OR_CRED_OWNER = ( + '(' + RULE_ADMIN_REQUIRED + ') ' 'or user_id:%(target.credential.user_id)s' ) diff --git a/keystone/common/policies/credential.py b/keystone/common/policies/credential.py index 675e31875f..41d49f6577 100644 --- a/keystone/common/policies/credential.py +++ b/keystone/common/policies/credential.py @@ -54,7 +54,7 @@ deprecated_delete_credential = policy.DeprecatedRule( credential_policies = [ policy.DocumentedRuleDefault( name=base.IDENTITY % 'get_credential', - check_str=base.SYSTEM_READER_OR_CRED_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER, scope_types=['system', 'project'], description='Show credentials details.', operations=[{'path': '/v3/credentials/{credential_id}', @@ -63,7 +63,7 @@ credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'list_credentials', - check_str=base.SYSTEM_READER_OR_CRED_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER, scope_types=['system', 'project'], description='List credentials.', operations=[{'path': '/v3/credentials', @@ -72,7 +72,7 @@ credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'create_credential', - check_str=base.SYSTEM_ADMIN_OR_CRED_OWNER, + check_str=base.ADMIN_OR_CRED_OWNER, scope_types=['system', 'project'], description='Create credential.', operations=[{'path': '/v3/credentials', @@ -81,7 +81,7 @@ credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'update_credential', - check_str=base.SYSTEM_ADMIN_OR_CRED_OWNER, + check_str=base.ADMIN_OR_CRED_OWNER, scope_types=['system', 'project'], description='Update credential.', operations=[{'path': '/v3/credentials/{credential_id}', @@ -90,7 +90,7 @@ credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'delete_credential', - check_str=base.SYSTEM_ADMIN_OR_CRED_OWNER, + check_str=base.ADMIN_OR_CRED_OWNER, scope_types=['system', 'project'], description='Delete credential.', operations=[{'path': '/v3/credentials/{credential_id}', diff --git a/keystone/common/policies/ec2_credential.py b/keystone/common/policies/ec2_credential.py index 9e52709225..0a876587ce 100644 --- a/keystone/common/policies/ec2_credential.py +++ b/keystone/common/policies/ec2_credential.py @@ -48,7 +48,7 @@ deprecated_ec2_delete_credential = policy.DeprecatedRule( ec2_credential_policies = [ policy.DocumentedRuleDefault( name=base.IDENTITY % 'ec2_get_credential', - check_str=base.SYSTEM_READER_OR_CRED_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER, scope_types=['system', 'project'], description='Show ec2 credential details.', operations=[{'path': ('/v3/users/{user_id}/credentials/OS-EC2/' @@ -58,7 +58,7 @@ ec2_credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'ec2_list_credentials', - check_str=base.RULE_SYSTEM_READER_OR_OWNER, + check_str=base.ADMIN_OR_SYSTEM_READER_OR_OWNER, scope_types=['system', 'project'], description='List ec2 credentials.', operations=[{'path': '/v3/users/{user_id}/credentials/OS-EC2', @@ -67,7 +67,7 @@ ec2_credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'ec2_create_credential', - check_str=base.RULE_SYSTEM_ADMIN_OR_OWNER, + check_str=base.RULE_ADMIN_OR_OWNER, scope_types=['system', 'project'], description='Create ec2 credential.', operations=[{'path': '/v3/users/{user_id}/credentials/OS-EC2', @@ -76,7 +76,7 @@ ec2_credential_policies = [ ), policy.DocumentedRuleDefault( name=base.IDENTITY % 'ec2_delete_credential', - check_str=base.SYSTEM_ADMIN_OR_CRED_OWNER, + check_str=base.ADMIN_OR_CRED_OWNER, scope_types=['system', 'project'], description='Delete ec2 credential.', operations=[{'path': ('/v3/users/{user_id}/credentials/OS-EC2/' diff --git a/keystone/common/policies/token.py b/keystone/common/policies/token.py index cb321b0593..974c8d96f2 100644 --- a/keystone/common/policies/token.py +++ b/keystone/common/policies/token.py @@ -38,13 +38,15 @@ deprecated_revoke_token = policy.DeprecatedRule( deprecated_since=versionutils.deprecated.TRAIN ) -SYSTEM_ADMIN_OR_TOKEN_SUBJECT = ( - '(role:admin and system_scope:all) or rule:token_subject' # nosec +ADMIN_OR_TOKEN_SUBJECT = ( + base.RULE_ADMIN_REQUIRED + ' or rule:token_subject' # nosec ) -SYSTEM_USER_OR_TOKEN_SUBJECT = ( +ADMIN_OR_SYSTEM_USER_OR_TOKEN_SUBJECT = ( + base.RULE_ADMIN_REQUIRED + ' or ' '(role:reader and system_scope:all) or rule:token_subject' # nosec ) -SYSTEM_USER_OR_SERVICE_OR_TOKEN_SUBJECT = ( +ADMIN_OR_SYSTEM_USER_OR_SERVICE_OR_TOKEN_SUBJECT = ( + base.RULE_ADMIN_REQUIRED + ' or ' '(role:reader and system_scope:all) ' # nosec 'or rule:service_role or rule:token_subject' # nosec ) @@ -53,7 +55,7 @@ SYSTEM_USER_OR_SERVICE_OR_TOKEN_SUBJECT = ( token_policies = [ policy.DocumentedRuleDefault( name=base.IDENTITY % 'check_token', - check_str=SYSTEM_USER_OR_TOKEN_SUBJECT, + check_str=ADMIN_OR_SYSTEM_USER_OR_TOKEN_SUBJECT, scope_types=['system', 'domain', 'project'], description='Check a token.', operations=[{'path': '/v3/auth/tokens', @@ -61,7 +63,7 @@ token_policies = [ deprecated_rule=deprecated_check_token), policy.DocumentedRuleDefault( name=base.IDENTITY % 'validate_token', - check_str=SYSTEM_USER_OR_SERVICE_OR_TOKEN_SUBJECT, + check_str=ADMIN_OR_SYSTEM_USER_OR_SERVICE_OR_TOKEN_SUBJECT, scope_types=['system', 'domain', 'project'], description='Validate a token.', operations=[{'path': '/v3/auth/tokens', @@ -69,7 +71,7 @@ token_policies = [ deprecated_rule=deprecated_validate_token), policy.DocumentedRuleDefault( name=base.IDENTITY % 'revoke_token', - check_str=SYSTEM_ADMIN_OR_TOKEN_SUBJECT, + check_str=ADMIN_OR_TOKEN_SUBJECT, scope_types=['system', 'domain', 'project'], description='Revoke a token.', operations=[{'path': '/v3/auth/tokens', diff --git a/keystone/tests/protection/v3/test_credentials.py b/keystone/tests/protection/v3/test_credentials.py index 800452f670..5a1960e38e 100644 --- a/keystone/tests/protection/v3/test_credentials.py +++ b/keystone/tests/protection/v3/test_credentials.py @@ -1131,11 +1131,13 @@ class ProjectAdminTests(base_classes.TestCaseWithBootstrap, # broken behavior with better scope checking. with open(self.policy_file_name, 'w') as f: overridden_policies = { - 'identity:get_credential': bp.SYSTEM_READER_OR_CRED_OWNER, - 'identity:list_credentials': bp.SYSTEM_READER_OR_CRED_OWNER, - 'identity:create_credential': bp.SYSTEM_ADMIN_OR_CRED_OWNER, - 'identity:update_credential': bp.SYSTEM_ADMIN_OR_CRED_OWNER, - 'identity:delete_credential': bp.SYSTEM_ADMIN_OR_CRED_OWNER + 'identity:get_credential': + bp.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER, + 'identity:list_credentials': + bp.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER, + 'identity:create_credential': bp.ADMIN_OR_CRED_OWNER, + 'identity:update_credential': bp.ADMIN_OR_CRED_OWNER, + 'identity:delete_credential': bp.ADMIN_OR_CRED_OWNER } f.write(jsonutils.dumps(overridden_policies)) diff --git a/keystone/tests/protection/v3/test_ec2_credential.py b/keystone/tests/protection/v3/test_ec2_credential.py index 7614173917..1f995d5a08 100644 --- a/keystone/tests/protection/v3/test_ec2_credential.py +++ b/keystone/tests/protection/v3/test_ec2_credential.py @@ -402,9 +402,9 @@ class ProjectAdminTests(base_classes.TestCaseWithBootstrap, # update permissions or update policies without breaking users. This # will cause these specific tests to fail since we're trying to correct # this broken behavior with better scope checking. - reader_or_cred_owner = bp.SYSTEM_READER_OR_CRED_OWNER + reader_or_cred_owner = bp.ADMIN_OR_SYSTEM_READER_OR_CRED_OWNER reader_or_owner = bp.RULE_SYSTEM_READER_OR_OWNER - admin_or_cred_owner = bp.SYSTEM_ADMIN_OR_CRED_OWNER + admin_or_cred_owner = bp.ADMIN_OR_CRED_OWNER with open(self.policy_file_name, 'w') as f: overridden_policies = { 'identity:ec2_get_credential': reader_or_cred_owner,