-
-mkdir ($ENV{"TMPDIR"}."/mrcompute");
-if ($$Job{knobs} =~ /^GPG_KEYS=(.*)/m) {
- # set up a fresh gnupg directory just for this process
- # TODO: reap abandoned gnupg dirs
- system ("rm", "-rf", $ENV{"TMPDIR"}."/mrcompute/.gnupg/$$");
- mkdir ($ENV{"TMPDIR"}."/mrcompute");
- mkdir ($ENV{"TMPDIR"}."/mrcompute/.gnupg", 0700);
- mkdir ($ENV{"TMPDIR"}."/mrcompute/.gnupg/$$", 0700) || croak ("mkdir: $!");
-
- my $newhomedir = $ENV{"TMPDIR"}."/mrcompute/.gnupg/$$";
-
- open C, ">", $newhomedir."/gpg.conf";
- print C "always-trust\n";
- close C;
-
- # import secret keys referenced in job spec
- my $hashes = $1;
- $hashes =~ s/\'/\'\\\'\'/g;
- my $gpg_out = `whget '$hashes' - | gpg --homedir "$newhomedir" --import 2>&1`;
- my %encrypt_to;
- while ($gpg_out =~ /^gpg: key ([0-9A-F]{8}): /gm) {
- my $keynum = $1;
- while (`gpg --homedir "$newhomedir" --list-keys "$keynum"` =~ /^uid\s.*<(.+?)>/gm) {
- $encrypt_to{$1} = 1;
- }
- }
- if (!%encrypt_to) {
- croak ("GPG_KEYS provided but failed to import keys:\n$gpg_out");
- }
-
- if ($have_database) {
-
- # make sure the job request was signed by all of the secret keys
- # contained in GPG_KEYS (otherwise, any VM can just copy the
- # GPG_KEYS hash from an existing mr-job and submit new jobs that can
- # read private data)
-
- my %did_not_sign;
- my $seckeys = `gpg --homedir "$newhomedir" --list-secret-keys --with-fingerprint`;
- while ($seckeys =~ /Key fingerprint.*?([0-9A-F][0-9A-F ]+[0-9A-F])/mgi) {
- $did_not_sign{$1} = 1;
- }
- my $srfile = "$newhomedir/signedrequest";
- open SREQ, ">", $srfile;
- print SREQ $$Job{"signedrequest"};
- close SREQ;
- my $gpg_v = `gpg --homedir "$newhomedir" --verify --with-fingerprint "$srfile" 2>&1 && echo ok`;
- unlink $srfile;
- if ($gpg_v =~ /\nok\n$/s) {
- while ($gpg_v =~ /Good signature.*? key fingerprint: (\S[^\n]+\S)/sgi) {
- delete $did_not_sign{$1};
- }
- }
- if (%did_not_sign) {
- croak (join ("\n",
- "Some secret keys provided did not sign this job request:",
- keys %did_not_sign) . "\n");
- }
- }
-
- my $hostname = `hostname`;
- chomp ($hostname);
-
- # tell mrjobsteps the decrypted secret key(s) and all public key(s) they might need
- $ENV{"GPG_KEYS"} = `gpg --homedir "$newhomedir" --export-secret-keys --armor`;
- $ENV{"GPG_PUBLIC_KEYS"} = `gpg --export --armor | ENCRYPT_TO= whput -`;
-
- # import all secret keys from my real home dir
- `gpg --export-secret-keys | gpg --homedir "$newhomedir" --import 2>&1`;
-
- # use the new gnupg dir from now on
- $ENV{"GNUPGHOME"} = $newhomedir;
-
- # if I have a secret key for root@{host} or {user}@{host} or
- # {configured-controller-gpg-uid}, add that as a recipient too so
- # I'll be able to read frozentokeys etc. later
- my %allkeys;
- while (`gpg --list-secret-keys` =~ /^uid\s.*?<(.+?)>/gm) {
- $allkeys{$1} = 1;
- }
- my $encrypting_to_self = 0;
- my @try_these_uids = ("root\@".$hostname, $ENV{"USER"}."\@".$hostname);
- push @try_these_uids, ($whc->{config}->{controller_gpg_uid})
- if exists $whc->{config}->{controller_gpg_uid};
- foreach my $id (@try_these_uids) {
- if (exists $allkeys{$id}) {
- $encrypt_to{$id} = 1;
- $encrypting_to_self = 1;
- last;
- }
- }
-
- if (!$encrypting_to_self) {
- croak ("Failed to find a secret key for any of [@try_these_uids] -- giving up instead of writing meta/freeze data that I won't be able to read");
- }
-
- # tell the client library (and child procs and jobsteps) to encrypt using these keys
- $ENV{"ENCRYPT_TO"} = join (",", sort keys %encrypt_to);
- Log (undef, "encrypt_to ('".$ENV{"ENCRYPT_TO"}."')");
- $whc->set_config ("encrypt_to", $ENV{"ENCRYPT_TO"});
-}
-