Beispiel #1
0
def test_show(capsys):
    process('certgen --show')
    out, err = capsys.readouterr()
    assert not err
    out_lines = out.splitlines()
    assert out_lines[0] == 'Created the self-signed certificate {!r}'.format(get_default_cert_path())
    assert not out_lines[1]
    assert out_lines[2] == 'Version: v3'
    assert out_lines[-2] == 'Fingerprint (SHA1):'
    assert out_lines[-1] == get_fingerprint(load_certificate(get_default_cert_path()))
Beispiel #2
0
def test_password(capsys):
    key_file = os.path.join(tempfile.gettempdir(), 'key.private')
    generate_key(path=key_file, password='******')

    process('certgen --key-file {} --key-file-password the password'.format(key_file))
    out, err = capsys.readouterr()
    assert out.rstrip() == 'Created the self-signed certificate {!r}'.format(get_default_cert_path())
    assert not err

    os.remove(key_file)
Beispiel #3
0
def test_defaults():
    # do not specify any kwargs
    remove_files()
    assert not os.path.isfile(cryptography.get_default_key_path())
    assert not os.path.isfile(cryptography.get_default_cert_path())

    # a private key will automatically be created
    cert_path = cryptography.generate_certificate()
    assert os.path.isfile(cryptography.get_default_key_path())
    assert cert_path == cryptography.get_default_cert_path()

    cert = cryptography.load_certificate(cert_path)
    assert isinstance(cert, cryptography.x509.Certificate)

    meta = cryptography.get_metadata(cert)
    assert meta['issuer']['common_name'] == HOSTNAME
    assert meta['subject']['common_name'] == HOSTNAME
    assert meta['key']['encryption'] == 'RSA'
    assert meta['key']['exponent'] == 65537
    assert meta['key']['size'] == 2048
Beispiel #4
0
def test_fingerprint():
    cryptography.generate_key()
    cryptography.generate_certificate()
    cert = cryptography.load_certificate(cryptography.get_default_cert_path())

    # don't care about the fingerprint value
    # test that calling the function does not raise an exception
    cryptography.get_fingerprint(cert)
    cryptography.get_fingerprint(cert, algorithm='SHA1')
    cryptography.get_fingerprint(cert, algorithm=cryptography.hashes.SHA1())
    cryptography.get_fingerprint(cert, algorithm='blake2s', digest_size=32)
    cryptography.get_fingerprint(cert, algorithm=cryptography.hashes.BLAKE2b(64))
Beispiel #5
0
def remove_files():
    filename = 'msl-network-testing'
    key_path = os.path.join(tempfile.gettempdir(), filename + '.key')
    cert_path = os.path.join(tempfile.gettempdir(), filename + '.crt')

    paths = [
        cryptography.get_default_key_path(),
        cryptography.get_default_cert_path(),
        key_path,
        cert_path
    ]

    for p in paths:
        try:
            os.remove(p)
        except FileNotFoundError:
            pass
        assert not os.path.isfile(p)
    return key_path, cert_path
Beispiel #6
0
def test_password_file(capsys):
    pw_file = os.path.join(tempfile.gettempdir(), 'password.tmp')
    pw = 'the password'
    with open(pw_file, mode='wt') as fp:
        fp.write(pw)

    key_file = os.path.join(tempfile.gettempdir(), 'key.private')
    generate_key(path=key_file, password=pw)

    process('certgen --key-file {} --key-file-password {}'.format(key_file, pw_file))
    out, err = capsys.readouterr()
    assert not err
    assert out.splitlines() == [
        'Reading the key password from the file',
        'Created the self-signed certificate {!r}'.format(get_default_cert_path())
    ]

    os.remove(pw_file)
    os.remove(key_file)
Beispiel #7
0
def test_algorithm(capsys):
    process('certgen --algorithm SHA512')
    out, err = capsys.readouterr()
    assert out.rstrip() == 'Created the self-signed certificate {!r}'.format(get_default_cert_path())
    assert not err
Beispiel #8
0
class Manager(object):

    key_file = cryptography.get_default_key_path()
    cert_file = cryptography.get_default_cert_path()
    database = os.path.join(home, 'testing.db')
    log_file = os.path.join(home, 'testing.log')

    def __init__(self,
                 *service_classes,
                 disable_tls=False,
                 password_manager=None,
                 auth_login=True,
                 auth_hostname=False,
                 cert_common_name=None,
                 add_heartbeat_task=False,
                 read_limit=None,
                 **kwargs):
        """Starts the Network Manager and all specified Services to use for testing.

        Parameters
        ----------
        service_classes
            The Service sub-classes to start (they have NOT been instantiated).
        **kwargs
            These are all sent to Service.__init__ for all `service_classes`.
        """
        self.port = self.get_available_port()
        self.auth_hostname = auth_hostname
        self.auth_login = auth_login
        self.disable_tls = disable_tls
        self._manager_proc = None

        self.remove_files()

        key_pw = 'dummy pw!'  # use a password for the key.. just for fun
        cryptography.generate_key(path=self.key_file,
                                  password=key_pw,
                                  algorithm='ecc')
        cryptography.generate_certificate(path=self.cert_file,
                                          key_path=self.key_file,
                                          key_password=key_pw,
                                          name=cert_common_name)

        # need a UsersTable with an administrator to be able to shutdown the Manager
        ut = UsersTable(database=self.database)
        self.admin_username, self.admin_password = '******', 'whatever'
        ut.insert(self.admin_username, self.admin_password, True)
        ut.close()

        # a convenience dictionary for connecting to the Manager as a Service or a Client
        self.kwargs = {
            'username': self.admin_username,
            'password': self.admin_password,
            'port': self.port,
            'cert_file': self.cert_file,
            'disable_tls': disable_tls,
            'password_manager': password_manager,
            'read_limit': read_limit,
        }

        # start the Network Manager in a subprocess
        command = [
            sys.executable, '-c', 'from msl.network import cli; cli.main()',
            'start', '-p',
            str(self.port), '-c', self.cert_file, '-k', self.key_file, '-D',
            key_pw, '-d', self.database, '-l', self.log_file
        ]
        if disable_tls:
            command.append('--disable-tls')
        if password_manager:
            command.extend(['-P', password_manager])
        elif auth_hostname:
            command.append('--auth-hostname')
        elif auth_login:
            command.append('--auth-login')

        # start the Network Manager
        self._manager_proc = subprocess.Popen(command)
        self.wait_start(self.port, 'Cannot start Manager')

        # start all Services
        self._service_threads = {}
        if service_classes:
            cxn = connect(**self.kwargs)
            for cls in service_classes:
                name = cls.__name__
                service = cls(**kwargs)
                if add_heartbeat_task and name == 'Heartbeat':
                    service.add_tasks(service.emit())
                thread = Thread(target=service.start,
                                kwargs=self.kwargs,
                                daemon=True)
                thread.start()
                t0 = time.time()
                while True:
                    time.sleep(0.1)
                    services = cxn.identities()['services']
                    if name in services:
                        break
                    if time.time() - t0 > 30:
                        in_use = self.is_port_in_use(service.port)
                        self.shutdown(cxn)
                        raise RuntimeError('Cannot start {0} service.\n'
                                           'Is Service port in use? {1}\n'
                                           '{0}.start kwargs: {2}\n'
                                           'Services: {3}'.format(
                                               name, in_use, self.kwargs,
                                               services))
                self._service_threads[service] = thread
            cxn.disconnect()

    def shutdown(self, connection=None):
        # shutdown the Manager and delete the dummy files that were created
        if connection is None:
            connection = connect(**self.kwargs)

        connection.admin_request('shutdown_manager')
        self._manager_proc.communicate(timeout=5)

        # self.wait_shutdown(connection.port, '{} will not shutdown'.format(connection))
        # for service, thread in self._service_threads.items():
        #     self.wait_shutdown(service.port, '{} will not shutdown'.format(service))

        self.remove_files()

    def __del__(self):
        if self._manager_proc is not None:
            self._manager_proc.terminate()
            self._manager_proc = None

    @staticmethod
    def wait_start(port, message):
        start_time = time.time()
        while not Manager.is_port_in_use(port):
            if time.time() - start_time > 30:
                raise RuntimeError(message)
            time.sleep(0.1)
        time.sleep(1)

    @staticmethod
    def wait_shutdown(port, message):
        start_time = time.time()
        while Manager.is_port_in_use(port):
            if time.time() - start_time > 30:
                raise RuntimeError(message)
            time.sleep(0.1)

    @staticmethod
    def is_port_in_use(port):
        if port is None:
            return False
        if sys.platform == 'darwin':
            cmd = ['lsof', '-nP', '-iTCP:%d' % port]
        else:
            cmd = ['netstat', '-an']
        p = subprocess.Popen(cmd,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        out, _ = p.communicate()
        return out.find(b':%d ' % port) > 0

    @staticmethod
    def get_available_port():
        with socket() as sock:
            sock.bind(('', 0))  # get any available port
            return sock.getsockname()[1]

    @staticmethod
    def remove_files():
        files = (Manager.key_file, Manager.cert_file, Manager.database,
                 Manager.log_file)
        for file in files:
            try:
                os.remove(file)
            except OSError:
                pass