173 lines
7.0 KiB
Diff
173 lines
7.0 KiB
Diff
From ab18393db0b34506c3fd11346b6d0f1b781b9d99 Mon Sep 17 00:00:00 2001
|
|
From: Ramana Raja <rraja@redhat.com>
|
|
Date: Wed, 25 Nov 2020 16:44:35 +0530
|
|
Subject: [PATCH 2/5] pybind/ceph_volume_client: Disallow authorize auth_id
|
|
|
|
This patch disallow the ceph_volume_client to authorize the auth_id
|
|
which is not created by ceph_volume_client. Those auth_ids could be
|
|
created by other means for other use cases which should not be modified
|
|
by ceph_volume_client.
|
|
|
|
Fixes: https://tracker.ceph.com/issues/48555
|
|
Signed-off-by: Ramana Raja <rraja@redhat.com>
|
|
Signed-off-by: Kotresh HR <khiremat@redhat.com>
|
|
(cherry picked from commit 3a85d2d04028a323952a31d18cdbefb710be2e2b)
|
|
---
|
|
src/pybind/ceph_volume_client.py | 63 ++++++++++++++++++++------------
|
|
1 file changed, 39 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/src/pybind/ceph_volume_client.py b/src/pybind/ceph_volume_client.py
|
|
index 25cd6b91ae2..e2ab64ee226 100644
|
|
--- a/src/pybind/ceph_volume_client.py
|
|
+++ b/src/pybind/ceph_volume_client.py
|
|
@@ -215,6 +215,7 @@ CEPHFSVOLUMECLIENT_VERSION_HISTORY = """
|
|
* 2 - Added get_object, put_object, delete_object methods to CephFSVolumeClient
|
|
* 3 - Allow volumes to be created without RADOS namespace isolation
|
|
* 4 - Added get_object_and_version, put_object_versioned method to CephFSVolumeClient
|
|
+ * 5 - Disallow authorize API for users not created by CephFSVolumeClient
|
|
"""
|
|
|
|
|
|
@@ -238,7 +239,7 @@ class CephFSVolumeClient(object):
|
|
"""
|
|
|
|
# Current version
|
|
- version = 4
|
|
+ version = 5
|
|
|
|
# Where shall we create our volumes?
|
|
POOL_PREFIX = "fsvolume_"
|
|
@@ -379,7 +380,18 @@ class CephFSVolumeClient(object):
|
|
continue
|
|
|
|
readonly = access_level == 'r'
|
|
- self._authorize_volume(volume_path, auth_id, readonly)
|
|
+ client_entity = "client.{0}".format(auth_id)
|
|
+ try:
|
|
+ existing_caps = self._rados_command(
|
|
+ 'auth get',
|
|
+ {
|
|
+ 'entity': client_entity
|
|
+ }
|
|
+ )
|
|
+ # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
|
|
+ except rados.Error:
|
|
+ existing_caps = None
|
|
+ self._authorize_volume(volume_path, auth_id, readonly, existing_caps)
|
|
|
|
# Recovered from partial auth updates for the auth ID's access
|
|
# to a volume.
|
|
@@ -975,6 +987,18 @@ class CephFSVolumeClient(object):
|
|
"""
|
|
|
|
with self._auth_lock(auth_id):
|
|
+ client_entity = "client.{0}".format(auth_id)
|
|
+ try:
|
|
+ existing_caps = self._rados_command(
|
|
+ 'auth get',
|
|
+ {
|
|
+ 'entity': client_entity
|
|
+ }
|
|
+ )
|
|
+ # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
|
|
+ except rados.Error:
|
|
+ existing_caps = None
|
|
+
|
|
# Existing meta, or None, to be updated
|
|
auth_meta = self._auth_metadata_get(auth_id)
|
|
|
|
@@ -988,7 +1012,14 @@ class CephFSVolumeClient(object):
|
|
'dirty': True,
|
|
}
|
|
}
|
|
+
|
|
if auth_meta is None:
|
|
+ if existing_caps is not None:
|
|
+ msg = "auth ID: {0} exists and not created by ceph_volume_client. Not allowed to modify".format(auth_id)
|
|
+ log.error(msg)
|
|
+ raise CephFSVolumeClientError(msg)
|
|
+
|
|
+ # non-existent auth IDs
|
|
sys.stderr.write("Creating meta for ID {0} with tenant {1}\n".format(
|
|
auth_id, tenant_id
|
|
))
|
|
@@ -998,14 +1029,6 @@ class CephFSVolumeClient(object):
|
|
'tenant_id': tenant_id.__str__() if tenant_id else None,
|
|
'volumes': volume
|
|
}
|
|
-
|
|
- # Note: this is *not* guaranteeing that the key doesn't already
|
|
- # exist in Ceph: we are allowing VolumeClient tenants to
|
|
- # 'claim' existing Ceph keys. In order to prevent VolumeClient
|
|
- # tenants from reading e.g. client.admin keys, you need to
|
|
- # have configured your VolumeClient user (e.g. Manila) to
|
|
- # have mon auth caps that prevent it from accessing those keys
|
|
- # (e.g. limit it to only access keys with a manila.* prefix)
|
|
else:
|
|
# Disallow tenants to share auth IDs
|
|
if auth_meta['tenant_id'].__str__() != tenant_id.__str__():
|
|
@@ -1025,7 +1048,7 @@ class CephFSVolumeClient(object):
|
|
self._auth_metadata_set(auth_id, auth_meta)
|
|
|
|
with self._volume_lock(volume_path):
|
|
- key = self._authorize_volume(volume_path, auth_id, readonly)
|
|
+ key = self._authorize_volume(volume_path, auth_id, readonly, existing_caps)
|
|
|
|
auth_meta['dirty'] = False
|
|
auth_meta['volumes'][volume_path_str]['dirty'] = False
|
|
@@ -1042,7 +1065,7 @@ class CephFSVolumeClient(object):
|
|
'auth_key': None
|
|
}
|
|
|
|
- def _authorize_volume(self, volume_path, auth_id, readonly):
|
|
+ def _authorize_volume(self, volume_path, auth_id, readonly, existing_caps):
|
|
vol_meta = self._volume_metadata_get(volume_path)
|
|
|
|
access_level = 'r' if readonly else 'rw'
|
|
@@ -1061,14 +1084,14 @@ class CephFSVolumeClient(object):
|
|
vol_meta['auths'].update(auth)
|
|
self._volume_metadata_set(volume_path, vol_meta)
|
|
|
|
- key = self._authorize_ceph(volume_path, auth_id, readonly)
|
|
+ key = self._authorize_ceph(volume_path, auth_id, readonly, existing_caps)
|
|
|
|
vol_meta['auths'][auth_id]['dirty'] = False
|
|
self._volume_metadata_set(volume_path, vol_meta)
|
|
|
|
return key
|
|
|
|
- def _authorize_ceph(self, volume_path, auth_id, readonly):
|
|
+ def _authorize_ceph(self, volume_path, auth_id, readonly, existing_caps):
|
|
path = self._get_path(volume_path)
|
|
log.debug("Authorizing Ceph id '{0}' for path '{1}'".format(
|
|
auth_id, path
|
|
@@ -1096,15 +1119,7 @@ class CephFSVolumeClient(object):
|
|
want_osd_cap = 'allow {0} pool={1}'.format(want_access_level,
|
|
pool_name)
|
|
|
|
- try:
|
|
- existing = self._rados_command(
|
|
- 'auth get',
|
|
- {
|
|
- 'entity': client_entity
|
|
- }
|
|
- )
|
|
- # FIXME: rados raising Error instead of ObjectNotFound in auth get failure
|
|
- except rados.Error:
|
|
+ if existing_caps is None:
|
|
caps = self._rados_command(
|
|
'auth get-or-create',
|
|
{
|
|
@@ -1116,7 +1131,7 @@ class CephFSVolumeClient(object):
|
|
})
|
|
else:
|
|
# entity exists, update it
|
|
- cap = existing[0]
|
|
+ cap = existing_caps[0]
|
|
|
|
# Construct auth caps that if present might conflict with the desired
|
|
# auth caps.
|
|
--
|
|
2.23.0
|
|
|