Mini Shell

Direktori : /opt/maint/scops/
Upload File :
Current File : //opt/maint/scops/list-ips.pl

#!/usr/bin/perl
# encoding: utf-8
#
# author: Kyle Yetter
#

# to skip certificate verification
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
our $VERSION = 1.0;

use strict;
use LWP::UserAgent;
use URI;
use File::Basename;
use LWP::Protocol::https;
use JSON::Syck;
use YAML::Any;

our $HOSTNAME = `hostname`;
chomp $HOSTNAME;

our $DOMAINIPS_FILE       = "/etc/domainips";
our $TRUEUSERDOMAINS_FILE = "/etc/trueuserdomains";
our $RESERVED_IPS_FILE    = "/etc/reservedipreasons";

our $IP_ASSIGNMENT_DETAILS = {};
our $DOMAINS_TO_USERS      = {};
our $RESERVED_IPS          = {};

if ( -f $RESERVED_IPS_FILE ) {
  open( my $in, "< $RESERVED_IPS_FILE" ) or die "Failed to open $RESERVED_IPS_FILE - $!";

  foreach ( <$in> ) {
    chomp;
    s(^\s+|\s+$)()g;           # strip the line
    next if /^\s*(?:#.*)?$/;   # skip over blank and comment lines
    my ( $ip, $comment ) = split( /\s*=\s*/, $_, 2 );
    $RESERVED_IPS->{ $ip } = $comment;
  }

  close( $in );
}

#
# Harvest the user <=> primary domain relationships on the server, as maintained
# within /etc/trueuserdomains. Point the domain to the username in the $DOMAINS_TO_USERS
# hash.
#
if ( -f $TRUEUSERDOMAINS_FILE ) {
  open( my $in, "< $TRUEUSERDOMAINS_FILE" ) or die "Failed to open $TRUEUSERDOMAINS_FILE - $!";

  foreach ( <$in> ) {
    chomp;
    s(^\s+|\s+$)()g;           # strip the line
    next if /^\s*(?:#.*)?$/;   # skip over blank and comment lines
    my ( $domain, $user ) = split( /\s*:\s*/, $_, 2 );
    $DOMAINS_TO_USERS->{ $domain } = $user;
  }

  close( $in );
}

#
# Harvest the domain <=> dedicated IP relationships on the server, as maintained
# within /etc/domainips. Use the domain to get any available user information
# havested above. Create a record tying together the user, domain, and IP and
# push it onto a list associated with the IP address.
#
if ( -f $DOMAINIPS_FILE ) {
  open( my $in, "< $DOMAINIPS_FILE" ) or die "Failed to open $DOMAINIPS_FILE - $!";

  foreach ( <$in> ) {
    chomp;
    s(^\s+|\s+$)()g;           # strip the line
    next if /^\s*(?:#.*)?$/;   # skip over blank and comment lines
    my ( $ip, $domain ) = split( /\s*:\s*/, $_, 2 );
    if ( exists $DOMAINS_TO_USERS->{ $domain } ) {
      my $user = $DOMAINS_TO_USERS->{ $domain };
      #my $dig  = shell_join( "dig", "+short", $domain );
      #my @dig_results = `$dig`;
      #chomp for @dig_results;
      #my $dig_matches = grep { $_ eq $ip } @dig_results;
      my $reserved = 0;
      if ( exists $RESERVED_IPS->{ $ip } ) {
        $reserved = $RESERVED_IPS->{ $ip } || 1;
      }

      my $record = {
        ip          => $ip,
        user        => $user,
        domain      => $domain,
        reserved    => $reserved #,
        #dig_matches => $dig_matches
      };

      push @{ $IP_ASSIGNMENT_DETAILS->{ $ip } }, $record;
    }
  }

  close( $in );
}


# set to 1 if we had to generate an access key
our $created_access_hash = 0;

our $access_key;

END {
  #
  # If we had to create a temporary access hash to make this work,
  # make sure it gets trashed
  #
  if ( -f '/root/.accesshash' && $created_access_hash ) {
    unlink( '/root/.accesshash' ) or die( "failed to remove /root/.accesshash" );
  }

}

#
# If successful, the call will return a reference to an array of IP records on the server,
# where each record is a hash with a key named 'ip' to indicate the IP it represents.
#
our $ip_list = &api_call( "listips" );

#
# Iterate through each entry in the IP list, where each hash is assigned to Perl's
# special $_ variable in the loop below. If additional details are found in the
# $IP_ASSIGNMENT_DETAILS data map gathered above, merge that hash with the IP data
# returned by the API. Assigning to $_ changes the item in the array in-place.
#
for ( @$ip_list ) {
  my $address = $_->{ ip };
  if ( exists $IP_ASSIGNMENT_DETAILS->{ $address } ) {
    my $details = pop( @{ $IP_ASSIGNMENT_DETAILS->{ $address } } );
    my %merged  = ( %$_, %$details );
    $_ = \%merged;
  } elsif ( $_->{ mainaddr } or exists $RESERVED_IPS->{ $address } ) {
    $_->{ domain } = $HOSTNAME;
    $_->{ user }   = '';
  }
}

#
# Finally, rebuild the original API call hash { result => [ ip info... ] } and
# dump it as JSON to be used by System Center.
#
open( OUT, "> /opt/scops/out/ips" ) or die $!;
print OUT JSON::Syck::Dump({ result => $ip_list });
close( OUT ) or die $!;

###############################################################################
############################### Helper Functions ##############################
###############################################################################


sub access_key {
  if ( $access_key ) { return $access_key; }

  unless ( -f '/root/.accesshash' ) {
    $ENV{ REMOTE_USER } = 'root';
    `/usr/local/cpanel/bin/mkaccesshash`;
    delete $ENV{ REMOTE_USER };
    $created_access_hash = 1;
  }

  if ( -f '/root/.accesshash' ) {
    open( my $f, "< /root/.accesshash" ) or die "could not read /root/.accesshash: $!";
    my @lines = <$f>;
    close( $f );
    $access_key = join( '', @lines );
    $access_key =~ s/\n//g;
  } else {
    die "could not read /root/.accesshash: $!";
  }

  return $access_key;
}

sub load_json($) {
  my ( $source ) = @_;
  my $data;
  eval { $data = JSON::Syck::Load( $source ); };
  if ( $@ ) {
    die( $@ . "\nJSON SOURCE:\n" . $source );
  }
  return $data;
}

sub api_call($%) {
  my $function = shift;
  my %params = @_;

  my $uri = URI->new( "https://127.0.0.1:2087/json-api/$function" );
  $uri->query_form( %params );

  my $auth     = "WHM root:" . access_key();
  my $ua       = LWP::UserAgent->new;
  my $request  = HTTP::Request->new( GET => "$uri" );
  $request->header( Authorization => $auth );
  my $response = $ua->request( $request );

  return &load_json( $response->content )->{ result };
}


#
# shell_escape
#
# Given a string argument, escape shell-unsafe characters to ensure the string
# represents a single token in a command line
#
sub shell_escape {
  my $token = @_ ? shift : $_;

  if ( length( $token ) == 0 ) { return "''"; }
  $token =~ s/([^A-Za-z0-9_\-\.,:\/@\n])/\\$1/g;
  $token =~ s/\n/'\n'/g;
  return $token;
}

sub shell_join {
  return join( ' ', map { shell_escape } @_ );
}

Zerion Mini Shell 1.0