Add new default roles in security_groups policies

This adds new defaults roles in security_groups API policies.
These policies are made granular and default to
PROJECT_READER_OR_SYSTEM_READER and PROJECT_MEMBER_OR_SYSTEM_ADMIN.

Partial implement blueprint policy-defaults-refresh-deprecated-apis

Change-Id: Ie1ea066e9683fc44d486bcde1eb0f01fca7645c7
This commit is contained in:
Ghanshyam Mann 2020-07-23 18:26:30 -05:00
parent 2939847226
commit a20ab7016e
5 changed files with 182 additions and 51 deletions

View File

@ -37,12 +37,6 @@ LOG = logging.getLogger(__name__)
SG_NOT_FOUND = object()
def _authorize_context(req):
context = req.environ['nova.context']
context.can(sg_policies.BASE_POLICY_NAME)
return context
class SecurityGroupControllerBase(object):
"""Base class for Security Group controllers."""
@ -155,7 +149,8 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.expected_errors((400, 404))
def show(self, req, id):
"""Return data about the given security group."""
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'show')
try:
id = security_group_api.validate_id(id)
@ -173,7 +168,8 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.response(202)
def delete(self, req, id):
"""Delete a security group."""
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'delete')
try:
id = security_group_api.validate_id(id)
@ -189,7 +185,8 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.expected_errors(404)
def index(self, req):
"""Returns a list of security groups."""
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'get')
search_opts = {}
search_opts.update(req.GET)
@ -210,7 +207,8 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.expected_errors((400, 403))
def create(self, req, body):
"""Creates a new security group."""
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'create')
security_group = self._from_body(body, 'security_group')
@ -235,7 +233,8 @@ class SecurityGroupController(SecurityGroupControllerBase, wsgi.Controller):
@wsgi.expected_errors((400, 404))
def update(self, req, id, body):
"""Update a security group."""
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'update')
try:
id = security_group_api.validate_id(id)
@ -270,8 +269,8 @@ class SecurityGroupRulesController(SecurityGroupControllerBase,
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors((400, 403, 404))
def create(self, req, body):
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'rule:create')
sg_rule = self._from_body(body, 'security_group_rule')
group_id = sg_rule.get('group_id')
source_group = {}
@ -345,7 +344,8 @@ class SecurityGroupRulesController(SecurityGroupControllerBase,
@wsgi.expected_errors((400, 404, 409))
@wsgi.response(202)
def delete(self, req, id):
context = _authorize_context(req)
context = req.environ['nova.context']
context.can(sg_policies.POLICY_NAME % 'rule:delete')
try:
id = security_group_api.validate_id(id)

View File

@ -35,37 +35,103 @@ in nova 23.0.0 release.
security_groups_policies = [
policy.DocumentedRuleDefault(
name=BASE_POLICY_NAME,
check_str=base.RULE_ADMIN_OR_OWNER,
description="""List, show, add, or remove security groups.
APIs which are directly related to security groups resource are deprecated:
Lists, shows information for, creates, updates and deletes
security groups. Creates and deletes security group rules. All these
APIs are deprecated.""",
name=POLICY_NAME % 'get',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
description="List security groups. This API is deprecated.",
operations=[
{
'method': 'GET',
'path': '/os-security-groups'
},
}
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'show',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,
description="Show security group. This API is deprecated.",
operations=[
{
'method': 'GET',
'path': '/os-security-groups/{security_group_id}'
},
}
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Create security group. This API is deprecated.",
operations=[
{
'method': 'POST',
'path': '/os-security-groups'
},
}
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'update',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Update security group. This API is deprecated.",
operations=[
{
'method': 'PUT',
'path': '/os-security-groups/{security_group_id}'
},
}
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Delete security group. This API is deprecated.",
operations=[
{
'method': 'DELETE',
'path': '/os-security-groups/{security_group_id}'
},
],
scope_types=['system', 'project']),
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'rule:create',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Create security group Rule. This API is deprecated.",
operations=[
{
'method': 'POST',
'path': '/os-security-group-rules'
}
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'rule:delete',
check_str=base.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
description="Delete security group Rule. This API is deprecated.",
operations=[
{
'method': 'DELETE',
'path': '/os-security-group-rules/{security_group_id}'
},
],
scope_types=['system', 'project'],
deprecated_rule=DEPRECATED_POLICY,
deprecated_reason=DEPRECATED_REASON,
deprecated_since='22.0.0'),
policy.DocumentedRuleDefault(
name=POLICY_NAME % 'list',
check_str=base.PROJECT_READER_OR_SYSTEM_READER,

View File

@ -135,6 +135,13 @@ policy_data = """
"os_compute_api:os-security-groups:list": "",
"os_compute_api:os-security-groups:add": "",
"os_compute_api:os-security-groups:remove": "",
"os_compute_api:os-security-groups:get": "",
"os_compute_api:os-security-groups:show": "",
"os_compute_api:os-security-groups:create": "",
"os_compute_api:os-security-groups:delete": "",
"os_compute_api:os-security-groups:update": "",
"os_compute_api:os-security-groups:rule:create": "",
"os_compute_api:os-security-groups:rule:delete": "",
"os_compute_api:os-server-diagnostics": "",
"os_compute_api:os-server-password:show": "",
"os_compute_api:os-server-password:clear": "",

View File

@ -127,7 +127,7 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
# as target to policy and always pass. If requester is not admin
# or owner of security groups then neutron will be returning the
# appropriate error.
self.everyone_authorized_contexts = [
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context, self.project_member_context,
self.project_reader_context, self.project_foo_context,
@ -136,22 +136,26 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
self.system_foo_context,
self.other_project_member_context
]
self.everyone_unauthorized_contexts = []
self.reader_unauthorized_contexts = []
self.sys_admin_or_owner_authorized_contexts = (
self.reader_authorized_contexts)
self.sys_admin_or_owner_unauthorized_contexts = (
self.reader_unauthorized_contexts)
@mock.patch('nova.network.security_group_api.list')
def test_list_security_groups_policy(self, mock_get):
rule_name = policies.BASE_POLICY_NAME
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name = policies.POLICY_NAME % 'get'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.index,
self.req)
@mock.patch('nova.network.security_group_api.get')
def test_show_security_groups_policy(self, mock_get):
rule_name = policies.BASE_POLICY_NAME
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name = policies.POLICY_NAME % 'show'
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name,
self.controller.show,
self.req, uuids.fake_id)
@ -159,24 +163,24 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.update_security_group')
def test_update_security_groups_policy(self, mock_update, mock_get):
rule_name = policies.BASE_POLICY_NAME
rule_name = policies.POLICY_NAME % 'update'
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.update,
self.req, uuids.fake_id, body=body)
@mock.patch('nova.network.security_group_api.create_security_group')
def test_create_security_groups_policy(self, mock_create):
rule_name = policies.BASE_POLICY_NAME
rule_name = policies.POLICY_NAME % 'create'
body = {'security_group': {
'name': 'test',
'description': 'test-desc'}}
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.create,
self.req, body=body)
@ -184,9 +188,9 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.destroy')
def test_delete_security_groups_policy(self, mock_destroy, mock_get):
rule_name = policies.BASE_POLICY_NAME
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name = policies.POLICY_NAME % 'delete'
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.controller.delete,
self.req, uuids.fake_id)
@ -194,13 +198,13 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.security_group_api.get')
@mock.patch('nova.network.security_group_api.create_security_group_rule')
def test_create_security_group_rules_policy(self, mock_create, mock_get):
rule_name = policies.BASE_POLICY_NAME
rule_name = policies.POLICY_NAME % 'rule:create'
body = {'security_group_rule': {
'ip_protocol': 'test', 'group_id': uuids.fake_id,
'parent_group_id': uuids.fake_id,
'from_port': 22, 'from_port': 22}}
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.rule_ctr.create,
self.req, body=body)
@ -210,9 +214,9 @@ class SecurityGroupsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.security_group_api.remove_rules')
def test_delete_security_group_rules_policy(self, mock_remove, mock_get,
mock_rules):
rule_name = policies.BASE_POLICY_NAME
self.common_policy_check(self.everyone_authorized_contexts,
self.everyone_unauthorized_contexts,
rule_name = policies.POLICY_NAME % 'rule:delete'
self.common_policy_check(self.sys_admin_or_owner_authorized_contexts,
self.sys_admin_or_owner_unauthorized_contexts,
rule_name,
self.rule_ctr.delete,
self.req, uuids.fake_id)
@ -297,3 +301,51 @@ class ServerSecurityGroupsNoLegacyPolicyTest(
self.system_foo_context, self.other_project_member_context,
self.other_project_reader_context
]
class SecurityGroupsNoLegacyPolicyTest(SecurityGroupsScopeTypePolicyTest):
"""Test Security Groups APIs policies with system scope enabled,
and no more deprecated rules that allow the legacy admin API to
access system_admin_or_owner APIs.
"""
without_deprecated_rules = True
rules_without_deprecation = {
policies.POLICY_NAME % 'get':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
policies.POLICY_NAME % 'show':
base_policy.PROJECT_READER_OR_SYSTEM_READER,
policies.POLICY_NAME % 'create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
policies.POLICY_NAME % 'update':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
policies.POLICY_NAME % 'delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
policies.POLICY_NAME % 'rule:create':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN,
policies.POLICY_NAME % 'rule:delete':
base_policy.PROJECT_MEMBER_OR_SYSTEM_ADMIN}
def setUp(self):
super(SecurityGroupsNoLegacyPolicyTest, self).setUp()
self.reader_authorized_contexts = [
self.legacy_admin_context, self.system_admin_context,
self.project_admin_context,
self.project_member_context, self.project_reader_context,
self.system_member_context, self.system_reader_context,
self.other_project_member_context
]
self.reader_unauthorized_contexts = [
self.project_foo_context,
self.system_foo_context
]
self.sys_admin_or_owner_authorized_contexts = [
self.system_admin_context, self.system_member_context,
self.project_admin_context, self.project_member_context,
self.legacy_admin_context, self.other_project_member_context
]
self.sys_admin_or_owner_unauthorized_contexts = [
self.system_reader_context,
self.project_reader_context, self.project_foo_context,
self.system_foo_context, self.other_project_reader_context
]

View File

@ -431,7 +431,11 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-networks:view",
"os_compute_api:os-rescue",
"os_compute_api:os-unrescue",
"os_compute_api:os-security-groups",
"os_compute_api:os-security-groups:create",
"os_compute_api:os-security-groups:update",
"os_compute_api:os-security-groups:delete",
"os_compute_api:os-security-groups:rule:create",
"os_compute_api:os-security-groups:rule:delete",
"os_compute_api:os-security-groups:add",
"os_compute_api:os-security-groups:remove",
"os_compute_api:os-server-password:clear",
@ -479,6 +483,8 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
self.system_reader_or_owner_rules = (
"os_compute_api:os-simple-tenant-usage:show",
"os_compute_api:os-security-groups:get",
"os_compute_api:os-security-groups:show",
"os_compute_api:os-security-groups:list",
"os_compute_api:os-volumes-attachments:index",
"os_compute_api:os-volumes-attachments:show",