Skip to content

Commit

Permalink
License file writing, coloured log output, POD
Browse files Browse the repository at this point in the history
  • Loading branch information
gregfoletta committed May 16, 2022
1 parent 9097cfa commit d94b3ff
Showing 1 changed file with 73 additions and 40 deletions.
113 changes: 73 additions & 40 deletions ftnt_license_registration.pl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use 5.010;
use Pod::Usage;
use Getopt::Long;
use Term::ANSIColor;
use Carp;
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
use CAM::PDF;
Expand All @@ -17,56 +18,89 @@
'username=s',
'password=s',
'client_id=s',
'no-licenses=s',
'help' => sub { pod2usage(1) }
) or pod2usage(2);

=pod
=head1 NAME
ftnt_license_registration - extract license information from Fortinet zip files and register with Fortinet support.
=head1 SYNOPSIS
./ftnt_license_registration --username <IAM API User> [--password <IAM API Password> --no-licenses]
Script will prefer FORTICARE_API_PASSWORD environment variable over command line argument.
=cut


croak "No --username specified" unless $args{username};

my %auth_info = (
# Extract the registration codes from zip files
my @codes = extract_reg_codes(@ARGV);

# Get our API access token
my $access_token = forticare_auth(
username => $args{username},
password => $ENV{FORTICARE_API_PASSWORD} // $args{password},
client_id => $args{client_id} // 'assetmanagement'
);

my @codes = extract_reg_codes(@ARGV);
# Register the devices
my @licenses = forticare_register($access_token, @codes);


# Write out the license files
write_license_files(@licenses) unless $args{'no-licenses'};

my $access_token = forticare_auth( %auth_info );
forticare_register($access_token, @codes);

### Functions ###

sub log_output {
print STDERR colored('- ', 'bold green');
say STDERR join ' ', @_;
}

sub log_error {
say STDERR colored('- '.join(' ', @_), 'bold red');
}

sub extract_reg_codes {
my (@zip_files) = @_;
my @codes;

my $zip = Archive::Zip->new();

for my $zipfile (@zip_files) {
say STDERR "- Reading $zipfile";
unless ($zip->read($zipfile) == AZ_OK) { die "Could not open zipfile '$zipfile'"; }

for my $itf_pdf ($zip->members()) {
my $pdf_contents = $itf_pdf->contents();
my $pdf = CAM::PDF->new($pdf_contents);

my ($registration_code) = $pdf->getPageText(1) =~ m{Registration Code\s+:\s+((\w+-?){5})};
# Read in each zipfile
ZIP:
for my $zip_file (@zip_files) {
log_output("Reading $zip_file");

if (!$registration_code) {
carp "Could not extract code from '$zipfile'";
next;
}
if ($zip->read($zip_file) != AZ_OK) {
carp "Could not open zipfile '$zip_file'";
next ZIP;
}
}

PDF:
for my $pdf_name ($zip->memberNames()) {
# Extract PDF contents
my $pdf = CAM::PDF->new( $zip->memberNamed( $pdf_name )->contents() );

# Regex out the registration code
my ($registration_code) = $pdf->getPageText(1) =~ m{Registration Code\s+:\s+((\w{5}-){4}(\w{6}))};

if (!$registration_code) {
carp "Error extracting code from '$pdf_name'";
next PDF;
}

say STDERR "- Extracted code $registration_code'";
log_output("Extracted code $registration_code");

push @codes, $registration_code;
}
push @codes, $registration_code;
}

return @codes;
Expand Down Expand Up @@ -96,30 +130,16 @@ sub forticare_auth {
return $res->{access_token};
}

sub forticare_licenses {
my ($access_token, $filter) = @_;

# Default filter
$filter //= 'FGVM';

my $ua = Mojo::UserAgent->new;

return $ua->post(
'https://support.fortinet.com/ES/api/registration/v3/products/list' =>
{ Authorization => "Bearer $access_token" } =>
json => { serialNumber => $filter }
)->result->json;
}


sub forticare_register {
my ($access_token, @reg_codes) = @_;

my @licenses;

my $ua = Mojo::UserAgent->new;

CODE:
for my $code (@reg_codes) {
say STDERR "Registering code '$code'";
log_output("Registering code $code");
my $res = $ua->post(
'https://support.fortinet.com/ES/api/registration/v3/licenses/register' =>
{ Authorization => "Bearer $access_token" } =>
Expand All @@ -130,14 +150,27 @@ sub forticare_register {
)->result;

if ($res->is_error) {
say STDERR "Error: ".$res->json->{message};
log_error("Error: ".$res->json->{message});
next CODE;
}

my $license = $res->json->{assetDetails}{license};

say STDERR "- Registered $license->{licenseSKU} ($license->{licenseSKU})";
log_output("Registered $license->{licenseSKU} ($license->{serialNumber})");

# Push the license and serial on to the stack
push @licenses, $license;
}

return @licenses;
}


sub write_license_files {
my (@licenses) = @_;

for my $license (@licenses) {
open(my $fh, '>:encoding(UTF-8)', $license->{serialNumber}."lic");
print $fh $license->{licenseFile};
close $fh;
}
}

0 comments on commit d94b3ff

Please sign in to comment.