def _install(jobList): self.cfg.flavor = [] openpgpkey.getKeyCache().setPublicPath( self.cfg.root + '/root/.gnupg/pubring.gpg') openpgpkey.getKeyCache().setPrivatePath( self.cfg.root + '/root/.gnupg/secring.gpg') self.cfg.pubRing = [self.cfg.root + '/root/.gnupg/pubring.gpg'] client = conaryclient.ConaryClient(self.cfg) client.setUpdateCallback(self.callback) if self.csCache: changeSetList = self.csCache.getChangeSets(client.getRepos(), jobList, callback=self.callback) else: changeSetList = [] updJob = client.newUpdateJob() try: client.prepareUpdateJob(updJob, jobList, keepExisting=False, resolveDeps=False, recurse=False, checkPathConflicts=False, fromChangesets=changeSetList, migrate=True) except conaryclient.update.NoNewTrovesError: # since we're migrating, this simply means there were no # operations to be performed pass else: util.mkdirChain(self.cfg.root + '/root') client.applyUpdate(updJob, replaceFiles=True, tagScript=self.cfg.root + '/root/tagscripts')
def _install(jobList): self.cfg.flavor = [] openpgpkey.getKeyCache().setPublicPath(self.cfg.root + '/root/.gnupg/pubring.gpg') openpgpkey.getKeyCache().setPrivatePath(self.cfg.root + '/root/.gnupg/secring.gpg') self.cfg.pubRing = [self.cfg.root + '/root/.gnupg/pubring.gpg'] client = conaryclient.ConaryClient(self.cfg) client.setUpdateCallback(self.callback) if self.csCache: changeSetList = self.csCache.getChangeSets( client.getRepos(), jobList, callback=self.callback) else: changeSetList = [] updJob = client.newUpdateJob() try: client.prepareUpdateJob(updJob, jobList, keepExisting=False, resolveDeps=False, recurse=False, checkPathConflicts=False, fromChangesets=changeSetList, migrate=True) except conaryclient.update.NoNewTrovesError: # since we're migrating, this simply means there were no # operations to be performed pass else: util.mkdirChain(self.cfg.root + '/root') client.applyUpdate(updJob, replaceFiles=True, tagScript=self.cfg.root + '/root/tagscripts')
def testInstallSignedTrove(self): # CNY-2555 fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' self.addComponent('test:run', '1', fileContents=[('/usr/share/foo1', 'blah')]) self.addCollection('test', '1', [':run']) self.cfg.signatureKey = fingerprint self.cfg.quiet = True signtrove.signTroves(self.cfg, ["test"]) # Install, have a non-existant keyring self.cfg.pubRing = "/some/keyring" openpgpkey.getKeyCache().reset() openpgpkey.getKeyCache().setPublicPath(self.cfg.pubRing) # This should change to an error when RMK-791 (related to CNY-2555) is # fixed self.logFilter.add() self.updatePkg("test") self.logFilter.remove() self.logFilter.compare( "error: While caching PGP key: Permission denied: /some")
def testUnknownSig(self): # the repository shouldn't blow up on this commit unless it's bene # run w/ requireSigs = True self.stopRepository(0) sigRepos = self.openRepository(0, requireSigs=True) fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') os.chdir(self.workDir) self.newpkg('testcase') os.chdir('testcase') self.writeFile('testcase.recipe', testRecipe) self.addfile('testcase.recipe') repos = self.openRepository() self.cfg.signatureKey = fingerprint try: checkin.commit(repos, self.cfg, 'testcase', None) self.fail("Repository should have required a signature") except DigitalSignatureVerificationError: pass self.stopRepository(0) repos = self.openRepository(0) checkin.commit(repos, self.cfg, 'testcase', None) self.cfg.signatureKey = None
def testTroveDisplaySigs(self): # go through a lot of trouble to sign this trove. # copied from sigtest. self.addComponent('foo:runtime', '1.0') from conary.lib import openpgpfile, openpgpkey from conary.build import signtrove fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') keyRing = open(resources.get_archive() + '/pubring.gpg') keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() # upload the public key repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) self.cfg.signatureKey = fingerprint self.cfg.quiet = True signtrove.signTroves(self.cfg, [ "foo:runtime"]) rs, txt = self.captureOutput(queryrep.displayTroves, self.cfg, ['foo:runtime'], digSigs=True) assert(txt.startswith('''\ foo:runtime=1.0-1-1 Digital Signature: F7440D78FE813C882212C2BF8AC2828190B1E477:'''))
def testUpdateMissingKey(self): fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') self.cfg.signatureKey = fingerprint self.addQuickTestComponent("test:doc", "1.0-1-1") signtrove.signTroves(self.cfg, ["test:doc"]) repos = self.openRepository() # utterly prevent the keycache from knowing about the key, # but give it a place to store a keyserver retrieved key. newKeyCache = openpgpkey.OpenPGPKeyFileCache() tmpPath = mkdtemp() pubRing = self.cfg.pubRing self.cfg.pubRing = [tmpPath + '/pubring.gpg'] newKeyCache.publicPaths = self.cfg.pubRing keyCacheCallback = openpgpkey.KeyCacheCallback(repos, self.cfg) newKeyCache.setCallback(keyCacheCallback) openpgpkey.setKeyCache(newKeyCache) try: self.updatePkg(self.rootDir, "test:doc") newKeyCache.getPublicKey(fingerprint) finally: self.cfg.pubRing = pubRing openpgpkey.setKeyCache(keyCache) util.rmtree(tmpPath)
def testChangeKeyOwner(self): fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') self.addQuickTestComponent("test:source", "1.0-1-1") self.cfg.signatureKey = fingerprint self.cfg.quiet = True repos = self.openRepository() anotherRepos = self.setupUser(repos, self.cfg.buildLabel, 'another', 'anotherpass', None, None) # put the public key into the repo keyRing = open( resources.get_path('conary_test', 'archive', 'pubring.gpg')) keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) repos.changePGPKeyOwner(self.cfg.buildLabel, 'another', fingerprint) assert (repos.listUsersMainKeys(self.cfg.buildLabel, 'another')[0] == fingerprint)
def testTroveDisplaySigs(self): # go through a lot of trouble to sign this trove. # copied from sigtest. self.addComponent('foo:runtime', '1.0') from conary.lib import openpgpfile, openpgpkey from conary.build import signtrove fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') keyRing = open(resources.get_archive() + '/pubring.gpg') keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() # upload the public key repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) self.cfg.signatureKey = fingerprint self.cfg.quiet = True signtrove.signTroves(self.cfg, ["foo:runtime"]) rs, txt = self.captureOutput(queryrep.displayTroves, self.cfg, ['foo:runtime'], digSigs=True) assert (txt.startswith('''\ foo:runtime=1.0-1-1 Digital Signature: F7440D78FE813C882212C2BF8AC2828190B1E477:'''))
def testNonRecursiveGroupSigs(self): fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') # make all components before assigning a key, so all start out blank self.addQuickTestComponent("test:doc", "1.0-1-1") self.makeSourceTrove('testcase', testRecipe) repos = self.openRepository() built = self.cookItem(repos, self.cfg, 'testcase', ignoreDeps=True) group = self.build(testGroup, "GroupTest") group = self.build(outerGroup, "OuterGroup") signatureKey = self.cfg.signatureKey self.cfg.signatureKey = fingerprint self.cfg.quiet = True v = versions.VersionFromString('/localhost@rpl:linux/1.0-1-1') f = deps.parseFlavor('') try: # first sign the outer group trove #signtrove.signTroves(self.cfg, [ "group-outer" ]) cvccmd.sourceCommand(self.cfg, ["sign", "group-outer"], {}) try: t = repos.getTrove('group-outer', v, f) self._checkDigitalSig(t, fingerprint) except openpgpfile.KeyNotFound: self.fail('Group signing failed to cover %s' % t) # check the sig on each trove in the group, since group signing # should be recursive for trvName in ('group-test', 'test:doc', 'testcase', 'testcase:runtime'): try: t = repos.getTrove(trvName, v, f) t.getDigitalSignature(fingerprint) self.fail('Group signing inadvenderntly signed %s' % trvName) except openpgpfile.KeyNotFound: pass # then check that the source trove wasn't signed... it wasn't # explicitly part of the group v = versions.VersionFromString('/localhost@rpl:linux/1.0-1') f = deps.parseFlavor('') t = repos.getTrove('testcase:source', v, f) try: signature = t.getDigitalSignature(fingerprint) self._checkDigitalSig(t, fingerprint) self.fail('signing group inadvendently signed source trove') except openpgpfile.KeyNotFound: pass finally: self.cfg.signatureKey = signatureKey
def runCommand(self, thisCommand, cfg, argSet, args, debugAll=False): client = conaryclient.ConaryClient(cfg) repos = client.getRepos() callback = commit.CheckinCallback(cfg) if not cfg.buildLabel and cfg.installLabelPath: cfg.buildLabel = cfg.installLabelPath[0] sys.excepthook = util.genExcepthook(debug=cfg.debugExceptions, debugCtrlC=debugAll) if cfg.installLabelPath: cfg.installLabel = cfg.installLabelPath[0] else: cfg.installLabel = None cfg.initializeFlavors() log.setMinVerbosity(log.INFO) log.resetErrorOccurred() # set the build flavor here, just to set architecture information # which is used when initializing a recipe class use.setBuildFlagsFromFlavor(None, cfg.buildFlavor, error=False) profile = False if argSet.has_key('lsprof'): import cProfile prof = cProfile.Profile() prof.enable() profile = 'lsprof' del argSet['lsprof'] keyCache = openpgpkey.getKeyCache() keyCache.setPublicPath(cfg.pubRing) repos = conaryclient.ConaryClient(cfg).getRepos() keyCacheCallback = openpgpkey.KeyCacheCallback(repos, cfg) keyCache.setCallback(keyCacheCallback) try: rv = options.MainHandler.runCommand(self, thisCommand, cfg, argSet, args, callback=callback, repos=client.getRepos(), profile=profile) finally: if profile == 'lsprof': prof.disable() prof.dump_stats('cvc.lsprof') prof.print_stats() elif profile: prof.stop() if log.errorOccurred(): sys.exit(2) return rv
def testMirror(self): sourceRepos, targetRepos = self.createRepositories() mirrorFile = self.createConfigurationFile() # this is really ugly, but needed to ensure test consistency db = self.servers.getServer(0).reposDB.connect() cu = db.cursor() # test simple trove mirroring self.createTroves(sourceRepos, 1, 2, "1.0") self.createTroves(sourceRepos, 1, 2, "2.0") self.sleep(1.2) self.createTroves(sourceRepos, 1, 2, "3.0") # the following is just to get the trigger to fire cu.execute("update Instances set changed=1") db.commit() self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # simulate multiple trove versions with the same mark self.createTroves(sourceRepos, 10, 2, "1.0", "~foo") self.createTroves(sourceRepos, 10, 2, "1.0", "~!foo") self.createTroves(sourceRepos, 10, 2, "1.1") # the following is just to get the trigger to fire cu.execute("update Instances set changed=1") db.commit() self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # test mirroring of ascii keys sourceRepos.addNewAsciiPGPKey(self.cfg.buildLabel, 'test', sigtest.unexpiredKey) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # test mirroring of new trove signatures self.createTroves(sourceRepos, 20, 2) self.cfg.signatureKey = '7CCD34B5C5D9CD1F637F6743D4F8F127C267B79D' signtrove.signTroves(self.cfg, ["test10:runtime", "test20:runtime"]) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) fprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fprint, '111111') self.cfg.signatureKey = fprint keyRing = open(resources.get_archive() + '/pubring.gpg') keyData = openpgpfile.exportKey(fprint, keyRing) keyData.seek(0) keyData = keyData.read() sourceRepos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) signtrove.signTroves(self.cfg, ["test11:runtime", "test21:runtime"]) self.createTroves(sourceRepos, 30, 2) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos)
def testMirror(self): sourceRepos, targetRepos = self.createRepositories() mirrorFile = self.createConfigurationFile() # this is really ugly, but needed to ensure test consistency db = self.servers.getServer(0).reposDB.connect() cu = db.cursor() # test simple trove mirroring self.createTroves(sourceRepos, 1, 2, "1.0") self.createTroves(sourceRepos, 1, 2, "2.0") self.sleep(1.2) self.createTroves(sourceRepos, 1, 2, "3.0") # the following is just to get the trigger to fire cu.execute("update Instances set changed=1") db.commit() self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # simulate multiple trove versions with the same mark self.createTroves(sourceRepos, 10, 2, "1.0", "~foo") self.createTroves(sourceRepos, 10, 2, "1.0", "~!foo") self.createTroves(sourceRepos, 10, 2, "1.1") # the following is just to get the trigger to fire cu.execute("update Instances set changed=1") db.commit() self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # test mirroring of ascii keys sourceRepos.addNewAsciiPGPKey(self.cfg.buildLabel, 'test', sigtest.unexpiredKey) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) # test mirroring of new trove signatures self.createTroves(sourceRepos, 20, 2) self.cfg.signatureKey = '7CCD34B5C5D9CD1F637F6743D4F8F127C267B79D' signtrove.signTroves(self.cfg, [ "test10:runtime", "test20:runtime" ]) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos) fprint='F7440D78FE813C882212C2BF8AC2828190B1E477' keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fprint, '111111') self.cfg.signatureKey = fprint keyRing = open(resources.get_archive() + '/pubring.gpg') keyData = openpgpfile.exportKey(fprint, keyRing) keyData.seek(0) keyData = keyData.read() sourceRepos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) signtrove.signTroves(self.cfg, [ "test11:runtime", "test21:runtime" ]) self.createTroves(sourceRepos, 30, 2) self.runMirror(mirrorFile) self.compareRepositories(sourceRepos, targetRepos)
def testFileUpdateMissingKey(self): fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' # make a changeset with useful stuff that could be installed cs = changeset.ChangeSet() flavor = deps.parseFlavor('') v = versions.VersionFromString('/%s/1.0-1-1' % self.cfg.buildLabel.asString()).copy() v.resetTimeStamps() t = trove.Trove('test:test', v, flavor, None) path = self.workDir + '/blah' f = open(path, 'w') f.write('hello, world!\n') f.close() pathId = sha1helper.md5String('/blah') f = files.FileFromFilesystem(path, pathId) fileId = f.fileId() t.addFile(pathId, '/blah', v, fileId) cs.addFile(None, fileId, f.freeze()) cs.addFileContents(pathId, fileId, changeset.ChangedFileTypes.file, filecontents.FromFilesystem(path), f.flags.isConfig()) diff = t.diff(None, absolute=1)[0] cs.newTrove(diff) cs.addPrimaryTrove('test:test', v, flavor) # sign the changeset csPath = os.path.join(self.workDir, 'test-1.0-1.ccs') cs = cook.signAbsoluteChangeset(cs, fingerprint) cs.writeToFile(csPath) tmpPath = mkdtemp() keyCache = openpgpkey.getKeyCache() newKeyCache = openpgpkey.OpenPGPKeyFileCache() pubRing = self.cfg.pubRing self.cfg.pubRing = [tmpPath + '/pubring.gpg'] keyCacheCallback = openpgpkey.KeyCacheCallback(None, self.cfg) newKeyCache.setCallback(keyCacheCallback) openpgpkey.setKeyCache(newKeyCache) try: self.updatePkg(self.rootDir, csPath) finally: self.cfg.pubRing = pubRing openpgpkey.setKeyCache(keyCache)
def _setupSignature(self, repos, fingerprint): # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') # get the public key keyRing = open(resources.get_archive('pubring.gpg')) if hasattr(openpgpfile, 'readKeyData'): keyData = openpgpfile.readKeyData(keyRing, fingerprint) else: keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() # upload the public key repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) self.buildCfg.signatureKey = fingerprint
def testSignedCheckout(self): fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') self.addQuickTestComponent("test:source", "1.0-1-1") self.cfg.signatureKey = fingerprint self.cfg.quiet = True # put the public key into the repo keyRing = open( resources.get_path('conary_test', 'archive', 'pubring.gpg')) keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) signtrove.signTroves(self.cfg, ["test:source"]) # alter key's trust value and determine that the doUpdate # code properly verifies trust thresholds pubKey = keyCache.getPublicKey(fingerprint) pubKey.trustLevel = openpgpfile.TRUST_UNTRUSTED keyCache.publicDict[fingerprint] = pubKey self.cfg.trustThreshold = openpgpfile.TRUST_ULTIMATE self.logFilter.add() try: checkout(repos, self.cfg, self.workDir, ["test"]) self.fail("checkin.checkout did not properly verify trust levels") except DigitalSignatureVerificationError: self.logFilter.compare([ 'warning: The trove test:source has ' 'signatures generated with untrusted keys. You can either ' 'resign the trove with a key that you trust, or add one of the ' 'keys to the list of trusted keys (the trustedKeys ' 'configuration option). The keys that were not trusted are: ' '90B1E477' ])
def __init__(self, cfg = None, passwordPrompter = None, resolverClass=resolve.DependencySolver, updateCallback=None, repos=None, modelFile=None): """ @param cfg: a custom L{conarycfg.ConaryConfiguration} object. If None, the standard Conary configuration is loaded from /etc/conaryrc, ~/.conaryrc, and ./conaryrc. @type cfg: L{conarycfg.ConaryConfiguration} """ ClientUpdate.__init__(self, callback=updateCallback) if cfg == None: cfg = conarycfg.ConaryConfiguration() cfg.initializeFlavors() self.repos = None self.cfg = cfg self.db = database.Database(cfg.root, cfg.dbPath, cfg.modelPath, modelFile=modelFile) if repos: self.repos = repos else: self.repos = self.createRepos(self.db, cfg, passwordPrompter = passwordPrompter) log.openSysLog(self.cfg.root, self.cfg.logFile) if not resolverClass: resolverClass = resolve.DependencySolver self.resolver = resolverClass(self, cfg, self.db) # Set up the callbacks for the PGP key cache keyCache = openpgpkey.getKeyCache() keyCache.setPublicPath(cfg.pubRing) keyCacheCallback = openpgpkey.KeyCacheCallback(self.repos, cfg) keyCache.setCallback(keyCacheCallback)
def checkTroveSignatures(self, trv, callback): assert(hasattr(callback, 'verifyTroveSignatures')) if callback.keyCache is None: callback.keyCache = openpgpkey.getKeyCache() for fingerprint, timestamp, sig in trv.troveInfo.sigs.digitalSigs.iter(): try: pubKey = callback.keyCache.getPublicKey(fingerprint) if pubKey.isRevoked(): raise openpgpfile.IncompatibleKey('Key %s is revoked' %pubKey.getFingerprint()) expirationTime = pubKey.getTimestamp() if expirationTime and expirationTime < timestamp: raise openpgpfile.IncompatibleKey('Key %s is expired' %pubKey.getFingerprint()) except openpgpfile.KeyNotFound: # missing keys could be okay; that depends on the threshold # we've set. it's the callbacks problem in any case. pass res = ChangeSetJob.checkTroveSignatures(self, trv, callback) if len(res[1]) and self.requireSigs: raise openpgpfile.KeyNotFound('Repository does not recognize ' 'key: %s'% res[1][0])
def testSignTrove(self): fingerprint = 'F7440D78FE813C882212C2BF8AC2828190B1E477' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') self.addQuickTestComponent("test:doc", "1.0-1-1") self.cfg.signatureKey = fingerprint self.cfg.quiet = True self.assertRaises(errors.DigitalSignatureError, signtrove.signTroves, self.cfg, ["test:doc"]) # get the public key keyRing = open( resources.get_path('conary_test', 'archive', 'pubring.gpg')) keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() # upload the public key repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) signtrove.signTroves(self.cfg, ["test:doc"]) # get the signed trove from the repository, verify that # everything is correct v = versions.VersionFromString('/localhost@rpl:linux/1.0-1-1') f = deps.parseFlavor('') t = repos.getTrove('test:doc', v, f) self._checkDigitalSig(t, fingerprint) self.assertEqual(t.verifyDigitalSignatures(), (openpgpfile.TRUST_TRUSTED, [], set())) # add another signature. This exercises code such as the # change set cache invalidation fingerprint2 = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' keyCache.getPrivateKey(fingerprint2, '111111') # upload the public key keyRing = open( resources.get_path('conary_test', 'archive', 'pubring.gpg')) keyData = openpgpfile.exportKey(fingerprint2, keyRing) keyData.seek(0) keyData = keyData.read() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) # sign with the second private key self.cfg.signatureKey = fingerprint2 self.cfg.quiet = True signtrove.signTroves(self.cfg, ["test:doc"]) # iterate over the signatures, making sure each signature version has # two sigs associated with it t = repos.getTrove('test:doc', v, f) self._checkDigitalSig(t, fingerprint) self._checkDigitalSig(t, fingerprint2) self.assertEqual(t.verifyDigitalSignatures(), (openpgpfile.TRUST_TRUSTED, [], set())) # attempt signing again with a key that already signed the trove self.assertRaises(errors.DigitalSignatureError, signtrove.signTroves, self.cfg, ["test:doc"])
def testReposRequireSigs(self): fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') callback = checkin.CheckinCallback() # make sure there's not a cached repo index 1 self.stopRepository(1) sigRepos = self.openRepository(1, requireSigs=True) ascKey = open(resources.get_path('conary_test', 'archive', 'key.asc')).read() buildLabel = self.cfg.buildLabel signatureKey = self.cfg.signatureKey signatureKeyMap = self.cfg.signatureKeyMap # try block protects test suite from the alteration of self.cfg # or most especially, the effects of leaving a requireSigs repo around try: self.cfg.signatureKey = None self.cfg.signatureKeyMap = None self.cfg.buildLabel = versions.Label('localhost1@rpl:linux') sigRepos.addNewAsciiPGPKey(self.cfg.buildLabel, 'test', ascKey) try: self.addQuickTestComponent("test:doc", "/localhost1@rpl:devel/1.0-1-1") self.fail("Repository should have required a signature") except DigitalSignatureVerificationError: pass name = 'testcase' fullName = name + '=/localhost1@rpl:linux' # test commit codepath. origDir = os.getcwd() try: os.chdir(self.workDir) self.newpkg(name) os.chdir(name) self.writeFile(name + '.recipe', testRecipe) self.addfile(name + '.recipe') try: checkin.commit(sigRepos, self.cfg, 'foobar', callback) self.fail("Repository should have rejected commit") except DigitalSignatureVerificationError: pass # but we really need a source trove for the rest of the paths self.cfg.signatureKey = fingerprint checkin.commit(sigRepos, self.cfg, fullName, None) self.cfg.signatureKey = None finally: os.chdir(origDir) # test cook codepath try: self.cookItem(sigRepos, self.cfg, fullName, callback=callback, ignoreDeps=True) self.fail("Repository should have rejected cook") except DigitalSignatureVerificationError: pass self.cfg.signatureKey = fingerprint self.cookItem(sigRepos, self.cfg, fullName, callback=callback, ignoreDeps=True) self.cfg.signatureKey = None # test clone codepath try: self.clone('/localhost1@rpl:shadow', 'testcase:source=/localhost1@rpl:linux') self.fail("Repository should have rejected clone") except DigitalSignatureVerificationError: pass # test branch codepath try: self.mkbranch("1.0-1", "localhost1@rpl:shadow", "testcase:source", shadow=False) self.fail("Repository should have rejected branch") except DigitalSignatureVerificationError: pass # test shadow codepath try: self.mkbranch("1.0-1", "localhost1@rpl:shadow", "testcase:source", shadow=True) self.fail("Repository should have rejected shadow") except DigitalSignatureVerificationError: pass finally: self.cfg.buildLabel = buildLabel self.cfg.signatureKey = signatureKey self.cfg.signatureKeyMap = signatureKeyMap # this repo MUST be destroyed, other tests will fail against it. self.stopRepository(1) sigRepos = self.openRepository(1) self.addQuickTestComponent("test:doc", "/localhost1@rpl:devel/1.0-1-1")
def testSignedUpdate(self): fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E' # supply the pass phrase for our private key keyCache = openpgpkey.getKeyCache() keyCache.getPrivateKey(fingerprint, '111111') self.addQuickTestComponent("test:doc", "1.0-1-1") self.cfg.signatureKey = fingerprint self.cfg.quiet = True # put the public key into the repo keyRing = open( resources.get_path('conary_test', 'archive', 'pubring.gpg')) keyData = openpgpfile.exportKey(fingerprint, keyRing) keyData.seek(0) keyData = keyData.read() repos = self.openRepository() repos.addNewPGPKey(self.cfg.buildLabel, 'test', keyData) signtrove.signTroves(self.cfg, ["test:doc"]) # alter key's trust value and determine that the doUpdate # code properly verifies trust thresholds pubKey = keyCache.getPublicKey(fingerprint) pubKey.trustLevel = openpgpfile.TRUST_UNTRUSTED keyCache.publicDict[fingerprint] = pubKey self.cfg.trustThreshold = openpgpfile.TRUST_ULTIMATE self.logFilter.add() try: self.discardOutput(doUpdate, self.cfg, 'test:doc') self.fail("updatecmd.doUpdate did not properly check trust levels") except DigitalSignatureVerificationError: self.logFilter.compare([ 'warning: The trove test:doc has ' 'signatures generated with untrusted keys. You can either ' 'resign the trove with a key that you trust, or add one of the ' 'keys to the list of trusted keys (the trustedKeys ' 'configuration option). The keys that were not trusted are: ' 'F94E405E' ]) # An example how one can catch the digital signature verification # error for each unsigned trove (and display some message in a GUI # maybe). In this case we just raise a different exception. class MyException(Exception): errorIsUncatchable = True class C_(callbacks.UpdateCallback): def verifyTroveSignatures(self, trv): try: return callbacks.UpdateCallback.verifyTroveSignatures( self, trv) except DigitalSignatureVerificationError: raise MyException("Error in trove %s" % trv.getName()) callback = C_(trustThreshold=self.cfg.trustThreshold) # We should catch our own exception now self.discardOutput(self.assertRaises, MyException, doUpdate, self.cfg, "test:doc", callback=callback)
def addNewKey(self, userId, pgpKeyData): # this ignore duplicate keys cu = self.db.cursor() stream = util.ExtendedStringIO(pgpKeyData) if openpgpfile.countKeys(stream) != 1: raise openpgpfile.IncompatibleKey( \ 'Submit only one key at a time.') inKey = openpgpfile.newKeyFromStream(stream) # make sure it's a public key if not isinstance(inKey, openpgpfile.PGP_PublicKey): raise openpgpfile.IncompatibleKey('Key must be a public key') inKey.verifySelfSignatures() mainFingerprint = inKey.getKeyFingerprint() # if key already exists we need to ensure it's safe to overwrite # the old one, and then just do it. r = cu.execute('SELECT KeyId, pgpKey FROM PGPKeys WHERE fingerprint=?', mainFingerprint) for (keyId, keyBlob) in cu.fetchall(): origKey = cu.frombinary(keyBlob) origKey = openpgpfile.newKeyFromString(origKey) modified = origKey.merge(inKey) if not modified: # Nothing to do here, the key in our DB is already a superset # of the incoming key break # origKey now is a superset of both the old key and the incoming # key. we can't allow the repo to let go of subkeys or # revocations. sio = StringIO() origKey.writeAll(sio) keyData = sio.getvalue() #reset the key cache so the changed key shows up keyCache = openpgpkey.getKeyCache() keyCache.remove(keyId) cu.execute('UPDATE PGPKeys set pgpKey=? where keyId=?', cu.binary(keyData), keyId) break else: #for cu.execute( 'INSERT INTO PGPKeys (userId, fingerprint, pgpKey) ' 'VALUES (?, ?, ?)', (userId, mainFingerprint, cu.binary(pgpKeyData))) keyId = cu.lastrowid keyFingerprints = [mainFingerprint] keyFingerprints.extend(x.getKeyFingerprint() for x in inKey.iterSubKeys()) for fingerprint in keyFingerprints: cu.execute( "SELECT COUNT(*) FROM PGPFingerprints " "WHERE keyId = ? and fingerprint = ?", (keyId, fingerprint)) if cu.fetchall()[0][0] > 0: continue cu.execute( 'INSERT INTO PGPFingerprints (keyId, fingerprint) ' 'VALUES(?, ?)', (keyId, fingerprint)) self.db.commit()
def addNewKey(self, userId, pgpKeyData): # this ignore duplicate keys cu = self.db.cursor() stream = util.ExtendedStringIO(pgpKeyData) if openpgpfile.countKeys(stream) != 1: raise openpgpfile.IncompatibleKey( \ 'Submit only one key at a time.') inKey = openpgpfile.newKeyFromStream(stream) # make sure it's a public key if not isinstance(inKey, openpgpfile.PGP_PublicKey): raise openpgpfile.IncompatibleKey('Key must be a public key') inKey.verifySelfSignatures() mainFingerprint = inKey.getKeyFingerprint() # if key already exists we need to ensure it's safe to overwrite # the old one, and then just do it. r = cu.execute('SELECT KeyId, pgpKey FROM PGPKeys WHERE fingerprint=?', mainFingerprint) for (keyId, keyBlob) in cu.fetchall(): origKey = cu.frombinary(keyBlob) origKey = openpgpfile.newKeyFromString(origKey) modified = origKey.merge(inKey) if not modified: # Nothing to do here, the key in our DB is already a superset # of the incoming key break # origKey now is a superset of both the old key and the incoming # key. we can't allow the repo to let go of subkeys or # revocations. sio = StringIO() origKey.writeAll(sio) keyData = sio.getvalue() #reset the key cache so the changed key shows up keyCache = openpgpkey.getKeyCache() keyCache.remove(keyId) cu.execute('UPDATE PGPKeys set pgpKey=? where keyId=?', cu.binary(keyData), keyId) break else: #for cu.execute('INSERT INTO PGPKeys (userId, fingerprint, pgpKey) ' 'VALUES (?, ?, ?)', (userId, mainFingerprint, cu.binary(pgpKeyData))) keyId = cu.lastrowid keyFingerprints = [ mainFingerprint ] keyFingerprints.extend(x.getKeyFingerprint() for x in inKey.iterSubKeys()) for fingerprint in keyFingerprints: cu.execute("SELECT COUNT(*) FROM PGPFingerprints " "WHERE keyId = ? and fingerprint = ?", (keyId, fingerprint)) if cu.fetchall()[0][0] > 0: continue cu.execute('INSERT INTO PGPFingerprints (keyId, fingerprint) ' 'VALUES(?, ?)', (keyId, fingerprint)) self.db.commit()