From owner-svn-doc-all@freebsd.org Wed Jul 4 17:32:47 2018 Return-Path: Delivered-To: svn-doc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 15D8210279FD; Wed, 4 Jul 2018 17:32:47 +0000 (UTC) (envelope-from matthew@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id BB53B89901; Wed, 4 Jul 2018 17:32:46 +0000 (UTC) (envelope-from matthew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 9C549651A; Wed, 4 Jul 2018 17:32:46 +0000 (UTC) (envelope-from matthew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w64HWkaO033949; Wed, 4 Jul 2018 17:32:46 GMT (envelope-from matthew@FreeBSD.org) Received: (from matthew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w64HWkiK033948; Wed, 4 Jul 2018 17:32:46 GMT (envelope-from matthew@FreeBSD.org) Message-Id: <201807041732.w64HWkiK033948@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: matthew set sender to matthew@FreeBSD.org using -f From: Matthew Seaman Date: Wed, 4 Jul 2018 17:32:46 +0000 (UTC) To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r51962 - head/share/pgpkeys X-SVN-Group: doc-head X-SVN-Commit-Author: matthew X-SVN-Commit-Paths: head/share/pgpkeys X-SVN-Commit-Revision: 51962 X-SVN-Commit-Repository: doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-doc-all@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: "SVN commit messages for the entire doc trees \(except for " user" , " projects" , and " translations" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Jul 2018 17:32:47 -0000 Author: matthew (ports committer) Date: Wed Jul 4 17:32:46 2018 New Revision: 51962 URL: https://svnweb.freebsd.org/changeset/doc/51962 Log: Add a perl script to report on PGP key validity for all current FreeBSD developers Approved by: allanjude Differential Revision: https://reviews.freebsd.org/D16096 Added: head/share/pgpkeys/pgpkeyreport (contents, props changed) Added: head/share/pgpkeys/pgpkeyreport ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/pgpkeys/pgpkeyreport Wed Jul 4 17:32:46 2018 (r51962) @@ -0,0 +1,196 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +# $FreeBSD$ +# +# Generate a report showing all of the active FreeBSD developers and +# all of the PGP keys registered, and whether those keys are still in +# date. + +use File::Temp qw{tempdir}; +use POSIX qw{strftime}; + +use constant { + SVNCOMMAND => '/usr/local/bin/svn', + SVNREPOURL => 'svn://svn.freebsd.org/', + REPOS => [qw{base ports doc}], + SVNCONF => 'svnadmin/conf', + PGPKEYPATH => 'head/share/pgpkeys', +}; + +$0 =~ s@.*/@@; + +sub svn_checkout($$$) +{ + my $repo = shift; + my $path = shift; + my $dest = shift; + my $output; + + open SVN, "-|", SVNCOMMAND . " co " . SVNREPOURL . "$repo/$path $dest" + or die "$0: can't checkout $repo/$path -- $!\n"; + while () { + $output .= $_; + } + close SVN; + + return; +} + +sub read_keys($) +{ + my $keyfile = shift; + my $pgp = []; + + open PGPKEY, "<$keyfile" + or die "$0: can't open $keyfile for reading -- $!"; + while () { + m@^pub\s+@ + && do { + my @fields = split /\s+/; + my $thiskey = {}; + + $thiskey->{keyid} = $fields[1]; + $thiskey->{created} = $fields[2]; + + # Remove the first three fields -- some times, that is all + # there are, and we don't want to read the creation date + # in place of the expiry date. + + splice @fields, 0, 3; + + if ( @fields && $fields[-1] =~ m/^([0-9-]{10})/ ) { + $thiskey->{expiry} = $1; + } else { + $thiskey->{expiry} = ''; + } + push @{$pgp}, $thiskey; + }; + } + close PGPKEY; + + return $pgp; +} + +sub scan_for_keys($$) +{ + my $developers = shift; + my $pgpkeydir = shift; + my $name; + + opendir( my $dh, $pgpkeydir ) + or die "$0: couldn't open directory $pgpkeydir -- $!\n"; + while ( my $f = readdir $dh ) { + next + unless $f =~ m/.key\Z/; + chomp $f; + ( $name = $f ) =~ s/.key//; + + $developers->{$name}->{keys} = read_keys("$pgpkeydir/$f"); + } + closedir $dh; + + return $developers; +} + +sub active_committers($$$) +{ + my $developers = shift; + my $repo = shift; + my $path = shift; + my $n; + my $r; + + $repo =~ m/^(.)/; + $r = $1; + + open ACCESS, "<$path" or die "$0: can't open access file for $repo -- $!\n"; + while ( my $name = ) { + next + if $name =~ m/^#/; + + ($n) = split( /\s+/, $name ); + chomp $n; + + $developers->{$n}->{$repo} = $r; + } + + return $developers; +} + +sub is_expired($) +{ + my $date = shift; + my $year; + my $month; + my $day; + my $unixtime; + my $expired; + + # Tri-state logic: we answer one of "yes", "no" or "dunno" + # + # Date is typically a string of form YYYY-MM-DD but we will accept + # any punctuation character as the field separator. + + ( $year, $month, $day ) = + ( $date =~ m/^(\d{4})[[:punct:]](\d{2})[[:punct:]](\d{2})/ ); + + return "unknown" + unless $year && $month && $day; + + $unixtime = strftime( "%s", 0, 0, 0, $day, $month - 1, $year - 1900 ); + + if ( $unixtime < $^T ) { + $expired = "expired"; + } else { + $expired = ""; + } + + return $expired; +} + +MAIN: +{ + my $workspace; + my $developers = {}; + + $workspace = tempdir( ".$0.XXXXXX", TMPDIR => 1, CLEANUP => 1 ) + or die "$0: can't create temporary directory -- $!\n"; + + svn_checkout( 'doc', PGPKEYPATH, "$workspace/pgpkeys" ); + + $developers = scan_for_keys( $developers, "$workspace/pgpkeys" ); + + for my $repo ( @{&REPOS} ) { + svn_checkout( $repo, SVNCONF, "$workspace/${repo}-conf" ); + + $developers = active_committers( $developers, $repo, + "$workspace/${repo}-conf/access" ); + } + + printf "#%18s %-5s %-26s %-10s %-10s %s\n", 'username', 'bits', 'keyid', + 'created', 'expired', 'state'; + + for my $d ( sort keys %{$developers} ) { + if ( !defined $developers->{$d}->{keys} ) { + printf "%19s %1s %1s %1s No PGP key\n", $d, + $developers->{$d}->{base} // '-', + $developers->{$d}->{ports} // '-', + $developers->{$d}->{doc} // '-'; + } + + for my $k ( @{ $developers->{$d}->{keys} } ) { + my $expired = is_expired( $k->{expiry} ); + + printf "%19s %1s %1s %1s %-26s %-10s %-10s %s\n", $d, + $developers->{$d}->{base} // '-', + $developers->{$d}->{ports} // '-', + $developers->{$d}->{doc} // '-', + $k->{keyid} // '', $k->{created} // '', + $k->{expiry} // '', $expired; + } + } + +}