X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=plugins%2Fsliverauth.py;h=ec65c72c3080044793d50fc70041cb1bc04ed93f;hb=ac6786141feadccdc48b819ab21a825a54881ded;hp=f22a60d1a588ece9a522d90d560ced6e7c741028;hpb=13bcb0775a93e1c91355f00270b0cfae8400d872;p=nodemanager.git diff --git a/plugins/sliverauth.py b/plugins/sliverauth.py index f22a60d..ec65c72 100644 --- a/plugins/sliverauth.py +++ b/plugins/sliverauth.py @@ -1,33 +1,30 @@ #!/usr/bin/python -tt # vim:set ts=4 sw=4 expandtab: -# NodeManager plugin to empower slivers to make API calls +# +# NodeManager plugin for creating credentials in slivers +# (*) empower slivers to make API calls throught hmac +# (*) also create a ssh key - used by the OMF resource controller +# for authenticating itself with its Experiment Controller +# in order to avoid spamming the DB with huge amounts of such tags, +# (*) slices need to have the 'enable_hmac' tag set +# (*) or the 'omf_control' tag set, respectively """ Sliver authentication support for NodeManager. """ -import errno import os import random import string import tempfile -import time +import socket import logger import tools -def start(options, conf): - logger.log("sliverauth plugin starting up...") - -def SetSliverTag(plc, slice, tagname, value): - node_id = tools.node_id() - slivertags=plc.GetSliceTags({"name":slice,"node_id":node_id,"tagname":tagname}) - if len(slivertags)==0: - slivertag_id=plc.AddSliceTag(slice,tagname,value,node_id) - else: - slivertag_id=slivertags[0]['slice_tag_id'] - plc.UpdateSliceTag(slivertag_id,value) +def start(): + logger.log("sliverauth: (dummy) plugin starting up...") def GetSlivers(data, config, plc): if 'OVERRIDES' in dir(config): @@ -36,44 +33,100 @@ def GetSlivers(data, config, plc): return if 'slivers' not in data: - logger.log("sliverauth: getslivers data lack's sliver information. IGNORING!") + logger.log_missing_data("sliverauth.GetSlivers", 'slivers') return for sliver in data['slivers']: - found_hmac = False - for attribute in sliver['attributes']: - name = attribute.get('tagname',attribute.get('name','')) - if name == 'hmac': - found_hmac = True - hmac = attribute['value'] - break - - if not found_hmac: - # XXX need a better random seed?! - random.seed(time.time()) - d = [random.choice(string.letters) for x in xrange(32)] - hmac = "".join(d) - SetSliverTag(plc,sliver['name'],'hmac',hmac) - logger.log("sliverauth setting %s hmac" % sliver['name']) - - path = '/vservers/%s/etc/planetlab' % sliver['name'] - if os.path.exists(path): - keyfile = '%s/key' % path - oldhmac = '' - if os.path.exists(keyfile): - f = open(keyfile,'r') - oldhmac = f.read() - f.close() - - if oldhmac <> hmac: - # create a temporary file in the vserver - fd, name = tempfile.mkstemp('','key',path) - os.write(fd,hmac) - os.close(fd) - if os.path.exists(keyfile): - os.unlink(keyfile) - os.rename(name,keyfile) - logger.log("sliverauth writing hmac to %s " % keyfile) - - os.chmod(keyfile,0400) + path = '/vservers/%s' % sliver['name'] + if not os.path.exists(path): + # ignore all non-plc-instantiated slivers + instantiation = sliver.get('instantiation', '') + if instantiation == 'plc-instantiated': + logger.log("sliverauth: plc-instantiated slice %s does not yet exist. IGNORING!" % sliver['name']) + continue + + system_slice = False + for chunk in sliver['attributes']: + if chunk['tagname'] == "system": + if chunk['value'] in (True, 1, '1') or chunk['value'].lower() == "true": + system_slice = True + + for chunk in sliver['attributes']: + if chunk['tagname']=='enable_hmac' and not system_slice: + manage_hmac (plc, sliver) + + if chunk['tagname']=='omf_control': + manage_sshkey (plc, sliver) + + +def SetSliverTag(plc, slice, tagname, value): + node_id = tools.node_id() + slivertags=plc.GetSliceTags({"name":slice, "node_id":node_id, "tagname":tagname}) + if len(slivertags)==0: + # looks like GetSlivers reports about delegated/nm-controller slices that do *not* belong to this node + # and this is something that AddSliceTag does not like + try: + slivertag_id=plc.AddSliceTag(slice, tagname, value, node_id) + except: + logger.log_exc ("sliverauth.SetSliverTag (probably delegated) slice=%(slice)s tag=%(tagname)s node_id=%(node_id)d"%locals()) + pass + else: + slivertag_id=slivertags[0]['slice_tag_id'] + plc.UpdateSliceTag(slivertag_id, value) + +def find_tag (sliver, tagname): + for attribute in sliver['attributes']: + # for legacy, try the old-fashioned 'name' as well + name = attribute.get('tagname', attribute.get('name', '')) + if name == tagname: + return attribute['value'] + return None + +def manage_hmac (plc, sliver): + hmac = find_tag (sliver, 'hmac') + + if not hmac: + # let python do its thing + random.seed() + d = [random.choice(string.letters) for x in xrange(32)] + hmac = "".join(d) + SetSliverTag(plc, sliver['name'], 'hmac', hmac) + logger.log("sliverauth: %s: setting hmac" % sliver['name']) + + path = '/vservers/%s/etc/planetlab' % sliver['name'] + if os.path.exists(path): + keyfile = '%s/key' % path + if (tools.replace_file_with_string(keyfile, hmac, chmod=0400)): + logger.log ("sliverauth: (over)wrote hmac into %s " % keyfile) + +# create the key if needed and returns the key contents +def generate_sshkey (sliver): +# initial version was storing stuff in the sliver directly +# keyfile="/vservers/%s/home/%s/.ssh/id_rsa"%(sliver['name'], sliver['name']) +# we're now storing this in the same place as the authorized_keys, which in turn +# gets mounted to the user's home directory in the sliver + keyfile="/home/%s/.ssh/id_rsa"%(sliver['name']) + pubfile="%s.pub"%keyfile + dotssh=os.path.dirname(keyfile) + # create dir if needed + if not os.path.isdir (dotssh): + os.mkdir (dotssh, 0700) + logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), dotssh ] ) + if not os.path.isfile(pubfile): + comment="%s@%s"%(sliver['name'], socket.gethostname()) + logger.log_call( [ 'ssh-keygen', '-t', 'rsa', '-N', '', '-f', keyfile , '-C', comment] ) + os.chmod (keyfile, 0400) + logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), keyfile, pubfile ] ) + with open(pubfile) as f: + return f.read().strip() +# a sliver can get created, deleted and re-created +# the slice having the tag is not sufficient to skip key geneneration +def manage_sshkey (plc, sliver): + # regardless of whether the tag is there or not, we need to grab the file + # if it's lost b/c e.g. the sliver was destroyed we cannot save the tags content + ssh_key = generate_sshkey(sliver) + old_tag = find_tag (sliver, 'ssh_key') + if ssh_key <> old_tag: + SetSliverTag(plc, sliver['name'], 'ssh_key', ssh_key) + logger.log ("sliverauth: %s: setting ssh_key" % sliver['name'])