Commit 8f0b8684 authored by David Seaward's avatar David Seaward

execute tunnel commands over SSH

parent 2e9017a7
......@@ -24,3 +24,6 @@ WOO_VERSION = wc/v1
WOO_PRODUCT_LIST = 123,124
WOO1_FIELD_LIST = Existing username,Username
WOO1_EMAIL_SUFFIX = @example.com
OVPN_HOSTNAME = ssh.example.com
OVPN_PORT = 22
OVPN_USERNAME = username
......@@ -17,6 +17,7 @@ def create_missing_user_limits(user):
if not Limit.objects.filter(user=user, service=code).exists():
Limit(user=user, service=code).save()
class Limit(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
service = models.CharField(max_length=30, choices=SERVICE_CHOICES)
......
import paramiko
from celery import shared_task
from celery.utils.log import get_task_logger
from django.conf import settings
......@@ -11,6 +12,7 @@ logger = get_task_logger(__name__)
def get_woo_connection():
return WOO_API(
url=settings.WOO_URL,
consumer_key=settings.WOO_CONSUMER_KEY,
......@@ -20,6 +22,37 @@ def get_woo_connection():
)
def get_openvpn_ssh_connection():
# make ssh connection to OpenVPN server
# (uses system host keys)
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.connect(
hostname=settings.OVPN_HOSTNAME,
port=settings.OVPN_PORT,
username=settings.OVPN_USERNAME,
)
return ssh
def openvpn_exec(ssh, command):
stdin, stdout, stderr = ssh.exec_command(command)
output = "".join(stdout.readlines())
if output == "":
output = "None."
error = "".join(stderr.readlines())
message = "Executed: %s. Output: %s" % (command, output,)
if len(error) == 0:
logger.info(message)
else:
raise Exception(message + "\n" + error)
def get_latest_woo1(connection, product_id):
return connection.get("orders?product=" + str(product_id))
......@@ -78,7 +111,7 @@ def is_existing_credit(credit):
return is_existing
def update_limit_woo1(credit):
def update_limit_woo1(ssh, credit):
# validate credit
if credit.account_name is None or not str.endswith(credit.account_name, settings.WOO1_EMAIL_SUFFIX):
......@@ -101,21 +134,38 @@ def update_limit_woo1(credit):
# FIXME: should not simply activate an inactive service
credit_timedelta = timezone.timedelta(days=int(external_bundle.time_credit * credit.quantity))
credit_days = int(external_bundle.time_credit * credit.quantity)
credit_timedelta = timezone.timedelta(days=credit_days)
activate(ssh, limit, credit_timedelta)
def activate(ssh, limit, credit_timedelta):
if limit.is_active:
limit.expiry_date += credit_timedelta
else:
limit.expiry_date = timezone.now() + credit_timedelta
limit.is_active = True
if limit.service == "TUNNEL":
openvpn_exec(ssh, "./create_new_ovpn_config --generate %s" % (limit.user.email,))
limit.save()
def deactivate(ssh, limit):
if limit.service == "TUNNEL":
openvpn_exec(ssh, "./create_new_ovpn_config --revoke %s" % (limit.user.email,))
limit.is_active = False
limit.save()
@transaction.atomic
def store_credit_and_update_limit(credit):
def store_credit_and_update_limit(ssh, credit):
try:
if credit.parser == "WOO1":
update_limit_woo1(credit)
update_limit_woo1(ssh, credit)
else:
raise Exception("Unrecognised parser " + credit.parser)
......@@ -132,6 +182,7 @@ def store_credit_and_update_limit(credit):
def monitor_woo1():
# get API connection to WooCommerce
woo_connection = get_woo_connection()
ssh = get_openvpn_ssh_connection()
# get product sales and parse the results
result_list = []
......@@ -160,7 +211,7 @@ def monitor_woo1():
)
if not is_existing_credit(credit):
store_credit_and_update_limit(credit)
store_credit_and_update_limit(ssh, credit)
else:
logger.info("Skipped stored result " + str(result))
except Exception as e:
......@@ -172,10 +223,10 @@ def deactivate_all_expired_limits():
now = timezone.now()
overdue_list = Limit.objects.filter(expiry_date__lte=now, is_active=True)
ssh = get_openvpn_ssh_connection()
for limit in overdue_list:
limit.is_active = False
limit.save()
# TODO: also send deactivation command
deactivate(ssh, limit)
@shared_task
......
......@@ -129,3 +129,11 @@ WOO_PRODUCT_LIST = config("WOO_PRODUCT_LIST", cast=Csv(int))
WOO1_EMAIL_SUFFIX = config("WOO1_EMAIL_SUFFIX")
WOO1_FIELD_LIST = config("WOO1_FIELD_LIST", cast=Csv())
#
# SSH CONNECTION TO OPENVPN SERVER
#
OVPN_HOSTNAME = config("OVPN_HOSTNAME")
OVPN_PORT = config("OVPN_PORT", cast=int)
OVPN_USERNAME = config("OVPN_USERNAME")
......@@ -9,5 +9,6 @@ django-crispy-forms==1.6.1
django-ldapdb==0.9.0
django-registration==2.2
jinja2-django-tags==0.5
paramiko==2.2.1
pyasn1==0.2.3
python-decouple==3.0
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment