channel-scripts/sign-binary-cache.pl

102 lines
2.8 KiB
Perl
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /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";