Last active
April 3, 2025 18:12
-
-
Save karlbaillie/38508fd92669101ec1fca4bea62bcefe to your computer and use it in GitHub Desktop.
AnyConnector: Manage Cisco Anyconnect Connections stored in KeePass through CLI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use File::KeePass; | |
use Term::ReadKey; | |
use Data::Dumper qw(Dumper); | |
use Getopt::Long qw(GetOptions); | |
use Digest::MD5 qw(md5_hex); | |
use MIME::Base64; | |
use File::Slurp; | |
my $file = "/path/to/keepass.kdbx"; | |
GetOptions ( | |
'con|connect=s' => \$connect, | |
'discon|disconnect' => \$disconnect, | |
'state' => \$state) | |
or die(usage()); | |
if ($connect) { | |
# get current status | |
open SAVOUT, ">&STDOUT"; # copy of STDOUT | |
open STDOUT, ">/dev/null"; | |
my $vpn_status = status(); | |
open STDOUT, ">&SAVOUT"; | |
close SAVOUT; | |
if ($vpn_status eq "Connected") { | |
disconnect(); | |
}; | |
my $master_pass = prompt_for_password(); | |
my $k = File::KeePass->new; | |
$k->load_db($file, $master_pass); | |
$k->unlock; | |
my $entry = $k->find_entry({title => "$connect-VPN"}); | |
if (!$entry) { | |
die("You have no KeePass entry named $connect-VPN\n"); | |
} | |
else { | |
print "Connecting to $connect...\n"; | |
open SAVOUT, ">&STDOUT"; # copy of STDOUT | |
open STDOUT, ">/dev/null"; | |
system qq(printf "y\n$entry->{'username'}\n$entry->{'password'}\ny" | /opt/cisco/anyconnect/bin/vpn -s connect $entry->{'url'}); | |
open STDOUT, ">&SAVOUT"; | |
close SAVOUT; | |
}; | |
status(); | |
sleep 1; | |
} elsif ($disconnect) { | |
disconnect(); | |
} elsif ($state) { | |
status(); | |
} else { | |
die(usage()); | |
}; | |
sub status { | |
my $status = `/opt/cisco/anyconnect/bin/vpn status`; | |
if ($status =~ "Connected") { | |
print "Connected\n"; | |
return "Connected"; | |
} else { | |
print "Not Connected\n"; | |
return "Not Today Punk"; | |
} | |
} | |
sub disconnect { | |
open SAVOUT, ">&STDOUT"; # copy of STDOUT | |
open STDOUT, ">/dev/null"; | |
system qq(/opt/cisco/anyconnect/bin/vpn disconnect); | |
open STDOUT, ">&SAVOUT"; | |
close SAVOUT; | |
print "Disconnected!\n" | |
} | |
sub prompt_for_password { | |
# location for password to be stored | |
my $passfile = md5_hex($file); # use keepass file location as a unique hash | |
# if password is stored read it | |
if (-e "/tmp/$passfile") { | |
my $decode = read_file("/tmp/$passfile"); | |
$password = decode_base64($decode); | |
$password =~ s/\R\z//; | |
return $password; | |
} | |
else { | |
# read password from stdin | |
require Term::ReadKey; | |
Term::ReadKey::ReadMode('noecho'); | |
print "Enter your KeePass database password: "; | |
my $password = Term::ReadKey::ReadLine(0); | |
Term::ReadKey::ReadMode('restore'); | |
print "\n"; | |
$password =~ s/\R\z//; | |
# encode password Bae64 | |
my $encoded = encode_base64($password); | |
# write password to a file | |
open(my $fh, '>', "/tmp/$passfile") or die "Could not find file /tmp/$passfile!"; | |
print $fh "$encoded\n"; | |
close $fh; | |
return $password; | |
} | |
} | |
sub usage { | |
die("Usage: $0 -c|connect ENV / -d|disconnect / -s|state\n"); | |
} | |
# EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment