Add policy to cover snapshotting of volume backed instances

This change adds a policy that can be configured to limit or prevent the
snapshotting of volume backed instances.

DocImpact
Change-Id: Id5486f3bb18c6431c4ae8def6540ba780ea15b0a
This commit is contained in:
Dave McNally
2015-04-23 15:52:35 +01:00
committed by Andrew Laski
parent f0ddb9f9a9
commit ad8d50f57b
6 changed files with 113 additions and 0 deletions

View File

@@ -17,6 +17,7 @@
"compute:shelve": "",
"compute:shelve_offload": "",
"compute:snapshot_volume_backed": "",
"compute:unshelve": "",
"compute:resize": "",
"compute:confirm_resize": "",
@@ -184,6 +185,7 @@
"network:delete_dns_domain": "",
"network:attach_external_network": "rule:admin_api",
"os_compute_api:servers:create_image:allow_volume_backed": "",
"os_compute_api:servers:start": "rule:admin_or_owner",
"os_compute_api:servers:stop": "rule:admin_or_owner",
"os_compute_api:os-access-ips:discoverable": "",

View File

@@ -1030,6 +1030,7 @@ class ServersController(wsgi.Controller):
try:
if self.compute_api.is_volume_backed_instance(context, instance,
bdms):
authorize(context, action="create_image:allow_volume_backed")
img = instance.image_ref
if not img:
properties = bdms.root_metadata(

View File

@@ -1080,6 +1080,10 @@ class Controller(wsgi.Controller):
try:
if self.compute_api.is_volume_backed_instance(context, instance,
bdms):
policy.enforce(context,
'compute:snapshot_volume_backed',
{'project_id': context.project_id,
'user_id': context.user_id})
img = instance.image_ref
if not img:
properties = bdms.root_metadata(

View File

@@ -3673,6 +3673,56 @@ class ServersPolicyEnforcementV21(test.NoDBTestCase):
rule, rule_name, self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
@mock.patch.object(compute_api.API, 'is_volume_backed_instance',
return_value=True)
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
@mock.patch.object(servers.ServersController, '_get_server')
def test_create_vol_backed_img_snapshotting_policy_blocks_project(self,
mock_is_vol_back,
mock_get_uuidi,
mock_get_server):
"""Don't permit a snapshot of a volume backed instance if configured
not to based on project
"""
rule_name = "os_compute_api:servers:create_image:allow_volume_backed"
rules = {
rule_name: "project:non_fake",
"os_compute_api:servers:create_image": "",
}
body = {
'createImage': {
'name': 'Snapshot 1',
},
}
self._common_policy_check(
rules, rule_name, self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
@mock.patch.object(compute_api.API, 'is_volume_backed_instance',
return_value=True)
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
@mock.patch.object(servers.ServersController, '_get_server')
def test_create_vol_backed_img_snapshotting_policy_blocks_role(self,
mock_is_vol_back,
mock_get_uuidi,
mock_get_server):
"""Don't permit a snapshot of a volume backed instance if configured
not to based on role
"""
rule_name = "os_compute_api:servers:create_image:allow_volume_backed"
rules = {
rule_name: "role:non_fake",
"os_compute_api:servers:create_image": "",
}
body = {
'createImage': {
'name': 'Snapshot 1',
},
}
self._common_policy_check(
rules, rule_name, self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
def _create_policy_check(self, rules, rule_name):
flavor_ref = 'http://localhost/123/flavors/3'
body = {

View File

@@ -32,6 +32,8 @@ from nova import db
from nova import exception
from nova.image import glance
from nova import objects
from nova.openstack.common import policy as common_policy
from nova import policy
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit import fake_block_device
@@ -1309,3 +1311,55 @@ class ServerActionsControllerTestV2(ServerActionsControllerTestV21):
self.mox.ReplayAll()
self.controller._action_rebuild(self.req, FAKE_UUID, body)
def test_create_vol_backed_img_snapshotting_policy_blocks_project(self):
"""Don't permit a snapshot of a volume backed instance if configured
not to based on project
"""
body = {
'createImage': {
'name': 'Snapshot 1',
},
}
rule_name = "compute:snapshot_volume_backed"
rules = {
rule_name:
common_policy.parse_rule("project_id:no_id"),
"compute:get":
common_policy.parse_rule("")
}
policy.set_rules(rules)
with mock.patch.object(compute_api.API, 'is_volume_backed_instance',
return_value=True):
exc = self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
def test_create_vol_backed_img_snapshotting_policy_blocks_role(self):
"""Don't permit a snapshot of a volume backed instance if configured
not to based on role
"""
body = {
'createImage': {
'name': 'Snapshot 1',
},
}
rule_name = "compute:snapshot_volume_backed"
rules = {
rule_name:
common_policy.parse_rule("role:no_role"),
"compute:get":
common_policy.parse_rule("")
}
policy.set_rules(rules)
with mock.patch.object(compute_api.API, 'is_volume_backed_instance',
return_value=True):
exc = self.assertRaises(exception.PolicyNotAuthorized,
self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())

View File

@@ -86,6 +86,7 @@ policy_data = """
"compute:reboot": "",
"compute:snapshot": "",
"compute:snapshot_volume_backed": "",
"compute:backup": "",
"compute:shelve": "",
@@ -120,6 +121,7 @@ policy_data = """
"os_compute_api:servers:revert_resize": "",
"os_compute_api:servers:show": "",
"os_compute_api:servers:create_image": "",
"os_compute_api:servers:create_image:allow_volume_backed": "",
"os_compute_api:servers:update": "",
"os_compute_api:servers:start": "",
"os_compute_api:servers:stop": "",