sliverauth generates a sliver ssh keypair and exposes it in the 'ssh_key' tag
[nodemanager.git] / plugins / sliverauth.py
1 #!/usr/bin/python -tt
2 # vim:set ts=4 sw=4 expandtab:
3 #
4 # $Id$
5 # $URL$
6 #
7 # NodeManager plugin for creating credentials in slivers
8 # (*) empower slivers to make API calls throught hmac
9 # (*) also create a ssh key - used by the OMF resource controller 
10 #     for authenticating itself with its Experiment Controller
11 # xxx todo : a config option for turning these 2 things on or off ?
12
13 """
14 Sliver authentication support for NodeManager.
15
16 """
17
18 import errno
19 import os
20 import random
21 import string
22 import tempfile
23 import time
24
25 import logger
26 import tools
27
28 def start(options, conf):
29     logger.log("sliverauth: (dummy) plugin starting up...")
30
31 def GetSlivers(data, config, plc):
32     if 'OVERRIDES' in dir(config):
33         if config.OVERRIDES.get('sliverauth') == '-1':
34             logger.log("sliverauth:  Disabled", 2)
35             return
36
37     if 'slivers' not in data:
38         logger.log_missing_data("sliverauth.GetSlivers", 'slivers')
39         return
40
41     for sliver in data['slivers']:
42         path = '/vservers/%s' % sliver['name']
43         if not os.path.exists(path):
44             # ignore all non-plc-instantiated slivers
45             instantiation = sliver.get('instantiation','')
46             if instantiation == 'plc-instantiated':
47                 logger.log("sliverauth: plc-instantiated slice %s does not yet exist. IGNORING!" % sliver['name'])
48             continue
49
50         manage_hmac (plc, sliver)
51         manage_sshkey (plc, sliver)
52
53
54 def SetSliverTag(plc, slice, tagname, value):
55     node_id = tools.node_id()
56     slivertags=plc.GetSliceTags({"name":slice,"node_id":node_id,"tagname":tagname})
57     if len(slivertags)==0:
58         # looks like GetSlivers reports about delegated/nm-controller slices that do *not* belong to this node
59         # and this is something that AddSliceTag does not like
60         try:
61             slivertag_id=plc.AddSliceTag(slice,tagname,value,node_id)
62         except:
63             logger.log_exc ("sliverauth.SetSliverTag (probably delegated) slice=%(slice)s tag=%(tagname)s node_id=%(node_id)d"%locals())
64             pass
65     else:
66         slivertag_id=slivertags[0]['slice_tag_id']
67         plc.UpdateSliceTag(slivertag_id,value)
68
69 def find_tag (sliver, tagname):
70     for attribute in sliver['attributes']:
71         # for legacy, try the old-fashioned 'name' as well
72         name = attribute.get('tagname',attribute.get('name',''))
73         if name == tagname:
74             return attribute['value']
75     return None
76
77 def manage_hmac (plc, sliver):
78     hmac = find_tag (sliver, 'hmac')
79
80     if not hmac:
81         # let python do its thing 
82         random.seed()
83         d = [random.choice(string.letters) for x in xrange(32)]
84         hmac = "".join(d)
85         SetSliverTag(plc,sliver['name'],'hmac',hmac)
86         logger.log("sliverauth: %s: setting hmac" % sliver['name'])
87
88     path = '/vservers/%s/etc/planetlab' % sliver['name']
89     if os.path.exists(path):
90         keyfile = '%s/key' % path
91         if (tools.replace_file_with_string(keyfile,hmac,chmod=0400)):
92             logger.log ("sliverauth: (over)wrote hmac into %s " % keyfile)
93
94 def manage_sshkey (plc, sliver):
95     ssh_key = find_tag (sliver, 'ssh_key')
96     
97     # generate if not present
98     if not ssh_key:
99         # create dir if needed
100         dotssh="/vservers/%s/home/%s/.ssh"%(sliver['name'],sliver['name'])
101         if not os.path.isdir (dotssh):
102             os.mkdir (dotssh, 0700)
103             logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), dotssh ] )
104         keyfile="%s/id_rsa"%dotssh
105         pubfile="%s.pub"%keyfile
106         if not os.path.isfile (pubfile):
107             logger.log_call( [ 'ssh-keygen', '-t', 'rsa', '-N', '', '-f', keyfile ] )
108             os.chmod (keyfile, 0400)
109             logger.log_call ( [ 'chown', "%s:slices"%(sliver['name']), keyfile, pubfile ] )
110         ssh_key = file(pubfile).read()
111         SetSliverTag(plc, sliver['name'], 'ssh_key', ssh_key)
112         logger.log ("sliverauth: %s: setting ssh_key" % sliver['name'])