예제 #1
0
def _reloadSamba():
	logger.notice(u"   Reloading samba")

	try:
		execute(u'service {name} reload'.format(name=getSambaServiceName(default="smbd")))
	except Exception as error:
		logger.warning(error)
예제 #2
0
파일: WIM.py 프로젝트: mpice-mn/python-opsi
def getImageInformation(imagePath):
    """
	Read information from a WIM file at `imagePath`.

	This method acts as a generator that yields information for each image
	in the file as a `dict`. The keys in the dict are all lowercase.
	Every dict has at least the key 'name'.
	"""
    if not os.path.exists(imagePath):
        raise OSError(u"File {0!r} not found!".format(imagePath))

    try:
        imagex = which('wimlib-imagex')
    except Exception as error:
        LOGGER.logException(error)
        LOGGER.warning("Unable to find 'wimlib-imagex': {0}".format(error))
        LOGGER.warning("Please install 'wimtools'.")
        raise RuntimeError("Unable to find 'wimlib-imagex': {0}".format(error))

    imageinfo = {}
    for line in execute("{imagex} info '{file}'".format(imagex=imagex,
                                                        file=imagePath)):
        if line and ':' in line:
            key, value = line.split(':', 1)
            key = key.strip().lower()
            value = value.strip()

            if key == 'languages':
                langs = value
                if ' ' in langs:
                    langs = langs.split(' ')
                elif ',' in langs:
                    langs = langs.split(',')
                else:
                    langs = [langs]

                languages = set()
                for lang in langs:
                    if lang.strip():
                        languages.add(lang.strip())

                value = languages

            imageinfo[key] = value
        elif not line and imageinfo:
            if 'name' in imageinfo:  # Do not return file information.
                LOGGER.debug("Collected information {0!r}".format(imageinfo))
                yield imageinfo

            imageinfo = {}
예제 #3
0
def isSamba4():
	"""
	Check if the current system uses samba 4.

	:return: True if running Samba 4. False otherwise.
	:rtype: bool
	"""
	samba4 = False

	try:
		smbd = which('smbd')
		result = execute('%s -V 2>/dev/null' % smbd)
		for line in result:
			if line.lower().startswith("version"):
				samba4 = line.split()[1].startswith('4')
	except Exception as error:
		logger.debug('Getting Samba Version failed due to: {0}', error)

	return samba4
예제 #4
0
    def _runPackageScript(self, scriptName, env={}):
        logger.info(u"Attempt to run package script {0!r}", scriptName)
        try:
            if not self.packageControlFile:
                raise ValueError(u"Metadata not present")

            if not self.clientDataDir:
                raise ValueError(u"Client data dir not set")

            script = os.path.join(self.tmpUnpackDir, u'OPSI', scriptName)
            if not os.path.exists(script):
                logger.info(u"Package script '%s' not found" % scriptName)
                return []

            logger.notice(u"Running package script '%s'" % scriptName)
            os.chmod(script, 0o700)

            os.putenv('PRODUCT_ID',
                      self.packageControlFile.getProduct().getId())
            os.putenv('PRODUCT_TYPE',
                      self.packageControlFile.getProduct().getType())
            os.putenv('PRODUCT_VERSION',
                      self.packageControlFile.getProduct().getProductVersion())
            os.putenv('PACKAGE_VERSION',
                      self.packageControlFile.getProduct().getPackageVersion())
            os.putenv('CLIENT_DATA_DIR', self.getProductClientDataDir())
            for (k, v) in env.items():
                os.putenv(k, v)

            return execute(script, timeout=PACKAGE_SCRIPT_TIMEOUT)
        except Exception as error:
            logger.logException(error, LOG_ERROR)
            self.cleanup()
            raise RuntimeError(
                u"Failed to execute package script '%s' of package '%s': %s" %
                (scriptName, self.packageFile, error))
        finally:
            logger.debug(
                u"Finished running package script {0!r}".format(scriptName))
예제 #5
0
def check_signature(bin_dir):
	logger.info("check_signature is called")
	if not RUNNING_ON_WINDOWS:
		return # Not yet implemented

	windowsVersion = sys.getwindowsversion() # pylint: disable=no-member
	if windowsVersion.major < 6 or (windowsVersion.major == 6 and windowsVersion.minor < 4):
		return # Get-AuthenticodeSignature is only defined for versions since 2016

	binary_list = [
		os.path.join(bin_dir, "opsiclientd.exe"),
		os.path.join(bin_dir, "opsiclientd_rpc.exe"),
		os.path.join(bin_dir, "action_processor_starter.exe")
	]
	for binary in binary_list:
		cmd = f'powershell.exe -ExecutionPolicy Bypass -Command \"(Get-AuthenticodeSignature \'{binary}\').Status -eq \'Valid\'\"'

		result = execute(cmd, captureStderr=True, waitForEnding=True, timeout=20)
		logger.debug(result)
		if not "True" in result:
			raise ValueError(f"Invalid Signature of file {binary}")
	logger.notice("Successfully verified %s", binary_list)
예제 #6
0
def createCertificate(path=None, config=None):
	"""
	Creates a certificate.

	Will overwrite any certificate that may exists in ``path``.

	.. versionchanged:: 4.0.6.2

		Incrementing previously set serial number on re-creation.
		For new certificates a random number will be generated.


	:param path: The path of the certificate. \
If this is `None` the default will be used.
	:type path: str
	:param config: The configuration of the certificate. \
If not given will use a default.
	:type config: dict
	:raises CertificateCreationError: If errors exist in configuration.
	"""
	try:
		which("ucr")
		LOGGER.notice(u"Don't use certificate creation method on UCS-Systems")
		return
	except Exception:
		pass

	if path is None:
		path = OPSICONFD_CERTFILE

	if config is None:
		certparams = DEFAULT_CERTIFICATE_PARAMETERS
	else:
		certparams = config

	try:
		certparams["expires"] = forceInt(certparams["expires"])
	except Exception:
		raise CertificateCreationError(
			u"No valid expiration date given. Must be an integer."
		)

	if certparams["commonName"] != forceHostId(getfqdn()):
		raise CertificateCreationError(
			u"commonName must be the FQDN of the local server"
		)

	LOGGER.notice(u"Creating new opsiconfd cert")
	LOGGER.notice(u"Generating new key pair")
	k = crypto.PKey()
	k.generate_key(crypto.TYPE_RSA, 2048)

	LOGGER.notice(u"Generating new self-signed cert")
	cert = crypto.X509()
	cert.get_subject().C = certparams['country']
	cert.get_subject().ST = certparams['state']
	cert.get_subject().L = certparams['locality']
	cert.get_subject().O = certparams['organization']
	cert.get_subject().CN = certparams['commonName']

	try:
		if certparams['organizationalUnit']:
			cert.get_subject().OU = certparams['organizationalUnit']
		else:
			del certparams['organizationalUnit']
	except KeyError:
		pass

	try:
		if certparams['emailAddress']:
			cert.get_subject().emailAddress = certparams['emailAddress']
		else:
			del certparams['emailAddress']
	except KeyError:
		pass

	LOGGER.notice("Generating new Serialnumber")
	# As described in RFC5280 this value is required and must be a
	# positive and unique integer.
	# Source: http://tools.ietf.org/html/rfc5280#page-19
	#
	# We currently do not have the ability to make the serial unique
	# but we assume that this is called only once in 2-3 years.
	# If we have an old serial number present we increment it by 1.
	# If we do not have an old serial number we create a random one.
	try:
		serialNumber = int(certparams['serialNumber']) + 1
	except (KeyError, ValueError):
		LOGGER.debug(u"Reading in the existing serial number failed.")
		LOGGER.info(u"Creating new random serial number.")
		serialNumber = random.randint(0, pow(2, 16))
	cert.set_serial_number(serialNumber)

	LOGGER.notice(
		u"Setting new expiration date (%d years)" % certparams["expires"]
	)
	cert.gmtime_adj_notBefore(0)
	cert.gmtime_adj_notAfter(certparams["expires"] * 365 * 24 * 60 * 60)

	LOGGER.notice(u"Filling certificate with new data")
	cert.set_issuer(cert.get_subject())
	cert.set_pubkey(k)
	cert.set_version(2)

	LOGGER.notice(u"Signing Certificate")
	cert.sign(k, str('sha512'))

	certcontext = "".join(
		(
			crypto.dump_certificate(crypto.FILETYPE_PEM, cert),
			crypto.dump_privatekey(crypto.FILETYPE_PEM, k)
		)
	)

	LOGGER.notice(u"Beginning to write certificate.")
	with open(path, "wt") as certfile:
		certfile.write(certcontext)

	with NamedTemporaryFile(mode="wt") as randfile:
		LOGGER.notice(u"Generating and filling new randomize string")
		randomBytes = os.urandom(512)
		randfile.write(randomBytes)

		execute(
			u"{command} dhparam -rand {tempfile} 512 >> {target}".format(
				command=which("openssl"), tempfile=randfile.name, target=path
			)
		)

	LOGGER.notice(u'Certificate creation done.')
예제 #7
0
def configureDHCPD(configFile=DHCPD_CONF):
    """
	Configure the configuration file for DHCPD.

	If any changes are made the original file will be backed up.
	The backup file has a timestamp appended to the filename.

	:param configFile: The configuration file for DHCP.
	"""
    if not os.path.exists(configFile):
        logger.warning("Can't find an dhcpd.conf. Aborting configuration.")
        return

    sysConfig = getNetworkConfiguration()
    logger.notice(u"Configuring dhcpd")

    dhcpdConf = DHCPDConfFile(configFile)
    dhcpdConf.parse()

    confChanged = False
    if dhcpdConf.getGlobalBlock().getParameters_hash().get(
            'use-host-decl-names', False):
        logger.info(u"  use-host-decl-names already enabled")
    else:
        confChanged = True
        logger.notice(u"  enabling use-host-decl-names")
        dhcpdConf.getGlobalBlock().addComponent(
            DHCPDConf_Parameter(startLine=-1,
                                parentBlock=dhcpdConf.getGlobalBlock(),
                                key='use-host-decl-names',
                                value=True))

    subnets = dhcpdConf.getGlobalBlock().getBlocks('subnet', recursive=True)
    if not subnets:
        confChanged = True
        logger.notice(u"  No subnets found, adding subnet")
        dhcpdConf.getGlobalBlock().addComponent(
            DHCPDConf_Block(startLine=-1,
                            parentBlock=dhcpdConf.getGlobalBlock(),
                            type='subnet',
                            settings=[
                                'subnet', sysConfig['subnet'], 'netmask',
                                sysConfig['netmask']
                            ]))

    for subnet in dhcpdConf.getGlobalBlock().getBlocks('subnet',
                                                       recursive=True):
        logger.info(u"  Found subnet %s/%s" %
                    (subnet.settings[1], subnet.settings[3]))
        groups = subnet.getBlocks('group')
        if not groups:
            confChanged = True
            logger.notice(u"    No groups found, adding group")
            subnet.addComponent(
                DHCPDConf_Block(startLine=-1,
                                parentBlock=subnet,
                                type='group',
                                settings=['group']))

        for group in subnet.getBlocks('group'):
            logger.info(u"    Configuring group")
            params = group.getParameters_hash(inherit='global')

            if params.get('next-server'):
                logger.info(u"      next-server already set")
            else:
                confChanged = True
                group.addComponent(
                    DHCPDConf_Parameter(startLine=-1,
                                        parentBlock=group,
                                        key='next-server',
                                        value=sysConfig['ipAddress']))
                logger.notice(u"      next-server set to %s" %
                              sysConfig['ipAddress'])

            if params.get('filename'):
                logger.info(u"      filename already set")
            else:
                confChanged = True
                filename = 'linux/pxelinux.0'
                if isSLES() or isOpenSUSE():
                    filename = 'opsi/pxelinux.0'
                group.addComponent(
                    DHCPDConf_Parameter(startLine=-1,
                                        parentBlock=group,
                                        key='filename',
                                        value=filename))
                logger.notice(u"      filename set to %s" % filename)

    restartCommand = getDHCPDRestartCommand(
        default=u'/etc/init.d/dhcp3-server restart')
    if confChanged:
        logger.notice(u"  Creating backup of %s" % configFile)
        shutil.copy(configFile,
                    configFile + u'.' + time.strftime("%Y-%m-%d_%H:%M"))

        logger.notice(u"  Writing new %s" % configFile)
        dhcpdConf.generate()

        logger.notice(u"  Restarting dhcpd")
        try:
            execute(restartCommand)
        except Exception as error:
            logger.warning(error)

    logger.notice(u"Configuring sudoers")
    patchSudoersFileToAllowRestartingDHCPD(restartCommand)

    opsiconfdUid = pwd.getpwnam(OPSICONFD_USER)[2]
    adminGroupGid = grp.getgrnam(ADMIN_GROUP)[2]
    os.chown(configFile, opsiconfdUid, adminGroupGid)
    os.chmod(configFile, 0o664)

    if isRHEL() or isCentOS():
        dhcpDir = os.path.dirname(configFile)
        if dhcpDir == '/etc':
            return

        logger.notice(
            'Detected Red Hat-family system. Providing rights on "{dir}" '
            'to group "{group}"'.format(dir=dhcpDir, group=ADMIN_GROUP))
        os.chown(dhcpDir, -1, adminGroupGid)

    backendConfigFile = os.path.join('/etc', 'opsi', 'backends', 'dhcpd.conf')
    logger.notice('Configuring backend file {0}'.format(backendConfigFile))
    insertDHCPDRestartCommand(backendConfigFile, restartCommand)