@@ -130,6 +130,8 @@ def __init__(
130130 bq_connection_id ,
131131 cloud_resource_manager_client ,
132132 cloud_function_service_account ,
133+ cloud_function_kms_key_name ,
134+ cloud_function_docker_repository ,
133135 ):
134136 self ._gcp_project_id = gcp_project_id
135137 self ._cloud_function_region = cloud_function_region
@@ -142,6 +144,8 @@ def __init__(
142144 bq_connection_client , cloud_resource_manager_client
143145 )
144146 self ._cloud_function_service_account = cloud_function_service_account
147+ self ._cloud_function_kms_key_name = cloud_function_kms_key_name
148+ self ._cloud_function_docker_repository = cloud_function_docker_repository
145149
146150 def create_bq_remote_function (
147151 self , input_args , input_types , output_type , endpoint , bq_function_name
@@ -344,7 +348,9 @@ def create_cloud_function(self, def_, cf_name, package_requirements=None):
344348 )
345349
346350 # Determine an upload URL for user code
347- upload_url_request = functions_v2 .GenerateUploadUrlRequest ()
351+ upload_url_request = functions_v2 .GenerateUploadUrlRequest (
352+ kms_key_name = self ._cloud_function_kms_key_name
353+ )
348354 upload_url_request .parent = self .get_cloud_function_fully_qualified_parent ()
349355 upload_url_response = self ._cloud_functions_client .generate_upload_url (
350356 request = upload_url_request
@@ -383,12 +389,16 @@ def create_cloud_function(self, def_, cf_name, package_requirements=None):
383389 function .build_config .source .storage_source .object_ = (
384390 upload_url_response .storage_source .object_
385391 )
392+ function .build_config .docker_repository = (
393+ self ._cloud_function_docker_repository
394+ )
386395 function .service_config = functions_v2 .ServiceConfig ()
387396 function .service_config .available_memory = "1024M"
388397 function .service_config .timeout_seconds = 600
389398 function .service_config .service_account_email = (
390399 self ._cloud_function_service_account
391400 )
401+ function .kms_key_name = self ._cloud_function_kms_key_name
392402 create_function_request .function = function
393403
394404 # Create the cloud function and wait for it to be ready to use
@@ -597,6 +607,8 @@ def remote_function(
597607 name : Optional [str ] = None ,
598608 packages : Optional [Sequence [str ]] = None ,
599609 cloud_function_service_account : Optional [str ] = None ,
610+ cloud_function_kms_key_name : Optional [str ] = None ,
611+ cloud_function_docker_repository : Optional [str ] = None ,
600612):
601613 """Decorator to turn a user defined function into a BigQuery remote function.
602614
@@ -699,6 +711,20 @@ def remote_function(
699711 for more details. Please make sure the service account has the
700712 necessary IAM permissions configured as described in
701713 https://cloud.google.com/functions/docs/reference/iam/roles#additional-configuration.
714+ cloud_function_kms_key_name (str, Optional):
715+ Customer managed encryption key to protect cloud functions and
716+ related data at rest. This is of the format
717+ projects/PROJECT_ID/locations/LOCATION/keyRings/KEYRING/cryptoKeys/KEY.
718+ Read https://cloud.google.com/functions/docs/securing/cmek for
719+ more details including granting necessary service accounts
720+ access to the key.
721+ cloud_function_docker_repository (str, Optional):
722+ Docker repository created with the same encryption key as
723+ `cloud_function_kms_key_name` to store encrypted artifacts
724+ created to support the cloud function. This is of the format
725+ projects/PROJECT_ID/locations/LOCATION/repositories/REPOSITORY_NAME.
726+ For more details see
727+ https://cloud.google.com/functions/docs/securing/cmek#before_you_begin.
702728 """
703729 import bigframes .pandas as bpd
704730
@@ -780,6 +806,16 @@ def remote_function(
780806 f"{ bq_location } ."
781807 )
782808
809+ # If any CMEK is intended then check that a docker repository is also specified
810+ if (
811+ cloud_function_kms_key_name is not None
812+ and cloud_function_docker_repository is None
813+ ):
814+ raise ValueError (
815+ "cloud_function_docker_repository must be specified with cloud_function_kms_key_name."
816+ " For more details see https://cloud.google.com/functions/docs/securing/cmek#before_you_begin"
817+ )
818+
783819 def wrapper (f ):
784820 if not callable (f ):
785821 raise TypeError ("f must be callable, got {}" .format (f ))
@@ -800,6 +836,8 @@ def wrapper(f):
800836 bq_connection_id ,
801837 resource_manager_client ,
802838 cloud_function_service_account ,
839+ cloud_function_kms_key_name ,
840+ cloud_function_docker_repository ,
803841 )
804842
805843 rf_name , cf_name = remote_function_client .provision_bq_remote_function (
0 commit comments