Skip to content

Commit

Permalink
Add state command
Browse files Browse the repository at this point in the history
Add `state` command for getting connection status
Refactor strings to make them consistent
Add requirements file
  • Loading branch information
gost-serb committed Dec 18, 2020
1 parent e19ed3a commit 2665da7
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 11 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Options:
Commands:
connect Endpoint address
disconnect Disconnect
state Get connection status
```

## Connect
Expand Down
31 changes: 23 additions & 8 deletions cisco_anyconnect_cli/cisco_anyconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@
import shutil
from subprocess import Popen, PIPE, STDOUT
import os
import re


class CiscoAnyConnect:

def __init__(self, path):
def __init__(self, path=None):
self.path = path
self.bin = self.detect_binary()
logging.info("Using " + self.bin)
logging.info(f"Using {self.bin}")

def connect(self, url, user, password):
logging.info("Connecting to '" + url + "' as '" + user + "'")
proc = Popen([self.bin, 'connect', url, '-s'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
def connect(self, url: str, user: str, password: str):
logging.info(f"Connecting to '{url}' as '{user}'")
proc = Popen([self.bin, "connect", url, "-s"], stdout=PIPE, stdin=PIPE, stderr=STDOUT)

stdout = proc.communicate(input=str(user + '\n' + password + '\n').encode())[0]
stdout = proc.communicate(input=f"{user}\n{password}\n".encode())[0]
logging.debug(stdout.decode())
proc.wait()

def disconnect(self):
proc = Popen([self.bin, 'disconnect'])
proc = Popen([self.bin, "disconnect"])
proc.communicate()

def state(self) -> str:
"""
Get connection state. Return actual state or Unknown if result was unexpected
"""
proc = Popen([self.bin, "state"], stdout=PIPE, stderr=STDOUT)
stdout = proc.communicate()[0].decode()
patt = re.compile(r".*state: (\w+)", re.MULTILINE)
res = re.findall(patt, stdout)

state = res[-1] if res else "Unknown"

logging.debug(state)
return state

def detect_binary(self):
executable = "vpncli.exe"
env_home = os.environ.get("CISCO_ANYCONNECT_HOME")
Expand All @@ -42,4 +57,4 @@ def detect_binary(self):
if path is not None and os.path.isfile(path):
return path

raise Exception("Could not find " + executable)
raise Exception(f"Could not find {executable}")
19 changes: 16 additions & 3 deletions cisco_anyconnect_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,33 @@ def disconnect(ctx):
sys.exit(1)


@click.command(help="Get connection state")
@click.pass_context
def state(ctx):
try:
client = CiscoAnyConnect(ctx.obj)
status = client.state()
logging.info(f"Connection state: {status}")
sys.exit(0)
except Exception as e:
logging.error(e)
sys.exit(1)


main.add_command(connect)
main.add_command(disconnect)
main.add_command(state)


def get_credentials(url):
logging.info("Retrieve credentials for '" + url + "'")
logging.info(f"Retrieve credentials for '{url}'")
try:
credentials = keepasshttp.get(url)
except Exception as e:
raise Exception("Could not connect to KeePassHTTP", e)

if credentials is None:
raise Exception(
"KeePass entry for '" + url + "' not found! Please add an entry with '" + url + "' as name or url")
raise Exception(f"KeePass entry for '{url}' not found! Please add an entry with '{url}' as name or url")

logging.info(f"Credentials found (User: {credentials.login})")
return credentials
Expand Down
10 changes: 10 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
certifi==2020.12.5
chardet==4.0.0
click==7.1.2
idna==2.10
keepasshttp==1.4.1
ordereddict==1.1
pycryptodome==3.9.9
requests==2.25.1
six==1.15.0
urllib3==1.26.2

0 comments on commit 2665da7

Please sign in to comment.