diff --git a/tunnel-as-a-service/emulated/charm.py b/tunnel-as-a-service/emulated/charm.py index 90e2c71..6c39bdb 100644 --- a/tunnel-as-a-service/emulated/charm.py +++ b/tunnel-as-a-service/emulated/charm.py @@ -1,5 +1,5 @@ import sys - +import os sys.path.append(".") from osm_ssh_proxy import SSHProxy import logging @@ -22,9 +22,9 @@ def __init__(self,unit): "listen_port": "51820", "save_config": "true", "forward_interface": "wg0", - "ssh-hostname": "10.0.12.107", + "ssh-hostname": "10.0.12.212", "username": "ubuntu", - "password": "ubuntu", + "password": "password", "vsi_id": "1", } class Unit(): @@ -32,6 +32,7 @@ def __init__(self): pass def is_leader(self): return True + class Event(): params = {} def __init__(self): @@ -121,33 +122,35 @@ def delete_peer(self, event): def get_ip_routes(self, event): return self.wg_toolkit.network_mgmt.get_ip_routes(event) - #Openstack management - def set_credentials(self,event): - return self.wg_toolkit.openstack_mgmt.set_credentials(event) - - def get_server_details(self,event): - return self.wg_toolkit.openstack_mgmt.get_server_details(event) - def get_server_ports(self,event): - return self.wg_toolkit.openstack_mgmt.get_server_ports(event) + # Passwd Actions + def install_openstack_wrapper(self,event): + return self.wg_toolkit.pwdBase.install_openstack_wrapper(event) + + def configure_key_gen(self,event): + return self.wg_toolkit.pwdBase.configure_key_gen(event) + + def get_public_key(self,event): + return self.wg_toolkit.pwdBase.get_public_key(event) + + def add_address_pair(self,event): + return self.wg_toolkit.pwdBase.add_address_pair(event) - def add_address_pairs(self,event): - return self.wg_toolkit.openstack_mgmt.add_address_pairs(event) if __name__ == "__main__": - tunnel_charm = TunnelCharm("ubuntu", "ubuntu", "10.0.12.107") + tunnel_charm = TunnelCharm("ubuntu", "password", "10.0.12.212") # Install wireguard and start thee tunnel #tunnel_charm.install_wg_packages(None) #tunnel_charm.wireguard_version_check(None) #tunnel_charm.configuration_keygen(None) #tunnel_charm.wireguard_server_configuration(None) # Add Peer - event = Event() - event.add_param("peer_key", "U5H6wmmosBhVLLm1A1p/Hbx7M/hhtvpQ8D+20K0ORj0=") - event.add_param("peer_endpoint", "155.44.99.111:51820") - event.add_param("allowed_networks", "10.10.10.0/24,10.10.11.0/24") - tunnel_charm.add_peer(event) + # event = Event() + # event.add_param("peer_key", "U5H6wmmosBhVLLm1A1p/Hbx7M/hhtvpQ8D+20K0ORj0=") + # event.add_param("peer_endpoint", "155.44.99.111:51820") + # event.add_param("allowed_networks", "10.10.10.0/24,10.10.11.0/24") + # tunnel_charm.add_peer(event) # Get VNF IPs #event = Event() #tunnel_charm.get_vnf_ip(event) @@ -220,29 +223,28 @@ def add_address_pairs(self,event): #event = Event() #tunnel_charm.get_wireguard_base_info(event) - #Set OpenStack Credentials - # event = Event() - # event.add_param("username",'') - # event.add_param('password','') - # event.add_param('user_domain_name','') - # event.add_param('domain_name','') - # event.add_param('project_name','') - # event.add_param('host','') - # tunnel_charm.set_credentials(event) - - # Get Server Details - # event = Event() - # event.add_param('server_id','26f4aec2-2148-43b9-9d9f-56e0c1d1c2cd') - # tunnel_charm.get_server_details(event) - - # Get Server Interfaces - # event = Event() - # event.add_param('server_id','26f4aec2-2148-43b9-9d9f-56e0c1d1c2cd') - # tunnel_charm.get_server_ports(event) + + # Configure key pair + event = Event() + tunnel_charm.install_openstack_wrapper(event) + #tunnel_charm.configure_key_gen(event) + event = Event() + tunnel_charm.get_public_key(event) + username = b'' + password = b'' + user_domain_name = b'' + domain_name = b'' + project_name = b'' + host = b'' + event = Event() + event.add_param("username",username) + event.add_param('password', password) + event.add_param('user_domain_name',user_domain_name) + event.add_param('domain_name',domain_name) + event.add_param('project_name',project_name) + event.add_param('host',host) + event.add_param('server_id','8b3ca827-f6bf-4065-add5-0341f78a2928') + event.add_param('address_pairs',"10.100.100.0/24, 192.168.100.0/24") + tunnel_charm.add_address_pair(event) - # Add Address Pairs - # event = Event() - # event.add_param('ports_id_list',['955989fe-9864-4216-9f3a-1ea8f4710ced']) - # event.add_param('ip_address_list',['10.100.100.0/24','192.168.100.0/24']) - # tunnel_charm.add_address_pairs(event) diff --git a/tunnel-as-a-service/emulated/passbolt/constants.py b/tunnel-as-a-service/emulated/passbolt/constants.py new file mode 100644 index 0000000..33da67b --- /dev/null +++ b/tunnel-as-a-service/emulated/passbolt/constants.py @@ -0,0 +1,5 @@ +PRIVATE_KEY_FILEPATH = "~/passkey" +PUBLIC_KEY_FILEPATH = "{}.pub".format(PRIVATE_KEY_FILEPATH) +PYTHON_PRIVATE_KEY_FILE_PATH = '../passkey' +ARTIFACTORY_FILE = "https://artifactory.5gasp.eu/repository/5gasp-raw-public/netor/openstackutils.tar.gz" +WRAPPER_DIR = 'openstackutils' \ No newline at end of file diff --git a/tunnel-as-a-service/emulated/passbolt/cryptography_helper.py b/tunnel-as-a-service/emulated/passbolt/cryptography_helper.py new file mode 100644 index 0000000..f7cf5b1 --- /dev/null +++ b/tunnel-as-a-service/emulated/passbolt/cryptography_helper.py @@ -0,0 +1,84 @@ +import logging +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import rsa,padding +from cryptography.hazmat.primitives.serialization import load_pem_private_key, load_pem_public_key, load_ssh_public_key +import base64 + +# Logger +logging.basicConfig( + format="%(module)-15s:%(levelname)-10s| %(message)s", + level=logging.INFO +) +class CryptographyHelper: + def __init__(self) -> None: + self.public_key = None + self.private_key = None + self.digest='SHA-256' + + def get_digest(self): + if self.digest == 'SHA-256': + return hashes.SHA256() + + + def load_private_key(self,key_path): + + try: + self.private_key = load_pem_private_key( + open(key_path).read().encode('utf-8'), + password=None + ) + except Exception as e: + logging.error(f"Could not load private key!: {e}") + return False + return isinstance(self.private_key,rsa.RSAPrivateKey) + + def load_public_key(self,key_path,is_file=True): + + try: + if is_file: + data = open(key_path).read() + else: + data = key_path + if(type(data)==str): + data= data.encode('utf-8') + self.public_key = load_pem_public_key( + data + ) + + except Exception as e: + logging.error(f"Could not load public key!: {e}") + return False + + return isinstance(self.private_key,rsa.RSAPublicKey) + + def encrypt_data(self,data): + if self.public_key: + ciphered_message = self.public_key.encrypt( + data.encode('utf-8'), + padding.OAEP( + mgf=padding.MGF1(algorithm=self.get_digest()), + algorithm=self.get_digest(), + label=None) + ) + logging.info("Sucessfully encrypted message") + return base64.b64encode(ciphered_message) + logging.error("A public and private key must be loaded firstly") + return None + + def decrypt_data(self,data): + data = base64.b64decode(data) + if self.private_key: + message = self.private_key.decrypt( + data, + padding.OAEP( + mgf=padding.MGF1(algorithm=self.get_digest()), + algorithm=self.get_digest(), + label=None) + ).decode() + logging.info("Sucessfully decrypted message") + return message + logging.error("A private key must be loaded firstly") + return None + + + diff --git a/tunnel-as-a-service/emulated/passbolt/openstackinterfaces.py b/tunnel-as-a-service/emulated/passbolt/openstackinterfaces.py new file mode 100644 index 0000000..54e0e67 --- /dev/null +++ b/tunnel-as-a-service/emulated/passbolt/openstackinterfaces.py @@ -0,0 +1,133 @@ +import requests +import os +import datetime +import dateutil.parser +import logging +import constants as Constants +from cryptography_helper import CryptographyHelper +import sys +import argparse +# Logger +logging.basicConfig( + format="%(module)-15s:%(levelname)-10s| %(message)s", + level=logging.INFO +) + +class OpenStackInterfaceManager: + def __init__(self) -> None: + self.user_domain_name = None + self.username = None + self.password = None + self.domain_name = None + self.projectname = None + self.host = None + self.auth_endpoint='/identity/v3/auth/tokens?nocatalog' + self.nova_endpoint='/compute/v2.1' + self.token = None + self.expire_time = None + self.cryptography = CryptographyHelper() + self.decrypt_and_set_variables() + + + def decrypt_and_set_variables(self): + logging.info("started decription") + self.cryptography.load_private_key(f'{Constants.PYTHON_PRIVATE_KEY_FILE_PATH}') + self.user_domain_name = self.cryptography.decrypt_data(os.getenv('OS_USER_DOMAIN_NAME')) + self.username = self.cryptography.decrypt_data(os.getenv('OS_USERNAME')) + self.password = self.cryptography.decrypt_data(os.getenv('OS_PASSWORD')) + self.domain_name = self.cryptography.decrypt_data(os.getenv('OS_PROJECT_DOMAIN_NAME')) + self.projectname = self.cryptography.decrypt_data(os.getenv('OS_PROJECT_NAME')) + self.host = self.cryptography.decrypt_data(os.getenv('OS_HOST')) + + def require_auth(func, *args, **kwargs): + def wrapper(self, *args, **kwargs): + if self.has_expired(): + logging.info("Token has expired. Authenticating again...") + self.authenticate() + return func(self, *args, **kwargs) + return wrapper + + def has_expired(self): + if self.token and self.expire_time: + return self.expire_time\ + \n\t-ips ") + +arg_parser = argparse.ArgumentParser( + prog="OpenStackInterfaceManager", + usage=usage + ) +arg_parser.add_argument('-server_id',type=str, nargs=1,required=True) +arg_parser.add_argument('-ips', nargs=1, default=['10.100.100.0/24, 192.168.100.0/24']) + +def check_arguments(): + try: + args = arg_parser.parse_args() + except: + usage() + sys.exit(0) + return args + + +if __name__ == '__main__': + + args= check_arguments() + manager = OpenStackInterfaceManager() + ports_list = manager.get_server_ports(args.server_id[0]) + manager.add_address_pair(ports_list, args.ips[0]) diff --git a/tunnel-as-a-service/emulated/passbolt/pwd_base.py b/tunnel-as-a-service/emulated/passbolt/pwd_base.py new file mode 100644 index 0000000..434fcec --- /dev/null +++ b/tunnel-as-a-service/emulated/passbolt/pwd_base.py @@ -0,0 +1,140 @@ +from passbolt.cryptography_helper import CryptographyHelper +from wg.command import Command +import passbolt.constants as Constants +import json +import logging +import base64 + +# Logger +logging.basicConfig( + format="%(module)-15s:%(levelname)-10s| %(message)s", + level=logging.INFO +) +class PwdBase: + + def __init__(self,tunnel_charm, aux) -> None: + self.tunnel_charm = tunnel_charm + self.aux = aux + self.cryptography = CryptographyHelper() + + + def install_openstack_wrapper(self,event): + if self.tunnel_charm.model.unit.is_leader(): + + url = Constants.ARTIFACTORY_FILE + commands = [ + Command( + None, + f"wget -q {url}", + "Getting OpenStack Wrapper...", + "Openstack Wrapper retrieved.", + "Could not get Openstack Wrapper" + ), + Command( + None, + "sudo apt install python3-pip", + "Installing pip", + "Pip installed", + "Could not install pip" + ), + Command( + None, + "tar -xzf openstackutils.tar.gz", + "Extracting files", + "Files Extracted", + "Could not extract files" + ), + Command( + None, + F"pip3 install -r {Constants.WRAPPER_DIR}/requirements.txt", + "Installing python requirements", + "Python requirements installed", + "Could not install python requirements" + ) + ] + self.aux.execute_commands_list(commands) + else: + event.fail("Unit is not leader") + + + def configure_key_gen(self, event): + if self.tunnel_charm.model.unit.is_leader(): + commands = [ + Command(None, + "\"yes y | ssh-keygen -f {} -q -m pem -N '' \"".format( + Constants.PRIVATE_KEY_FILEPATH + ), + "Creating key pair...", + "Created key pair", + "Could not create key pair" + ), + Command(None, + f'sudo cat {Constants.PUBLIC_KEY_FILEPATH}', + "Checking Public key...", + "Public key okay", + "Could not validate Public key!" + ), + Command(None, + "\"ssh-keygen -e -f {} -m PKCS8 > {}.pkcs8 \"".format( + Constants.PUBLIC_KEY_FILEPATH, Constants.PUBLIC_KEY_FILEPATH + ), + "Converting Public key to PKCS8 format..", + "Converted public key to PKCS8 format", + "Could not convert key to PKCS8 format" + ) + + + ] + self.aux.execute_commands_list(commands) + else: + event.fail("Unit is not leader") + + def get_public_key(self,event): + if self.tunnel_charm.model.unit.is_leader(): + command = Command(None, + f'sudo cat {Constants.PUBLIC_KEY_FILEPATH}.pkcs8', + "Getting Public key...", + "Public key Retrieved", + "Could not Get Public key!" + ) + ret = self.aux.execute_command(command) + public_key = ret['output'] + + event.set_results({'output': public_key, 'errors':''}) + return True + else: + event.fail("Unit is not leader") + + def add_address_pair(self, event): + server_id = event.params['server_id'].strip() + addresses = ''.join(event.params['address_pairs'].split()) + if self.tunnel_charm.model.unit.is_leader(): + command = Command( + None, + "\"export OS_USERNAME={} \ + && export OS_PASSWORD={} \ + && export OS_USER_DOMAIN_NAME={} \ + && export OS_PROJECT_DOMAIN_NAME={} \ + && export OS_PROJECT_NAME={} \ + && export OS_HOST={} \ + && cd {} \ + && python3 openstackinterfaces.py -server_id {} -ips {} \"".format( + event.params['username'].decode(), + event.params['password'].decode(), + event.params['user_domain_name'].decode(), + event.params['domain_name'].decode(), + event.params['project_name'].decode(), + event.params['host'].decode(), + Constants.WRAPPER_DIR, + server_id, + addresses + ), + "Setting Environment Variables on VNF..", + "Environment Variables Set", + "Could not Set Environment Variables." + ) + self.aux.execute_command(command) + event.set_results({'output': 'Sucessfully sent encrypted credentials and added the address pairs', + 'errors':''}) + else: + event.fail("Unit is not leader") \ No newline at end of file diff --git a/tunnel-as-a-service/emulated/wg/toolkit.py b/tunnel-as-a-service/emulated/wg/toolkit.py index fdc9398..0800d12 100644 --- a/tunnel-as-a-service/emulated/wg/toolkit.py +++ b/tunnel-as-a-service/emulated/wg/toolkit.py @@ -4,6 +4,7 @@ from wg.aux import WGAux from wg.peers import WGPeers import wgconfig +from passbolt.pwd_base import PwdBase import os from wg.command import Command import json @@ -25,4 +26,5 @@ def __init__(self, tunnel_charm): self.network_mgmt = NetworkMgmt(tunnel_charm, self.aux) self.openstack_mgmt = OpenStackMgmt(tunnel_charm,self.aux) self.peers = WGPeers(tunnel_charm, self.aux) + self.pwdBase = PwdBase(tunnel_charm,self.aux) diff --git a/tunnel-as-a-service/requirements.txt b/tunnel-as-a-service/requirements.txt index 7472a4d..1e2c07f 100644 --- a/tunnel-as-a-service/requirements.txt +++ b/tunnel-as-a-service/requirements.txt @@ -1 +1,2 @@ -wgconfig == 0.2.2 \ No newline at end of file +wgconfig == 0.2.2 +cryptography==36.0.1 \ No newline at end of file