diff options
Diffstat (limited to 'azurelinuxagent/distro/default/provision.py')
-rw-r--r-- | azurelinuxagent/distro/default/provision.py | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/azurelinuxagent/distro/default/provision.py b/azurelinuxagent/distro/default/provision.py new file mode 100644 index 0000000..1e9c459 --- /dev/null +++ b/azurelinuxagent/distro/default/provision.py @@ -0,0 +1,165 @@ +# Copyright 2014 Microsoft Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Requires Python 2.4+ and Openssl 1.0+ +# + +""" +Provision handler +""" + +import os +import azurelinuxagent.logger as logger +from azurelinuxagent.future import text +import azurelinuxagent.conf as conf +from azurelinuxagent.event import add_event, WALAEventOperation +from azurelinuxagent.exception import * +from azurelinuxagent.utils.osutil import OSUTIL, OSUtilError +import azurelinuxagent.protocol as prot +import azurelinuxagent.protocol.ovfenv as ovf +import azurelinuxagent.utils.shellutil as shellutil +import azurelinuxagent.utils.fileutil as fileutil + +CUSTOM_DATA_FILE="CustomData" + +class ProvisionHandler(object): + + def process(self): + #If provision is not enabled, return + if not conf.get_switch("Provisioning.Enabled", True): + logger.info("Provisioning is disabled. Skip.") + return + + provisioned = os.path.join(OSUTIL.get_lib_dir(), "provisioned") + if os.path.isfile(provisioned): + return + + logger.info("run provision handler.") + protocol = prot.FACTORY.get_default_protocol() + try: + status = prot.ProvisionStatus(status="NotReady", + subStatus="Provision started") + protocol.report_provision_status(status) + + self.provision() + fileutil.write_file(provisioned, "") + thumbprint = self.reg_ssh_host_key() + + logger.info("Finished provisioning") + status = prot.ProvisionStatus(status="Ready") + status.properties.certificateThumbprint = thumbprint + protocol.report_provision_status(status) + + add_event(name="WALA", is_success=True, message="", + op=WALAEventOperation.Provision) + except ProvisionError as e: + logger.error("Provision failed: {0}", e) + status = prot.ProvisionStatus(status="NotReady", + subStatus= text(e)) + protocol.report_provision_status(status) + add_event(name="WALA", is_success=False, message=text(e), + op=WALAEventOperation.Provision) + + def reg_ssh_host_key(self): + keypair_type = conf.get("Provisioning.SshHostKeyPairType", "rsa") + if conf.get_switch("Provisioning.RegenerateSshHostKeyPair"): + shellutil.run("rm -f /etc/ssh/ssh_host_*key*") + shellutil.run(("ssh-keygen -N '' -t {0} -f /etc/ssh/ssh_host_{1}_key" + "").format(keypair_type, keypair_type)) + thumbprint = self.get_ssh_host_key_thumbprint(keypair_type) + return thumbprint + + def get_ssh_host_key_thumbprint(self, keypair_type): + cmd = "ssh-keygen -lf /etc/ssh/ssh_host_{0}_key.pub".format(keypair_type) + ret = shellutil.run_get_output(cmd) + if ret[0] == 0: + return ret[1].rstrip().split()[1].replace(':', '') + else: + raise ProvisionError(("Failed to generate ssh host key: " + "ret={0}, out= {1}").format(ret[0], ret[1])) + + + def provision(self): + logger.info("Copy ovf-env.xml.") + try: + ovfenv = ovf.copy_ovf_env() + except prot.ProtocolError as e: + raise ProvisionError("Failed to copy ovf-env.xml: {0}".format(e)) + + logger.info("Handle ovf-env.xml.") + try: + logger.info("Set host name.") + OSUTIL.set_hostname(ovfenv.hostname) + + logger.info("Publish host name.") + OSUTIL.publish_hostname(ovfenv.hostname) + + self.config_user_account(ovfenv) + + self.save_customdata(ovfenv) + + if conf.get_switch("Provisioning.DeleteRootPassword"): + OSUTIL.del_root_password() + except OSUtilError as e: + raise ProvisionError("Failed to handle ovf-env.xml: {0}".format(e)) + + def config_user_account(self, ovfenv): + logger.info("Create user account if not exists") + OSUTIL.useradd(ovfenv.username) + + if ovfenv.user_password is not None: + logger.info("Set user password.") + use_salt = conf.get_switch("Provision.UseSalt", True) + salt_type = conf.get_switch("Provision.SaltType", 6) + OSUTIL.chpasswd(ovfenv.username, ovfenv.user_password, + use_salt,salt_type) + + logger.info("Configure sudoer") + OSUTIL.conf_sudoer(ovfenv.username, ovfenv.user_password is None) + + logger.info("Configure sshd") + OSUTIL.conf_sshd(ovfenv.disable_ssh_password_auth) + + #Disable selinux temporary + sel = OSUTIL.is_selinux_enforcing() + if sel: + OSUTIL.set_selinux_enforce(0) + + self.deploy_ssh_pubkeys(ovfenv) + self.deploy_ssh_keypairs(ovfenv) + + if sel: + OSUTIL.set_selinux_enforce(1) + + OSUTIL.restart_ssh_service() + + def save_customdata(self, ovfenv): + logger.info("Save custom data") + customdata = ovfenv.customdata + if customdata is None: + return + lib_dir = OSUTIL.get_lib_dir() + fileutil.write_file(os.path.join(lib_dir, CUSTOM_DATA_FILE), + OSUTIL.decode_customdata(customdata)) + + def deploy_ssh_pubkeys(self, ovfenv): + for pubkey in ovfenv.ssh_pubkeys: + logger.info("Deploy ssh public key.") + OSUTIL.deploy_ssh_pubkey(ovfenv.username, pubkey) + + def deploy_ssh_keypairs(self, ovfenv): + for keypair in ovfenv.ssh_keypairs: + logger.info("Deploy ssh key pairs.") + OSUTIL.deploy_ssh_keypair(ovfenv.username, keypair) + |