def testBlowfishWithFixedValues(): """ Testing that blowfish encryption returns the desired values. This is important to assure that across different versions and platforms we always get the same values. """ key = "08e23bfada2293e0ecbd7612acf15275" encryptedPassword = blowfishEncrypt(key, "tanz1tanz2tanz3") assert encryptedPassword == '3b189043053c4e32befa7291c2f162c3' pcpatchPassword = blowfishDecrypt(key, encryptedPassword) assert pcpatchPassword == "tanz1tanz2tanz3"
def getDepotserverCredentials(self, configService): url = urlparse(self.get('depot_server', 'url')) if url.scheme in ("webdav", "webdavs", "http", "https"): return (self.get('global', 'host_id'), self.get('global', 'opsi_host_key')) if not configService: raise Exception("Not connected to config service") depotServerUsername = self.get('depot_server', 'username') encryptedDepotServerPassword = configService.user_getCredentials( username='******', hostId=self.get('global', 'host_id'))['password'] depotServerPassword = blowfishDecrypt( self.get('global', 'opsi_host_key'), encryptedDepotServerPassword) secret_filter.add_secrets(depotServerPassword) logger.debug("Using username '%s' for depot connection", depotServerUsername) return (depotServerUsername, depotServerPassword)
def testGettingPcpatchCredentials(fakeCredentialsBackend): """ Test reading and decrypting the pcpatch password with per-client encryption. This is essentially what is done in the opsi-linux-bootimage. """ backend = fakeCredentialsBackend backend.user_setCredentials(username="******", password='******') host = OpsiClient("someclient.opsi.test", opsiHostKey=generateOpsiHostKey()) backend.host_insertObject(host) creds = backend.user_getCredentials("pcpatch", host.id) password = blowfishDecrypt(host.opsiHostKey, creds['password']) assert password == 'somepassword'
def _replicateMasterToWorkBackend(self): # pylint: disable=too-many-branches,too-many-locals,too-many-statements if not self._masterBackend: raise BackendConfigurationError("Master backend undefined") # This is needed for the following situation: # - package1 is set to "setup" which defines a dependency to package2 "setup after" # - opsiclientd processes these actions with cached config # - before opsiclientd config sync returns the results back to config service, package3 is set to "setup" # - package3 also defines a dependency to package2 "setup after" # - so package3 will be set to setup on service side too # - now the sync starts again and the actions for package1 and package2 will be set to "none" on service side # - setup of packgage2 which is required by package3 will not be exceuted productOnClients = {} product_ids_with_action = [] for productOnClient in self._masterBackend.productOnClient_getObjects( clientId=self._clientId): productOnClients[productOnClient.productId] = productOnClient if productOnClient.actionRequest not in (None, 'none'): product_ids_with_action.append(productOnClient.productId) if productOnClients and product_ids_with_action: updateProductOnClients = [] for productDependency in self._masterBackend.productDependency_getObjects( productId=product_ids_with_action): if (productDependency.requiredAction not in (None, '') and productDependency.productId in productOnClients and productOnClients[productDependency.productId]. actionRequest == productDependency.productAction and productDependency.requiredProductId in productOnClients and productOnClients[productDependency.requiredProductId]. actionRequest != productDependency.requiredAction): logger.notice( "Setting missing required action for dependency %s/%s %s/%s", productDependency.productId, productDependency.productAction, productDependency.requiredProductId, productDependency.requiredAction) productOnClients[ productDependency. requiredProductId].actionRequest = productDependency.productAction updateProductOnClients.append( productOnClients[productDependency.requiredProductId]) if updateProductOnClients: # Update is sufficient, creating a ProductOnClient is not required (see comment above) self._masterBackend.productOnClient_updateObjects( updateProductOnClients) self._cacheBackendInfo(self._masterBackend.backend_info()) self._workBackend.backend_deleteBase() self._workBackend.backend_createBase() br = BackendReplicator(readBackend=self._masterBackend, writeBackend=self._workBackend) br.replicate(serverIds=[], depotIds=[self._depotId], clientIds=[self._clientId], groupIds=[], productIds=[], productTypes=['LocalbootProduct'], audit=False, licenses=False) self._snapshotBackend.backend_deleteBase() licenseOnClients = self._masterBackend.licenseOnClient_getObjects( clientId=self._clientId) for productOnClient in self._workBackend.productOnClient_getObjects( clientId=self._clientId): if productOnClient.actionRequest in (None, 'none'): continue licensePools = self._masterBackend.licensePool_getObjects( productIds=[productOnClient.productId]) if not licensePools: logger.debug("No license pool found for product '%s'", productOnClient.productId) continue licensePool = licensePools[0] try: licenseOnClient = None for loc in licenseOnClients: if loc.licensePoolId == licensePool.id: licenseOnClient = loc logger.notice("Reusing existing licenseOnClient '%s'", licenseOnClient) break else: logger.notice("Acquiring license for product '%s'", productOnClient.productId) licenseOnClient = self._masterBackend.licenseOnClient_getOrCreateObject( clientId=self._clientId, productId=productOnClient.productId) if licenseOnClient: # Fake deletion # This will delete the licenseOnClient (free the license) while syncing config back to server # In case licenseOnClient_getObjects will be called on the CacheBackend the licenseOnClients # will be recreated, so the objects will be recreated after deletion self._fireEvent('objectsDeleted', [licenseOnClient]) self._fireEvent('backendModified') statistics = { "licensePools": 0, "softwareLicenses": 0, "licenseContracts": 0 } for licensePool in self._masterBackend.licensePool_getObjects( id=licenseOnClient.licensePoolId): logger.debug("Storing LicensePool: %s", licensePool) self._workBackend.licensePool_insertObject(licensePool) statistics["licensePools"] += 1 for softwareLicense in self._masterBackend.softwareLicense_getObjects( id=licenseOnClient.softwareLicenseId): logger.debug("Storing SoftwareLicense: %s", softwareLicense) for licenseContract in self._masterBackend.licenseContract_getObjects( id=softwareLicense.licenseContractId): logger.debug("Storing LicenseContract: %s", licenseContract) self._workBackend.licenseContract_insertObject( licenseContract) statistics["licenseContracts"] += 1 self._workBackend.softwareLicense_insertObject( softwareLicense) statistics["softwareLicenses"] += 1 logger.debug("Storing LicenseOnClient: %s", licenseOnClient) self._workBackend.licenseOnClient_insertObject( licenseOnClient) logger.notice( "LicenseOnClient stored for product '%s', %s", productOnClient.productId, statistics) except Exception as license_sync_error: # pylint: disable=broad-except logger.error("Failed to acquire license for product '%s': %s", productOnClient.productId, license_sync_error) self._snapshotBackend.backend_createBase() br = BackendReplicator(readBackend=self._workBackend, writeBackend=self._snapshotBackend) br.replicate() if self._clientId != config.get('global', 'host_id'): logger.error( "Client id '%s' does not match config global.host_id '%s'", self._clientId, config.get('global', 'host_id')) clients = self._workBackend.host_getObjects(id=self._clientId) if not clients: raise BackendMissingDataError( "Host '{self._clientId}' not found in replicated backend") opsiHostKey = clients[0].getOpsiHostKey() if opsiHostKey != config.get('global', 'opsi_host_key'): logger.error( "Host key '%s' from work backend does not match config global.opsi_host_key '%s'", opsiHostKey, config.get('global', 'opsi_host_key')) password = self._masterBackend.user_getCredentials( username='******', hostId=self._clientId) password = password['password'] logger.notice( "Creating opsi passwd file '%s' using opsi host key '%s...'", self._opsiPasswdFile, opsiHostKey[:10]) self.user_setCredentials(username='******', password=blowfishDecrypt( opsiHostKey, password)) auditHardwareConfig = self._masterBackend.auditHardware_getConfig() with codecs.open(self._auditHardwareConfigFile, 'w', 'utf8') as file: file.write(json.dumps(auditHardwareConfig)) self._workBackend._setAuditHardwareConfig(auditHardwareConfig) # pylint: disable=protected-access self._workBackend.backend_createBase()
def testBlowfishEncryptionFailsWithNoKey(randomText, blowfishKey): encodedText = blowfishEncrypt(blowfishKey, randomText) with pytest.raises(BlowfishError): blowfishDecrypt(None, encodedText)
def testBlowfishEncryptionFailures(randomText, blowfishKey): encodedText = blowfishEncrypt(blowfishKey, randomText) with pytest.raises(BlowfishError): blowfishDecrypt(blowfishKey + 'f00b4', encodedText)
def testBlowfishEncryption(randomText, blowfishKey): encodedText = blowfishEncrypt(blowfishKey, randomText) assert encodedText != randomText decodedText = blowfishDecrypt(blowfishKey, encodedText) assert randomText == decodedText