コード例 #1
0
ファイル: DHCPD.py プロジェクト: mpice-mn/python-opsi
    def __init__(self, **kwargs):
        self._name = 'dhcpd'

        ConfigDataBackend.__init__(self, **kwargs)

        self._dhcpdConfigFile = System.Posix.locateDHCPDConfig(
            u'/etc/dhcp3/dhcpd.conf')
        self._reloadConfigCommand = '/usr/bin/sudo {command}'.format(
            command=System.Posix.getDHCPDRestartCommand(
                default='/etc/init.d/dhcp3-server restart'))

        self._fixedAddressFormat = u'IP'
        self._defaultClientParameters = {
            'next-server': socket.gethostbyname(getfqdn()),
            'filename': u'linux/pxelinux.0'
        }
        self._dhcpdOnDepot = False

        # Parse arguments
        for (option, value) in kwargs.items():
            option = option.lower()
            if option == 'dhcpdconfigfile':
                self._dhcpdConfigFile = value
            elif option == 'reloadconfigcommand':
                self._reloadConfigCommand = value
            elif option == 'defaultclientparameters':
                self._defaultClientParameters = forceDict(value)
            elif option == 'fixedaddressformat':
                if value not in (u'IP', u'FQDN'):
                    raise BackendBadValueError(
                        u"Bad value '%s' for fixedAddressFormat, possible values are %s"
                        % (value, u', '.join(('IP', 'FQDN'))))
                self._fixedAddressFormat = value
            elif option == 'dhcpdondepot':
                self._dhcpdOnDepot = forceBool(value)

        if self._defaultClientParameters.get(
                'next-server'
        ) and self._defaultClientParameters['next-server'].startswith(u'127'):
            raise BackendBadValueError(
                u"Refusing to use ip address '%s' as default next-server" %
                self._defaultClientParameters['next-server'])

        self._dhcpdConfFile = DHCPDConfFile(self._dhcpdConfigFile)
        self._reloadEvent = threading.Event()
        self._reloadEvent.set()
        self._reloadLock = threading.Lock()
        self._reloadThread = None
        self._depotId = forceHostId(getfqdn())
        self._opsiHostKey = None
        self._depotConnections = {}
コード例 #2
0
def getLocalFQDN():
    'Get the FQDN of the local machine.'
    # Lazy imports to not hinder other tests.
    from OPSI.Types import forceHostId
    from OPSI.Util import getfqdn

    return forceHostId(getfqdn())
コード例 #3
0
def testCertificateFileAfterRenewal(tempDir):
    exampleCertificate = getAbsolutePathToTestCert('example.pem')

    certificate_folder = tempDir
    shutil.copy(exampleCertificate, certificate_folder)
    certificate_path = os.path.join(certificate_folder, 'example.pem')
    assert os.path.exists(certificate_path)

    old_config = loadConfigurationFromCertificate(certificate_path)

    configForCreating = old_config
    configForCreating['commonName'] = forceHostId(getfqdn())
    renewCertificate(path=certificate_path, config=configForCreating)

    assert os.path.exists(certificate_path)
    backupFile = '{file}.bak'.format(file=certificate_path)
    assert os.path.exists(backupFile), u"Missing backup-file!"

    new_config = loadConfigurationFromCertificate(certificate_path)

    keysToCompare = ('organizationalUnit', 'commonName', 'country', 'state',
                     'locality', 'organization', 'emailAddress')

    for key in keysToCompare:
        assert old_config[key] == new_config[key], (
            u"Difference at key {0!r} between old and new: {1!r} vs. {2!r}".
            format(key, old_config[key], new_config[key]))

    assert old_config['serialNumber'] != new_config['serialNumber']
コード例 #4
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGettingFQDNIfConfigFileEmpty(tempDir):
	fqdn = "opsi.fqdntestcase.invalid"
	with patchAddress(fqdn=fqdn):
		confPath = os.path.join(tempDir, randomString(8))
		with open(confPath, 'w'):
			pass

		assert fqdn == getfqdn(conf=confPath)
コード例 #5
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGettingFQDNIfConfigMissing():
	fqdn = "opsi.fqdntestcase.invalid"

	configFilePath = randomString(32)
	while os.path.exists(configFilePath):
		configFilePath = randomString(32)

	with patchAddress(fqdn=fqdn):
		assert fqdn == getfqdn(conf=configFilePath)
コード例 #6
0
    def __init__(self, **kwargs):
        ConfigDataBackend.__init__(self, **kwargs)

        self._name = 'opsipxeconfd'
        self._port = u'/var/run/opsipxeconfd/opsipxeconfd.socket'
        self._timeout = 10
        self._depotId = forceHostId(getfqdn())
        self._opsiHostKey = None
        self._depotConnections = {}
        self._updateThreads = {}
        self._updateThreadsLock = threading.Lock()
        self._parseArguments(kwargs)
コード例 #7
0
    def __init__(self, backend, **kwargs):
        self._name = 'depotserver'

        ExtendedBackend.__init__(self, backend)

        self._packageLog = os.path.join(LOG_DIR, 'package.log')
        self._sshRSAPublicKeyFile = u'/etc/ssh/ssh_host_rsa_key.pub'

        self._depotId = forceHostId(getfqdn())
        if not self._context.host_getIdents(id=self._depotId):  # pylint: disable=maybe-no-member
            raise BackendMissingDataError(u"Depot '%s' not found in backend" %
                                          self._depotId)
        self._packageManager = DepotserverPackageManager(self)
コード例 #8
0
def customConfig():
    hostname = forceHostId(getfqdn())
    yield {
        'organizationalUnit': u'asdf',
        'expires': 3,
        'commonName': hostname,
        'country': u'ZZ',  # Top
        'state': u'HE',
        'locality': u'Breidenbach',
        'organization': u'Unittest',
        'emailAddress': u'*****@*****.**',
        'serialNumber': 1010,
    }
コード例 #9
0
ファイル: WIM.py プロジェクト: mpice-mn/python-opsi
def _getProductProperty(backend, productId, propertyId):
    productFilter = {"productId": productId, "propertyId": propertyId}
    properties = backend.productProperty_getObjects(**productFilter)
    LOGGER.debug("Properties: {0}".format(properties))

    if not properties:
        raise RuntimeError("No property {1!r} for product {0!r} found!".format(
            productId, propertyId))
    elif len(properties) > 1:
        LOGGER.debug(
            "Found more than one property... trying to be more specific")

        serverId = getfqdn()
        prodOnDepot = backend.productOnDepot_getObjects(depotId=serverId,
                                                        productId=productId)
        if not prodOnDepot:
            raise RuntimeError(
                "Did not find product {0!r} on depot {1!r}".format(
                    productId, serverId))
        elif len(prodOnDepot) > 1:
            raise RuntimeError("Too many products {0!r} on depot {1!r}".format(
                productId, serverId))

        prodOnDepot = prodOnDepot[0]
        productFilter['packageVersion'] = prodOnDepot.packageVersion
        productFilter['productVersion'] = prodOnDepot.productVersion
        LOGGER.debug('New filter: {0}'.format(productFilter))
        properties = backend.productProperty_getObjects(**productFilter)
        LOGGER.debug("Properties: {0}".format(properties))

        if not properties:
            raise RuntimeError(
                "Unable to find property {1!r} for product {0!r}!".format(
                    productId, propertyId))
        elif len(properties) > 1:
            raise RuntimeError("Too many product properties found - aborting.")

    return properties[0]
コード例 #10
0
ファイル: Certificate.py プロジェクト: mpice-mn/python-opsi
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.')
コード例 #11
0
ファイル: Certificate.py プロジェクト: mpice-mn/python-opsi
from OpenSSL import crypto

from OPSI.Logger import Logger
from OPSI.System import which, execute
from OPSI.Types import forceHostId, forceInt
from OPSI.Util import getfqdn

OPSICONFD_CERTFILE = u'/etc/opsi/opsiconfd.pem'
DEFAULT_CERTIFICATE_PARAMETERS = {
	"country": "DE",
	"state": "RP",
	"locality": "Mainz",
	"organization": "uib gmbh",
	"organizationalUnit": "",
	"commonName": forceHostId(getfqdn()),
	"emailAddress": "",
	"expires": 2,
}
LOGGER = Logger()


class NoCertificateError(Exception):
	pass


class CertificateCreationError(Exception):
	pass


class UnreadableCertificateError(Exception):
コード例 #12
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGetFQDNByIPAddress():
	fqdn = "opsi.fqdntestcase.invalid"
	address = '127.0.0.1'

	with patchAddress(fqdn=fqdn, address=address):
		assert fqdn == getfqdn(name=address)
コード例 #13
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGettingFQDNFromEnvironment():
	fqdn = "opsi.fqdntestcase.invalid"
	with patchAddress(fqdn="nomatch.uib.local"):
		with patchEnvironmentVariables(OPSI_HOSTNAME=fqdn):
			assert fqdn == getfqdn()
コード例 #14
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGettingFQDNFromGlobalConfig():
	with patchAddress(fqdn="nomatch.opsi.invalid"):
		fqdn = "opsi.test.invalid"
		with fakeGlobalConf(fqdn=fqdn) as configPath:
			assert fqdn == getfqdn(conf=configPath)
コード例 #15
0
ファイル: test_util.py プロジェクト: mpice-mn/python-opsi
def testGettingFQDN():
	fqdn = "opsi.fqdntestcase.invalid"

	with patchAddress(fqdn=fqdn):
		assert fqdn == getfqdn()
コード例 #16
0
ファイル: test_acl.py プロジェクト: mpice-mn/python-opsi
def testDenyingAccessToOtherObjects(extendedConfigDataBackend):
    """
    It must be possible to deny access to foreign objects.

    In this test we first make sure that the access to productOnClient_create
    is possible for the object accessing the backend.
    After that we test the same referencing another object which we
    want to fail.
    """
    backend = extendedConfigDataBackend

    serverFqdn = forceHostId(getfqdn())  # using local FQDN
    depotserver1 = {
        "isMasterDepot": True,
        "type": "OpsiConfigserver",
        "id": serverFqdn,
    }

    backend.host_createObjects(depotserver1)

    clients = getClients()
    backend.host_createObjects(clients)
    client1 = clients[0]
    client2 = clients[1]

    products = getProducts()
    backend.product_createObjects(products)

    product1 = products[0]

    backend.config_createObjects([{
        "id": u'clientconfig.depot.id',
        "type": "UnicodeConfig",
    }])
    backend.configState_create(u'clientconfig.depot.id',
                               client1.getId(),
                               values=[depotserver1['id']])

    productOnDepot1 = OPSI.Object.ProductOnDepot(
        productId=product1.getId(),
        productType=product1.getType(),
        productVersion=product1.getProductVersion(),
        packageVersion=product1.getPackageVersion(),
        depotId=depotserver1['id'],
        locked=False)

    backend.productOnDepot_createObjects([productOnDepot1])

    backendAccessControl = BackendAccessControl(
        username=client1.id,
        password=client1.opsiHostKey,
        backend=backend,
        acl=[
            [
                'productOnClient_create',
                [{
                    'type': u'self',
                    'ids': [],
                    'denyAttributes': [],
                    'allowAttributes': []
                }]
            ],
        ])

    backendAccessControl.productOnClient_create(productId=product1.id,
                                                productType=product1.getType(),
                                                clientId=client1.id,
                                                installationStatus='installed')

    with pytest.raises(Exception):
        backendAccessControl.productOnClient_create(
            productId=product1.id,
            productType=product1.getType(),
            clientId=client2.id,  # here is the difference
            installationStatus='installed')