diff options
-rw-r--r-- | cobbler/action_power.py | 22 | ||||
-rw-r--r-- | cobbler/api.py | 14 | ||||
-rw-r--r-- | cobbler/commands.py | 6 | ||||
-rw-r--r-- | cobbler/modules/cli_system.py | 4 | ||||
-rw-r--r-- | cobbler/templar.py | 15 |
5 files changed, 50 insertions, 11 deletions
diff --git a/cobbler/action_power.py b/cobbler/action_power.py index cf1f1060..39f279fd 100644 --- a/cobbler/action_power.py +++ b/cobbler/action_power.py @@ -41,17 +41,24 @@ class PowerTool: Handles conversion of internal state to the tftpboot tree layout """ - def __init__(self,system,api): + def __init__(self,system,api,force_user,force_pass): """ Power library constructor requires a cobbler system object. """ self.system = system self.api = api + self.force_user = force_user + self.force_pass = force_pass def power(self, desired_state): """ state is either "on" or "off". Rebooting is implemented at the api.py level. + + The user and password need not be supplied. If not supplied they + will be taken from the environment, COBBLER_POWER_USER and COBBLER_POWER_PASS. + If provided, these will override any other data and be used instead. Users + interested in maximum security should take that route. """ template = self.get_command_template() @@ -60,6 +67,12 @@ class PowerTool: meta = utils.blender(self.api, False, self.system) meta["power_mode"] = desired_state + # allow command line overrides of the username/password + if self.force_user is not None: + meta["power_user"] = self.force_user + if self.force_pass is not None: + meta["power_pass"] = self.force_pass + tmp = templar.Templar(self.api._config) cmd = tmp.render(template_file, meta, None, self.system) template_file.close() @@ -73,6 +86,13 @@ class PowerTool: print " user : %s" % self.system.power_user print " id : %s" % self.system.power_id + # if no username/password data, check the environment + + if meta.get("power_user","") == "": + meta["power_user"] = os.environ.get("COBBLER_POWER_USER","") + if meta.get("power_pass","") == "": + meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS","") + print "" print "- %s" % cmd diff --git a/cobbler/api.py b/cobbler/api.py index 16e02953..d1f75044 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -606,24 +606,24 @@ class BootAPI: def get_kickstart_templates(self): return utils.get_kickstar_templates(self) - def power_on(self, system): + def power_on(self, system, user, password): """ Powers up a system that has power management configured. """ - return action_power.PowerTool(system,self).power("on") + return action_power.PowerTool(system,self,user,password).power("on") - def power_off(self, system): + def power_off(self, system, user, password): """ Powers down a system that has power management configured. """ - return action_power.PowerTool(system,self).power("off") + return action_power.PowerTool(system,self,user,password).power("off") - def reboot(self,system): + def reboot(self,system, user, password): """ Cycles power on a system that has power management configured. """ - self.power_off(system) + self.power_off(system, user, password) time.sleep(1) - return self.power_on(system) + return self.power_on(system, user, password) diff --git a/cobbler/commands.py b/cobbler/commands.py index d2da685d..380f374c 100644 --- a/cobbler/commands.py +++ b/cobbler/commands.py @@ -276,21 +276,21 @@ class CobblerFunction: obj = collect_fn().find(self.options.name) if obj is None: raise CX(_("object not found")) - self.api.power_on(obj) + self.api.power_on(obj,self.options.power_user,self.options.power_pass) return None if "poweroff" in self.args: obj = collect_fn().find(self.options.name) if obj is None: raise CX(_("object not found")) - self.api.power_off(obj) + self.api.power_off(obj,self.options.power_user,self.options.power_pass) return None if "reboot" in self.args: obj = collect_fn().find(self.options.name) if obj is None: raise CX(_("object not found")) - self.api.reboot(obj) + self.api.reboot(obj,self.options.power_user,self.options.power_pass) return None if "remove" in self.args: diff --git a/cobbler/modules/cli_system.py b/cobbler/modules/cli_system.py index ec3797bc..6673c15c 100644 --- a/cobbler/modules/cli_system.py +++ b/cobbler/modules/cli_system.py @@ -94,11 +94,15 @@ class SystemFunction(commands.CobblerFunction): p.add_option("--power-address", dest="power_address", help="address of power mgmt device, if required") p.add_option("--power-id", dest="power_id", help="plug-number or blade name, if required") + if not self.matches_args(args,["dumpvars","remove","report","getks","list"]): p.add_option("--power-pass", dest="power_pass", help="password for power management interface") + if not self.matches_args(args,["dumpvars","poweron","poweroff","reboot","remove","report","getks","list"]): p.add_option("--power-type", dest="power_type", help="one of: none, apc_snmp, bullpap, drac, ether-wake, ilo, ipmilan, ipmitool, wti") + if not self.matches_args(args,["dumpvars","remove","report","getks","list"]): p.add_option("--power-user", dest="power_user", help="username for power management interface, if required") + if not self.matches_args(args,["dumpvars","poweron","poweroff","reboot","remove","report","getks","list"]): p.add_option("--profile", dest="profile", help="name of cobbler profile (REQUIRED)") p.add_option("--server-override", dest="server_override", help="overrides server value in settings file") p.add_option("--static", dest="static", help="specifies this interface does (0) or does not use DHCP (1), default 0") diff --git a/cobbler/templar.py b/cobbler/templar.py index b68af380..bea9f440 100644 --- a/cobbler/templar.py +++ b/cobbler/templar.py @@ -40,6 +40,19 @@ class Templar: self.api = config.api self.settings = config.settings() + def check_for_invalid_imports(self,data): + """ + Ensure that Cheetah code is not importing Python modules + that may allow for advanced priveledges by ensuring we whitelist + the imports that we allow + """ + lines = data.split("\n") + for line in lines: + if line.find("#import") != -1: + rest=line.replace("#import","").replace(" ","").strip() + if rest not in [ "time", "random" ]: + raise CX("potentially insecure import in template: %s" % rest) + def render(self, data_input, search_table, out_path, subject=None): """ Render data_input back into a file. @@ -55,6 +68,8 @@ class Templar: else: raw_data = data_input + self.check_for_invalid_imports(raw_data) + # backward support for Cobbler's legacy (and slightly more readable) # template syntax. raw_data = raw_data.replace("TEMPLATE::","$") |