feat(iam): Support the mTLS IAM domain for Certificate based Access (… · googleapis/google-auth-library-python@8dcf91a
@@ -22,12 +22,14 @@
2222import base64
2323import http.client as http_client
2424import json
25+import os
25262627from google.auth import _exponential_backoff
2728from google.auth import _helpers
2829from google.auth import credentials
2930from google.auth import crypt
3031from google.auth import exceptions
32+from google.auth.transport import mtls
31333234IAM_RETRY_CODES = {
3335http_client.INTERNAL_SERVER_ERROR,
@@ -38,25 +40,33 @@
38403941_IAM_SCOPE = ["https://www.googleapis.com/auth/iam"]
404241-_IAM_ENDPOINT = (
42-"https://iamcredentials.googleapis.com/v1/projects/-"
43-+ "/serviceAccounts/{}:generateAccessToken"
44-)
45-46-_IAM_SIGN_ENDPOINT = (
47-"https://iamcredentials.googleapis.com/v1/projects/-"
48-+ "/serviceAccounts/{}:signBlob"
49-)
50-51-_IAM_SIGNJWT_ENDPOINT = (
52-"https://iamcredentials.googleapis.com/v1/projects/-"
53-+ "/serviceAccounts/{}:signJwt"
54-)
55-56-_IAM_IDTOKEN_ENDPOINT = (
57-"https://iamcredentials.googleapis.com/v1/"
58-+ "projects/-/serviceAccounts/{}:generateIdToken"
59-)
43+# 1. Determine if we should use mTLS.
44+# Note: We only support automatic mTLS on the default googleapis.com universe.
45+if hasattr(mtls, "should_use_client_cert"):
46+use_client_cert = mtls.should_use_client_cert()
47+else: # pragma: NO COVER
48+# if unsupported, fallback to reading from env var
49+use_client_cert = (
50+os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false").lower() == "true"
51+ )
52+53+# 2. Construct the template domain using the library's DEFAULT_UNIVERSE_DOMAIN constant.
54+# This ensures that the .replace() calls in the classes will work correctly.
55+if use_client_cert:
56+# We use the .mtls. prefix only for the default universe template
57+_IAM_DOMAIN = f"iamcredentials.mtls.{credentials.DEFAULT_UNIVERSE_DOMAIN}"
58+else:
59+_IAM_DOMAIN = f"iamcredentials.{credentials.DEFAULT_UNIVERSE_DOMAIN}"
60+61+# 3. Create the common base URL template
62+# We use double brackets {{}} so .format() can be called later for the email.
63+_IAM_BASE_URL = f"https://{_IAM_DOMAIN}/v1/projects/-/serviceAccounts/{{}}"
64+65+# 4. Define the endpoints as templates
66+_IAM_ENDPOINT = _IAM_BASE_URL + ":generateAccessToken"
67+_IAM_SIGN_ENDPOINT = _IAM_BASE_URL + ":signBlob"
68+_IAM_SIGNJWT_ENDPOINT = _IAM_BASE_URL + ":signJwt"
69+_IAM_IDTOKEN_ENDPOINT = _IAM_BASE_URL + ":generateIdToken"
607061716272class Signer(crypt.Signer):