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))
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']
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)
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))
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)
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()
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
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'] == '*****@*****.**'
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')
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
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()