Mini Shell
Direktori : /opt/sharedrads/ |
|
Current File : //opt/sharedrads/cpanel-api |
#!/usr/bin/perl
# encoding: utf-8
#
# author: Kyle Yetter
#
=begin
=head1 call-api
call-api - Change the basic configuration of a cPanel account.
=head1 SYNOPSIS
call-api [options] I<function> I<arg-name>=I<val> ...
call-api [options] -1 I<user> I<module> I<function> I<arg1> ... I<argN>
call-api [options] -2 I<user> I<module> I<function> I<arg-name>=I<val> ...
=head1 DESCRIPTION
Run a cPanel remote API call and dump the server response in a variety of formats
See the following documenation pages for the cPanel API to learn more about
API calls and the functions they provide.
http://docs.cpanel.net/twiki/bin/view/SoftwareDevelopmentKit/XmlApi
http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api1/WebHome
http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api2/WebHome
=head1 OPTIONS
=over 8
=item B<-1>, B<--modular-v1>
Specify the call as being a v1 module API function.
=item B<-2>, B<--module-v2>
Specify the call as being a v2 module API function.
=item B<-D>, B<--debug>
Print the WHM API URI sent to the server and dump the resulting data structure
=item B<-x>, B<--xml>
Run the call through cPanel's XML API and output the XML result
=item B<-j>, B<--json>
Run the call through cPanel's JSON API and output the raw JSON result
=item B<-y>, B<--yaml>
Run the call through cPanel's JSON API and dump the output data in YAML format
=item B<-b>, B<--bleach>, B<--no-color>
Do not use color escapes in the output
=item B<-h>, B<--help>
You know the drill
=item B<-v>, B<--version>
Ditto
=back
=cut
# to skip certificate verification
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
our $VERSION = 1.3;
use strict;
use LWP::UserAgent;
use URI;
use File::Basename;
use File::Slurp qw( slurp read_dir );
use Getopt::Long;
use JSON::Syck;
use Term::ANSIColor;
use Pod::Usage;
our $BASIC = 0;
our $MODULAR_V1 = 1;
our $MODULAR_V2 = 2;
our $API_TYPE = 'json';
our $FORMAT = 'yaml';
# display extra debugging info if true
our $DEBUG = 0;
# if true, don't colorize output with ANSI escape sequences
our $BLEACH = 0;
# specifies whether this is a basic or modular API call
our $CALL_MODE = $BASIC;
# 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" );
}
}
sub c($$) {
my ( $str, $style ) = @_;
$str = colored( $str, $style ) unless $BLEACH;
return $str;
}
sub d {
if ( $DEBUG ) {
my ( $fmt, @params ) = @_;
local $\ = "\n";
my $message = c( sprintf( $fmt, @params ), 'cyan' );
print STDERR "DEBUG: $message";
}
}
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' ) {
$ACCESS_KEY = slurp( "/root/.accesshash" ) or die "could not read /root/.accesshash: $!";
$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/$API_TYPE-api/$function" );
$uri->query_form( %params );
d "query URI: %s", $uri;
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 $response->content;
}
sub modular_api_v1($$$@) {
my $user = shift;
my $module = shift;
my $func = shift;
my @args = @_;
my %opts = (
"cpanel_${API_TYPE}api_user" => $user,
"cpanel_${API_TYPE}api_module" => $module,
"cpanel_${API_TYPE}api_func" => $func,
"cpanel_${API_TYPE}api_apiversion" => 1
);
for my $i ( 0 .. $#args ) {
$opts{ "arg-$i" } = $args[ $i ];
}
return api_call( 'cpanel', %opts );
}
sub modular_api_v2($$$%) {
my $user = shift;
my $module = shift;
my $func = shift;
my %opts = (
"cpanel_${API_TYPE}api_user" => $user,
"cpanel_${API_TYPE}api_module" => $module,
"cpanel_${API_TYPE}api_func" => $func,
"cpanel_${API_TYPE}api_apiversion" => 2,
@_
);
return api_call( 'cpanel', %opts );
}
sub parse_keyword_args(@) {
my %data;
for my $arg ( @_ ) {
my ( $k, $v ) = split( /=/, $arg, 2 );
defined( $v ) or $v = 1;
$data{ $k } = $v;
}
return %data;
}
sub fail_with_help {
my $message = shift;
if ( $message ) {
$message = c( $message, "red" );
}
pod2usage({
-message => $message,
-exitval => 1,
-verbose => 2,
-output => \*STDERR
});
}
GetOptions(
'1|modular-v1' => sub {
$CALL_MODE = $MODULAR_V1;
},
'2|modular-v2' => sub {
$CALL_MODE = $MODULAR_V2;
},
'x|xml' => sub {
$API_TYPE = 'xml';
$FORMAT = 'xml';
},
'j|json' => sub {
$API_TYPE = 'json';
$FORMAT = 'json';
},
'y|yaml' => sub {
$API_TYPE = 'json';
$FORMAT = 'yaml';
},
'D|d|debug' => \$DEBUG,
'b|bleach' => \$BLEACH,
'h|help' => sub { pod2usage( 0 ); },
'v|version' => sub { print "$VERSION\n"; exit 0; }
);
my $result;
if ( $CALL_MODE == $BASIC ) {
my $func = shift( @ARGV ) or fail_with_help( "no API function name provided" );
my %params = parse_keyword_args( @ARGV );
$result = api_call( $func, %params );
} elsif ( $CALL_MODE == $MODULAR_V1 ) {
my $user = shift( @ARGV ) or fail_with_help( "no user name provided" );
my $mod = shift( @ARGV ) or fail_with_help( "no module name provided" );
my $func = shift( @ARGV ) or fail_with_help( "no function name provided" );
my @params = @ARGV;
$result = modular_api_v1( $user, $mod, $func, @params );
} else {
my $user = shift( @ARGV ) or fail_with_help( "no user name provided" );
my $mod = shift( @ARGV ) or fail_with_help( "no module name provided" );
my $func = shift( @ARGV ) or fail_with_help( "no function name provided" );
my %params = parse_keyword_args( @ARGV );
$result = modular_api_v2( $user, $mod, $func, %params );
}
if ( $FORMAT eq 'xml' or $FORMAT eq "json" ) {
print $result;
} elsif ( $FORMAT eq 'yaml' ) {
eval {
require YAML::Any;
1;
} or do {
die "Cannot provide YAML output -- failed to load YAML::Any: $@";
};
print YAML::Any::Dump( load_json( $result ) );
}
Zerion Mini Shell 1.0