ia64/xen-unstable

view tools/python/xen/xm/addlabel.py @ 16273:ceb195042ca7

acm, xm: Propagate error codes.

Fix propagation of error codes to the shell in some of the security
related xm commands.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author Keir Fraser <keir@xensource.com>
date Tue Oct 30 09:33:49 2007 +0000 (2007-10-30)
parents 993655d24b55
children 5255eac35270
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2006 International Business Machines Corp.
16 # Author: Reiner Sailer <sailer@us.ibm.com>
17 # Author: Bryan D. Payne <bdpayne@us.ibm.com>
18 #============================================================================
20 """Labeling a domain configuration file or a resource.
21 """
22 import os
23 import sys
25 from xen.util import dictio
26 import xen.util.xsm.xsm as security
27 from xen.xm.opts import OptionError
28 from xen.util import xsconstants
29 from xen.xm import main as xm_main
30 from xen.xm.main import server
32 def help():
33 return """
34 Format: xm addlabel <label> dom <configfile> [<policy>]
35 xm addlabel <label> mgt <domain name> [<policy type>:<policy>]
36 xm addlabel <label> res <resource> [[<policy type>:]<policy>]
37 xm addlabel <label> vif-<idx> <domain name> [<policy type>:<policy>]
39 This program adds an acm_label entry into the 'configfile'
40 for a domain or allows to label a xend-managed domain.
41 The global resource label file for is extended with labels for
42 resources. It derives the policy from the running hypervisor
43 if it is not given (optional parameter). If a label already
44 exists for the given domain or resource, then addlabel fails.
46 For xend-managed domains, the 'mgt' parameter should be used and
47 the 'xm' tool must have been configured to use the xen-api for
48 communication with xen. If a policy is provided as last parameter,
49 its type must also be given. Currently only one type of policy is
50 supported and identified as 'ACM'. An example for a valid string
51 is 'ACM:xm-test'. """
54 def validate_config_file(configfile):
55 """Performs a simple sanity check on the configuration file passed on
56 the command line. We basically just want to make sure that it's
57 not a domain image file so we check for a few configuration values
58 and then we are satisfied. Returned 1 on success, otherwise 0.
59 """
60 # read in the config file
61 globs = {}
62 locs = {}
63 try:
64 execfile(configfile, globs, locs)
65 except:
66 print "Invalid configuration file."
67 return 0
69 # sanity check on the data from the file
70 count = 0
71 required = ['kernel', 'memory', 'name']
72 for (k, v) in locs.items():
73 if k in required:
74 count += 1
75 if count != 3:
76 print "Invalid configuration file."
77 return 0
78 else:
79 return 1
82 def add_resource_label(label, resource, policyref, policy_type):
83 """Adds a resource label to the global resource label file.
84 """
86 if xm_main.serverType != xm_main.SERVER_XEN_API:
88 # sanity check: make sure this label can be instantiated later on
89 ssidref = security.label2ssidref(label, policyref, 'res')
91 #build canonical resource name
92 resource = security.unify_resname(resource,mustexist=False)
94 # see if this resource is already in the file
95 access_control = {}
96 fil = security.res_label_filename
97 try:
98 access_control = dictio.dict_read("resources", fil)
99 except:
100 print "Resource file not found, creating new file at:"
101 print "%s" % (fil)
103 if access_control.has_key(resource):
104 security.err("This resource is already labeled.")
106 # write the data to file
107 new_entry = { resource : tuple([policy_type, policyref, label]) }
108 access_control.update(new_entry)
109 dictio.dict_write(access_control, "resources", fil)
110 else:
111 res = [ policy_type, policyref, label ]
112 res_xapi = security.format_resource_label(res)
113 old = server.xenapi.XSPolicy.get_resource_label(resource)
114 if old == "":
115 try:
116 server.xenapi.XSPolicy.set_resource_label(resource,
117 res_xapi,
118 "")
119 except Exception, e:
120 raise security.XSMError("Could not label this resource: %s" %
121 str(e))
122 else:
123 raise security.XSMError("'%s' is already labeled with '%s'" %
124 (resource,old))
126 def add_domain_label(label, configfile, policyref):
127 # sanity checks: make sure this label can be instantiated later on
128 ssidref = security.label2ssidref(label, policyref, 'dom')
130 new_label = "access_control = ['policy=%s,label=%s']\n" % \
131 (policyref, label)
132 if not os.path.isfile(configfile):
133 security.err("Configuration file \'" + configfile + "\' not found.")
134 config_fd = open(configfile, "ra+")
135 for line in config_fd:
136 if not security.access_control_re.match(line):
137 continue
138 config_fd.close()
139 security.err("Config file \'" + configfile + "\' is already labeled.")
140 config_fd.write(new_label)
141 config_fd.close()
143 def add_domain_label_xapi(label, domainname, policyref, policy_type):
144 if xm_main.serverType != xm_main.SERVER_XEN_API:
145 raise OptionError('Xm must be configured to use the xen-api.')
146 uuids = server.xenapi.VM.get_by_name_label(domainname)
147 if len(uuids) == 0:
148 raise OptionError('A VM with that name does not exist.')
149 if len(uuids) != 1:
150 raise OptionError('There are multiple domains with the same name.')
151 uuid = uuids[0]
152 sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
153 try:
154 old_lab = server.xenapi.VM.get_security_label(uuid)
155 rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
156 except Exception, e:
157 raise security.XSMError("Could not label the domain: %s" % e)
158 if int(rc) < 0:
159 raise OptionError('Could not label domain.')
160 else:
161 ssidref = int(rc)
162 if ssidref != 0:
163 print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %\
164 (domainname,label,ssidref)
165 else:
166 print "Set the label of dormant domain '%s' to '%s'." % \
167 (domainname,label)
169 def add_vif_label(label, vmname, idx, policyref, policy_type):
170 if xm_main.serverType != xm_main.SERVER_XEN_API:
171 raise OptionError('Need to be configure for using xen-api.')
172 vm_refs = server.xenapi.VM.get_by_name_label(vmname)
173 if len(vm_refs) == 0:
174 raise OptionError('A VM with the name %s does not exist.' %
175 vmname)
176 vif_refs = server.xenapi.VM.get_VIFs(vm_refs[0])
177 if len(vif_refs) <= idx:
178 raise OptionError("Bad VIF index.")
179 vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
180 if not vif_ref:
181 print "Internal error: VIF does not exist."
182 sec_lab = "%s:%s:%s" % (policy_type, policyref, label)
183 try:
184 old_lab = server.xenapi.VIF.get_security_label(vif_ref)
185 rc = server.xenapi.VIF.set_security_label(vif_ref,
186 sec_lab, old_lab)
187 if int(rc) != 0:
188 print "Could not label the VIF."
189 else:
190 print "Successfully labeled the VIF."
191 except Exception, e:
192 print "Could not label the VIF: %s" % str(e)
195 def main(argv):
196 policyref = None
197 policy_type = ""
198 if len(argv) not in (4, 5):
199 raise OptionError('Needs either 2 or 3 arguments')
201 label = argv[1]
203 if len(argv) == 5:
204 policyref = argv[4]
205 elif security.on():
206 policyref = security.active_policy
207 policy_type = xsconstants.ACM_POLICY_ID
208 else:
209 raise OptionError("No active policy. Must specify policy on the "
210 "command line.")
212 if argv[2].lower() == "dom":
213 configfile = argv[3]
214 if configfile[0] != '/':
215 for prefix in [".", "/etc/xen"]:
216 configfile = prefix + "/" + configfile
217 if os.path.isfile(configfile):
218 break
219 if not validate_config_file(configfile):
220 raise OptionError('Invalid config file')
221 else:
222 add_domain_label(label, configfile, policyref)
223 elif argv[2].lower() == "mgt":
224 domain = argv[3]
225 if policy_type == "":
226 tmp = policyref.split(":")
227 if len(tmp) != 2:
228 raise OptionError("Policy name in wrong format.")
229 policy_type, policyref = tmp
230 add_domain_label_xapi(label, domain, policyref, policy_type)
231 elif argv[2].lower() == "res":
232 resource = argv[3]
233 if policy_type == "":
234 tmp = policyref.split(":")
235 if len(tmp) == 1:
236 policy_type = xsconstants.ACM_POLICY_ID
237 elif len(tmp) == 2:
238 policy_type, policyref = tmp
239 else:
240 raise OptionError("Policy name in wrong format.")
241 add_resource_label(label, resource, policyref, policy_type)
242 elif argv[2].lower().startswith("vif-"):
243 try:
244 idx = int(argv[2][4:])
245 if idx < 0:
246 raise
247 except:
248 raise OptionError("Bad VIF device index.")
249 vmname = argv[3]
250 if policy_type == "":
251 tmp = policyref.split(":")
252 if len(tmp) != 2:
253 raise OptionError("Policy name in wrong format.")
254 policy_type, policyref = tmp
255 add_vif_label(label, vmname, idx, policyref, policy_type)
256 else:
257 raise OptionError('Need to specify either "dom", "mgt" or "res" as '
258 'object to add label to.')
260 if __name__ == '__main__':
261 try:
262 main(sys.argv)
263 except Exception, e:
264 sys.stderr.write('Error: %s\n' % str(e))
265 sys.exit(-1)