forked from the-distro/channel-scripts
102 lines
2.8 KiB
Perl
Executable file
102 lines
2.8 KiB
Perl
Executable file
#! /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";
|