diff --git a/heat/api/openstack/v1/util.py b/heat/api/openstack/v1/util.py index 46ae955eb5..ee2b92dc73 100644 --- a/heat/api/openstack/v1/util.py +++ b/heat/api/openstack/v1/util.py @@ -31,9 +31,7 @@ def registered_policy_enforce(handler): def handle_stack_method(controller, req, tenant_id, **kwargs): _target = {"project_id": tenant_id} - if req.context.tenant_id != tenant_id and not ( - req.context.is_admin or - req.context.system_scope == all): + if req.context.tenant_id != tenant_id and not req.context.is_admin: raise exc.HTTPForbidden() allowed = req.context.policy.enforce( context=req.context, @@ -57,9 +55,7 @@ def no_policy_enforce(handler): """ @functools.wraps(handler) def handle_stack_method(controller, req, tenant_id, **kwargs): - if req.context.tenant_id != tenant_id and not ( - req.context.is_admin or - req.context.system_scope == all): + if req.context.tenant_id != tenant_id and not req.context.is_admin: raise exc.HTTPForbidden() return handler(controller, req, **kwargs) diff --git a/heat/common/policy.py b/heat/common/policy.py index bfcadbaf4d..ab17f5b200 100644 --- a/heat/common/policy.py +++ b/heat/common/policy.py @@ -85,20 +85,29 @@ class Enforcer(object): """ do_raise = False if not exc else True credentials = context.to_policy_values() - if is_registered_policy: - try: - return self.enforcer.authorize(rule, target, credentials, - do_raise=do_raise, - exc=exc, action=rule) - except policy.PolicyNotRegistered: - if self.log_not_registered: - with excutils.save_and_reraise_exception(): - LOG.exception(_('Policy not registered.')) - else: - raise - else: - return self.enforcer.enforce(rule, target, credentials, - do_raise, exc=exc, *args, **kwargs) + + try: + if is_registered_policy: + try: + return self.enforcer.authorize(rule, target, credentials, + do_raise=do_raise, + exc=exc, action=rule) + except policy.PolicyNotRegistered: + if self.log_not_registered: + with excutils.save_and_reraise_exception(): + LOG.exception(_('Policy not registered.')) + else: + raise + else: + return self.enforcer.enforce(rule, target, credentials, + do_raise, exc=exc, *args, + **kwargs) + except policy.InvalidScope: + LOG.debug('Policy check for %(action)s failed with scope check ' + '%(credentials)s', + {'action': rule, + 'credentials': context.to_policy_values()}) + raise exc(action=rule) def enforce(self, context, action, scope=None, target=None, is_registered_policy=False): diff --git a/heat/policies/actions.py b/heat/policies/actions.py index 1aa53fd70c..cf24499855 100644 --- a/heat/policies/actions.py +++ b/heat/policies/actions.py @@ -68,7 +68,8 @@ deprecated_cancel_without_rollback = policy.DeprecatedRule( actions_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'action', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Performs non-lifecycle operations on the stack ' '(Snapshot, Resume, Cancel update, or check stack resources). ' 'This is the default for all actions but can be overridden by more ' @@ -81,8 +82,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'snapshot', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Create stack snapshot', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', @@ -92,8 +93,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'suspend', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Suspend a stack.', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', @@ -103,8 +104,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'resume', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Resume a suspended stack.', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', @@ -114,8 +115,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'check', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Check stack resources.', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', @@ -125,8 +126,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'cancel_update', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Cancel stack operation and roll back.', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', @@ -136,8 +137,8 @@ actions_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'cancel_without_rollback', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Cancel stack operation without rolling back.', operations=[{ 'path': '/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/actions', diff --git a/heat/policies/base.py b/heat/policies/base.py index cdc3b9f7d6..3aef7ec2f3 100644 --- a/heat/policies/base.py +++ b/heat/policies/base.py @@ -30,22 +30,12 @@ PROJECT_STACK_USER = 'role:heat_stack_user and project_id:%(project_id)s' # Composite check strings that are useful for policies that protect APIs that # operate at different scopes. -SYSTEM_ADMIN_OR_PROJECT_MEMBER = ( - '(' + SYSTEM_ADMIN + ')' - ' or (' + PROJECT_MEMBER + ')' -) -SYSTEM_OR_PROJECT_READER = ( - '(' + SYSTEM_READER + ')' - ' or (' + PROJECT_READER + ')' -) -SYSTEM_ADMIN_OR_PROJECT_MEMBER_OR_STACK_USER = ( - '(' + SYSTEM_ADMIN + ')' - ' or (' + PROJECT_MEMBER + ')' +PROJECT_MEMBER_OR_STACK_USER = ( + '(' + PROJECT_MEMBER + ')' ' or (' + PROJECT_STACK_USER + ')' ) -SYSTEM_OR_PROJECT_READER_OR_STACK_USER = ( - '(' + SYSTEM_READER + ')' - ' or (' + PROJECT_READER + ')' +PROJECT_READER_OR_STACK_USER = ( + '(' + PROJECT_READER + ')' ' or (' + PROJECT_STACK_USER + ')' ) diff --git a/heat/policies/build_info.py b/heat/policies/build_info.py index 5bc8e21da7..d39ebdbcf9 100644 --- a/heat/policies/build_info.py +++ b/heat/policies/build_info.py @@ -32,8 +32,8 @@ deprecated_build_info = policy.DeprecatedRule( build_info_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'build_info', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show build information.', operations=[ { diff --git a/heat/policies/cloudformation.py b/heat/policies/cloudformation.py index 2508d8d927..49f921fa5b 100644 --- a/heat/policies/cloudformation.py +++ b/heat/policies/cloudformation.py @@ -106,80 +106,80 @@ deprecated_list_stack_resources = policy.DeprecatedRule( cloudformation_policies = [ policy.RuleDefault( name=POLICY_ROOT % 'ListStacks', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_list_stacks ), policy.RuleDefault( name=POLICY_ROOT % 'CreateStack', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], deprecated_rule=deprecated_create_stack ), policy.RuleDefault( name=POLICY_ROOT % 'DescribeStacks', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_describe_stacks ), policy.RuleDefault( name=POLICY_ROOT % 'DeleteStack', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], deprecated_rule=deprecated_delete_stack ), policy.RuleDefault( name=POLICY_ROOT % 'UpdateStack', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], deprecated_rule=deprecated_update_stack ), policy.RuleDefault( name=POLICY_ROOT % 'CancelUpdateStack', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], deprecated_rule=deprecated_cancel_update_stack ), policy.RuleDefault( name=POLICY_ROOT % 'DescribeStackEvents', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_describe_stack_events ), policy.RuleDefault( name=POLICY_ROOT % 'ValidateTemplate', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_validate_template ), policy.RuleDefault( name=POLICY_ROOT % 'GetTemplate', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_get_template ), policy.RuleDefault( name=POLICY_ROOT % 'EstimateTemplateCost', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_estimate_template_cost ), policy.RuleDefault( name=POLICY_ROOT % 'DescribeStackResource', - check_str=base.SYSTEM_OR_PROJECT_READER_OR_STACK_USER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER_OR_STACK_USER, + scope_types=['project'], deprecated_rule=deprecated_describe_stack_resource ), policy.RuleDefault( name=POLICY_ROOT % 'DescribeStackResources', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_describe_stack_resources ), policy.RuleDefault( name=POLICY_ROOT % 'ListStackResources', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], deprecated_rule=deprecated_list_stack_resources ) ] diff --git a/heat/policies/events.py b/heat/policies/events.py index b314e7003a..ca261a891d 100644 --- a/heat/policies/events.py +++ b/heat/policies/events.py @@ -38,8 +38,8 @@ deprecated_show = policy.DeprecatedRule( events_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List events.', operations=[ { @@ -52,8 +52,8 @@ events_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show event.', operations=[ { diff --git a/heat/policies/resource.py b/heat/policies/resource.py index 85f582155f..093c1a6c41 100644 --- a/heat/policies/resource.py +++ b/heat/policies/resource.py @@ -55,8 +55,8 @@ deprecated_signal = policy.DeprecatedRule( resource_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List resources.', operations=[ { @@ -69,8 +69,8 @@ resource_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'metadata', - check_str=base.SYSTEM_OR_PROJECT_READER_OR_STACK_USER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER_OR_STACK_USER, + scope_types=['project'], description='Show resource metadata.', operations=[ { @@ -83,8 +83,8 @@ resource_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'signal', - check_str=base.SYSTEM_OR_PROJECT_READER_OR_STACK_USER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER_OR_STACK_USER, + scope_types=['project'], description='Signal resource.', operations=[ { @@ -97,8 +97,8 @@ resource_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'mark_unhealthy', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Mark resource as unhealthy.', operations=[ { @@ -111,8 +111,8 @@ resource_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show resource.', operations=[ { diff --git a/heat/policies/resource_types.py b/heat/policies/resource_types.py index 3bb3fc6f1d..4a7bc4c6e1 100644 --- a/heat/policies/resource_types.py +++ b/heat/policies/resource_types.py @@ -19,70 +19,96 @@ POLICY_ROOT = 'resource_types:%s' resource_types_policies = [ policy.RuleDefault( name=POLICY_ROOT % 'OS::Nova::Flavor', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Cinder::EncryptedVolumeType', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Cinder::VolumeType', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Cinder::Quota', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::Quota', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Nova::Quota', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Octavia::Quota', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Manila::ShareType', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::ProviderNet', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::QoSPolicy', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::QoSBandwidthLimitRule', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::QoSDscpMarkingRule', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::QoSMinimumBandwidthRule', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::QoSMinimumPacketRateRule', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Neutron::Segment', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Nova::HostAggregate', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Cinder::QoSSpecs', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Cinder::QoSAssociation', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Keystone::*', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + # NOTE(tkajinam): Keystone does not yet support project scope SRBAC + # but we limit the scope to project one here to make + # this consistent with the scope enforcement in stack + # resources. + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Blazar::Host', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Octavia::Flavor', - check_str=base.RULE_PROJECT_ADMIN), + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']), policy.RuleDefault( name=POLICY_ROOT % 'OS::Octavia::FlavorProfile', - check_str=base.RULE_PROJECT_ADMIN) + check_str=base.RULE_PROJECT_ADMIN, + scope_types=['project']) ] diff --git a/heat/policies/service.py b/heat/policies/service.py index 3c3f422793..bd460e7976 100644 --- a/heat/policies/service.py +++ b/heat/policies/service.py @@ -31,7 +31,8 @@ deprecated_index = policy.DeprecatedRule( service_policies = [ policy.RuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_READER, + check_str=base.PROJECT_ADMIN, + scope_types=['project'], deprecated_rule=deprecated_index ) ] diff --git a/heat/policies/software_configs.py b/heat/policies/software_configs.py index be5ca0441e..c582fe4f74 100644 --- a/heat/policies/software_configs.py +++ b/heat/policies/software_configs.py @@ -21,12 +21,6 @@ The software configuration API now support system scope and default roles. POLICY_ROOT = 'software_configs:%s' -deprecated_global_index = policy.DeprecatedRule( - name=POLICY_ROOT % 'global_index', - check_str=base.RULE_DENY_EVERYBODY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since=versionutils.deprecated.WALLABY -) deprecated_index = policy.DeprecatedRule( name=POLICY_ROOT % 'index', check_str=base.RULE_DENY_STACK_USER, @@ -55,8 +49,7 @@ deprecated_delete = policy.DeprecatedRule( software_configs_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'global_index', - check_str=base.SYSTEM_READER, - scope_types=['system', 'project'], + check_str=base.RULE_DENY_EVERYBODY, description='List configs globally.', operations=[ { @@ -64,12 +57,11 @@ software_configs_policies = [ 'method': 'GET' } ], - deprecated_rule=deprecated_global_index ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List configs.', operations=[ { @@ -81,8 +73,8 @@ software_configs_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Create config.', operations=[ { @@ -94,8 +86,8 @@ software_configs_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show config details.', operations=[ { @@ -107,8 +99,8 @@ software_configs_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Delete config.', operations=[ { diff --git a/heat/policies/software_deployments.py b/heat/policies/software_deployments.py index 08e59c6eb7..0f06658370 100644 --- a/heat/policies/software_deployments.py +++ b/heat/policies/software_deployments.py @@ -56,8 +56,8 @@ deprecated_delete = policy.DeprecatedRule( software_deployments_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List deployments.', operations=[ { @@ -69,8 +69,8 @@ software_deployments_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Create deployment.', operations=[ { @@ -82,8 +82,8 @@ software_deployments_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show deployment details.', operations=[ { @@ -95,8 +95,8 @@ software_deployments_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'update', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Update deployment.', operations=[ { @@ -108,8 +108,8 @@ software_deployments_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Delete deployment.', operations=[ { @@ -121,8 +121,8 @@ software_deployments_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'metadata', - check_str=base.SYSTEM_OR_PROJECT_READER_OR_STACK_USER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER_OR_STACK_USER, + scope_types=['project'], description='Show server configuration metadata.', operations=[ { diff --git a/heat/policies/stacks.py b/heat/policies/stacks.py index cebcf5af54..0142b08f69 100644 --- a/heat/policies/stacks.py +++ b/heat/policies/stacks.py @@ -57,12 +57,6 @@ deprecated_generate_template = policy.DeprecatedRule( deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY ) -deprecated_global_index = policy.DeprecatedRule( - name=POLICY_ROOT % 'global_index', - check_str=base.RULE_DENY_EVERYBODY, - deprecated_reason=DEPRECATED_REASON, - deprecated_since=versionutils.deprecated.WALLABY -) deprecated_index = policy.DeprecatedRule( name=POLICY_ROOT % 'index', check_str=base.RULE_DENY_STACK_USER, @@ -206,8 +200,8 @@ deprecated_lookup = policy.DeprecatedRule( stacks_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'abandon', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Abandon stack.', operations=[ { @@ -220,8 +214,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'create', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Create stack.', operations=[ { @@ -233,8 +227,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Delete stack.', operations=[ { @@ -246,8 +240,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'detail', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List stacks in detail.', operations=[ { @@ -259,8 +253,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'export', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Export stack.', operations=[ { @@ -273,8 +267,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'generate_template', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Generate stack template.', operations=[ { @@ -287,8 +281,7 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'global_index', - check_str=base.SYSTEM_READER, - scope_types=['system', 'project'], + check_str=base.RULE_DENY_EVERYBODY, description='List stacks globally.', operations=[ { @@ -296,12 +289,11 @@ stacks_policies = [ 'method': 'GET' } ], - deprecated_rule=deprecated_global_index ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'index', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List stacks.', operations=[ { @@ -313,8 +305,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'list_resource_types', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List resource types.', operations=[ { @@ -326,8 +318,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'list_template_versions', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List template versions.', operations=[ { @@ -339,8 +331,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'list_template_functions', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List template functions.', operations=[ { @@ -353,8 +345,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'lookup', - check_str=base.SYSTEM_OR_PROJECT_READER_OR_STACK_USER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER_OR_STACK_USER, + scope_types=['project'], description='Find stack.', operations=[ { @@ -366,8 +358,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'preview', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Preview stack.', operations=[ { @@ -379,8 +371,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'resource_schema', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show resource type schema.', operations=[ { @@ -392,8 +384,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show stack.', operations=[ { @@ -405,8 +397,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'template', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Get stack template.', operations=[ { @@ -419,8 +411,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'environment', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Get stack environment.', operations=[ { @@ -433,8 +425,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'files', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Get stack files.', operations=[ { @@ -447,8 +439,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'update', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Update stack.', operations=[ { @@ -460,8 +452,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'update_patch', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Update stack (PATCH).', operations=[ { @@ -474,7 +466,7 @@ stacks_policies = [ policy.DocumentedRuleDefault( name=POLICY_ROOT % 'update_no_change', check_str='rule:%s' % (POLICY_ROOT % 'update_patch'), - scope_types=['system', 'project'], + scope_types=['project'], description='Update stack (PATCH) with no changes.', operations=[ { @@ -485,8 +477,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'preview_update', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Preview update stack.', operations=[ { @@ -499,8 +491,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'preview_update_patch', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Preview update stack (PATCH).', operations=[ { @@ -513,8 +505,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'validate_template', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Validate template.', operations=[ { @@ -526,8 +518,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'snapshot', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Snapshot Stack.', operations=[ { @@ -540,8 +532,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show_snapshot', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show snapshot.', operations=[ { @@ -554,8 +546,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'delete_snapshot', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Delete snapshot.', operations=[ { @@ -568,8 +560,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'list_snapshots', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List snapshots.', operations=[ { @@ -582,8 +574,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'restore_snapshot', - check_str=base.SYSTEM_ADMIN_OR_PROJECT_MEMBER, - scope_types=['system', 'project'], + check_str=base.PROJECT_MEMBER, + scope_types=['project'], description='Restore snapshot.', operations=[ { @@ -596,8 +588,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'list_outputs', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='List outputs.', operations=[ { @@ -610,8 +602,8 @@ stacks_policies = [ ), policy.DocumentedRuleDefault( name=POLICY_ROOT % 'show_output', - check_str=base.SYSTEM_OR_PROJECT_READER, - scope_types=['system', 'project'], + check_str=base.PROJECT_READER, + scope_types=['project'], description='Show outputs.', operations=[ { diff --git a/heat/tests/policy/test_acl_personas.yaml b/heat/tests/policy/test_acl_personas.yaml index 1fe5ce40a4..fb021f686e 100644 --- a/heat/tests/policy/test_acl_personas.yaml +++ b/heat/tests/policy/test_acl_personas.yaml @@ -7,7 +7,6 @@ actions_most_restricted: - "cancel_update" - "cancel_without_rollback" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -17,7 +16,6 @@ actions_restricted: actions: - "check" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -36,7 +34,6 @@ cloud_formation_most_restricted: - "EstimateTemplateCost" - "DescribeStackResources" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -46,15 +43,14 @@ cloud_formation_restricted: actions: - "DescribeStackResource" allowed: - - "system_admin" - "project_member" + - "stack_user" build_info_acl: scope: "build_info" actions: - "build_info" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -65,7 +61,6 @@ events_acl: - "index" - "show" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -76,9 +71,8 @@ resource_least_restricted: - "metadata" - "signal" allowed: - - "system_reader" - - "system_reader" - "stack_user" + - "project_reader" resource_restricted: scope: "resource" @@ -86,7 +80,6 @@ resource_restricted: - "index" - "show" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -96,7 +89,6 @@ resource_most_restricted: actions: - "mark_unhealthy" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -106,14 +98,19 @@ service_acl: actions: - "index" allowed: - - "system_reader" + - "project_admin" + denied: + - "project_member" + - "stack_user" -software_configs_least_restricted: +software_configs_restricted_index: scope: "software_configs" actions: - "global_index" - allowed: - - "system_reader" + denied: + - "system_admin" + - "project_admin" + - "stack_user" software_configs_most_restricted: scope: "software_configs" @@ -121,7 +118,6 @@ software_configs_most_restricted: - "create" - "delete" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -130,10 +126,8 @@ software_configs_restricted: scope: "software_configs" actions: - "index" - - "create" - "show" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -145,7 +139,6 @@ software_deployments_most_restricted: - "update" - "delete" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -156,17 +149,16 @@ software_deployments_restricted: - "index" - "show" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" - software_deployments_least_restricted: scope: "software_deployments" actions: - "metadata" allowed: + - "project_reader" - "stack_user" stacks_most_restricted: @@ -186,7 +178,6 @@ stacks_most_restricted: - "delete_snapshot" - "restore_snapshot" allowed: - - "system_admin" - "project_member" denied: - "stack_user" @@ -210,7 +201,6 @@ stacks_restricted: - "list_outputs" - "show_output" allowed: - - "system_reader" - "project_reader" denied: - "stack_user" @@ -219,15 +209,15 @@ stacks_restricted_index: scope: "stacks" actions: - "global_index" - allowed: + denied: - "system_admin" + - "project_admin" stacks_open: scope: "stacks" actions: - "lookup" allowed: - - "system_reader" - "project_reader" - "stack_user" @@ -236,6 +226,4 @@ create_stacks: actions: - "create" allowed: - - "system_admin" - - "project_admin" - "project_member" diff --git a/heat/tests/policy/test_new_acl_personas.yaml b/heat/tests/policy/test_new_acl_personas.yaml new file mode 100644 index 0000000000..a17902e4d9 --- /dev/null +++ b/heat/tests/policy/test_new_acl_personas.yaml @@ -0,0 +1,263 @@ +actions_most_restricted: + scope: "actions" + actions: + - "snapshot" + - "suspend" + - "resume" + - "cancel_update" + - "cancel_without_rollback" + allowed: + - "project_member" + denied: + - "project_reader" + - "stack_user" + - "system_admin" + +actions_restricted: + scope: "actions" + actions: + - "check" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +cloud_formation_most_restricted: + scope: "cloudformation" + actions: + - "CreateStack" + - "DeleteStack" + - "UpdateStack" + allowed: + - "project_member" + denied: + - "project_reader" + - "stack_user" + - "system_admin" + +cloud_formation_restricted: + scope: "cloudformation" + actions: + - "ListStacks" + - "DescribeStacks" + - "DescribeStackEvents" + - "GetTemplate" + - "EstimateTemplateCost" + - "DescribeStackResources" + - "ValidateTemplate" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +cloud_formation_least_restricted: + scope: "cloudformation" + actions: + - "DescribeStackResource" + allowed: + - "project_reader" + - "stack_user" + denied: + - "system_admin" + +build_info_acl: + scope: "build_info" + actions: + - "build_info" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +events_acl: + scope: "events" + actions: + - "index" + - "show" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +resource_least_restricted: + scope: "resource" + actions: + - "metadata" + - "signal" + allowed: + - "stack_user" + - "project_reader" + denied: + - "system_admin" + +resource_restricted: + scope: "resource" + actions: + - "index" + - "show" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +resource_most_restricted: + scope: "resource" + actions: + - "mark_unhealthy" + allowed: + - "project_member" + denied: + - "project_reader" + - "stack_user" + - "system_admin" + +service_acl: + scope: "service" + actions: + - "index" + allowed: + - "project_admin" + denied: + - "system_admin" + - "project_member" + - "stack_user" + +software_configs_restricted_index: + scope: "software_configs" + actions: + - "global_index" + denied: + - "system_admin" + - "project_admin" + +software_configs_most_restricted: + scope: "software_configs" + actions: + - "create" + - "delete" + allowed: + - "project_member" + denied: + - "stack_user" + +software_configs_restricted: + scope: "software_configs" + actions: + - "index" + - "show" + allowed: + - "project_reader" + denied: + - "stack_user" + +software_deployments_most_restricted: + scope: "software_deployments" + actions: + - "create" + - "update" + - "delete" + allowed: + - "project_member" + denied: + - "stack_user" + +software_deployments_restricted: + scope: "software_deployments" + actions: + - "index" + - "show" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +software_deployments_least_restricted: + scope: "software_deployments" + actions: + - "metadata" + allowed: + - "project_reader" + - "stack_user" + denied: + - "system_admin" + +stacks_most_restricted: + scope: "stacks" + actions: + - "abandon" + - "create" + - "delete" + - "export" + - "generate_template" + - "update" + - "update_patch" + - "preview_update" + - "preview_update_patch" + - "validate_template" + - "snapshot" + - "delete_snapshot" + - "restore_snapshot" + allowed: + - "project_member" + denied: + - "project_reader" + - "stack_user" + - "system_admin" + +stacks_restricted: + scope: "stacks" + actions: + - "detail" + - "index" + - "list_resource_types" + - "list_template_versions" + - "list_template_functions" + - "preview" + - "resource_schema" + - "show" + - "template" + - "environment" + - "files" + - "show_snapshot" + - "list_snapshots" + - "list_outputs" + - "show_output" + allowed: + - "project_reader" + denied: + - "stack_user" + - "system_admin" + +stacks_restricted_index: + scope: "stacks" + actions: + - "global_index" + denied: + - "system_admin" + - "project_admin" + +stacks_open: + scope: "stacks" + actions: + - "lookup" + allowed: + - "project_reader" + - "stack_user" + denied: + - "system_admin" + +create_stacks: + scope: "stacks" + actions: + - "create" + allowed: + - "project_member" + denied: + - "project_reader" + - "system_admin" diff --git a/heat/tests/test_common_policy.py b/heat/tests/test_common_policy.py index 99c23c436d..e085d1935b 100644 --- a/heat/tests/test_common_policy.py +++ b/heat/tests/test_common_policy.py @@ -78,7 +78,7 @@ class TestPolicyEnforcer(common.HeatTestCase): def test_deprecated_policies(self, **kwargs): self._test_legacy_rbac_policies(**kwargs) - @ddt.file_data('policy/test_acl_personas.yaml') + @ddt.file_data('policy/test_new_acl_personas.yaml') @ddt.unpack def test_secure_rbac_policies(self, **kwargs): self.fixture.config(group='oslo_policy', enforce_scope=True) diff --git a/releasenotes/notes/policy-defaults-refresh-984844c65ae48599.yaml b/releasenotes/notes/policy-defaults-refresh-984844c65ae48599.yaml new file mode 100644 index 0000000000..5584ccad57 --- /dev/null +++ b/releasenotes/notes/policy-defaults-refresh-984844c65ae48599.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Heat policies have been modified to isolate the system and project level + APIs policy. Because of this change, system users will not be allowed to + perform any operations on project level resources.