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 = {}
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())
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']
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)
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)
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)
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)
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, }
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]
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.')
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):
def testGetFQDNByIPAddress(): fqdn = "opsi.fqdntestcase.invalid" address = '127.0.0.1' with patchAddress(fqdn=fqdn, address=address): assert fqdn == getfqdn(name=address)
def testGettingFQDNFromEnvironment(): fqdn = "opsi.fqdntestcase.invalid" with patchAddress(fqdn="nomatch.uib.local"): with patchEnvironmentVariables(OPSI_HOSTNAME=fqdn): assert fqdn == getfqdn()
def testGettingFQDNFromGlobalConfig(): with patchAddress(fqdn="nomatch.opsi.invalid"): fqdn = "opsi.test.invalid" with fakeGlobalConf(fqdn=fqdn) as configPath: assert fqdn == getfqdn(conf=configPath)
def testGettingFQDN(): fqdn = "opsi.fqdntestcase.invalid" with patchAddress(fqdn=fqdn): assert fqdn == getfqdn()
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')