def __init__(self, inifile): """ This method does nothing in this cronjob """ self.inifile = os.path.abspath(inifile) conf = appconfig('config:' + self.inifile) pylons.config = load_environment(conf.global_conf, conf.local_conf) self.config = pylons.config self.gpg = GnuPG()
class GpgKey(formencode.validators.FieldStorageUploadConverter): """ Validator for an uploaded GPG key. They must with the 'BEGIN PGP PUBLIC KEY BLOCK' text. """ def __init__(self): self.gpg_id = None self.gnupg = GnuPG() def _to_python(self, value, c): """ Validate the GPG key. ``value`` FieldStorage uploaded file. ``c`` """ if not value.value.startswith('-----BEGIN PGP PUBLIC KEY BLOCK-----'): log.error('GPG key does not start with BEGIN PGP PUBLIC KEY BLOCK') raise formencode.Invalid(_('Invalid GPG key'), value, c) if self.gnupg.is_unusable(): log.error('Unable to validate GPG key because gpg is unusable.') raise formencode.Invalid(_('Internal error: debexpo is not ' + 'properly configured to handle' + 'GPG keys'), value, c) self.gpg_id = self.gnupg.parse_key_id(value.value) if self.gpg_id is None: log.error("Failed to parse GPG key") raise formencode.Invalid(_('Invalid GPG key'), value, c) return formencode.validators.FieldStorageUploadConverter._to_python(self, value, c) def key_id(self): return self.gpg_id
class UpdateKeyring(object): def __init__(self, inifile): """ This method does nothing in this cronjob """ self.inifile = os.path.abspath(inifile) conf = appconfig('config:' + self.inifile) pylons.config = load_environment(conf.global_conf, conf.local_conf) self.config = pylons.config self.gpg = GnuPG() def invoke(self): """ Loops through the debexpo.upload.incoming directory and runs the debexpo.importer for each file """ if 'debexpo.gpg_keyring' not in self.config: print("debexpo.gpg_keyring was not configured or is not writable") return try: keyring = open(self.config['debexpo.gpg_keyring'], "a+") keyring.close() except IOError as e: print("Can't access file: %s: %s" % (self.config['debexpo.gpg_keyring'], str(e))) return print("Regenerate keyring into %s" % (keyring.name)) (_, keyring) = tempfile.mkstemp() for user in meta.session.query(User).all(): if not user.gpg: continue temp = tempfile.NamedTemporaryFile(delete=True) temp.write(user.gpg) temp.flush() (out, err) = self.gpg.add_signature(temp.name, keyring) temp.close() if err != 0: print("gpg failed to import keyring: %s" % (out)) continue print(out) shutil.move(keyring, self.config['debexpo.gpg_keyring']) meta.session.close()
def main(self): """ Actually start the import of the package. Do several environment sanity checks, move files into the right place, and then create the database entries for the imported package. """ # Set up importer self._setup() log.debug('Importer started with arguments: %s' % sys.argv[1:]) filecheck = CheckFiles() signature = GnuPG() # Try parsing the changes file, but fail if there's an error. try: self.changes = Changes(filename=self.changes_file) filecheck.test_files_present(self.changes) filecheck.test_md5sum(self.changes) except Exception as e: # XXX: The user won't ever see this message. The changes file was # invalid, we don't know whom send it to self._reject("Your changes file appears invalid. Refusing your upload\n%s" % (e.message)) # Determine user from changed-by field # This might be temporary, the GPG check should replace the user later # At this stage it is only helpful to get an email address to send blame mails to self._determine_uploader() # Next, find out whether the changes file was signed with a valid signature, if not reject immediately if not self.skip_gpg: if not signature.is_signed(self.changes_file): self._reject('Your upload does not appear to be signed') (gpg_out, gpg_status) = signature.verify_sig_full(self.changes_file) if gpg_status != 0: self._reject('Your upload does not contain a valid signature. Output was:\n%s' % (gpg_out)) log.debug("GPG signature matches user %s" % (self.user.email)) # XXX: Replace self.user by something which was verified by GPG! if self.user_id == -1: self._reject('Couldn\'t find user %s. Exiting.' % self.user.email) log.debug("User found in database. Has id: %s", self.user.id) self.files = self.changes.get_files() self.files_to_remove = [] distribution = self.changes['Distribution'].lower() allowed_distributions = ('oldstable', 'stable', 'unstable', 'experimental', 'stable-backports', 'oldstable-backports', 'oldstable-backports-sloppy', 'oldstable-security', 'stable-security', 'testing-security', 'stable-proposed-updates', 'testing-proposed-updates', 'sid', 'wheezy', 'squeeze', 'lenny', 'squeeze-backports', 'lenny-backports', 'lenny-security', 'lenny-backports-sloppy', 'lenny-volatile', 'squeeze-security', 'squeeze-updates', 'wheezy-security', 'unreleased') if distribution not in allowed_distributions: self._reject("You are not uploading to one of those Debian distributions: %s" % (reduce(lambda x,xs: x + " " + xs, allowed_distributions))) # Look whether the orig tarball is present, and if not, try and get it from # the repository. (orig, orig_file_found) = filecheck.find_orig_tarball(self.changes) if orig_file_found != constants.ORIG_TARBALL_LOCATION_LOCAL: log.debug("Upload does not contain orig.tar.gz - trying to find it elsewhere") if orig and orig_file_found == constants.ORIG_TARBALL_LOCATION_REPOSITORY: filename = os.path.join(pylons.config['debexpo.repository'], self.changes.get_pool_path(), orig) if os.path.isfile(filename): log.debug("Found tar.gz in repository as %s" % (filename)) shutil.copy(filename, pylons.config['debexpo.upload.incoming']) # We need the orig.tar.gz for the import run, plugins need to extract the source package # also Lintian needs it. However the orig.tar.gz is in the repository already, so we can # remove it later self.files_to_remove.append(orig) destdir = pylons.config['debexpo.repository'] # Check whether the files are already present log.debug("Checking whether files are already in the repository") toinstall = [] pool_dir = os.path.join(destdir, self.changes.get_pool_path()) log.debug("Pool directory: %s", pool_dir) for file in self.files: if os.path.isfile(file) and os.path.isfile(os.path.join(pool_dir, file)): log.warning('%s is being installed even though it already exists' % file) toinstall.append(file) elif os.path.isfile(file): log.debug('File %s is safe to install' % os.path.join(pool_dir, file)) toinstall.append(file) # skip another corner case, where the dsc contains a orig.tar.gz but wasn't uploaded # by doing nothing here for that case # Run post-upload plugins. post_upload = Plugins('post-upload', self.changes, self.changes_file, user_id=self.user_id) if post_upload.stop(): log.critical('post-upload plugins failed') self._remove_changes() sys.exit(1) # Check whether a post-upload plugin has got the orig tarball from somewhere. if not orig_file_found and not filecheck.is_native_package(self.changes): (orig, orig_file_found) = filecheck.find_orig_tarball(self.changes) if orig_file_found == constants.ORIG_TARBALL_LOCATION_NOT_FOUND: # When coming here it means: # a) The uploader did not include a orig.tar.gz in his upload # b) We couldn't find a orig.tar.gz in our repository # c) No plugin could get the orig.tar.gz # ... time to give up if orig == None: orig = "any original tarball (orig.tar.gz)" self._reject("Rejecting incomplete upload. " "You did not upload %s and we didn't find it on any of our alternative resources.\n" \ "If you tried to upload a package which only increased the Debian revision part, make sure you include the full source (pass -sa to dpkg-buildpackage)" % ( orig )) else: toinstall.append(orig) # Check whether the debexpo.repository variable is set if 'debexpo.repository' not in pylons.config: self._fail('debexpo.repository not set') # Check whether debexpo.repository is a directory if not os.path.isdir(pylons.config['debexpo.repository']): self._fail('debexpo.repository is not a directory') # Check whether debexpo.repository is writeable if not os.access(pylons.config['debexpo.repository'], os.W_OK): self._fail('debexpo.repository is not writeable') qa = Plugins('qa', self.changes, self.changes_file, user_id=self.user_id) if qa.stop(): self._reject('QA plugins failed the package') # Loop through parent directories in the target installation directory to make sure they # all exist. If not, create them. for dir in self.changes.get_pool_path().split('/'): destdir = os.path.join(destdir, dir) if not os.path.isdir(destdir): log.debug('Creating directory: %s' % destdir) os.mkdir(destdir) # Install files in repository for file in toinstall: log.debug("Installing new file %s" % (file)) shutil.move(file, os.path.join(destdir, file)) self._remove_temporary_files() # Create the database rows self._create_db_entries(qa) # Execute post-successful-upload plugins f = open(self.changes_file) changes_contents = f.read() f.close() Plugins('post-successful-upload', self.changes, self.changes_file, changes_contents=changes_contents) # Remove the changes file self._remove_changes() # Refresh the Sources/Packages files. log.debug('Updating Sources and Packages files') r = Repository(pylons.config['debexpo.repository']) r.update() log.debug('Done')
def _get_gnupg(self, gpg_path='/usr/bin/gpg'): keyring_path = self._get_data_file('pubring_with_355304E4.gpg') gnupg = GnuPG(gpg_path, keyring_path) return gnupg
def __init__(self): self.gpg_id = None self.gnupg = GnuPG()