Skip to content

Commit

Permalink
Merge pull request #20 from mistio/privmist
Browse files Browse the repository at this point in the history
[WIP - Do not merge] Private Networks
  • Loading branch information
d-mo authored Jun 29, 2016
2 parents 22a318d + e30bcd4 commit b149fa4
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 11 deletions.
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
'prettytable',
'cryptography',
'ansible==1.9.3',
'HTMLParser'
'HTMLParser',
'netaddr'
]


Expand All @@ -22,7 +23,7 @@ def readme():

setup(
name='mist',
version='1.8',
version='1.9',
description='Python client for mist.io',
long_description=readme(),
classifiers=[
Expand Down
46 changes: 44 additions & 2 deletions src/mistclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,6 @@ def add_and_run_script(self, cloud_id, machine_id, script_params="",
script_params="", env=None, su=False,
fire_and_forget=True)



def get_templates(self, **_):
req = self.request(self.uri + '/templates')
response = req.get()
Expand Down Expand Up @@ -663,3 +661,47 @@ def show_stack(self, stack_id):
req = self.request(self.uri + "/stacks/" + stack_id)
response = req.get()
return response.json()

def list_tunnels(self):
req = self.request(self.uri + '/tunnels')
response = req.get()
return response.json()

def add_tunnel(self, name, cidrs, excluded_cidrs, description):
payload = {
'name': name,
'cidrs': cidrs,
'excluded_cidrs': excluded_cidrs,
'description': description
}

req = self.request(self.uri + '/tunnels', data=json.dumps(payload))
response = req.post()
return response.json()

def edit_tunnel(self, tunnel_id, name, cidrs, description):
payload = {
'name': name,
'cidrs': cidrs,
'description': description
}

req = self.request(self.uri + '/tunnel/' + tunnel_id,
data=json.dumps(payload))
response = req.put()
return response.json()

def delete_tunnel(self, tunnel_id):
req = self.request(self.uri + '/tunnel/' + tunnel_id)
response = req.delete()
return response

def tunnel_script(self, tunnel_id):
req = self.request(self.uri + '/tunnel/' + tunnel_id + '/script')
response = req.get()
return response.text

def tunnel_command(self, tunnel_id):
req = self.request(self.uri + '/tunnel/' + tunnel_id + '/command')
response = req.get()
return response.text
6 changes: 3 additions & 3 deletions src/mistclient/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,10 +675,10 @@ def __init__(self, key, mist_client):
self.info = key

def __str__(self):
return "%s => %s" % (self.__class__.__name__, self.id)
return "%s => %s" % (self.__class__.__name__, self.name)

def __repr__(self):
return "%s => %s" % (self.__class__.__name__, self.id)
return "%s => %s" % (self.__class__.__name__, self.name)

def request(self, *args, **kwargs):
"""
Expand Down Expand Up @@ -789,7 +789,7 @@ def __init__(self, script, mist_client):
self.description = script['description']

def __str__(self):
return "%s => %s" % (self.__class__.__name__, self.id)
return "%s => %s" % (self.__class__.__name__, self.name)

def __repr__(self):
return "%s => %s" % (self.__class__.__name__, self.name)
Expand Down
4 changes: 2 additions & 2 deletions src/mistcommand/helpers/stacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ def list_stacks(client, pretty):
if pretty:
x = PrettyTable(["Name", "ID", "Description", "Template", "Deployed"])
for stack in stacks:
x.add_row([stack['name'], stack['id'], stack['description'],
x.add_row([stack['name'], stack['_id'], stack['description'],
stack['template'], stack['deploy']])
print x
else:
for stack in stacks:
print "%-40s %-40s %-40s %-40s" % (stack['name'], stack['id'],
print "%-40s %-40s %-40s %-40s" % (stack['name'], stack['_id'],
stack['description'],
stack['template'])

Expand Down
4 changes: 2 additions & 2 deletions src/mistcommand/helpers/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def list_templates(client, pretty):
if pretty:
x = PrettyTable(["Name", "ID", "Description"])
for template in templates:
x.add_row([template['name'], template['id'], template['description']])
x.add_row([template['name'], template['_id'], template['description']])
print x
else:
for template in templates:
print "%-40s %-40s %-40s" \
% (template['name'], template['id'], template['description'])
% (template['name'], template['_id'], template['description'])


def show_template(client, template_id, pretty):
Expand Down
105 changes: 105 additions & 0 deletions src/mistcommand/helpers/tunnels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import sys

from netaddr import IPAddress, IPNetwork

from prettytable import PrettyTable
from mistcommand.helpers.login import authenticate


def tunnel_action(args):
client = authenticate()
if args.action == 'list-tunnels':
list_tunnels(client, args.pretty)
elif args.action == 'add-tunnel':
tunnel = add_tunnel(client, args)
print '\nTunnel <%s> to %s added successfully\n' % (args.name, args.cidrs)
print 'Now, copy-paste and run the configuration script on your VPN ' \
'client in order to complete the VPN tunnel\'s establishment\n'
print '='*50 + '\n'
get_conf(client, tunnel['_id'])
print '='*50 + '\n'
print 'Or, you can simply run the following `curl` command directly ' \
'in your VPN client\'s shell:\n'
get_cmd(client, tunnel['_id'])
elif args.action == 'edit-tunnel':
edit_tunnel(client, args)
print 'Tunnel %s was edited successfully' % args.tunnel
elif args.action == 'delete-tunnel':
client.delete_tunnel(args.tunnel)
print 'Tunnel %s removed' % args.tunnel
elif args.action == 'tunnel-script':
get_conf(client, args.tunnel)
elif args.action == 'tunnel-command':
get_cmd(client, args.tunnel)


def list_tunnels(client, pretty):
tunnels = client.list_tunnels()
if not tunnels:
print 'Could not find any VPN Tunnels'
sys.exit(0)
if pretty:
x = PrettyTable(['Name', 'ID', 'CIDRs', 'Description'])
for tunnel in tunnels:
description = tunnel.get('description', '-')
x.add_row([tunnel['name'], tunnel['_id'], tunnel['cidrs'], description])
print x
else:
for tunnel in tunnels:
description = tunnel.get('description', '-')
print '%-40s %-40s %-40s %-40s' % (tunnel['name'], tunnel['_id'],
tunnel['cidrs'], description)


def add_tunnel(client, args):
name = args.name
cidrs = args.cidrs
excluded_cidrs = args.exclude_cidrs if args.exclude_cidrs else []
description = args.description

for cidr in cidrs:
for network in ['192.168.0.0/16', '172.16.0.0/12', '10.0.0.0/8']:
if IPNetwork(cidr) in IPNetwork(network):
break
else:
while True:
print 'You are attempting to route a public IP over VPN'
prompt = raw_input('Are you sure you want to proceed [Y/n]: ')
if prompt in ['Y', 'y', 'yes']:
break
elif prompt in ['N', 'n', 'no']:
sys.exit(0)
break

return client.add_tunnel(name=name, cidrs=cidrs,
excluded_cidrs=excluded_cidrs,
description=description)


def edit_tunnel(client, args):
tunnel_id = args.tunnel
name = args.name
cidrs = args.cidrs
description = args.description

client.edit_tunnel(tunnel_id=tunnel_id, name=name, cidrs=cidrs,
description=description)


def get_conf(client, tunnel_id):
tunnels = client.list_tunnels()
if not tunnels:
print 'Could not find any VPN Tunnels'
sys.exit(0)
for tunnel in tunnels:
if tunnel['_id'] == tunnel_id:
script = tunnel['script']
break
else:
print 'The ID provided does not correspond to any VPN Tunnel'
sys.exit(0)
print script


def get_cmd(client, tunnel_id):
print client.tunnel_command(tunnel_id)
92 changes: 92 additions & 0 deletions src/mistcommand/mist
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ from mistcommand.helpers.metrics import metric_action
from mistcommand.helpers.scripts import script_action
from mistcommand.helpers.mistansible import ansible_action
from mistcommand.helpers.ssh import ssh_action
from mistcommand.helpers.tunnels import tunnel_action

from requests.packages import urllib3
urllib3.disable_warnings()
Expand Down Expand Up @@ -1013,6 +1014,94 @@ def main():
help="Workflow to be run"
)

# -------------------VPN ACTIONS-------------------
p_list_tunnels = subparsers.add_parser(
'list-tunnels',
description='List all available VPN Tunnels'
)
p_list_tunnels.add_argument(
'--pretty', action='store_true',
help='Print in a table format'
)

p_add_tunnel = subparsers.add_parser(
'add-tunnel',
description='Add a new VPN Tunnel'
)
p_add_tunnel.add_argument(
'--name', required=True,
help='Tunnel name'
)
p_add_tunnel.add_argument(
'--cidrs', nargs='+', required=True,
help='List of private networks in CIDR notation '
'accessible via this tunnel'
)
p_add_tunnel.add_argument(
'--exclude-cidrs', nargs='+',
help='List of private networks in CIDR notation you wish to exclude '
'from your VPN configuration in order to avoid potential, local '
'routing conflicts (OPTIONAL)'
)
p_add_tunnel.add_argument(
'--description',
help='Description (OPTIONAL)'
)

p_edit_tunnel = subparsers.add_parser(
'edit-tunnel',
description='Edit an existing VPN Tunnel'
)
p_edit_tunnel.add_argument(
'tunnel',
help='ID of the tunnel to be edited.'
'You can retrieve all tunnel IDs by invoking list-tunnels'
)
p_edit_tunnel.add_argument(
'--name', required=True,
help='Existing/new name of the specified tunnel'
)
p_edit_tunnel.add_argument(
'--cidrs', nargs='+', required=True,
help='Existing/new list of the reachable private'
'networks in CIDR notation'
)
p_edit_tunnel.add_argument(
'--description',
help='Description (OPTIONAL)'
)

p_delete_tunnel = subparsers.add_parser(
'delete-tunnel',
description='Delete an existing VPN Tunnel'
)
p_delete_tunnel.add_argument(
'tunnel',
help='ID of the tunnel to be deleted.'
'You can retrieve all tunnel IDs by invoking list-tunnels'
)

p_tunnel_script = subparsers.add_parser(
'tunnel-script',
description='Configuration script for setting up the VPN Tunnel'
)
p_tunnel_script.add_argument(
'tunnel',
help='Get the configuration script of the VPN Tunnel.'
'You can retrieve the tunnel ID by invoking list-tunnels'
)

p_tunnel_command = subparsers.add_parser(
'tunnel-command',
description='Shell command to automatically download and install'
'the VPN client\'s configuration'
)
p_tunnel_command.add_argument(
'tunnel',
help='Get the shell command for downloading and running the VPN '
'configuration script. '
'You can retrieve the tunnel ID by invoking list-tunnels'
)
# -------------------METRICS ACTIONS-------------------
p_list_metrics = subparsers.add_parser(
'list-metrics',
Expand Down Expand Up @@ -1148,6 +1237,9 @@ def main():
elif args.action in ['list-stacks', 'create-stack', 'delete-stack',
'run-workflow']:
stack_action(args)
elif args.action in ['list-tunnels', 'add-tunnel', 'edit-tunnel',
'delete-tunnel', 'tunnel-script', 'tunnel-command']:
tunnel_action(args)
elif args.action in ['list-metrics', 'add-metric', 'add-custom-metric']:
metric_action(args)
elif args.action == 'user-info':
Expand Down

0 comments on commit b149fa4

Please sign in to comment.