예제 #1
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))
예제 #2
0
def test_rsa(kwargs):
    key_file, cert_file = remove_files()

    out = cryptography.generate_key(
        path=key_file, password=kwargs['password'], size=kwargs['size']
    )
    assert out == key_file

    out = cryptography.generate_certificate(
        path=cert_file, key_path=key_file, key_password=kwargs['password'],
        algorithm=kwargs['algorithm'], years_valid=kwargs['years_valid'],
    )
    assert out == cert_file

    cert = cryptography.load_certificate(cert_file)
    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'] == kwargs['size']
    assert meta['fingerprint'] == cryptography.get_fingerprint(cert)
    duration = meta['valid_to'].year - meta['valid_from'].year
    if kwargs['years_valid'] is None:
        assert duration == DEFAULT_YEARS_VALID
    else:
        assert duration == kwargs['years_valid']
예제 #3
0
def test_get_metadata_as_string():
    cert = cryptography.load_certificate(cryptography.generate_certificate())
    string = cryptography.get_metadata_as_string(cert)
    assert re.search(r'Encryption: RSA', string)
    assert re.search(r'Size: 2048', string)
    assert re.search(r'Common Name: {}'.format(HOSTNAME), string)
    assert re.search(cryptography.get_fingerprint(cert), string)
예제 #4
0
def test_stdout(capsys):
    path = generate_certificate()
    process('certdump {}'.format(path))
    out, err = capsys.readouterr()
    out_lines = out.splitlines()
    assert not err
    assert out_lines[0] == 'Version: v3'
    assert out_lines[-2] == 'Fingerprint (SHA1):'
    assert out_lines[-1] == get_fingerprint(load_certificate(path))
예제 #5
0
def test_file(capsys):
    tmp = os.path.join(tempfile.gettempdir(), 'out.tmp')
    path = generate_certificate()
    process('certdump {} --out {}'.format(path, tmp))
    out, err = capsys.readouterr()
    assert out.rstrip() == 'Dumped the certificate details to ' + tmp
    assert not err

    with open(tmp, mode='rt') as fp:
        lines = [line.rstrip() for line in fp.readlines()]

    assert lines[0] == 'Certificate details for {}'.format(path)
    assert lines[1] == 'Version: v3'
    assert lines[-2] == 'Fingerprint (SHA1):'
    assert lines[-1] == get_fingerprint(load_certificate(path))

    os.remove(tmp)
예제 #6
0
def test_wrong_certificate():
    manager = conftest.Manager()
    key = os.path.join(tempfile.gettempdir(), '.msl', 'wrong-certificate.key')
    cert = os.path.join(tempfile.gettempdir(), '.msl', 'wrong-certificate.crt')
    assert cryptography.generate_key(path=key) == key
    assert cryptography.generate_certificate(path=cert, key_path=key) == cert
    kwargs = manager.kwargs.copy()
    kwargs['cert_file'] = cert
    with pytest.raises(ConnectionError) as e:
        connect(**kwargs)
    msg = str(e.value)
    assert 'Perhaps the Network Manager is using a new certificate' in msg
    assert '{}:{}'.format(constants.HOSTNAME, kwargs['port']) in msg
    assert 'wrong-certificate.crt' in msg
    os.remove(key)
    os.remove(cert)
    manager.shutdown()
예제 #7
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
예제 #8
0
def test_custom_subject_name():
    a = cryptography.x509.NameAttribute
    o = cryptography.x509.NameOID
    name = cryptography.x509.Name([
        a(o.COUNTRY_NAME, 'ZZ'),
        a(o.STATE_OR_PROVINCE_NAME, 'Here'),
        a(o.LOCALITY_NAME, 'City'),
        a(o.ORGANIZATION_NAME, 'ORG'),
        a(o.COMMON_NAME, 'MSLNZ12345'),
        a(o.EMAIL_ADDRESS, '*****@*****.**'),
    ])

    cert_path = cryptography.generate_certificate(name=name)
    meta = cryptography.get_metadata(cryptography.load_certificate(cert_path))
    assert meta['issuer'] == meta['subject']
    assert meta['subject']['country_name'] == 'ZZ'
    assert meta['subject']['state_or_province_name'] == 'Here'
    assert meta['subject']['locality_name'] == 'City'
    assert meta['subject']['organization_name'] == 'ORG'
    assert meta['subject']['common_name'] == 'MSLNZ12345'
    assert meta['subject']['email_address'] == '*****@*****.**'
예제 #9
0
def test_raises():
    for value in ['', 'invalid']:
        match = r'The encryption algorithm must be RSA, DSA or ECC'
        with pytest.raises(ValueError, match=match):
            cryptography.generate_key(algorithm=value)

        match = r'Invalid curve name {!r}'.format(value.upper())
        with pytest.raises(ValueError, match=match):
            cryptography.generate_key(algorithm='ECC', curve=value)

        match = r'Invalid hash algorithm {!r}'.format(value.upper())
        with pytest.raises(ValueError, match=match):
            cryptography.generate_certificate(algorithm=value)

    for obj in [None, True, set(), dict(), tuple(), 2, 1.2, 8j]:
        with pytest.raises(TypeError, match=r'The "cert" parameter must be a string or bytes'):
            cryptography.load_certificate(obj)
        with pytest.raises(TypeError, match=r'must be a string or HashAlgorithm instance'):
            cryptography.generate_certificate(algorithm=None)

    with pytest.raises(ValueError, match=r'Digest size must be \d+'):
        cryptography.generate_certificate(algorithm='BLAKE2b')
예제 #10
0
def test_years_valid_fractional():
    cert_path = cryptography.generate_certificate(years_valid=7.4)
    meta = cryptography.get_metadata(cryptography.load_certificate(cert_path))
    # this approximate calculation should be good enough to within a few days
    assert abs((meta['valid_to'] - meta['valid_from']).days - 7.4 * 365) < 5
예제 #11
0
    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()