2 # vim:set ts=4 sw=4 expandtab:
4 # NodeManager plugin for creating credentials in slivers
5 # (*) empower slivers to make API calls throught hmac
6 # (*) also create a ssh key - used by the OMF resource controller
7 # for authenticating itself with its Experiment Controller
8 # in order to avoid spamming the DB with huge amounts of such tags,
9 # (*) slices need to have the 'enable_hmac' tag set
10 # (*) or the 'omf_control' tag set, respectively
13 Sliver authentication support for NodeManager.
27 logger.log("sliverauth: (dummy) plugin starting up...")
29 def GetSlivers(data, config, plc):
30 if 'OVERRIDES' in dir(config):
31 if config.OVERRIDES.get('sliverauth') == '-1':
32 logger.log("sliverauth: Disabled", 2)
35 if 'slivers' not in data:
36 logger.log_missing_data("sliverauth.GetSlivers", 'slivers')
39 for sliver in data['slivers']:
40 path = '/vservers/%s' % sliver['name']
41 if not os.path.exists(path):
42 # ignore all non-plc-instantiated slivers
43 instantiation = sliver.get('instantiation','')
44 if instantiation == 'plc-instantiated':
45 logger.log("sliverauth: plc-instantiated slice %s does not yet exist. IGNORING!" % sliver['name'])
49 for chunk in sliver['attributes']:
50 if chunk['tagname'] == "system":
51 if chunk['value'] in (True, 1, '1') or chunk['value'].lower() == "true":
54 for chunk in sliver['attributes']:
55 if chunk['tagname']=='enable_hmac' and not system_slice:
56 manage_hmac (plc, sliver)
57 elif chunk['tagname']=='omf_control':
58 manage_sshkey (plc, sliver)
61 def SetSliverTag(plc, slice, tagname, value):
62 node_id = tools.node_id()
63 slivertags=plc.GetSliceTags({"name":slice,"node_id":node_id,"tagname":tagname})
64 if len(slivertags)==0:
65 # looks like GetSlivers reports about delegated/nm-controller slices that do *not* belong to this node
66 # and this is something that AddSliceTag does not like
68 slivertag_id=plc.AddSliceTag(slice,tagname,value,node_id)
70 logger.log_exc ("sliverauth.SetSliverTag (probably delegated) slice=%(slice)s tag=%(tagname)s node_id=%(node_id)d"%locals())
73 slivertag_id=slivertags[0]['slice_tag_id']
74 plc.UpdateSliceTag(slivertag_id,value)
76 def find_tag (sliver, tagname):
77 for attribute in sliver['attributes']:
78 # for legacy, try the old-fashioned 'name' as well
79 name = attribute.get('tagname',attribute.get('name',''))
81 return attribute['value']
84 def manage_hmac (plc, sliver):
85 hmac = find_tag (sliver, 'hmac')
88 # let python do its thing
90 d = [random.choice(string.letters) for x in xrange(32)]
92 SetSliverTag(plc,sliver['name'],'hmac',hmac)
93 logger.log("sliverauth: %s: setting hmac" % sliver['name'])
95 path = '/vservers/%s/etc/planetlab' % sliver['name']
96 if os.path.exists(path):
97 keyfile = '%s/key' % path
98 if (tools.replace_file_with_string(keyfile,hmac,chmod=0400)):
99 logger.log ("sliverauth: (over)wrote hmac into %s " % keyfile)
101 # create the key if needed and returns the key contents
102 def generate_sshkey (sliver):
103 # initial version was storing stuff in the sliver directly
104 # keyfile="/vservers/%s/home/%s/.ssh/id_rsa"%(sliver['name'],sliver['name'])
105 # we're now storing this in the same place as the authorized_keys, which in turn
106 # gets mounted to the user's home directory in the sliver
107 keyfile="/home/%s/.ssh/id_rsa"%(sliver['name'])
108 pubfile="%s.pub"%keyfile
109 dotssh=os.path.dirname(keyfile)
110 # create dir if needed
111 if not os.path.isdir (dotssh):
112 os.mkdir (dotssh, 0700)
113 logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), dotssh ] )
114 if not os.path.isfile (pubfile):
115 comment="%s@%s"%(sliver['name'],socket.gethostname())
116 logger.log_call( [ 'ssh-keygen', '-t', 'rsa', '-N', '', '-f', keyfile , '-C', comment] )
117 os.chmod (keyfile, 0400)
118 logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), keyfile, pubfile ] )
119 return file(pubfile).read().strip()
121 # a sliver can get created, deleted and re-created
122 # the slice having the tag is not sufficient to skip key geneneration
123 def manage_sshkey (plc, sliver):
124 # regardless of whether the tag is there or not, we need to grab the file
125 # if it's lost b/c e.g. the sliver was destroyed we cannot save the tags content
126 ssh_key = generate_sshkey(sliver)
127 old_tag = find_tag (sliver, 'ssh_key')
128 if ssh_key <> old_tag:
129 SetSliverTag(plc, sliver['name'], 'ssh_key', ssh_key)
130 logger.log ("sliverauth: %s: setting ssh_key" % sliver['name'])