1212from botocore .auth import SigV4Auth
1313from botocore .awsrequest import AWSRequest
1414from botocore .utils import InstanceMetadataRegionFetcher
15+ from google .auth import impersonated_credentials
16+ from google .auth .transport .requests import Request
1517
1618from .errorcode import ER_INVALID_WIF_SETTINGS , ER_WIF_CREDENTIALS_NOT_FOUND
1719from .errors import ProgrammingError
@@ -185,6 +187,7 @@ def create_aws_attestation(
185187
186188
187189def create_gcp_attestation (
190+ impersonations : list [str ] | None = None ,
188191 session_manager : SessionManager | None = None ,
189192) -> WorkloadIdentityAttestation :
190193 """Tries to create a workload identity attestation for GCP.
@@ -207,6 +210,24 @@ def create_gcp_attestation(
207210 )
208211
209212 jwt_str = res .content .decode ("utf-8" )
213+ if impersonations :
214+ try :
215+ for impersonation in impersonations :
216+ jwt_str = impersonated_credentials .Credentials (
217+ source_credentials = jwt_str ,
218+ target_principal = impersonation ,
219+ target_audience = SNOWFLAKE_AUDIENCE ,
220+ )
221+
222+ # Refresh the last impersonated credential to get the final token
223+ jwt_str .refresh (Request ())
224+ jwt_str = jwt_str .token
225+ except Exception as e :
226+ raise ProgrammingError (
227+ msg = f"Error impersonating GCP service account: { e } . Ensure the service account has the 'Service Account Token Creator' role." ,
228+ errno = ER_WIF_CREDENTIALS_NOT_FOUND ,
229+ )
230+
210231 _ , subject = extract_iss_and_sub_without_signature_verification (jwt_str )
211232 return WorkloadIdentityAttestation (
212233 AttestationProvider .GCP , jwt_str , {"sub" : subject }
@@ -295,6 +316,7 @@ def create_attestation(
295316 provider : AttestationProvider ,
296317 entra_resource : str | None = None ,
297318 token : str | None = None ,
319+ impersonations : list [str ] | None = None ,
298320 session_manager : SessionManager | None = None ,
299321) -> WorkloadIdentityAttestation :
300322 """Entry point to create an attestation using the given provider.
@@ -313,7 +335,7 @@ def create_attestation(
313335 elif provider == AttestationProvider .AZURE :
314336 return create_azure_attestation (entra_resource , session_manager )
315337 elif provider == AttestationProvider .GCP :
316- return create_gcp_attestation (session_manager )
338+ return create_gcp_attestation (impersonations , session_manager )
317339 elif provider == AttestationProvider .OIDC :
318340 return create_oidc_attestation (token )
319341 else :
0 commit comments