#!/usr/bin/env perl # # Copyright 2020, Mischa Peters , Netskope. # Netskope_ZScalerImporter.pl - Version 3.0 - 20200615 # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # ZScaler integration with Netskope # use 5.024; use strict; use warnings; use autodie; use Config::Tiny; use Time::HiRes qw(gettimeofday); use POSIX qw(strftime); use HTTP::Tiny; use HTTP::CookieJar; use JSON::PP; use Text::CSV; use MIME::Lite; my $LOGMODE = ""; #my @CONFIG_FILES = grep { -e } ('./netskope.cnf', './.netskope.cnf', '/etc/netskope.cnf', "$ENV{'HOME'}/.netskope.cnf", "$ENV{'HOME'}/netskope.cnf"); my @CONFIG_FILES = grep { -e } ('./tbi.cnf'); my $config = Config::Tiny->read($CONFIG_FILES[-1], 'utf8'); my $USER_COUNT = $config->{report}{USER_COUNT}; my $MAX_DOMAIN= $config->{report}{MAX_DOMAIN}; my $NTSKP_TENANT = $config->{netskope}{NTSKP_TENANT}; my $NTSKP_TOKEN = $config->{netskope}{NTSKP_TOKEN}; my $NTSKP_TIMEPERIOD = $config->{netskope}{NTSKP_TIMEPERIOD}; my $ZS_MAX_DOMAINS = $config->{zscaler}{ZS_MAX_DOMAINS}; my $ZS_BASE_URI = $config->{zscaler}{ZS_BASE_URI}; my $ZS_API_KEY = $config->{zscaler}{ZS_API_KEY}; my $ZS_API_USERNAME = $config->{zscaler}{ZS_API_USERNAME}; my $ZS_API_PASSWORD = $config->{zscaler}{ZS_API_PASSWORD}; my $ZS_CATEGORY_NAME = $config->{zscaler}{ZS_CATEGORY_NAME}; my $ZS_CATEGORY_DESC = $config->{zscaler}{ZS_CATEGORY_DESC}; my $PROXY = $config->{general}{PROXY}; my $SMTP = $config->{general}{SMTP}; my $FROM = $config->{general}{FROM}; my $TO = $config->{general}{TO}; my $SUBJECT = $config->{general}{SUBJECT}; my $TEXT = $config->{general}{TEXT} . "\n\n"; my %HEADERS = ("Content-Type" => "application/json", "Cache-Control" => "no-cache"); my $EMAIL_CSV = ""; ### Netskope ### sub mail_csv { my $msg = MIME::Lite->new(From=> $FROM, To => $TO, Subject => $SUBJECT, Type => 'TEXT', Data => $TEXT); $msg->send('smtp', $SMTP, Debug=>0); say "MAIL From: $FROM -> $TO - Attach CSV" if $LOGMODE; } sub _check_return { my ($status, $content, $uri) = @_; if ($status =~ /^2/ && $LOGMODE) { print "URI: $uri\nHTTP RESPONSE: $status\n"; print "CONTENT:\n$content\n" if ($LOGMODE eq "DEBUG"); } if ($status !~ /^2/) { print "URI: $uri\nHTTP RESPONSE: $status\n$content\n"; my $msg = MIME::Lite->new(From => $FROM, To => $TO, Subject => 'API Error along the way', Type => 'TEXT', Data => "URI: $uri\nHTTP RESPONSE: $status\n$content\n\n", ); $msg->send('smtp', $SMTP, Debug=>0); say "MAIL From: $FROM -> $TO - Error Notification" if $LOGMODE; say "exit 1"; exit 1; } } sub netskope { my $uri = "$NTSKP_TENANT/api/v1/alerts?token=$NTSKP_TOKEN&timeperiod=$NTSKP_TIMEPERIOD&type=policy"; my $request = HTTP::Tiny->new('default_headers' => \%HEADERS); my $response = $request->get($uri); _check_return($response->{'status'}, $response->{'content'}, $uri); my $json = JSON::PP->new->utf8->decode($response->{'content'}); my $data = $json->{'data'}; printf "%-7s %-45s %-35s %s\n", "Action", "Page", "Policy", "Category"; say "#############################################################################################################################"; my @seen; for my $item (@{$data}) { if (exists($item->{'page'})) { next if (grep {$_ eq $item->{'site'}} @seen); printf "%-7s %-45s %-35s %s\n", $item->{'action'}, $item->{'page'}, $item->{'policy'}, $item->{'category'}; push @seen, $item->{'site'}; } } } say "Running in $LOGMODE mode..." if $LOGMODE; netskope(); say "Completed." if $LOGMODE;