Script for signing existing .narinfo files in a binary cache
This commit is contained in:
parent
d84441483e
commit
c76fc42d03
101
sign-binary-cache.pl
Executable file
101
sign-binary-cache.pl
Executable file
|
@ -0,0 +1,101 @@
|
||||||
|
#! /usr/bin/env nix-shell
|
||||||
|
#! nix-shell -i perl -p perl perlPackages.NetAmazonS3 perlPackages.ForksSuper perlPackages.DBDSQLite
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Forks::Super 'bg_eval';
|
||||||
|
use List::MoreUtils qw(part);
|
||||||
|
use MIME::Base64;
|
||||||
|
use Net::Amazon::S3;
|
||||||
|
use Nix::Manifest;
|
||||||
|
use Nix::Store;
|
||||||
|
use Nix::Utils;
|
||||||
|
|
||||||
|
my $bucketName = "nix-cache";
|
||||||
|
my $nrProcesses = 16;
|
||||||
|
my $secretKeyFile = "/home/eelco/Misc/Keys/cache.nixos.org-1/secret";
|
||||||
|
|
||||||
|
my $s = readFile $secretKeyFile;
|
||||||
|
chomp $s;
|
||||||
|
my ($keyName, $secretKey) = split ":", $s;
|
||||||
|
die "invalid secret key file ‘$secretKeyFile’\n" unless defined $keyName && defined $secretKey;
|
||||||
|
|
||||||
|
my @files;
|
||||||
|
while (<>) {
|
||||||
|
chomp;
|
||||||
|
push @files, $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
# S3 setup.
|
||||||
|
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die;
|
||||||
|
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die;
|
||||||
|
|
||||||
|
my $s3 = Net::Amazon::S3->new(
|
||||||
|
{ aws_access_key_id => $aws_access_key_id,
|
||||||
|
aws_secret_access_key => $aws_secret_access_key,
|
||||||
|
retry => 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
my $bucket = $s3->bucket($bucketName) or die;
|
||||||
|
|
||||||
|
# Process .narinfos.
|
||||||
|
sub signNarInfo {
|
||||||
|
my ($fn) = @_;
|
||||||
|
|
||||||
|
die unless $fn =~ /\.narinfo$/;
|
||||||
|
|
||||||
|
my $get = $bucket->get_key($fn, "GET");
|
||||||
|
die "failed to get $fn\n" unless defined $get;
|
||||||
|
|
||||||
|
my $contents = $get->{value};
|
||||||
|
|
||||||
|
$contents =~ /^StorePath: (\S+)$/m;
|
||||||
|
die "corrupt NAR info $fn" unless defined $1;
|
||||||
|
my $storePath = $1;
|
||||||
|
|
||||||
|
if ($contents =~ /^Sig:/m) {
|
||||||
|
print STDERR "skipping already signed $fn\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print STDERR "signing $fn...\n";
|
||||||
|
|
||||||
|
my $narInfo = parseNARInfo($storePath, $contents);
|
||||||
|
die "failed to parse NAR info of $fn\n" unless $narInfo;
|
||||||
|
|
||||||
|
# Legacy: convert base16 to base32.
|
||||||
|
my $narHash = $narInfo->{narHash};
|
||||||
|
if (length $narHash != 59) {
|
||||||
|
$narHash = `nix-hash --type sha256 --to-base32 ${\(substr($narHash, 7))}`;
|
||||||
|
chomp $narHash;
|
||||||
|
$narHash = "sha256:$narHash";
|
||||||
|
}
|
||||||
|
|
||||||
|
#print STDERR "$storePath -> $narInfo->{narHash} $narHash $narInfo->{narSize}\n";
|
||||||
|
|
||||||
|
my $refs = [ map { "$Nix::Config::storeDir/$_" } @{$narInfo->{refs}} ];
|
||||||
|
my $fingerprint = fingerprintPath($storePath, $narHash, $narInfo->{narSize}, $refs);
|
||||||
|
#print STDERR "FP = $fingerprint\n";
|
||||||
|
my $sig = encode_base64(signString(decode_base64($secretKey), $fingerprint), "");
|
||||||
|
$contents .= "Sig: $keyName:$sig\n";
|
||||||
|
|
||||||
|
$bucket->add_key($fn, $contents) or die "failed to upload $fn\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fork processes to sign files in parallel.
|
||||||
|
my $i = 0;
|
||||||
|
my @filesPerProcess = part { $i++ % $nrProcesses } @files;
|
||||||
|
my @res;
|
||||||
|
for (my $n = 0; $n < $nrProcesses; $n++) {
|
||||||
|
push @res, bg_eval {
|
||||||
|
foreach my $fn (@{$filesPerProcess[$n]}) {
|
||||||
|
eval {
|
||||||
|
signNarInfo($fn);
|
||||||
|
};
|
||||||
|
warn "$@" if $@;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $res (@res) { if ($res) { } }
|
||||||
|
print STDERR "DONE\n";
|
Loading…
Reference in a new issue