def ssl_credentials(self): """Get the created SSL channel credentials. For devices with endpoint verification support, if the device certificate loading has any problems, corresponding exceptions will be raised. For a device without endpoint verification support, no exceptions will be raised. Returns: grpc.ChannelCredentials: The created grpc channel credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel creation failed for any reason. """ if self._is_mtls: try: _, cert, key, _ = _mtls_helper.get_client_ssl_credentials() self._ssl_credentials = grpc.ssl_channel_credentials( certificate_chain=cert, private_key=key) except exceptions.ClientCertError as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) six.raise_from(new_exc, caught_exc) else: self._ssl_credentials = grpc.ssl_channel_credentials() return self._ssl_credentials
def test_success(self, mock_popen): mock_popen.return_value = self.create_mock_process( pytest.public_cert_bytes + pytest.private_key_bytes, b"") cert, key = _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA) assert cert == pytest.public_cert_bytes assert key == pytest.private_key_bytes
def test_success(self, mock_popen): mock_popen.return_value = self.create_mock_process( PUBLIC_CERT_BYTES + PRIVATE_KEY_BYTES, b"") cert, key = _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA) assert cert == PUBLIC_CERT_BYTES assert key == PRIVATE_KEY_BYTES
def ssl_credentials(self): """Get the created SSL channel credentials. For devices with endpoint verification support, if the device certificate loading has any problems, corresponding exceptions will be raised. For a device without endpoint verification support, no exceptions will be raised. Returns: grpc.ChannelCredentials: The created grpc channel credentials. Raises: OSError: If the cert provider command launch fails. RuntimeError: If the cert provider command has a runtime error. ValueError: If the context aware metadata file is malformed or if the cert provider command doesn't produce both the client certificate and key. """ if self._context_aware_metadata_path: metadata = _mtls_helper._read_dca_metadata_file( self._context_aware_metadata_path) cert, key = _mtls_helper.get_client_ssl_credentials(metadata) self._ssl_credentials = grpc.ssl_channel_credentials( certificate_chain=cert, private_key=key) else: self._ssl_credentials = grpc.ssl_channel_credentials() return self._ssl_credentials
def ssl_credentials(self): """Get the created SSL channel credentials. For devices with endpoint verification support, if the device certificate loading has any problems, corresponding exceptions will be raised. For a device without endpoint verification support, no exceptions will be raised. Returns: grpc.ChannelCredentials: The created grpc channel credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS channel creation failed for any reason. """ if self._context_aware_metadata_path: try: metadata = _mtls_helper._read_dca_metadata_file( self._context_aware_metadata_path) cert, key = _mtls_helper.get_client_ssl_credentials(metadata) self._ssl_credentials = grpc.ssl_channel_credentials( certificate_chain=cert, private_key=key) except (OSError, RuntimeError, ValueError) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) six.raise_from(new_exc, caught_exc) else: self._ssl_credentials = grpc.ssl_channel_credentials() return self._ssl_credentials
def SSLCredentials(config_path): """Generates the client SSL credentials. Args: config_path: path to the context aware configuration file. Raises: CertProvisionException: if the cert could not be provisioned. ConfigException: if there is an issue in the context aware config. Returns: Tuple[bytes, bytes]: client certificate and private key bytes in PEM format. """ try: ( has_cert, cert_bytes, key_bytes, _ ) = _mtls_helper.get_client_ssl_credentials( generate_encrypted_key=False, context_aware_metadata_path=config_path) if has_cert: return cert_bytes, key_bytes except google_auth_exceptions.ClientCertError as caught_exc: new_exc = CertProvisionException(caught_exc) six.raise_from(new_exc, caught_exc) raise ConfigException()
def test_success_without_metadata(self, mock_check_dca_metadata_path): mock_check_dca_metadata_path.return_value = False has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials( ) assert not has_cert assert cert is None assert key is None assert passphrase is None
def test_success_with_cert_chain(self, mock_popen): PUBLIC_CERT_CHAIN_BYTES = pytest.public_cert_bytes + pytest.public_cert_bytes mock_popen.return_value = self.create_mock_process( PUBLIC_CERT_CHAIN_BYTES + pytest.private_key_bytes, b"") cert, key = _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA) assert cert == PUBLIC_CERT_CHAIN_BYTES assert key == pytest.private_key_bytes
def callback(): try: _, cert_bytes, key_bytes, passphrase_bytes = _mtls_helper.get_client_ssl_credentials( generate_encrypted_key=True ) with open(cert_path, "wb") as cert_file: cert_file.write(cert_bytes) with open(key_path, "wb") as key_file: key_file.write(key_bytes) except (exceptions.ClientCertError, OSError) as caught_exc: new_exc = exceptions.MutualTLSChannelError(caught_exc) six.raise_from(new_exc, caught_exc) return cert_path, key_path, passphrase_bytes
def test_success( self, mock_check_dca_metadata_path, mock_read_dca_metadata_file, mock_run_cert_provider_command, ): mock_check_dca_metadata_path.return_value = True mock_read_dca_metadata_file.return_value = { "cert_provider_command": ["command"] } mock_run_cert_provider_command.return_value = (b"cert", b"key", None) has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials( ) assert has_cert assert cert == b"cert" assert key == b"key" assert passphrase is None
def test_success_with_encrypted_key( self, mock_check_dca_metadata_path, mock_read_dca_metadata_file, mock_run_cert_provider_command, ): mock_check_dca_metadata_path.return_value = True mock_read_dca_metadata_file.return_value = { "cert_provider_command": ["command"] } mock_run_cert_provider_command.return_value = (b"cert", b"key", b"passphrase") has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials( generate_encrypted_key=True) assert has_cert assert cert == b"cert" assert key == b"key" assert passphrase == b"passphrase" mock_run_cert_provider_command.assert_called_once_with( ["command", "--with_passphrase"], expect_encrypted_key=True)
def EncryptedSSLCredentials(config_path): """Generates the encrypted client SSL credentials. The encrypted client SSL credentials are stored in a file which is returned along with the password. Args: config_path: path to the context aware configuration file. Raises: CertProvisionException: if the cert could not be provisioned. ConfigException: if there is an issue in the context aware config. Returns: Tuple[str, bytes]: cert and key file path and passphrase bytes. """ try: ( has_cert, cert_bytes, key_bytes, passphrase_bytes ) = _mtls_helper.get_client_ssl_credentials( generate_encrypted_key=True, context_aware_metadata_path=config_path) if has_cert: cert_path = os.path.join( config.Paths().global_config_dir, 'caa_cert.pem') with files.BinaryFileWriter(cert_path) as f: f.write(cert_bytes) f.write(key_bytes) return cert_path, passphrase_bytes except google_auth_exceptions.ClientCertError as caught_exc: new_exc = CertProvisionException(caught_exc) six.raise_from(new_exc, caught_exc) except files.Error as e: log.debug('context aware settings discovery file %s - %s', config_path, e) raise ConfigException()
def test_customize_context_aware_metadata_path( self, mock_check_dca_metadata_path, mock_read_dca_metadata_file, mock_run_cert_provider_command, ): context_aware_metadata_path = "/path/to/metata/data" mock_check_dca_metadata_path.return_value = context_aware_metadata_path mock_read_dca_metadata_file.return_value = { "cert_provider_command": ["command"] } mock_run_cert_provider_command.return_value = (b"cert", b"key", None) has_cert, cert, key, passphrase = _mtls_helper.get_client_ssl_credentials( context_aware_metadata_path=context_aware_metadata_path) assert has_cert assert cert == b"cert" assert key == b"key" assert passphrase is None mock_check_dca_metadata_path.assert_called_with( context_aware_metadata_path) mock_read_dca_metadata_file.assert_called_with( context_aware_metadata_path)
def test_missing_cert_command(self, mock_check_dca_metadata_path, mock_read_dca_metadata_file): mock_check_dca_metadata_path.return_value = True mock_read_dca_metadata_file.return_value = {} with pytest.raises(exceptions.ClientCertError): _mtls_helper.get_client_ssl_credentials()
def test_missing_key(self, mock_popen): mock_popen.return_value = self.create_mock_process( PUBLIC_CERT_BYTES, b"") with pytest.raises(ValueError): assert _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA)
def test_missing_cert_provider_command(self): with pytest.raises(ValueError): assert _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA_NO_CERT_PROVIDER_COMMAND)
def test_popen_raise_exception(self, mock_popen): mock_popen.side_effect = OSError() with pytest.raises(OSError): assert _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA)
def test_cert_provider_returns_error(self, mock_popen): mock_popen.return_value = self.create_mock_process(b"", b"some error") mock_popen.return_value.returncode = 1 with pytest.raises(RuntimeError): assert _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA)
def test_missing_cert(self, mock_popen): mock_popen.return_value = self.create_mock_process( pytest.private_key_bytes, b"") with pytest.raises(ValueError): assert _mtls_helper.get_client_ssl_credentials( CONTEXT_AWARE_METADATA)