From d94dc3e7b93ed013497b0d1329480e55fd7dc077 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Tue, 12 Dec 2017 15:43:36 +0000 Subject: [PATCH] Add support for object_prefix permissions The grammer for ceph osd capabilities shows that permissions can be applied to a pool or to a object_prefix: match := [pool[=] | object_prefix ] This patch adds support for requesting object_prefix permissions on a given set of prefixes. http://docs.ceph.com/docs/firefly/man/8/ceph-authtool/#osd-capabilities Partial-Bug: #1696073 Change-Id: I799f87fe2178ed7d3e44f14e2fa0683f917d2f0d --- ceph/broker.py | 10 +++- unit_tests/test_broker.py | 98 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/ceph/broker.py b/ceph/broker.py index cb1968d..1c0b928 100644 --- a/ceph/broker.py +++ b/ceph/broker.py @@ -187,6 +187,9 @@ def handle_add_permissions_to_key(request, service): group = get_group(group_name=group_name) service_obj = get_service_groups(service=service_name, namespace=group_namespace) + if request.get('object-prefix-permissions'): + service_obj['object_prefix_perms'] = request.get( + 'object-prefix-permissions') format("Service object: {}".format(service_obj)) permission = request.get('group-permission') or "rwx" if service_name not in group['services']: @@ -241,8 +244,13 @@ def pool_permission_list_for_service(service): for permission, groups in permission_types.items(): permission = "allow {}".format(permission) for group in groups: - for pool in service['groups'][group]['pools']: + for pool in service['groups'][group].get('pools', []): permissions.append("{} pool={}".format(permission, pool)) + for permission, prefixes in sorted( + service.get("object_prefix_perms", {}).items()): + for prefix in prefixes: + permissions.append("allow {} object_prefix {}".format(permission, + prefix)) return ["mon", "allow r", "osd", ', '.join(permissions)] diff --git a/unit_tests/test_broker.py b/unit_tests/test_broker.py index 9e78b5a..864a2e3 100644 --- a/unit_tests/test_broker.py +++ b/unit_tests/test_broker.py @@ -531,3 +531,101 @@ class CephBrokerTestCase(unittest.TestCase): expect_service_name, expect_service_obj, expect_group_namespace) + + @patch.object(ceph.broker, 'save_service') + @patch.object(ceph.broker, 'save_group') + @patch.object(ceph.broker, 'monitor_key_get') + @patch.object(ceph.broker, 'update_service_permissions') + def test_handle_add_permissions_to_key_obj_prefs(self, + mock_update_serv_perms, + mock_monitor_key_get, + mock_save_group, + mock_save_service): + mkey = { + 'cephx.services.glance': ('{"groups": {}, "group_names": ' + '{"rwx": ["images"]}}'), + 'cephx.groups.images': ('{"services": ["glance", "cinder-ceph", ' + '"nova-compute"], "pools": ["glance"]}')} + mock_monitor_key_get.side_effect = lambda service, key: mkey[key] + expect_service_name = u'glance' + expected_group = { + u'services': [ + u'glance', + u'cinder-ceph', + u'nova-compute'], + u'pools': [u'glance']} + expect_service_obj = { + u'groups': { + u'images': expected_group}, + u'group_names': { + u'rwx': [u'images']}, + u'object_prefix_perms': { + u'rwx': [u'rbd_children'], u'r': ['another']}} + expect_group_namespace = None + ceph.broker.handle_add_permissions_to_key( + request={ + u'namespace': None, + u'group-permission': u'rwx', + u'group': u'images', + u'name': u'glance', + u'object-prefix-permissions': { + u'rwx': [u'rbd_children'], u'r': ['another']}, + u'op': u'add-permissions-to-key'}, + service='admin') + mock_save_group.assert_called_once_with( + group=expected_group, + group_name='images') + mock_save_service.assert_called_once_with( + service=expect_service_obj, + service_name=expect_service_name) + mock_update_serv_perms.assert_called_once_with( + expect_service_name, + expect_service_obj, + expect_group_namespace) + + def test_pool_permission_list_for_service_obj_pref(self): + expected_group = { + u'services': [ + u'glance', + u'cinder-ceph', + u'nova-compute'], + u'pools': [u'glance']} + expect_service_obj = { + u'groups': { + u'images': expected_group}, + u'group_names': { + u'rwx': [u'images']}, + u'object_prefix_perms': { + u'rwx': [u'rbd_children'], u'r': ['another']}} + self.assertEqual(ceph.broker.pool_permission_list_for_service( + expect_service_obj), + [ + 'mon', + 'allow r', + 'osd', + ('allow rwx pool=glance, ' + 'allow r object_prefix another, ' + 'allow rwx object_prefix rbd_children')]) + + def test_pool_permission_list_for_glance(self): + expected_group = { + u'services': [ + u'glance', + u'cinder-ceph', + u'nova-compute'], + u'pools': [u'glance']} + expect_service_obj = { + u'groups': { + u'images': expected_group}, + u'group_names': { + u'rwx': [u'images']}, + u'object_prefix_perms': { + u'class-read': [u'rbd_children']}} + self.assertEqual(ceph.broker.pool_permission_list_for_service( + expect_service_obj), + [ + 'mon', + 'allow r', + 'osd', + ('allow rwx pool=glance, ' + 'allow class-read object_prefix rbd_children')])