Project4/BIRNPortalIssues/generate-grid-mapfile.prl

From CVRG Wiki

Jump to: navigation, search

Image:CVRG_wiki-90x48px.gif Project 4 - BIRNPortalIssues


#!/usr/bin/perl
#
# See perldoc at __END__ for info.
#
# This needs to run periodically (say, once a day) on the GAMA machine.
# The output should be sent to a URL on the gama machine.
# This presumes that a web server is running on the gama machine.  Which there is
# under rocks.
#--------------------------------------------------------------------------------

sub usage { exec "perldoc $0" }

use strict;
use vars qw(
        $opt_cert_dir
        $opt_help
        $opt_out
);
use Getopt::Long;
use Fcntl qw(:flock);

GetOptions(
        'cert-dir=s' => \$opt_cert_dir,
        'out=s' => \$opt_out,
        'h' => \$opt_help,
) || usage();


my $map_file = [];
opendir(D, "$opt_cert_dir") or die("$0: could not open cert dir: $!\n");
foreach my $cert (map { "$opt_cert_dir/$_/usercert.pem" } grep { /.@./ } readdir(D)) {
        my $subject = (`cat $cert | openssl x509 -subject | perl -pe's/.* //'`)[0];
        chomp $subject;
        my ($user) = ($subject =~ m{CN=(.*?)/});

        unless($user) {
                warn("No valid username in subject ($subject).\n");
                next;
        }

        push @$map_file, [ $subject, "bt.$user" ];
}

# Use advisory locking here, rather than the standard lock-file approach, which
# hangs frequently if there are minor permissioning problems.
local *OUT = \*STDOUT;
if( $opt_out ) {
        open(OUT, ">$opt_out")
          or die("$0: could not open $opt_out for writing: $!\n");
}
if( flock( OUT, LOCK_EX | LOCK_NB ) ) {
        print OUT "# This is the BIRN grid mapfile\n";
        print OUT "# This file was generated on @{[scalar localtime(time)]}\n";
        print OUT "#--------------------------------------------------------------------------------\n";
        foreach (@$map_file) {
                print OUT "\"$_->[0]\"\t$_->[1]\n";
        }
        print OUT "# End of file\n";
        close(OUT);
        flock(OUT, LOCK_UN | LOCK_NB );
}
else {
        print STDERR "Unable to obtain output file lock\n";
}

__END__

=head1  NAME

generate-grid-mapfile.prl

=head1  SYNOPSIS

Generates a grid mapfile.  See below for info on the grid mapfile.

=head1  DESCRIPTION

Users in a grid aren't "real".  They're fake.  They get certificates, which are signed
by some trusted authority.  In our case, that's the root Certificate Authority.  The
problem is that these certificates need to somehow map to fakey users on real computers
at some point, and that's what a grid mapfile does.  It's normally stored in /etc/grid-security/grid-mapfile
and is a hashmap of "SUBJECT" to "local user", where SUBJECT is the X.509 Distinguished
Name as described in some officious sounding standard.

So, we's gots this CA thing that creates certificates, and we's gots these computers
that need this mapping.  This program generates that mapping.  Of course, it assumes
that we know all the remote machine's usernames, but in the case of BIRN that's not
too hard---just prepand "bt." in front of it.

=head2  OPTIONS

=item  --out=<string> [OPT]

Name of grid mapfile output.  If not specified, goes to stdout.

=item  --cert-dir=<string> [REQ]

The directory that holds the NAREGI CA certs.  This is currently specific to
NAREGI, in the sense that it assumes the user's email address is a directory in the
cert-dir directory, and that within the email-named directory is a usercert.pem file
which can then be processed by the openssl command line utility.  In other words,
it iterates through all <cert-dir>/<email-like-address>/usercert.pem files to get
the appropriate information.

=head2  AUTHOR

Neil Jones

=head2  BUGS

None identified yet.

=cut

Personal tools
Project Infrastructures