94 lines
3.0 KiB
Perl
94 lines
3.0 KiB
Perl
![]() |
#!/usr/bin/env perl
|
||
|
#
|
||
|
# Copyright 2023, Mischa Peters <mischa.p AT talon-sec DOT com>, Talon Cyber Security.
|
||
|
# claimfdomain.pl
|
||
|
# Version 1.0 - 20230610
|
||
|
#
|
||
|
# 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.
|
||
|
#
|
||
|
# Claim Domain force-validate for Talon via Frontegg
|
||
|
#
|
||
|
use 5.026;
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
use autodie;
|
||
|
use Config::Tiny;
|
||
|
use File::Basename;
|
||
|
use File::stat;
|
||
|
use POSIX qw(strftime);
|
||
|
use HTTP::Tiny;
|
||
|
use JSON::PP;
|
||
|
|
||
|
my $USAGE = <<"END_USAGE";
|
||
|
Usage: $0 <domain>
|
||
|
END_USAGE
|
||
|
|
||
|
my $domain = $ARGV[0];
|
||
|
$domain || die($USAGE);
|
||
|
|
||
|
my @CONFIG_FILES = grep { -e } ('./talon.cnf', './.talon.cnf', '/etc/talon.cnf', "$ENV{'HOME'}/.talon.cnf", "$ENV{'HOME'}/talon.cnf");
|
||
|
my $config = Config::Tiny->read($CONFIG_FILES[-1], 'utf8') || die("Uable to find talon.cnf");
|
||
|
my $FRONTEGG_URL = $config->{talon}{FRONTEGG_URL};
|
||
|
my $FRONTEGG_CLIENTID = $config->{talon}{FRONTEGG_CLIENTID};
|
||
|
my $FRONTEGG_KEY = $config->{talon}{FRONTEGG_KEY};
|
||
|
my $TTL = "82800";
|
||
|
my $STORE = dirname($0) . "/token.txt";
|
||
|
|
||
|
my %HEADERS = ("Accept" => "application/json", "Content-Type" => "application/json", "Cache-Control" => "no-cache");
|
||
|
my $request = HTTP::Tiny->new('default_headers' => \%HEADERS);
|
||
|
my $json = JSON::PP->new;
|
||
|
my $url;
|
||
|
my $body;
|
||
|
my $response;
|
||
|
my $token;
|
||
|
|
||
|
#
|
||
|
# POST authenticate and get token
|
||
|
#
|
||
|
|
||
|
if (-e $STORE) {
|
||
|
my $mtime = stat($STORE)->mtime();
|
||
|
if ((time() - $mtime) < $TTL) {
|
||
|
print "Using stored token\n";
|
||
|
open my $fh_token, '<', $STORE;
|
||
|
$token = <$fh_token>;
|
||
|
close $fh_token;
|
||
|
} else {
|
||
|
unlink($STORE);
|
||
|
}
|
||
|
}
|
||
|
if (! -e $STORE) {
|
||
|
print "Fetching new token\n";
|
||
|
$url = "${FRONTEGG_URL}/auth/vendor/";
|
||
|
print "$url\n";
|
||
|
$body = JSON::PP->new->space_after->encode({clientId => $FRONTEGG_CLIENTID, secret => $FRONTEGG_KEY});
|
||
|
$response = $request->post($url, {'content' => $body});
|
||
|
$token = $json->decode($response->{'content'})->{'token'};
|
||
|
|
||
|
print "$response->{'status'} $response->{'reason'}\n";
|
||
|
print "Received TOKEN: ${token}\n";
|
||
|
|
||
|
open my $fh_token, '>', $STORE;
|
||
|
print $fh_token "$token";
|
||
|
close $fh_token;
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# PUT force-validate
|
||
|
#
|
||
|
$url = "${FRONTEGG_URL}/team/resources/sso/v1/configurations/domains/${domain}/force-validate";
|
||
|
print "$url\n";
|
||
|
$body = JSON::PP->new->space_after->encode({validated => \1});
|
||
|
$response = $request->put($url, {'headers' => {"Authorization" => "Bearer $token"}, 'content' => $body});
|
||
|
print "$response->{'status'} $response->{'reason'}\n";
|