Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
296 changes: 60 additions & 236 deletions ceph_cfg/keyring.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,35 @@
from . import util_which


log = logging.getLogger(__name__)
KEYRINGS = {
"admin": {
"path": "/etc/ceph/%s.client.admin.keyring",
"name": "client.admin",
"caps": { "mon": "allow *", "osd": "allow *", "mds": "allow *" },
},
"mon": {
"path": os.path.join(constants._path_ceph_lib, "bootstrap-mon/%s.keyring"),
"name": "mon.",
"caps": { "mon": "allow *" },
},
"osd": {
"path": os.path.join(constants._path_ceph_lib, "bootstrap-osd/%s.keyring"),
"name": "client.bootstrap-osd",
"caps": { "mon": "allow profile bootstrap-osd" },
},
"mds": {
"path": os.path.join(constants._path_ceph_lib, "bootstrap-mds/%s.keyring"),
"name": "client.bootstrap-mds",
"caps": { "mon": "allow profile bootstrap-mds" },
},
"rgw": {
"path": os.path.join(constants._path_ceph_lib, "bootstrap-rgw/%s.keyring"),
"name": "client.bootstrap-rgw",
"caps": { "mon": "allow profile bootstrap-rgw" },
},
}

log = logging.getLogger(__name__)

class Error(Exception):
"""
Expand All @@ -24,33 +51,13 @@ def __str__(self):
doc = self.__doc__.strip()
return ': '.join([doc] + [str(a) for a in self.args])

def _get_path_keyring_admin(cluster_name):
return '/etc/ceph/%s.client.admin.keyring' % (cluster_name)


def _get_path_keyring_mon(cluster_name):
# Get the path for the mon bootstrap keyring.
return os.path.join(constants._path_ceph_lib, 'bootstrap-mon/%s.keyring' % (cluster_name))


def _get_path_keyring_osd(cluster_name):
return os.path.join(constants._path_ceph_lib, 'bootstrap-osd/%s.keyring' % (cluster_name))

def _get_path_keyring_mds(cluster_name):
return os.path.join(constants._path_ceph_lib, 'bootstrap-mds/%s.keyring' % (cluster_name))


def _get_path_keyring_rgw(cluster_name):
return os.path.join(constants._path_ceph_lib, 'bootstrap-rgw/%s.keyring' % (cluster_name))


def _keying_read(key_path):
def _keyring_read(key_path):
output = ""
with open(key_path, 'r') as infile:
output = infile.read()
return output

def _keying_write(key_path,content):
def _keyring_write(key_path,content):
dirname = os.path.dirname(key_path)
if not os.path.isdir(dirname):
os.makedirs(dirname)
Expand All @@ -66,17 +73,12 @@ def _keying_write(key_path,content):
return


def Property(func):
return property(**func())



class keyring_facard(object):
key_type = None

class keyring_implementation_base(object):
def __init__(self, mdl):
self.model = mdl


def invoke_ceph_authtool(self, keyring_name, keyring_path, caps, secret=None, extra_args=[]):
"""create arguments for invoking the ceph authtool, this simplifies most of
the ways that ceph authtool could be invoked.
Expand Down Expand Up @@ -109,23 +111,29 @@ def invoke_ceph_authtool(self, keyring_name, keyring_path, caps, secret=None, ex
return args


def get_arguments_create(self, path, secret=None):
extra_args=[]
# Not sure why this special case is necessary for the admin key
if self.key_type == "admin":
if self.model.ceph_version.major == 0:
if self.model.ceph_version.minor < 95:
extra_args+=["--set-uid=0"]
return self.invoke_ceph_authtool(self.keyring_identity_get(), path, KEYRINGS[self.key_type]["caps"], secret=secret, extra_args=extra_args)


def present(self):
"""
Is keyring present
Check if keyring is present
"""
keyring_path = self.get_path_keyring()
if os.path.isfile(keyring_path):
return True
return False
return os.path.isfile(self.keyring_path_get())


def create(self, secret = None):
"""
Create keyring
"""
keyring_path = self.get_path_keyring()
if os.path.isfile(keyring_path):
return _keying_read(keyring_path)
if self.present():
return _keyring_read(self.keyring_path_get())
try:
tmpd = tempfile.mkdtemp()
key_path = os.path.join(tmpd,"keyring")
Expand All @@ -138,7 +146,7 @@ def create(self, secret = None):
cmd_out["stdout"],
cmd_out["stderr"])
)
output = _keying_read(key_path)
output = _keyring_read(key_path)
finally:
shutil.rmtree(tmpd)
return output
Expand All @@ -148,26 +156,24 @@ def write_content(self, key_content):
"""
Persist keyring
"""
keyring_path = self.get_path_keyring()
if os.path.isfile(keyring_path):
if self.present():
return True
_keying_write(keyring_path, key_content)
_keyring_write(self.keyring_path_get(), key_content)
return True


def write_secret(self, secret):
"""
Persist keyring
"""
keyring_path = self.get_path_keyring()
if os.path.isfile(keyring_path):
if os.path.isfile(self.keyring_path_get()):
return True
if secret is None:
raise Error("Keyring secret is invalid")
keyring_dir = os.path.dirname(keyring_path)
keyring_dir = os.path.dirname(self.keyring_path_get())
if not os.path.isdir(keyring_dir):
os.makedirs(keyring_dir)
arguments = self.get_arguments_create(keyring_path, secret)
arguments = self.get_arguments_create(self.keyring_path_get(), secret)
cmd_out = utils.execute_local_command(arguments)
if cmd_out["retcode"] != 0:
raise Error("Failed executing '%s' Error rc=%s, stdout=%s stderr=%s" % (
Expand All @@ -181,209 +187,27 @@ def write_secret(self, secret):

def remove(self):
"""
Delete keyring
Remove keyring
"""
keyring_path = self.get_path_keyring()
if os.path.isfile(keyring_path):
log.info("Removing:%s" % (keyring_path))
if self.present():
log.info("Removing: %s" % (self.keyring_path_get()))
try:
os.remove(keyring_path)
os.remove(self.keyring_path_get())
except OSError:
raise Error("Keyring could not be deleted")
return True


class keyring_implementation_admin(keyring_implementation_base):
def __init__(self, mdl):
keyring_implementation_base.__init__(self, mdl)
self.keyring_name = "client.admin"
self.caps = {"mon":"allow *", "osd":"allow *", "mds":"allow *"}

def get_path_keyring(self):
return _get_path_keyring_admin(self.model.cluster_name)

def get_arguments_create(self, path, secret=None):
extra_args=[]
if self.model.ceph_version.major == 0:
if self.model.ceph_version.minor < 95:
extra_args+=["--set-uid=0"]
return self.invoke_ceph_authtool(self.keyring_name, path, self.caps, secret=secret, extra_args=extra_args)

class keyring_implementation_mon(keyring_implementation_base):
def __init__(self, mdl):
keyring_implementation_base.__init__(self, mdl)
self.keyring_name = "mon."
self.caps = {"mon": "allow *"}

def get_path_keyring(self):
if self.model.cluster_name is None:
raise Error("Cluster name not found")
return _get_path_keyring_mon(self.model.cluster_name)

def get_arguments_create(self, path, secret=None):
return self.invoke_ceph_authtool(self.keyring_name, path, self.caps, secret=secret)


class keyring_implementation_osd(keyring_implementation_base):
def __init__(self, mdl):
keyring_implementation_base.__init__(self, mdl)
self.keyring_name = "client.bootstrap-osd"
self.caps = {"mon": "allow profile bootstrap-osd"}

def get_path_keyring(self):
if self.model.cluster_name is None:
raise Error("Cluster name not found")
return _get_path_keyring_osd(self.model.cluster_name)

def get_arguments_create(self, path, secret=None):
return self.invoke_ceph_authtool(self.keyring_name, path, self.caps, secret=secret)

class keyring_implementation_rgw(keyring_implementation_base):
def __init__(self, mdl):
keyring_implementation_base.__init__(self, mdl)
self.keyring_name = "client.bootstrap-rgw"
self.caps = {"mon": "allow profile bootstrap-rgw"}

def get_path_keyring(self):
if self.model.cluster_name is None:
raise Error("Cluster name not found")
return _get_path_keyring_rgw(self.model.cluster_name)


def get_arguments_create(self, path, secret=None):
return self.invoke_ceph_authtool(self.keyring_name, path, self.caps, secret=secret)


class keyring_implementation_mds(keyring_implementation_base):
def __init__(self, mdl):
keyring_implementation_base.__init__(self, mdl)
self.keyring_name = "client.bootstrap-mds"
self.caps = {"mon": "allow profile bootstrap-mds"}

def get_path_keyring(self):
if self.model.cluster_name is None:
raise Error("Cluster name not found")
return _get_path_keyring_mds(self.model.cluster_name)

def get_arguments_create(self, path, secret=None):
return self.invoke_ceph_authtool(self.keyring_name, path, self.caps, secret=secret)


class keyring_facard(object):
def __init__(self, mdl):
self.model = mdl
self._availableKeys = set(["admin", "mds", "mon", "osd", "rgw"])
self._clear_implementation()


def _clear_implementation(self):
self._keyType = None
self._keyImp = None


@Property
def key_type():
doc = "key_type"

def fget(self):
return self._keyType


def fset(self, name):
if name is None:
self._clear_implementation()
if not name in self._availableKeys:
self._clear_implementation()
raise ValueError("Invalid key_type with value:%s" % (name))
implementation = None
if name == "admin":
implementation = keyring_implementation_admin(self.model)
if name == "mds":
implementation = keyring_implementation_mds(self.model)
if name == "mon":
implementation = keyring_implementation_mon(self.model)
if name == "osd":
implementation = keyring_implementation_osd(self.model)
if name == "rgw":
implementation = keyring_implementation_rgw(self.model)
if implementation is None:
self._clear_implementation()
raise ValueError("Programming error for key_type with value:%s" % (name))
try:
implementation.get_path_keyring()
except (Error) as err:
self._clear_implementation()
raise err
self._keyImp = implementation
self._keyType = name
return self._keyType


def fdel(self):
self._clear_implementation()


return locals()


def present(self):
"""
Create keyring
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.present()


def create(self, secret = None):
"""
Create keyring
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.create(secret)


def write_content(self, key_content):
"""
Persist keyring
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.write_content(key_content)


def write_secret(self, secret):
"""
Persist keyring
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.write_secret(secret)


def remove(self):
"""
Remove keyring
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.remove()


def keyring_path_get(self):
"""
Get keyring path
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.get_path_keyring()
return KEYRINGS[self.key_type]["path"] % self.model.cluster_name


def keyring_identity_get(self):
"""
Get keyring path
Get keyring name
"""
if self._keyImp is None:
raise Error("Programming error: key type unset")
return self._keyImp.keyring_name
return KEYRINGS[self.key_type]["name"]