def test_smtp_login_expect_reject(self):
        message = EmailMessage()
        message["From"] = "*****@*****.**"
        message["To"] = "*****@*****.**"
        message["Subject"] = "Test"

        machine: pb.SshMachine = pb.SshMachine(host="remote.example.com",
                                               user="******",
                                               keyfile="~/.ssh/id_rsa")
        server = DeployedServer(machine)
        connection: rpyc.Connection = server.classic_connect()

        with connection.modules.smtplib.SMTP("mail.example.com") as smtp:
            with self.assertRaises(smtplib.SMTPNotSupportedError) as e:
                smtp.login(user="******", password="******")
                smtp.send_message(message,
                                  from_addr="*****@*****.**",
                                  to_addrs="*****@*****.**")
            self.assertIn("SMTP AUTH extension not supported by server",
                          str(e.exception),
                          msg=str(e.exception))

        connection.close()
        server.close()
        machine.close()
    def test_login_mailaddress_starttls_wrong_credentials_expect_rejected(
            self):
        message = EmailMessage()
        message["From"] = "*****@*****.**"
        message["To"] = "*****@*****.**"
        message["Subject"] = "Test"

        machine: pb.SshMachine = pb.SshMachine(host="remote.example.com",
                                               user="******",
                                               keyfile="~/.ssh/id_rsa")
        server = DeployedServer(machine)
        connection: rpyc.Connection = server.classic_connect()

        with connection.modules.smtplib.SMTP("mail.example.com", 587) as smtp:
            smtp.starttls()

            with self.assertRaises(smtplib.SMTPAuthenticationError) as e:
                smtp.login(user="******", password="******")
            self.assertIn("Error: authentication failed",
                          str(e.exception),
                          msg=str(e.exception))

        connection.close()
        server.close()
        machine.close()
def mapleDeployment(host, loacalMaple, loaclMapleHandler, loaclMapleDataMerger,
                    loaclGetDestination):
    # create the deployment
    mach = SshMachine(host,
                      user="******",
                      keyfile="/home/zitongc2/.ssh/id_rsa")
    server = DeployedServer(mach)

    # and now you can connect to it the usual way
    conn = server.classic_connect()
    print("[INFO] Connected to ", host)
    conn._config['sync_request_timeout'] = None

    def getResult(string):
        print(string)

    remoteMaple = conn.teleport(loacalMaple)
    remoteMapleHandler = teleport_function(conn, loaclMapleHandler)
    remoteMapleHandler(remoteMaple, "/home/zitongc2/test/phase0/input",
                       getResult)

    # print("[INFO] Done processing, now sendind result to desinated location")
    remoteMapleDataMerger = teleport_function(conn, loaclMapleDataMerger)
    remoteMapleDataMerger(loaclGetDestination)

    # when you're done - close the server and everything will disappear
    print("[INFO] done")
    server.close()
Example #4
0
class SshHost(BaseHost):
    def __init__(self, **kwargs):
        BaseHost.__init__(self, **kwargs)
        self._mach = None
        self.deployment = None
    def connect(self):
        if self.deployment is None:
            self._mach = SshMachine(**self.kwargs)
            self.deployment = DeployedServer(self._mach)
        return self.deployment.classic_connect()
    def close(self):
        if self.deployment is not None:
            self.deployment.close()
            self._mach.close()
Example #5
0
    def create_remote_node(self,
                           hostname,
                           username,
                           keyfile,
                           ntype,
                           addr,
                           config=None):
        if config is None:
            config = {}
        remote_machine = SshMachine(host=hostname,
                                    user=username,
                                    keyfile=keyfile)
        remote_server = DeployedServer(remote_machine)
        conn = remote_server.classic_connect()
        site = conn.modules.site
        python_pkg_path = site.getsitepackages()[0]
        # if `asgrids` wasn't available remotely, now we installed it
        # but we need to reconnect to get an updated conn.modules
        # TODO Might not be needed if using execute/eval
        if not self.check_remote(remote_server, python_pkg_path):
            remote_server.close()
            remote_server = DeployedServer(remote_machine)

        self.remote_machines.append(remote_machine)
        self.remote_servers.append(remote_server)
        conn = remote_server.classic_connect()
        serving_thread = BgServingThread(conn)
        self.server_threads.append(serving_thread)
        self.conns[addr] = conn

        # Using execute/eval allows working on a remote single namespace
        # useful when teleporting functions that need using remote object names
        # as using conn.modules create a locate but not a remote namespace member
        if ntype is 'load':
            conn.execute("from asgrids import NetworkLoad")
            conn.execute("node=NetworkLoad()")
            conn.execute("node.local='{}'".format(addr))
            node = conn.namespace['node']
        elif ntype is 'allocator':
            conn.execute("from asgrids import NetworkAllocator")
            conn.execute("node=NetworkAllocator()")
            node = conn.namespace['node']
        else:
            raise ValueError("Can't handle ntype == {}".format(ntype))
        self.nodes[addr] = node

        # Return node netref object and rpyc connection
        return node, conn
Example #6
0
class SshHost(BaseHost):
    def __init__(self, **kwargs):
        BaseHost.__init__(self, **kwargs)
        self._mach = None
        self.deployment = None

    def connect(self):
        if self.deployment is None:
            self._mach = SshMachine(**self.kwargs)
            self.deployment = DeployedServer(self._mach)
        return self.deployment.classic_connect()

    def close(self):
        if self.deployment is not None:
            self.deployment.close()
            self._mach.close()
Example #7
0
class RPyCConnection(BaseConnection):
    """RPyC wrapper for component connection.

    In case the machine doesn't already run SlaveService, we will try to use SSH to upload and
    deploy RPyC SlaveService.
    """
    def __init__(self,
                 hostname: str,
                 username: Optional[str] = None,
                 password: Optional[str] = None) -> None:
        """Connects (or start with SSH if needed) to RPyC remote SlaveService.

        Connect to RPyC SlaveService on remote machine. If the service isn't running, try
        to deploy it with SSHConnection and RPyC zero deploy library.

        Args:
            hostname: The hostname of the component we want to connect to.
            username: Username for SSH login (if needed).
            password: Password for SSH login (if needed).
        """

        self._server = None
        try:
            # Checks if the machine already runs RPyC SlaveService.
            self._connection = rpyc.classic.connect(hostname, keepalive=True)
        except ConnectionRefusedError:
            if username is None or password is None:
                # Not given necessary SSH credentials.
                raise

            with SSHConnection(hostname, username, password) as ssh:
                # Upload RPyC and start SlaveService in a temporarily directory.
                self._server = DeployedServer(ssh.shell)  # pylint: disable=no-member
                self._connection = self._server.classic_connect()

    @property
    def rpyc(self) -> rpyc.Connection:
        """The RPyc connection to component."""

        return self._connection

    def close(self) -> None:
        """Closes RPyC connections."""

        self._connection.close()
        if self._server is not None:
            self._server.close()
    def test_login_username_smtps_expect_pass(self):
        message = EmailMessage()
        message["From"] = "*****@*****.**"
        message["To"] = "*****@*****.**"
        message["Subject"] = "Test"

        machine: pb.SshMachine = pb.SshMachine(host="remote.example.com",
                                               user="******",
                                               keyfile="~/.ssh/id_rsa")
        server = DeployedServer(machine)
        connection: rpyc.Connection = server.classic_connect()

        with connection.modules.smtplib.SMTP_SSL("mail.example.com",
                                                 465) as smtp:
            smtp.login(user="******", password="******")

        connection.close()
        server.close()
        machine.close()
Example #9
0
def juiceDeployment(host, loacalJuice, loaclJuiceHandler,
                    localJuiceDataMerger):
    # create the deployment
    mach = SshMachine(host,
                      user="******",
                      keyfile="/home/zitongc2/.ssh/id_rsa")
    server = DeployedServer(mach)

    # and now you can connect to it the usual way
    conn = server.classic_connect()
    print("[INFO] Connected to ", host)
    conn._config['sync_request_timeout'] = None

    remoteJuice = conn.teleport(loacalJuice)
    remoteMapleHandler = teleport_function(conn, loaclJuiceHandler)
    remoteMapleHandler(remoteJuice)

    print("[INFO] Done processing, now sendind result to desinated location")
    remoteJuiceDataMerger = teleport_function(conn, localJuiceDataMerger)
    remoteJuiceDataMerger(socket.gethostbyname(socket.gethostname()))

    # when you're done - close the server and everything will disappear
    server.close()
    def test_logged_out_starttls_expect_client_host_rejected(self):
        message = EmailMessage()
        message["From"] = "*****@*****.**"
        message["To"] = "*****@*****.**"
        message["Subject"] = "Test"

        machine: pb.SshMachine = pb.SshMachine(host="remote.example.com",
                                               user="******",
                                               keyfile="~/.ssh/id_rsa")
        server = DeployedServer(machine)
        connection: rpyc.Connection = server.classic_connect()

        with connection.modules.smtplib.SMTP("mail.example.com", 587) as smtp:
            smtp.starttls()
            with self.assertRaises(smtplib.SMTPRecipientsRefused) as e:
                smtp.send_message(message,
                                  from_addr="*****@*****.**",
                                  to_addrs="*****@*****.**")
            self.assertIn("Client host rejected: Access denied",
                          str(e.exception))

        connection.close()
        server.close()
        machine.close()
Example #11
0
class Controller:
    """
    Stores connection variables and perfoms
    monitoring and data syncing functions
    """

    def __init__(self, username, ipaddress):
        # Connection Parameters
        self.user      = username
        self.ip        = ipaddress
        # Connection Resources
        self.nxTunnel  = None
        self.nxServer  = None
        self.nxConnA   = None
        self.nxConnB   = None
        self.rest      = vellosREST(ipaddress)
        # Extend logger of parent script importing this module
        self.logger = logging.getLogger('vBrokerLog.controller.Controller')
        # Resources local to controller
        self.pdb = '/var/lib/pdb/pdb-rest.db'
        # Flag when monitored proc/s or system has failed
        self.has_failed = Event()

    def __enter__(self):
        self.connect()

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()

    def to_dict(self):
        """Return dict of crucial attributes"""
        controller_dict = {
                'user_name' : self.user,
                'ip_address': self.ip
                }
        return controller_dict

    def _execute(self, cmd):
        """Execute shell command """
        try:
            if self.is_connected():
                self.nxConnA.modules.subprocess.check_call(cmd)
            else:
                return False
        except subprocess.CalledProcessError:
            return False

        return True
    
    def connect(self):
        """Initiate ssh tunnel & rpyc server"""
        self.logger.info('Opening connection @%s'%self.ip)
        try:
            with RLock():
                self.nxTunnel = SshMachine(self.ip,self.user)
                self.nxServer = DeployedServer(self.nxTunnel)
                self.nxConnA  = self.nxServer.classic_connect()
                self.nxConnB  = self.nxServer.classic_connect()
        except Exception:
            self.logger.error('Failed opening @%s' % self.ip)
        self.logger.info('Successfully connected @%s'%self.ip)

    def close(self):
        """Close ssh tunnel % destroy rpyc server"""
        self.logger.info('Closing connection @%s'%self.ip)
        try:
            self.nxServer.close()
        except Exception as e:
            self.logger.error('Failed closing @%s - %s'%(self.ip,e))

    def is_connected(self):
        """Test if ssh tunnel & rpyc connection is active"""
        try:
            with RLock():
                self.nxConnA.ping()
                #self.nxConnB.ping()
        except:
            return False
        return True

    def ping(self):
        """Ping controller"""
        cmd = ['ping','-c','1',self.ip]
        try:
            self.logger.info('Pinging @%s'%self.ip)
            with open(os.devnull, 'w') as devnull:
                subprocess.check_call(cmd,stdout=devnull)
        except:
            self.logger.error('Failed to ping @%s'%self.ip)
            return False
        return True

    def assert_connection(self):
        """Monitor connection, attempt reconnect if down"""
        if not self.is_connected():
            self.logger.error('lost connection @%s'%self.ip)
            if self.ping():
                self.logger.info('ping @%s succeeded'% self.ip)
                try:
                    if not self.is_connected():
                        self.logger.debug('still not connected')
                        self.close()
                        self.connect()
                    self.logger.debug('connection found')
                    self.control_plane_down()
                except:
                    with RLock():
                        self.has_failed.set()
                        return False
                    self.logger.error('reconnect @%s fail'% self.ip)
            else:
                with RLock():
                    self.has_failed.set()
                    return False
        else:
            return True

    def monitor(self, procs, interval, kill_monitor):
        """Monitor processes and exit if failure"""
        watch = Watch(
                self,
                procs, 
                interval, 
                kill_monitor, 
                self.has_failed
                )
        watch.run()

    def sync(self, dst, event):
        """Sync pdb-rest.db to to local target"""
        pdbsync = Sync(
                self, 
                dst, 
                event)
        pdbsync.run()

    def restore(self, nodes, flows):
        """Install data using REST, ignore if error"""
        self.logger.info('Restoring nodes @%s'%self.ip)
        for node_id, node in nodes.iteritems():
            snode = json.dumps(node)
            try:
                self.logger.debug('Installing node: %s'%snode)
                self.rest.putNode(node_id, snode)
            except Exception as e:
                self.logger.debug('%s - %s'%(node_id,e))
                pass
        self.logger.info('Restoring flows @%s'%self.ip)
        for flow_id, flow in flows.iteritems():
            sflow = json.dumps(flow)
            try:
                self.logger.debug('Installing flow: %s'%sflow)
                self.rest.putFlow(flow_id, json.dumps(flow))
            except Exception as e:
                self.logger.error('%s - %s'%(flow_id,e))
                pass
        return True

    def remove(self, nodes, flows):
        """Remove data using REST, ignore if error"""
        self.logger.info('Removing data @%s'%self.ip)
        for flow_id, flow in flows.iteritems():
            sflow = json.dumps(flow)
            try:
                self.logger.debug('Removing flow: %s'%sflow)
                self.rest.deleteFlow(flow_id)
            except Exception as e:
                self.logger.error('%s - %s'%(flow_id,e))
                pass
        for node_id, node in nodes.iteritems():
            snode = json.dumps(node)
            try:
                self.logger.debug('Removing node: %s'%snode)
                self.rest.deleteNode(node_id)
            except Exception as e:
                self.logger.error('%s - %s'%(node_id,e))
                pass
        return True

    def diff_switches(self, switches):
        """Diff passed in switches with ones in inventory"""
        self.logger.info('Diffing Switches @%s'%self.ip)
        try:
            active_switches = self.rest.getSwitchNames()['items']
        except Exception as e:
            self.logger.error('Could not get switches: %s'%e)
        return set(switches) <= set(active_switches)

    def control_plane_up(self):
        """Bring control plane interface up"""
        self.logger.info('Bringing up br0 @%s'%self.ip)
        up_cmd = ['/sbin/ifconfig', 'br0', 'up']
        return self._execute(up_cmd)

    def control_plane_down(self):
        """Bring control plane interface down"""
        self.logger.info('Bringing down br0 @%s'%self.ip)
        down_cmd = ['/sbin/ifconfig', 'br0', 'down']
        return self._execute(down_cmd)