Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

feat: add client_cert_source_for_mtls parameter to grpc transport #114

Merged
merged 9 commits into from Mar 17, 2021
Expand Up @@ -94,8 +94,36 @@ class DataTransferServiceAsyncClient:
DataTransferServiceClient.parse_common_location_path
)

from_service_account_info = DataTransferServiceClient.from_service_account_info
from_service_account_file = DataTransferServiceClient.from_service_account_file
@classmethod
def from_service_account_info(cls, info: dict, *args, **kwargs):
"""Creates an instance of this client using the provided credentials info.

Args:
info (dict): The service account private key info.
args: Additional arguments to pass to the constructor.
kwargs: Additional arguments to pass to the constructor.

Returns:
DataTransferServiceAsyncClient: The constructed client.
"""
return DataTransferServiceClient.from_service_account_info.__func__(DataTransferServiceAsyncClient, info, *args, **kwargs) # type: ignore

@classmethod
def from_service_account_file(cls, filename: str, *args, **kwargs):
"""Creates an instance of this client using the provided credentials
file.

Args:
filename (str): The path to the service account private key json
file.
args: Additional arguments to pass to the constructor.
kwargs: Additional arguments to pass to the constructor.

Returns:
DataTransferServiceAsyncClient: The constructed client.
"""
return DataTransferServiceClient.from_service_account_file.__func__(DataTransferServiceAsyncClient, filename, *args, **kwargs) # type: ignore

from_service_account_json = from_service_account_file

@property
Expand Down
Expand Up @@ -328,21 +328,17 @@ def __init__(
util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"))
)

ssl_credentials = None
client_cert_source_func = None
is_mtls = False
if use_client_cert:
if client_options.client_cert_source:
import grpc # type: ignore

cert, key = client_options.client_cert_source()
ssl_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)
is_mtls = True
client_cert_source_func = client_options.client_cert_source
else:
creds = SslCredentials()
is_mtls = creds.is_mtls
ssl_credentials = creds.ssl_credentials if is_mtls else None
is_mtls = mtls.has_default_client_cert_source()
client_cert_source_func = (
mtls.default_client_cert_source() if is_mtls else None
)

# Figure out which api endpoint to use.
if client_options.api_endpoint is not None:
Expand Down Expand Up @@ -385,7 +381,7 @@ def __init__(
credentials_file=client_options.credentials_file,
host=api_endpoint,
scopes=client_options.scopes,
ssl_channel_credentials=ssl_credentials,
client_cert_source_for_mtls=client_cert_source_func,
quota_project_id=client_options.quota_project_id,
client_info=client_info,
)
Expand Down
Expand Up @@ -15,7 +15,16 @@
# limitations under the License.
#

from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple
from typing import (
Any,
AsyncIterable,
Awaitable,
Callable,
Iterable,
Sequence,
Tuple,
Optional,
)

from google.cloud.bigquery_datatransfer_v1.types import datatransfer
from google.cloud.bigquery_datatransfer_v1.types import transfer
Expand Down
Expand Up @@ -62,6 +62,7 @@ def __init__(
api_mtls_endpoint: str = None,
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
ssl_channel_credentials: grpc.ChannelCredentials = None,
client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None,
quota_project_id: Optional[str] = None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
Expand Down Expand Up @@ -92,6 +93,10 @@ def __init__(
``api_mtls_endpoint`` is None.
ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
for grpc channel. It is ignored if ``channel`` is provided.
client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
A callback to provide client certificate bytes and private key bytes,
both in PEM format. It is used to configure mutual TLS channel. It is
ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
Expand All @@ -108,6 +113,11 @@ def __init__(
"""
self._ssl_channel_credentials = ssl_channel_credentials

if api_mtls_endpoint:
warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
if client_cert_source:
warnings.warn("client_cert_source is deprecated", DeprecationWarning)

if channel:
# Sanity check: Ensure that channel and credentials are not both
# provided.
Expand All @@ -117,11 +127,6 @@ def __init__(
self._grpc_channel = channel
self._ssl_channel_credentials = None
elif api_mtls_endpoint:
warnings.warn(
"api_mtls_endpoint and client_cert_source are deprecated",
DeprecationWarning,
)

host = (
api_mtls_endpoint
if ":" in api_mtls_endpoint
Expand Down Expand Up @@ -165,12 +170,18 @@ def __init__(
scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
)

if client_cert_source_for_mtls and not ssl_channel_credentials:
cert, key = client_cert_source_for_mtls()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)

# create a new channel. The provided one is ignored.
self._grpc_channel = type(self).create_channel(
host,
credentials=credentials,
credentials_file=credentials_file,
ssl_credentials=ssl_channel_credentials,
ssl_credentials=self._ssl_channel_credentials,
scopes=scopes or self.AUTH_SCOPES,
quota_project_id=quota_project_id,
options=[
Expand Down
Expand Up @@ -106,6 +106,7 @@ def __init__(
api_mtls_endpoint: str = None,
client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
ssl_channel_credentials: grpc.ChannelCredentials = None,
client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None,
quota_project_id=None,
client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
Expand Down Expand Up @@ -137,6 +138,10 @@ def __init__(
``api_mtls_endpoint`` is None.
ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
for grpc channel. It is ignored if ``channel`` is provided.
client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]):
A callback to provide client certificate bytes and private key bytes,
both in PEM format. It is used to configure mutual TLS channel. It is
ignored if ``channel`` or ``ssl_channel_credentials`` is provided.
quota_project_id (Optional[str]): An optional project to use for billing
and quota.
client_info (google.api_core.gapic_v1.client_info.ClientInfo):
Expand All @@ -153,6 +158,11 @@ def __init__(
"""
self._ssl_channel_credentials = ssl_channel_credentials

if api_mtls_endpoint:
warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning)
if client_cert_source:
warnings.warn("client_cert_source is deprecated", DeprecationWarning)

if channel:
# Sanity check: Ensure that channel and credentials are not both
# provided.
Expand All @@ -162,11 +172,6 @@ def __init__(
self._grpc_channel = channel
self._ssl_channel_credentials = None
elif api_mtls_endpoint:
warnings.warn(
"api_mtls_endpoint and client_cert_source are deprecated",
DeprecationWarning,
)

host = (
api_mtls_endpoint
if ":" in api_mtls_endpoint
Expand Down Expand Up @@ -210,12 +215,18 @@ def __init__(
scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
)

if client_cert_source_for_mtls and not ssl_channel_credentials:
cert, key = client_cert_source_for_mtls()
self._ssl_channel_credentials = grpc.ssl_channel_credentials(
certificate_chain=cert, private_key=key
)

# create a new channel. The provided one is ignored.
self._grpc_channel = type(self).create_channel(
host,
credentials=credentials,
credentials_file=credentials_file,
ssl_credentials=ssl_channel_credentials,
ssl_credentials=self._ssl_channel_credentials,
scopes=scopes or self.AUTH_SCOPES,
quota_project_id=quota_project_id,
options=[
Expand Down
76 changes: 38 additions & 38 deletions google/cloud/bigquery_datatransfer_v1/types/__init__.py
Expand Up @@ -15,70 +15,70 @@
# limitations under the License.
#

from .transfer import (
EmailPreferences,
ScheduleOptions,
TransferConfig,
TransferRun,
TransferMessage,
TransferType,
TransferState,
)
from .datatransfer import (
DataSourceParameter,
CheckValidCredsRequest,
CheckValidCredsResponse,
CreateTransferConfigRequest,
DataSource,
DataSourceParameter,
DeleteTransferConfigRequest,
DeleteTransferRunRequest,
GetDataSourceRequest,
ListDataSourcesRequest,
ListDataSourcesResponse,
CreateTransferConfigRequest,
UpdateTransferConfigRequest,
GetTransferConfigRequest,
DeleteTransferConfigRequest,
GetTransferRunRequest,
DeleteTransferRunRequest,
ListDataSourcesRequest,
ListDataSourcesResponse,
ListTransferConfigsRequest,
ListTransferConfigsResponse,
ListTransferRunsRequest,
ListTransferRunsResponse,
ListTransferLogsRequest,
ListTransferLogsResponse,
CheckValidCredsRequest,
CheckValidCredsResponse,
ListTransferRunsRequest,
ListTransferRunsResponse,
ScheduleTransferRunsRequest,
ScheduleTransferRunsResponse,
StartManualTransferRunsRequest,
StartManualTransferRunsResponse,
UpdateTransferConfigRequest,
)
from .transfer import (
EmailPreferences,
ScheduleOptions,
TransferConfig,
TransferMessage,
TransferRun,
TransferState,
TransferType,
)

__all__ = (
"EmailPreferences",
"ScheduleOptions",
"TransferConfig",
"TransferRun",
"TransferMessage",
"TransferType",
"TransferState",
"DataSourceParameter",
"CheckValidCredsRequest",
"CheckValidCredsResponse",
"CreateTransferConfigRequest",
"DataSource",
"DataSourceParameter",
"DeleteTransferConfigRequest",
"DeleteTransferRunRequest",
"GetDataSourceRequest",
"ListDataSourcesRequest",
"ListDataSourcesResponse",
"CreateTransferConfigRequest",
"UpdateTransferConfigRequest",
"GetTransferConfigRequest",
"DeleteTransferConfigRequest",
"GetTransferRunRequest",
"DeleteTransferRunRequest",
"ListDataSourcesRequest",
"ListDataSourcesResponse",
"ListTransferConfigsRequest",
"ListTransferConfigsResponse",
"ListTransferRunsRequest",
"ListTransferRunsResponse",
"ListTransferLogsRequest",
"ListTransferLogsResponse",
"CheckValidCredsRequest",
"CheckValidCredsResponse",
"ListTransferRunsRequest",
"ListTransferRunsResponse",
"ScheduleTransferRunsRequest",
"ScheduleTransferRunsResponse",
"StartManualTransferRunsRequest",
"StartManualTransferRunsResponse",
"UpdateTransferConfigRequest",
"EmailPreferences",
"ScheduleOptions",
"TransferConfig",
"TransferMessage",
"TransferRun",
"TransferState",
"TransferType",
)
9 changes: 5 additions & 4 deletions synth.metadata
Expand Up @@ -4,15 +4,15 @@
"git": {
"name": ".",
"remote": "https://github.com/googleapis/python-bigquery-datatransfer.git",
"sha": "34f506e81cbbbc3485a4e8a9cff87df82b3d6756"
"sha": "61bd36f705de327075e715e5dece4b7a82a2ab5c"
}
},
{
"git": {
"name": "googleapis",
"remote": "https://github.com/googleapis/googleapis.git",
"sha": "520682435235d9c503983a360a2090025aa47cd1",
"internalRef": "350246057"
"sha": "c13fb8cb376bb666de80ed33e11550955b4357af",
"internalRef": "363304304"
}
},
{
Expand Down Expand Up @@ -93,6 +93,7 @@
"CONTRIBUTING.rst",
"LICENSE",
"MANIFEST.in",
"README.rst",
"docs/_static/custom.css",
"docs/_templates/layout.html",
"docs/bigquery_datatransfer_v1/data_transfer_service.rst",
Expand Down Expand Up @@ -137,4 +138,4 @@
"tests/unit/gapic/bigquery_datatransfer_v1/__init__.py",
"tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py"
]
}
}
6 changes: 3 additions & 3 deletions synth.py
Expand Up @@ -37,7 +37,7 @@
),
include_protos=True,
)
s.move(library, excludes=["setup.py", "docs/index.rst"])
s.move(library, excludes=["*.tar.gz", "setup.py", "docs/index.rst"])


# ----------------------------------------------------------------------------
Expand All @@ -56,12 +56,12 @@
s.replace(
"google/cloud/bigquery_datatransfer_v1/__init__.py",
r"from \.services\.data_transfer_service import DataTransferServiceClient",
"\g<0>\nfrom .services.data_transfer_service import DataTransferServiceAsyncClient",
"\\g<0>\nfrom .services.data_transfer_service import DataTransferServiceAsyncClient",
)
s.replace(
"google/cloud/bigquery_datatransfer_v1/__init__.py",
r"'DataTransferServiceClient',",
'\g<0>\n "DataTransferServiceAsyncClient"',
'\\g<0>\n "DataTransferServiceAsyncClient"',
)


Expand Down