2121from collections import OrderedDict
2222from math import ceil
2323from typing import Dict , List , Tuple , Union , Optional
24- from typing import List
2524from urllib .parse import urlparse
2625
2726import fastavro
2827import grpc
2928import pandas as pd
3029import pyarrow as pa
3130import pyarrow .parquet as pq
31+
3232from feast .core .CoreService_pb2 import (
3333 GetFeastCoreVersionRequest ,
3434 ListFeatureSetsResponse ,
4848from feast .core .FeatureSet_pb2 import FeatureSetStatus
4949from feast .feature_set import FeatureSet , Entity
5050from feast .job import Job
51- from feast .serving .ServingService_pb2 import FeatureReference
5251from feast .loaders .abstract_producer import get_producer
5352from feast .loaders .file import export_source_to_staging_location
5453from feast .loaders .ingest import KAFKA_CHUNK_PRODUCTION_TIMEOUT
5554from feast .loaders .ingest import get_feature_row_chunks
55+ from feast .serving .ServingService_pb2 import FeatureReference
5656from feast .serving .ServingService_pb2 import GetFeastServingInfoResponse
5757from feast .serving .ServingService_pb2 import (
5858 GetOnlineFeaturesRequest ,
6969
7070GRPC_CONNECTION_TIMEOUT_DEFAULT = 3 # type: int
7171GRPC_CONNECTION_TIMEOUT_APPLY = 600 # type: int
72- FEAST_SERVING_URL_ENV_KEY = "FEAST_SERVING_URL" # type: str
73- FEAST_CORE_URL_ENV_KEY = "FEAST_CORE_URL" # type: str
74- FEAST_PROJECT_ENV_KEY = "FEAST_PROJECT" # type: str
72+ FEAST_CORE_URL_ENV_KEY = "FEAST_CORE_URL"
73+ FEAST_SERVING_URL_ENV_KEY = "FEAST_SERVING_URL"
74+ FEAST_PROJECT_ENV_KEY = "FEAST_PROJECT"
75+ FEAST_CORE_SECURE_ENV_KEY = "FEAST_CORE_SECURE"
76+ FEAST_SERVING_SECURE_ENV_KEY = "FEAST_SERVING_SECURE"
7577BATCH_FEATURE_REQUEST_WAIT_TIME_SECONDS = 300
7678CPU_COUNT = os .cpu_count () # type: int
7779
@@ -82,7 +84,8 @@ class Client:
8284 """
8385
8486 def __init__ (
85- self , core_url : str = None , serving_url : str = None , project : str = None
87+ self , core_url : str = None , serving_url : str = None , project : str = None ,
88+ core_secure : bool = None , serving_secure : bool = None
8689 ):
8790 """
8891 The Feast Client should be initialized with at least one service url
@@ -91,10 +94,14 @@ def __init__(
9194 core_url: Feast Core URL. Used to manage features
9295 serving_url: Feast Serving URL. Used to retrieve features
9396 project: Sets the active project. This field is optional.
94- """
95- self ._core_url = core_url
96- self ._serving_url = serving_url
97- self ._project = project
97+ core_secure: Use client-side SSL/TLS for Core gRPC API
98+ serving_secure: Use client-side SSL/TLS for Serving gRPC API
99+ """
100+ self ._core_url : str = core_url
101+ self ._serving_url : str = serving_url
102+ self ._project : str = project
103+ self ._core_secure : bool = core_secure
104+ self ._serving_secure : bool = serving_secure
98105 self .__core_channel : grpc .Channel = None
99106 self .__serving_channel : grpc .Channel = None
100107 self ._core_service_stub : CoreServiceStub = None
@@ -149,6 +156,52 @@ def serving_url(self, value: str):
149156 """
150157 self ._serving_url = value
151158
159+ @property
160+ def core_secure (self ) -> bool :
161+ """
162+ Retrieve Feast Core client-side SSL/TLS setting
163+
164+ Returns:
165+ Whether client-side SSL/TLS is enabled
166+ """
167+
168+ if self ._core_secure is not None :
169+ return self ._core_secure
170+ return os .getenv (FEAST_CORE_SECURE_ENV_KEY , "" ).lower () is "true"
171+
172+ @core_secure .setter
173+ def core_secure (self , value : bool ):
174+ """
175+ Set the Feast Core client-side SSL/TLS setting
176+
177+ Args:
178+ value: True to enable client-side SSL/TLS
179+ """
180+ self ._core_secure = value
181+
182+ @property
183+ def serving_secure (self ) -> bool :
184+ """
185+ Retrieve Feast Serving client-side SSL/TLS setting
186+
187+ Returns:
188+ Whether client-side SSL/TLS is enabled
189+ """
190+
191+ if self ._serving_secure is not None :
192+ return self ._serving_secure
193+ return os .getenv (FEAST_SERVING_SECURE_ENV_KEY , "" ).lower () is "true"
194+
195+ @serving_secure .setter
196+ def serving_secure (self , value : bool ):
197+ """
198+ Set the Feast Serving client-side SSL/TLS setting
199+
200+ Args:
201+ value: True to enable client-side SSL/TLS
202+ """
203+ self ._serving_secure = value
204+
152205 def version (self ):
153206 """
154207 Returns version information from Feast Core and Feast Serving
@@ -185,7 +238,10 @@ def _connect_core(self, skip_if_connected: bool = True):
185238 raise ValueError ("Please set Feast Core URL." )
186239
187240 if self .__core_channel is None :
188- self .__core_channel = grpc .insecure_channel (self .core_url )
241+ if self .core_secure or self .core_url .endswith (":443" ):
242+ self .__core_channel = grpc .secure_channel (self .core_url , grpc .ssl_channel_credentials ())
243+ else :
244+ self .__core_channel = grpc .insecure_channel (self .core_url )
189245
190246 try :
191247 grpc .channel_ready_future (self .__core_channel ).result (
@@ -214,7 +270,10 @@ def _connect_serving(self, skip_if_connected=True):
214270 raise ValueError ("Please set Feast Serving URL." )
215271
216272 if self .__serving_channel is None :
217- self .__serving_channel = grpc .insecure_channel (self .serving_url )
273+ if self .serving_secure or self .serving_url .endswith (":443" ):
274+ self .__serving_channel = grpc .secure_channel (self .serving_url , grpc .ssl_channel_credentials ())
275+ else :
276+ self .__serving_channel = grpc .insecure_channel (self .serving_url )
218277
219278 try :
220279 grpc .channel_ready_future (self .__serving_channel ).result (
0 commit comments