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:
committed by
Andrew Laski
parent
f0ddb9f9a9
commit
ad8d50f57b
@@ -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": "",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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": "",
|
||||
|
||||
Reference in New Issue
Block a user