#! /home/conda/feedstock_root/build_artifacts/gct_1705239453311/_build_env/bin/perl # # Copyright 1999-2006 University of Chicago # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # grid-mapfile-check-consistency use strict; use warnings; use English; use FileHandle; use File::Spec; use Getopt::Long; # Prototypes sub main ( @ ); sub check_gridmap_location (); sub parse_options (); sub display_help (); sub display_version (); sub verify_mapfile_existence (); sub load_gridmap_file ( $ ); sub check_valid_login_names ( $ ); # Gridmap file name, handle, and hash my $GRID_MAP_FILE = ""; my $gridmap_handle; my %LINES; # Gridmap file check status codes my $existence_check = 0; my $load_check = 0; my $valid_login_names_check = 0; # DiRT support # DIRT_TIMESTAMP="1629915172" # DIRT_BRANCH_ID="0" # Invoke "main" main ( @ARGV ); ####################################################################### # Function: main # Description: # Main function of the program # Parameters: # command line options # Returns: # 0 if checks passed # 1 if gridmap file is not readable # 2 if gridmap file is empty # 3 if loading gridmap file failed (e.g. hardware errors) # 4 if there are invalid login names in gridmap file ####################################################################### sub main ( @ ) { check_gridmap_location(); parse_options(); print "Checking " . $GRID_MAP_FILE . " grid mapfile\n"; print "Verifying grid mapfile existence..."; $existence_check = verify_mapfile_existence(); if ($existence_check == 1) { print "ERROR: " . $GRID_MAP_FILE . " file is not readable\n"; exit 1; } elsif ($existence_check == 2) { print "\nGrid mapfile " . $GRID_MAP_FILE . " is empty\n"; exit 2; } print "OK\n"; print "Checking for duplicate entries..."; $load_check = load_gridmap_file(\%LINES); if ($load_check == 1) { print "ERROR: Cannot load " . $GRID_MAP_FILE . "\n"; exit 3; } elsif ($load_check == 0) { print "OK\n"; } print "Checking for valid user names..."; $valid_login_names_check = check_valid_login_names(\%LINES); if ($valid_login_names_check == 0) { print "OK\n"; } elsif ($valid_login_names_check == 1) { exit 4; } exit 0; } ####################################################################### # Helper functions ####################################################################### # Function: check_gridmap_location # Description: # Checks location of gridmap file conforming to rules # defined by GSI # Parameters: # None # Returns: # None ####################################################################### sub check_gridmap_location () { if (defined $ENV{"GRIDMAP"}) { $GRID_MAP_FILE = $ENV{"GRIDMAP"}; } else { if ($REAL_USER_ID == 0) { $GRID_MAP_FILE = "/etc/grid-security/grid-mapfile"; } else { my $local_gridmap_file = $ENV{"HOME"} . "/.gridmap"; if (-e $local_gridmap_file && -r $local_gridmap_file) { $GRID_MAP_FILE = $local_gridmap_file; } else { $GRID_MAP_FILE = "/etc/grid-security/grid-mapfile"; } } } } ####################################################################### # Function: parse_options # Description: # Parses script options. If gridmap file was specified, # new value overrides previous one. # Parameters: # None # Returns: # 0 help of version options selected ####################################################################### sub parse_options () { my $parser; my $help = 0; my $version = 0; my $mapfile = ""; $parser = new Getopt::Long::Parser; $parser->getoptions("usage|help|h" => \$help, "version|v" => \$version, "mapfile|file|f=s" => \$mapfile); if ($help == 1) { display_help(); exit 0; } elsif ($version == 1) { display_version(); exit 0; } elsif ($mapfile ne "") { $GRID_MAP_FILE = File::Spec->rel2abs($mapfile); } } ####################################################################### # Function: display_help # Description: # Displays help information # Parameters: # None # Returns: # None ####################################################################### sub display_help () { my ($volume, $directory, $file) = File::Spec->splitpath($0); print $file . " checks the consistency of the Grid mapfile\n"; print "Options:\n"; print "--help, -help, --usage, -usage, --h, -h Displays help\n"; print "--version, -version, --v, -v Displays version\n"; print "--mapfile FILE, -mapfile FILE, --file FILE, -file FILE, --f FILE, -f FILE Path of gridmap to be used\n"; } ####################################################################### # Function: display_version # Description: # Displays version information # Parameters: # None # Returns: # None ####################################################################### sub display_version () { my ($volume, $directory, $file) = File::Spec->splitpath($0); my $program_version = '$Revision$'; $program_version =~ /Revision: ([\d\.]+)/; print $file . ": " . $1 . "\n"; } ###################################################################### # Function: verify_mapfile_existence # Description: # If a gridmap file is a symlink, follows it. # Checks if the gridmap file is readable. # Checks if the gridmap file is writable. # Checks if the gridmap file is empty. # If the file is either non-writable or empty, # appropriate warning is printed. # Parameters: # None # Returns: # 0 gridmap file is readable, writable and non-empty # 1 gridmap file is non-readable (failed) # 2 gridmap file is non-writable ####################################################################### sub verify_mapfile_existence () { if (-l $GRID_MAP_FILE) { my $link = readlink($GRID_MAP_FILE); $GRID_MAP_FILE = $link; } if (! -r $GRID_MAP_FILE) { return 1; } if (! -w $GRID_MAP_FILE) { print "\nWARNING: Grid mapfile " . $GRID_MAP_FILE . " is not writable\n"; } if (-z $GRID_MAP_FILE) { return 2; } return 0; } ##################################################### # Function: load_gridmap_file # Description: # Loads entire gridmap into a single hash. # Single DN may be mapped to multiple users # therefore hash contains lists not scalars. # It speeds up later non-sequential access. # It detects some errors: # - missing double quotes # - missing usernames # - duplicate entries (logical names) # Parameters: # Hash which is to hold entire gridmap as lines # Returns: # 0 gridmap file loaded successfully # 1 gridmap file loading failed # 2 if there are duplicate entries ##################################################### sub load_gridmap_file ( $ ) { $gridmap_handle = new FileHandle ("< $GRID_MAP_FILE"); if (!defined ($gridmap_handle)) { return 1; } my ($key, $value); my $href = shift; my $duplicate_counter = 0; my $buffer; while (! $gridmap_handle->eof() ) { $buffer = $gridmap_handle->getline(); chomp ($buffer); if ($buffer !~ /^\s*$/ && $buffer !~ /^\s*\#/) { $buffer =~ s/^\s*//; $buffer =~ /^"(.*)"\s*(\S*)\s*$/; if (! defined ($1)) { print "\nERROR: Missing double quotes in the following entry: " . $buffer . "\n"; } elsif (! defined ($2)) { print "\nERROR: Missing user name(s) in the following entry: " . $buffer . "\n"; } else { ($key, $value) = ($1,$2); if (exists ($$href{$key}) ) { $duplicate_counter++; $$href{$key} .= ",$value"; print "\nERROR: Found duplicate entry: " . $buffer . "\n"; } else { $$href{$key} = $value; } } } } if ($duplicate_counter > 0) { print "ERROR: Found " . $duplicate_counter . " duplicate(s)\n"; return 2; } return 0; } ##################################################### # Function: check_valid_login_names # Description: # Checks all gridmap entries if user names are # valid login names. # If invalid user names are found, then each # invalid entry is printed. # Prints number of invalid entries if this # number is non-zero. # Parameters: # Reference to a hash holding gridmap entries # Returns: # 0 all entries are valid # 1 if there are invalid login names ##################################################### sub check_valid_login_names ( $ ) { my ($href, $entry, $user, $user_id); my @user_names; my %invalid_login_names = (); $href = shift; foreach $entry (values(%$href)) { if ($entry =~ /,/) { @user_names = split (/,/, $entry); } else { $user_names[0] = $entry; } foreach $user (@user_names) { $user_id = getpwnam("$user"); if (! defined ($user_id) || $user_id < 0) { print "\nERROR: " . $user . " is not a valid local username\n"; if (! exists ($invalid_login_names{"$user"}) ) { $invalid_login_names{"$user"} = 1; } } } } my $counter = keys (%invalid_login_names); if ($counter > 0) { print "ERROR: Found " . $counter . " invalid username(s)\n"; return 1; } else { return 0; } }