From ef88f3d5ef696b71a65a81f143b13ae27175a1c5 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 29 Mar 2012 11:37:07 -0500 Subject: Add developer status table to master keys page This shows the cross-product of each master key with each developer key so you can see who has been signed, where signatures are missing, etc. Signed-off-by: Dan McGee --- main/templatetags/pgp.py | 8 +++++++ public/views.py | 21 ++++++++++++++--- sitestatic/archweb.css | 8 +++++++ templates/public/keys.html | 56 ++++++++++++++++++++++++++++++++++++++-------- visualize/views.py | 2 +- 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/main/templatetags/pgp.py b/main/templatetags/pgp.py index 1ffc5241..50b1aa17 100644 --- a/main/templatetags/pgp.py +++ b/main/templatetags/pgp.py @@ -50,4 +50,12 @@ def pgp_fingerprint(key_id, autoescape=True): return mark_safe(format_key(esc(key_id))) pgp_fingerprint.needs_autoescape = True + +@register.assignment_tag +def signature_exists(signatures, signer, signee): + if not signer or not signee: + return False + lookup = (signer[-16:], signee[-16:]) + return lookup in signatures + # vim: set ts=4 sw=4 et: diff --git a/public/views.py b/public/views.py index 1e1ffc6c..a85d7389 100644 --- a/public/views.py +++ b/public/views.py @@ -1,6 +1,8 @@ +from datetime import datetime + from django.conf import settings from django.contrib.auth.models import User -from django.db.models import Count +from django.db.models import Count, Q from django.http import Http404 from django.views.decorators.cache import cache_control from django.views.generic import list_detail @@ -88,17 +90,30 @@ def feeds(request): @cache_control(max_age=300) def keys(request): + not_expired = Q(expires__gt=datetime.utcnow) | Q(expires__isnull=True) master_keys = MasterKey.objects.select_related('owner', 'revoker', 'owner__userprofile', 'revoker__userprofile').filter( revoked__isnull=True) - sig_counts = PGPSignature.objects.filter(valid=True, - expires__isnull=True).values_list('signer').annotate( + + sig_counts = PGPSignature.objects.filter( + not_expired, valid=True).values_list('signer').annotate( Count('signer')) sig_counts = dict((key_id[-16:], ct) for key_id, ct in sig_counts) + for key in master_keys: key.signature_count = sig_counts.get(key.pgp_key[-16:], 0) + + users = User.objects.filter(is_active=True).select_related( + 'userprofile__pgp_key').order_by('first_name', 'last_name') + + # frozenset because we are going to do lots of __contains__ lookups + signatures = frozenset(PGPSignature.objects.filter( + not_expired, valid=True).values_list('signer', 'signee')) + context = { 'keys': master_keys, + 'active_users': users, + 'signatures': signatures, } return direct_to_template(request, 'public/keys.html', context) diff --git a/sitestatic/archweb.css b/sitestatic/archweb.css index d2286329..ac0dff52 100644 --- a/sitestatic/archweb.css +++ b/sitestatic/archweb.css @@ -957,6 +957,14 @@ ul.signoff-list { color: red; } +#key-status .signed-yes { + color: green; +} + +#key-status .signed-no { + color: red; +} + /* highlight current website in the navbar */ #archnavbar.anb-home ul li#anb-home a, #archnavbar.anb-packages ul li#anb-packages a, diff --git a/templates/public/keys.html b/templates/public/keys.html index 6b06cc32..a7c91c43 100644 --- a/templates/public/keys.html +++ b/templates/public/keys.html @@ -15,15 +15,6 @@

The {{ keys|length }} key{{ keys|pluralize }} listed below should be regarded as the current set of master keys. They are available on public keyservers and should be signed by the owner of the key.

-

All official Arch Linux developers and trusted users should have their - key signed by at least three of these master keys. This is in accordance - with the PGP web of trust concept. If a user is willing to - marginally trust all of the master keys, three signatures from different - master keys will consider a given developer's key as valid. For more - information on trust, please consult the - GNU Privacy Handbook - and Using trust to - validate keys.

@@ -55,5 +46,52 @@ {% endfor %}
+ +

The following table shows all active developers and trusted users along + with the status of their personal signing key. A 'Yes' indicates that the + personal key of the developer is signed by the given master key. A 'No' + indicates it has not been signed; however, this does not necessarily mean + the key should not be trusted.

+

All official Arch Linux developers and trusted users should have their + key signed by at least three master keys if they are responsible for + packaging software in the repositories. This is in accordance with the PGP + web of trust concept. If a user is willing to marginally trust all + of the master keys, three signatures from different master keys will + consider a given developer's key as valid. For more information on trust, + please consult the + GNU Privacy Handbook + and Using trust to + validate keys.

+ + + + + + + {% for key in keys %} + + {% endfor %} + + + + + {% for key in keys %} + + {% endfor %} + + + + {% for user in active_users %} + + + + {% spaceless %}{% for key in keys %} + {% signature_exists signatures key.pgp_key user.userprofile.pgp_key as signed %} + + {% endfor %}{% endspaceless %} + + {% endfor %} + +
PGP Key{{ key.owner.get_full_name }}
{% pgp_key_link key.pgp_key %}
{{ user.get_full_name }}{% pgp_key_link user.userprofile.pgp_key %}{{ signed|yesno|capfirst }}
{% endblock %} diff --git a/visualize/views.py b/visualize/views.py index be6057b2..afc5429d 100644 --- a/visualize/views.py +++ b/visualize/views.py @@ -102,7 +102,7 @@ def pgp_keys(request): 'group': 'cacert', }) - not_expired = Q(expires__gt=datetime.now) | Q(expires__isnull=True) + not_expired = Q(expires__gt=datetime.utcnow) | Q(expires__isnull=True) signatures = PGPSignature.objects.filter(not_expired, valid=True) edge_list = [{ 'signee': sig.signee, 'signer': sig.signer } for sig in signatures] -- cgit v1.2.3-55-g3dc8