Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ###############################################################################
- #
- # Display list of GlobalProtect users
- #
- # Ken Cornetet - Kimball Electronics
- #
- #
- # Revision History
- #
- # When Who What
- # -----------------------------------------------------------------------------
- # 2020-02-27 kcornet Original
- # 2021-12-28 kcornet Get Palos from network inventory database
- #
- ###############################################################################
- use strict;
- use CGI qw/:standard/;
- use CGI::Carp qw(fatalsToBrowser);
- use Data::Dumper;
- use Text::Unidecode;
- use Net::Ping;
- use KII::kii_ad;
- use DBI;
- use 5.010;
- my $t0 = time();
- print "Content-type: text/html\n\n";
- #print qq(<head><meta http-equiv="refresh" content="60"></head>);
- my $userid = remote_user();
- $userid = '' unless defined $userid;
- $userid =~ s/..*\\//;
- $userid = lc($userid);
- my $password = $ENV{AUTH_PASSWORD};
- my $palo = param('palo');
- if( ! $palo ) { # Initial call, create form
- step1();
- } else {
- step2();
- }
- exit 0;
- ###############################################################################
- #
- # Draw the initial form asking the user what router to manage
- #
- ###############################################################################
- sub step1 {
- my %netinv;
- my @units;
- LoadNetInventory(\%netinv);
- foreach my $device ( sort keys %netinv ) {
- push @units, $device if $netinv{$device}->{MODEL1} =~ /^pa-/i;
- }
- print start_form;
- print "<p>Pick the Palo to view: \n";
- print "<select name=palo>\n";
- print "<option value=\"all\">all\n";
- foreach my $unit (sort @units) {
- $unit = uc $unit;
- print "<option value=\"$unit\">$unit\n";
- }
- print "</select>\n";
- print '<p><input type=submit value="Next" name=button>';
- print end_form;
- }
- sub step2 {
- my $unit = param('palo');
- my @units;
- if( $palo eq 'all' ) {
- my %netinv;
- LoadNetInventory(\%netinv);
- foreach my $device (sort keys %netinv) {
- push @units, $device if $netinv{$device}->{MODEL1} =~ /^pa-/i;
- }
- } else {
- push @units, $unit;
- }
- my $total = 0;
- foreach my $unit (sort @units) {
- my $pa = PaloAltoBasicAuth::new($unit, $userid, $password);
- if( ! $pa ) {
- print "<h3>Error: could not open session to $unit</h3><p>\n";
- next;
- }
- next unless IsActive($pa);
- my @gateways = GetGateways($pa);
- foreach my $gw (sort @gateways) {
- next unless $gw;
- my $res = GetUsers($pa, $gw);
- next unless $res;
- #print "<pre>\n", Dumper($res), "</pre><p>\n";
- my $n = UserCount($res);
- $total += $n;
- print "<font size=+1><b>", uc($unit), "</b> $gw Users: $n</font><br>";
- HandleUser($res);
- }
- print "<hr>\n";
- }
- print "<p>Total GlobalProtect users: $total\n";
- print "<hr><font size=-1>\n";
- print "Run time : ", time() - $t0, " seconds<br>";
- print "CPU time (user) : ", (times)[0], " seconds<br>";
- print "CPU time (system): ", (times)[1], " seconds<br>\n";
- print "</font>\n";
- }
- ###############################################################################
- #
- # Get user's display name from AD
- #
- ###############################################################################
- sub AdInfo {
- my $id = shift;
- state $objAD;
- $objAD = kii_ad->new( warn=>0 ) unless $objAD;
- return undef unless $objAD;
- my ($adsPath) = $objAD->Find( filter=>"(samAccountName=$id)" );
- return undef unless $adsPath;
- my $objUser = $objAD->GetObject($adsPath);
- return undef unless $objUser;
- return ( $objUser->Get("DisplayName"), $objUser->Get("Company") );
- }
- ###############################################################################
- #
- # Get total count of users from this record
- #
- ###############################################################################
- sub UserCount {
- my $res = shift;
- my $entries = $res->{result}->{entry};
- return 0 unless $entries;
- return scalar @{$entries};
- }
- ###############################################################################
- #
- # Display user information
- #
- ###############################################################################
- sub HandleUser {
- my $res = shift;
- my $entries = $res->{result}->{entry};
- return unless $entries;
- return unless scalar @{$entries};
- print "<table border=1>\n";
- print "<tr><th>USERID<th>USER<th>COMPUTER<th>LOGIN TIME<th>CLIENT<th>VIRTUAL IP<th>PUBLIC IP<th>VPN TYPE<th>TUNNEL TYPE<th>PINGS\n";
- foreach my $entry ( sort byuser @{$entries} ) {
- my ($disp, $comp) = AdInfo($entry->{username});
- print "<tr>";
- print "<td>", $entry->{username};
- print "<td> $disp ($comp)";
- print "<td>", unidecode($entry->{computer});
- print "<td>", $entry->{'login-time'};
- print "<td>", $entry->{client};
- print "<td>", $entry->{'virtual-ip'};
- print "<td>";
- print "<a href=\"/scripts/arin.pl?ip=$entry->{'public-ip'}\">$entry->{'public-ip'}</a>";
- print "<td>", $entry->{'vpn-type'};
- print "<td>", $entry->{'tunnel-type'};
- print "<td>", IsAlive($entry->{'virtual-ip'}) ? "yes":"no";
- print "\n";
- }
- print "</table><p>\n";
- }
- ###############################################################################
- #
- # Function to allow sorting by user name
- #
- ###############################################################################
- sub byuser {
- return lc $a->{username} cmp lc $b->{username};
- }
- ###############################################################################
- #
- # Ping global protect client
- #
- ###############################################################################
- sub IsAlive {
- my $host = shift;
- my $p = Net::Ping->new("icmp", 2);
- return 1 if $p->ping($host);
- return undef;
- }
- ###############################################################################
- #
- # Get the gateways defined on a given Palo
- #
- ###############################################################################
- sub GetGateways {
- my $pa = shift;
- my $res = $pa->get( qq(/api/?type=op&cmd=<show><global-protect-gateway><statistics></statistics></global-protect-gateway></show>) );
- my @ret;
- my $gateways = $res->{result}->{Gateway};
- return undef unless $gateways;
- # print "<pre>\n";
- # print Dumper($gateways);
- # print "</pre>\n";
- if( ref $gateways eq 'ARRAY' ) {
- foreach my $gw ( @{$gateways} ) {
- push @ret, $gw->{name};
- }
- } else {
- push @ret, $gateways->{name};
- }
- return @ret;
- }
- ###############################################################################
- #
- # Get users for a given gateway
- #
- ###############################################################################
- sub GetUsers {
- my $pa = shift;
- my $gateway = shift;
- my $res = $pa->get( qq(/api/?type=op&cmd=<show><global-protect-gateway><current-user><gateway>$gateway</gateway></current-user></global-protect-gateway></show>) );
- return $res;
- }
- ###############################################################################
- #
- # Is this Palo a single unit, or an active HA unit?
- #
- ###############################################################################
- sub IsActive {
- my $pa = shift;
- my $res = $pa->get( qq(/api/?type=op&cmd=<show><high-availability><state></state></high-availability></show>) );
- #print "<pre>\n";
- #print Dumper($res);
- #print "</pre>\n";
- return 1 if $res->{result}->{enabled} eq 'no'; # not HA
- return 1 if $res->{result}->{enabled} eq 'yes' and $res->{result}->{group}->{'local-info'}->{state} eq 'active';
- return 0;
- }
- ###############################################################################
- #
- # Load network inventory
- #
- ###############################################################################
- sub LoadNetInventory {
- my $r = shift;
- # Redacted because it is site specific
- }
- ###############################################################################
- #
- # Package to access Palo API using userid/password authentication
- #
- ###############################################################################
- package PaloAltoBasicAuth;
- use LWP::UserAgent;
- use HTTP::Request::Common qw(POST GET );
- use Data::Dumper;
- use XML::Simple qw(:strict);
- use MIME::Base64;
- ##################################################################################################
- #
- # Create object. Requires server, userid, password
- #
- ##################################################################################################
- our $content;
- sub new {
- #my $class = shift;
- my $server = shift;
- my $user = shift;
- my $passwd = shift;
- my $self = {};
- $self->{server} = $server;
- #$self->{user} = $user;
- #$self->{passwd} = $passwd;
- $self->{auth} = encode_base64("$user:$passwd");
- $self->{ua} = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
- $self->{ua}->default_header('Authorization' => "Basic $self->{auth}");
- bless $self;
- return $self;
- }
- ##################################################################################################
- #
- # Perform an http GET
- #
- # Builds a URL out of the passed controller name and cached appid, then does a http GET
- #
- # If request fails, return undef
- #
- # If request succeeds, decode returned JSON into a perl hash and return ref to it
- #
- ##################################################################################################
- sub get {
- my $self = shift;
- my $s = shift;
- my $url = "https://$self->{server}$s";
- my $req = (GET $url);
- my $res = $self->{ua}->request($req);
- return undef unless $res->code() == 200;
- #print Dumper($res->content());
- #print "\n\n";
- my $ref = XMLin($res->content(), ForceArray => ['entry'], KeyAttr => '');
- #print Dumper($ref);
- return $ref;
- }
- sub name {
- my $self = shift;
- return $self->{server};
- }
Add Comment
Please, Sign In to add comment