Add support for generating a keyring

This commit is contained in:
Laurent Bachelier 2012-01-29 15:56:16 +01:00
commit dd60e65174
4 changed files with 283 additions and 1 deletions

193
modules/.keys/laurentb.asc Normal file
View file

@ -0,0 +1,193 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.17 (GNU/Linux)
mQGiBEoO39oRBADQ6wZsdkNbrw8HuJj4s8ORsZHffxOnuHx+r4FupyJex1XBLONC
i/egP22hkuNL62W0kC9nNkNWHZQN9aB37Gd8XHDjJJhVgwtBmvNoiSKnaGiY+txP
1BT8zj0lukMt0+R74qWLWsnIBcS/jea8179Fag4qnrz1C6fdc3/991BKFwCgtYL0
QUfalTwm+Whh8HHSvfk6QzkD/3dO5p3kCyJw7jsX0feX7tyks2IRofq0zUZgc3Oz
ROX+pRowFC+FH0AUoi7RnKWOFtBS008gPuVEfNI/tA36h8b/ZHhyoxn9C6aBG/TX
rn1zVnz1kGlghn09IgbneBfxV8iNTqHu2NDY7/5YodNBk7MSVe2TWwiCEpQAKAiW
A5f2A/9o7nRYQyxAWp/OYkNYbXHHUkqeywfF3BrA36WAj6c2dAU0dJzm30A0DmEW
GMJbO4ywO6QvPONPrawKXHkL8+Br+UjSzriMZnoTilAF9Y7vhNpwuz5WGyGPe1Nf
xOI0Vh6LMD/r1CmqfHG077EAeoBEH1K2DrWnFfWiu6JeQ5XRl7QqTGF1cmVudCBC
YWNoZWxpZXIgPGxhdXJlbnRAYmFjaGVsaWVyLm5hbWU+iGYEExECACYCGyMGCwkI
BwMCBBUCCAMEFgIDAQIeAQIXgAUCTA/6ugUJCLRKYAAKCRDgcwXjnMREXtkLAJ9c
Dn4G9EvobPUl2KgOgpfLN3VOagCgjkhDvtqI01I6tVFZE4bL5+VNfObR3nveeQEQ
AAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUE
BAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExci
JCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4e
Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCACqAJYDASIAAhEBAxEB
/8QAHQAAAQQDAQEAAAAAAAAAAAAABgQFBwgAAgMBCf/EAD0QAAIBAgQEBAUDAgQE
BwAAAAECAwQRAAUSIQYTMUEHIlFhCBQycYEjkaEVQlKxwdEYJDPhJSZigqLw8f/E
ABkBAAMBAQEAAAAAAAAAAAAAAAACAwEEBf/EACQRAAICAgIBBQADAAAAAAAAAAAB
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
=8yy4
-----END PGP PUBLIC KEY BLOCK-----

33
modules/.keys/romain.asc Normal file
View file

@ -0,0 +1,33 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.17 (GNU/Linux)
mQENBEoOr78BCADAsCwWXDvedstjc9L3YSlXJ6KDd12WVD+iEiVGUqToJkWwp05k
uVvvibhNxjDJzZqfWxBvfhFXkf/APF8PoTvkA4l51WOfPGSZejiKMcenij+3HjKa
GCPjLlY9rlTUjA5Alw533WP4Wja0EILXy0xjS9eXN2/Vbtrh7sbwU3cs9KOgDjEH
dcR/ZgRGrqiLuVd83L2rlyoWZ5KM2KCkMjtpPBFUXOf5pyCV683wd+grdsHzL8Lm
MAyVPPCmwrCKdkrG4/xjlBo0Ghjwq4gH6ShclcdJlwjfBY/CLtv5voM+TxKZ2wg0
6FIwyZdh0F8G4c5PhiL+TXKrAV76WNwgwE1VABEBAAG0I1JvbWFpbiBCaWdub24g
PHJvbWFpbkBwZWVyZnVzZS5vcmc+iQE2BBMBAgAgBQJKDq+/AhsvBgsJCAcDAgQV
AggDBBYCAwECHgECF4AACgkQ8a5sCGs03G3Djwf7B8CKV9ZOvarZlQsaqzzA5AVM
/jB+oi86tjCDvTB4pgdbVUcni4MxWzTCU5OUXPbjzaFr+liB8tsGbSSFCJxMSdMu
DMhCcjU48XB3aSTXfvrKRqf/7kBdIqRqNB4KvmXGQI6NQl68O/BNQ8zX++M39GXR
tCzKS9VcWOdra8KN45ADVjVx3v8MCBguc9GTXM5EXxdoIUjU9ClWAklfWWJZBHGB
9NnPITfup28rjxXoITgXjF5Irk3uOEyleQ3fDM1uzLw5u/EHNh+uQJgV5Y5YHY9g
b9VT97iIfimw4vJ5stCKCwf7wz9VbGdBpNRMNepGV+/wVOg37nl2nFLZV9pCtLQg
Um9tYWluIEJpZ25vbiA8cm9tYWluQGJpZ25vbi5tZT6JATgEEwECACIFAk1ytV4C
Gy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPGubAhrNNxtHVwH+wTw7zcC
Xx+pQPR+s4gbtKwb0L95psuN5fUl2f9jEnAWwOSvkYoBmbA0+dYCtokFGIbFNmzU
ajBXwFkVEdphyVYxH4DnIwmwmafMA/QjYiQB91zRPpZQKCG1ioKlM/He9wJsrskl
zaqUEs3BuAx4n45vsiuERjJFwejbfqlI3PYSnS1/ncVpvn1pREn3a+QJ2hDMx2Ns
Znh0HkhJ6LLB8F2Z5bFSDcpTAiNgECRc3eleiTQT+89RrbvpPUi8iIFUcWmGxYBU
Atk6miGgjKpy98Ezc1LWfPOSaZjNBxhvtlicx+bDqkcMYPakZ1gLNWWyW2iNljDF
KiLhXstA/eNC3qC0IVJvbWFpbiBCaWdub24gPHJvbWFpbkBzeW1saW5rLm1lPokB
OAQTAQIAIgUCTXK1SgIbLwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ8a5s
CGs03G2b6Qf/VjmEs0pBdpg/Ewj7HmikxIQ7lvX5um1YHjLyLNdp6W6wylmzh3u5
dsaajEWmPbUhaDre7gTtxPNJFs6FXksfquUiZySXA45R+XH8Qh/TWJAY8FjdaZwB
tgOn4rka+n0rQeG1fklHw4Z3AREm/GmfeA63nkmS5SvdXskAz1iXB20Hyb6bGy5b
Y7ZJNhJ8Ocz2THizc2od3Bx8Pzw3DHs+NaW5sK/NJJN9QgpdLA4lo0KeidCALEXF
CReDEaT4Cs/Ds3u8QkuR+s+8qN5BOYcIWz79T/hLFw46SezEz9gjJ+NR1nIMd2um
bwnyciYEGVOfG4DsU/IRwnbk+HWcLNTFnw==
=mTlW
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -25,6 +25,7 @@ import tarfile
import os import os
import shutil import shutil
import sys import sys
import subprocess
from copy import copy from copy import copy
from contextlib import closing from contextlib import closing
@ -100,6 +101,36 @@ class WeboobRepos(ReplApplication):
r.build_index(source_path, index_file) r.build_index(source_path, index_file)
if r.signed:
gpg = self._find_gpg()
if not gpg:
raise Exception('Unable to find the gpg executable.')
krname = os.path.join(repo_path, r.KEYRING)
if os.path.exists(krname):
kr_mtime = int(datetime.fromtimestamp(os.path.getmtime(krname)).strftime('%Y%m%d%H%M'))
if not os.path.exists(krname) or kr_mtime < r.key_update:
print 'Generate keyring'
# Remove all existing keys
if os.path.exists(krname):
os.remove(krname)
# Add all valid keys
for keyfile in os.listdir(os.path.join(source_path, r.KEYDIR)):
keypath = os.path.join(source_path, r.KEYDIR, keyfile)
subprocess.check_call([gpg,
'--no-default-keyring',
'--keyring', krname,
'--import', keypath])
# Does not make much sense in our case
if os.path.exists(krname+'~'):
os.remove(krname+'~')
if not os.path.exists(krname):
raise Exception('No valid key file found.')
kr_mtime = mktime(strptime(str(r.key_update), '%Y%m%d%H%M'))
os.utime(krname, (kr_mtime, kr_mtime))
else:
print 'Keyring is up to date'
for name, module in r.modules.iteritems(): for name, module in r.modules.iteritems():
tarname = os.path.join(repo_path, '%s.tar.gz' % name) tarname = os.path.join(repo_path, '%s.tar.gz' % name)
module_path = os.path.join(source_path, name) module_path = os.path.join(source_path, name)
@ -119,6 +150,16 @@ class WeboobRepos(ReplApplication):
if os.path.exists(icon_path): if os.path.exists(icon_path):
shutil.copy(icon_path, os.path.join(repo_path, '%s.png' % name)) shutil.copy(icon_path, os.path.join(repo_path, '%s.png' % name))
@staticmethod
def _find_gpg():
if os.getenv('GPG_EXECUTABLE'):
return os.getenv('GPG_EXECUTABLE')
paths = os.getenv('PATH', os.defpath).split(os.pathsep)
for path in paths:
fpath = os.path.join(path, 'gpg')
if os.path.exists(fpath) and os.access(fpath, os.X_OK):
return fpath
def _archive_excludes(self, filename): def _archive_excludes(self, filename):
# Skip *.pyc files in tarballs. # Skip *.pyc files in tarballs.
if filename.endswith('.pyc'): if filename.endswith('.pyc'):

View file

@ -91,6 +91,8 @@ class RepositoryUnavailable(Exception):
class Repository(object): class Repository(object):
INDEX = 'modules.list' INDEX = 'modules.list'
KEYDIR = '.keys'
KEYRING = 'trusted.gpg'
def __init__(self, url): def __init__(self, url):
self.url = url self.url = url
@ -98,6 +100,8 @@ class Repository(object):
self.update = 0 self.update = 0
self.maintainer = u'' self.maintainer = u''
self.local = None self.local = None
self.signed = False
self.key_update = 0
self.modules = {} self.modules = {}
@ -170,6 +174,8 @@ class Repository(object):
self.name = items['name'] self.name = items['name']
self.update = int(items['update']) self.update = int(items['update'])
self.maintainer = items['maintainer'] self.maintainer = items['maintainer']
self.signed = bool(int(items.get('signed', '0')))
self.key_update = int(items.get('key_update', '0'))
except KeyError, e: except KeyError, e:
raise RepositoryUnavailable('Missing global parameters in repository: %s' % e) raise RepositoryUnavailable('Missing global parameters in repository: %s' % e)
except ValueError, e: except ValueError, e:
@ -203,10 +209,17 @@ class Repository(object):
print 'Rebuild index' print 'Rebuild index'
self.modules.clear() self.modules.clear()
if os.path.isdir(os.path.join(path, self.KEYDIR)):
self.signed = True
self.key_update = self.get_tree_mtime(os.path.join(path, self.KEYDIR), True)
else:
self.signed = False
self.key_update = 0
sys.path.append(path) sys.path.append(path)
for name in sorted(os.listdir(path)): for name in sorted(os.listdir(path)):
module_path = os.path.join(path, name) module_path = os.path.join(path, name)
if not os.path.isdir(module_path) or '.' in name: if not os.path.isdir(module_path) or '.' in name or name == self.KEYDIR:
continue continue
try: try:
@ -252,6 +265,8 @@ class Repository(object):
config.set(DEFAULTSECT, 'name', self.name) config.set(DEFAULTSECT, 'name', self.name)
config.set(DEFAULTSECT, 'update', self.update) config.set(DEFAULTSECT, 'update', self.update)
config.set(DEFAULTSECT, 'maintainer', self.maintainer) config.set(DEFAULTSECT, 'maintainer', self.maintainer)
config.set(DEFAULTSECT, 'signed', int(self.signed))
config.set(DEFAULTSECT, 'key_update', self.key_update)
if private: if private:
config.set(DEFAULTSECT, 'url', self.url) config.set(DEFAULTSECT, 'url', self.url)