aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/google-auth/py3/google/auth
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2023-12-27 23:31:58 +0100
committerGitHub <noreply@github.com>2023-12-27 23:31:58 +0100
commitd67bfb4b4b7549081543e87a31bc6cb5c46ac973 (patch)
tree8674f2f1570877cb653e7ddcff37ba00288de15a /contrib/python/google-auth/py3/google/auth
parent1f6bef05ed441c3aa2d565ac792b26cded704ac7 (diff)
downloadydb-d67bfb4b4b7549081543e87a31bc6cb5c46ac973.tar.gz
Import libs 4 (#758)
Diffstat (limited to 'contrib/python/google-auth/py3/google/auth')
-rw-r--r--contrib/python/google-auth/py3/google/auth/__init__.py20
-rw-r--r--contrib/python/google-auth/py3/google/auth/_helpers.py40
-rw-r--r--contrib/python/google-auth/py3/google/auth/compute_engine/__init__.py3
-rw-r--r--contrib/python/google-auth/py3/google/auth/compute_engine/_metadata.py58
-rw-r--r--contrib/python/google-auth/py3/google/auth/compute_engine/credentials.py13
-rw-r--r--contrib/python/google-auth/py3/google/auth/credentials.py20
-rw-r--r--contrib/python/google-auth/py3/google/auth/crypt/_cryptography_rsa.py15
-rw-r--r--contrib/python/google-auth/py3/google/auth/crypt/es256.py15
-rw-r--r--contrib/python/google-auth/py3/google/auth/external_account.py21
-rw-r--r--contrib/python/google-auth/py3/google/auth/transport/_custom_tls_signer.py79
-rw-r--r--contrib/python/google-auth/py3/google/auth/transport/requests.py1
-rw-r--r--contrib/python/google-auth/py3/google/auth/transport/urllib3.py9
-rw-r--r--contrib/python/google-auth/py3/google/auth/version.py2
13 files changed, 251 insertions, 45 deletions
diff --git a/contrib/python/google-auth/py3/google/auth/__init__.py b/contrib/python/google-auth/py3/google/auth/__init__.py
index 2875772b37..765bbd7058 100644
--- a/contrib/python/google-auth/py3/google/auth/__init__.py
+++ b/contrib/python/google-auth/py3/google/auth/__init__.py
@@ -15,6 +15,8 @@
"""Google Auth Library for Python."""
import logging
+import sys
+import warnings
from google.auth import version as google_auth_version
from google.auth._default import (
@@ -29,5 +31,23 @@ __version__ = google_auth_version.__version__
__all__ = ["default", "load_credentials_from_file", "load_credentials_from_dict"]
+
+class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER
+ """
+ Deprecation warning raised when Python 3.7 runtime is detected.
+ Python 3.7 support will be dropped after January 1, 2024.
+ """
+
+ pass
+
+
+# Checks if the current runtime is Python 3.7.
+if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER
+ message = (
+ "After January 1, 2024, new releases of this library will drop support "
+ "for Python 3.7."
+ )
+ warnings.warn(message, Python37DeprecationWarning)
+
# Set default logging handler to avoid "No handler found" warnings.
logging.getLogger(__name__).addHandler(logging.NullHandler())
diff --git a/contrib/python/google-auth/py3/google/auth/_helpers.py b/contrib/python/google-auth/py3/google/auth/_helpers.py
index ad2c095f28..a6c07f7d82 100644
--- a/contrib/python/google-auth/py3/google/auth/_helpers.py
+++ b/contrib/python/google-auth/py3/google/auth/_helpers.py
@@ -17,16 +17,15 @@
import base64
import calendar
import datetime
+from email.message import Message
import sys
import urllib
from google.auth import exceptions
-# Token server doesn't provide a new a token when doing refresh unless the
-# token is expiring within 30 seconds, so refresh threshold should not be
-# more than 30 seconds. Otherwise auth lib will send tons of refresh requests
-# until 30 seconds before the expiration, and cause a spike of CPU usage.
-REFRESH_THRESHOLD = datetime.timedelta(seconds=20)
+# The smallest MDS cache used by this library stores tokens until 4 minutes from
+# expiry.
+REFRESH_THRESHOLD = datetime.timedelta(minutes=3, seconds=45)
def copy_docstring(source_class):
@@ -63,13 +62,42 @@ def copy_docstring(source_class):
return decorator
+def parse_content_type(header_value):
+ """Parse a 'content-type' header value to get just the plain media-type (without parameters).
+
+ This is done using the class Message from email.message as suggested in PEP 594
+ (because the cgi is now deprecated and will be removed in python 3.13,
+ see https://peps.python.org/pep-0594/#cgi).
+
+ Args:
+ header_value (str): The value of a 'content-type' header as a string.
+
+ Returns:
+ str: A string with just the lowercase media-type from the parsed 'content-type' header.
+ If the provided content-type is not parsable, returns 'text/plain',
+ the default value for textual files.
+ """
+ m = Message()
+ m["content-type"] = header_value
+ return (
+ m.get_content_type()
+ ) # Despite the name, actually returns just the media-type
+
+
def utcnow():
"""Returns the current UTC datetime.
Returns:
datetime: The current time in UTC.
"""
- return datetime.datetime.utcnow()
+ # We used datetime.utcnow() before, since it's deprecated from python 3.12,
+ # we are using datetime.now(timezone.utc) now. "utcnow()" is offset-native
+ # (no timezone info), but "now()" is offset-aware (with timezone info).
+ # This will cause datetime comparison problem. For backward compatibility,
+ # we need to remove the timezone info.
+ now = datetime.datetime.now(datetime.timezone.utc)
+ now = now.replace(tzinfo=None)
+ return now
def datetime_to_secs(value):
diff --git a/contrib/python/google-auth/py3/google/auth/compute_engine/__init__.py b/contrib/python/google-auth/py3/google/auth/compute_engine/__init__.py
index 5c84234e93..7e1206fc1b 100644
--- a/contrib/python/google-auth/py3/google/auth/compute_engine/__init__.py
+++ b/contrib/python/google-auth/py3/google/auth/compute_engine/__init__.py
@@ -14,8 +14,9 @@
"""Google Compute Engine authentication."""
+from google.auth.compute_engine._metadata import detect_gce_residency_linux
from google.auth.compute_engine.credentials import Credentials
from google.auth.compute_engine.credentials import IDTokenCredentials
-__all__ = ["Credentials", "IDTokenCredentials"]
+__all__ = ["Credentials", "IDTokenCredentials", "detect_gce_residency_linux"]
diff --git a/contrib/python/google-auth/py3/google/auth/compute_engine/_metadata.py b/contrib/python/google-auth/py3/google/auth/compute_engine/_metadata.py
index 04abe178f5..1c884c3c43 100644
--- a/contrib/python/google-auth/py3/google/auth/compute_engine/_metadata.py
+++ b/contrib/python/google-auth/py3/google/auth/compute_engine/_metadata.py
@@ -156,6 +156,7 @@ def get(
recursive=False,
retry_count=5,
headers=None,
+ return_none_for_not_found_error=False,
):
"""Fetch a resource from the metadata server.
@@ -173,6 +174,8 @@ def get(
retry_count (int): How many times to attempt connecting to metadata
server using above timeout.
headers (Optional[Mapping[str, str]]): Headers for the request.
+ return_none_for_not_found_error (Optional[bool]): If True, returns None
+ for 404 error instead of throwing an exception.
Returns:
Union[Mapping, str]: If the metadata server returns JSON, a mapping of
@@ -216,9 +219,21 @@ def get(
"metadata service. Compute Engine Metadata server unavailable".format(url)
)
+ content = _helpers.from_bytes(response.data)
+
+ if response.status == http_client.NOT_FOUND and return_none_for_not_found_error:
+ _LOGGER.info(
+ "Compute Engine Metadata server call to %s returned 404, reason: %s",
+ path,
+ content,
+ )
+ return None
+
if response.status == http_client.OK:
- content = _helpers.from_bytes(response.data)
- if response.headers["content-type"] == "application/json":
+ if (
+ _helpers.parse_content_type(response.headers["content-type"])
+ == "application/json"
+ ):
try:
return json.loads(content)
except ValueError as caught_exc:
@@ -229,14 +244,14 @@ def get(
raise new_exc from caught_exc
else:
return content
- else:
- raise exceptions.TransportError(
- "Failed to retrieve {} from the Google Compute Engine "
- "metadata service. Status: {} Response:\n{}".format(
- url, response.status, response.data
- ),
- response,
- )
+
+ raise exceptions.TransportError(
+ "Failed to retrieve {} from the Google Compute Engine "
+ "metadata service. Status: {} Response:\n{}".format(
+ url, response.status, response.data
+ ),
+ response,
+ )
def get_project_id(request):
@@ -256,6 +271,29 @@ def get_project_id(request):
return get(request, "project/project-id")
+def get_universe_domain(request):
+ """Get the universe domain value from the metadata server.
+
+ Args:
+ request (google.auth.transport.Request): A callable used to make
+ HTTP requests.
+
+ Returns:
+ str: The universe domain value. If the universe domain endpoint is not
+ not found, return the default value, which is googleapis.com
+
+ Raises:
+ google.auth.exceptions.TransportError: if an error other than
+ 404 occurs while retrieving metadata.
+ """
+ universe_domain = get(
+ request, "universe/universe_domain", return_none_for_not_found_error=True
+ )
+ if not universe_domain:
+ return "googleapis.com"
+ return universe_domain
+
+
def get_service_account_info(request, service_account="default"):
"""Get information about a service account from the metadata server.
diff --git a/contrib/python/google-auth/py3/google/auth/compute_engine/credentials.py b/contrib/python/google-auth/py3/google/auth/compute_engine/credentials.py
index 7ae673880f..a035c7697a 100644
--- a/contrib/python/google-auth/py3/google/auth/compute_engine/credentials.py
+++ b/contrib/python/google-auth/py3/google/auth/compute_engine/credentials.py
@@ -28,6 +28,7 @@ from google.auth import iam
from google.auth import jwt
from google.auth import metrics
from google.auth.compute_engine import _metadata
+from google.auth.transport import requests as google_auth_requests
from google.oauth2 import _client
@@ -73,6 +74,8 @@ class Credentials(credentials.Scoped, credentials.CredentialsWithQuotaProject):
self._quota_project_id = quota_project_id
self._scopes = scopes
self._default_scopes = default_scopes
+ self._universe_domain_cached = False
+ self._universe_domain_request = google_auth_requests.Request()
def _retrieve_info(self, request):
"""Retrieve information about the service account.
@@ -131,6 +134,16 @@ class Credentials(credentials.Scoped, credentials.CredentialsWithQuotaProject):
def requires_scopes(self):
return not self._scopes
+ @property
+ def universe_domain(self):
+ if self._universe_domain_cached:
+ return self._universe_domain
+ self._universe_domain = _metadata.get_universe_domain(
+ self._universe_domain_request
+ )
+ self._universe_domain_cached = True
+ return self._universe_domain
+
@_helpers.copy_docstring(credentials.CredentialsWithQuotaProject)
def with_quota_project(self, quota_project_id):
return self.__class__(
diff --git a/contrib/python/google-auth/py3/google/auth/credentials.py b/contrib/python/google-auth/py3/google/auth/credentials.py
index 80a2a5c0b4..800781c408 100644
--- a/contrib/python/google-auth/py3/google/auth/credentials.py
+++ b/contrib/python/google-auth/py3/google/auth/credentials.py
@@ -52,8 +52,9 @@ class Credentials(metaclass=abc.ABCMeta):
self._quota_project_id = None
"""Optional[str]: Project to use for quota and billing purposes."""
self._trust_boundary = None
- """Optional[str]: Encoded string representation of credentials trust
- boundary."""
+ """Optional[dict]: Cache of a trust boundary response which has a list
+ of allowed regions and an encoded string representation of credentials
+ trust boundary."""
self._universe_domain = "googleapis.com"
"""Optional[str]: The universe domain value, default is googleapis.com
"""
@@ -135,8 +136,21 @@ class Credentials(metaclass=abc.ABCMeta):
headers["authorization"] = "Bearer {}".format(
_helpers.from_bytes(token or self.token)
)
+ """Trust boundary value will be a cached value from global lookup.
+
+ The response of trust boundary will be a list of regions and a hex
+ encoded representation.
+
+ An example of global lookup response:
+ {
+ "locations": [
+ "us-central1", "us-east1", "europe-west1", "asia-east1"
+ ]
+ "encoded_locations": "0xA30"
+ }
+ """
if self._trust_boundary is not None:
- headers["x-identity-trust-boundary"] = self._trust_boundary
+ headers["x-allowed-locations"] = self._trust_boundary["encoded_locations"]
if self.quota_project_id:
headers["x-goog-user-project"] = self.quota_project_id
diff --git a/contrib/python/google-auth/py3/google/auth/crypt/_cryptography_rsa.py b/contrib/python/google-auth/py3/google/auth/crypt/_cryptography_rsa.py
index 4f2d611666..1a3e9ff52c 100644
--- a/contrib/python/google-auth/py3/google/auth/crypt/_cryptography_rsa.py
+++ b/contrib/python/google-auth/py3/google/auth/crypt/_cryptography_rsa.py
@@ -134,3 +134,18 @@ class RSASigner(base.Signer, base.FromServiceAccountMixin):
key, password=None, backend=_BACKEND
)
return cls(private_key, key_id=key_id)
+
+ def __getstate__(self):
+ """Pickle helper that serializes the _key attribute."""
+ state = self.__dict__.copy()
+ state["_key"] = self._key.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.PKCS8,
+ encryption_algorithm=serialization.NoEncryption(),
+ )
+ return state
+
+ def __setstate__(self, state):
+ """Pickle helper that deserializes the _key attribute."""
+ state["_key"] = serialization.load_pem_private_key(state["_key"], None)
+ self.__dict__.update(state)
diff --git a/contrib/python/google-auth/py3/google/auth/crypt/es256.py b/contrib/python/google-auth/py3/google/auth/crypt/es256.py
index 7920cc7ffb..820e4becce 100644
--- a/contrib/python/google-auth/py3/google/auth/crypt/es256.py
+++ b/contrib/python/google-auth/py3/google/auth/crypt/es256.py
@@ -158,3 +158,18 @@ class ES256Signer(base.Signer, base.FromServiceAccountMixin):
key, password=None, backend=_BACKEND
)
return cls(private_key, key_id=key_id)
+
+ def __getstate__(self):
+ """Pickle helper that serializes the _key attribute."""
+ state = self.__dict__.copy()
+ state["_key"] = self._key.private_bytes(
+ encoding=serialization.Encoding.PEM,
+ format=serialization.PrivateFormat.PKCS8,
+ encryption_algorithm=serialization.NoEncryption(),
+ )
+ return state
+
+ def __setstate__(self, state):
+ """Pickle helper that deserializes the _key attribute."""
+ state["_key"] = serialization.load_pem_private_key(state["_key"], None)
+ self.__dict__.update(state)
diff --git a/contrib/python/google-auth/py3/google/auth/external_account.py b/contrib/python/google-auth/py3/google/auth/external_account.py
index c45e6f2133..e7fed8695a 100644
--- a/contrib/python/google-auth/py3/google/auth/external_account.py
+++ b/contrib/python/google-auth/py3/google/auth/external_account.py
@@ -132,7 +132,10 @@ class Credentials(
self._default_scopes = default_scopes
self._workforce_pool_user_project = workforce_pool_user_project
self._universe_domain = universe_domain or _DEFAULT_UNIVERSE_DOMAIN
- self._trust_boundary = "0" # expose a placeholder trust boundary value.
+ self._trust_boundary = {
+ "locations": [],
+ "encoded_locations": "0x0",
+ } # expose a placeholder trust boundary value.
if self._client_id:
self._client_auth = utils.ClientAuthentication(
@@ -412,6 +415,22 @@ class Credentials(
new_cred._metrics_options = self._metrics_options
return new_cred
+ def with_universe_domain(self, universe_domain):
+ """Create a copy of these credentials with the given universe domain.
+
+ Args:
+ universe_domain (str): The universe domain value.
+
+ Returns:
+ google.auth.external_account.Credentials: A new credentials
+ instance.
+ """
+ kwargs = self._constructor_args()
+ kwargs.update(universe_domain=universe_domain)
+ new_cred = self.__class__(**kwargs)
+ new_cred._metrics_options = self._metrics_options
+ return new_cred
+
def _initialize_impersonated_credentials(self):
"""Generates an impersonated credentials.
diff --git a/contrib/python/google-auth/py3/google/auth/transport/_custom_tls_signer.py b/contrib/python/google-auth/py3/google/auth/transport/_custom_tls_signer.py
index 07f14df02d..57a563d03b 100644
--- a/contrib/python/google-auth/py3/google/auth/transport/_custom_tls_signer.py
+++ b/contrib/python/google-auth/py3/google/auth/transport/_custom_tls_signer.py
@@ -107,6 +107,22 @@ def load_signer_lib(signer_lib_path):
return lib
+def load_provider_lib(provider_lib_path):
+ _LOGGER.debug("loading provider library from %s", provider_lib_path)
+
+ # winmode parameter is only available for python 3.8+.
+ lib = (
+ ctypes.CDLL(provider_lib_path, winmode=0)
+ if sys.version_info >= (3, 8) and os.name == "nt"
+ else ctypes.CDLL(provider_lib_path)
+ )
+
+ lib.ECP_attach_to_ctx.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
+ lib.ECP_attach_to_ctx.restype = ctypes.c_int
+
+ return lib
+
+
# Computes SHA256 hash.
def _compute_sha256_digest(to_be_signed, to_be_signed_len):
from cryptography.hazmat.primitives import hashes
@@ -199,21 +215,31 @@ class CustomTlsSigner(object):
self._enterprise_cert_file_path = enterprise_cert_file_path
self._cert = None
self._sign_callback = None
+ self._provider_lib = None
def load_libraries(self):
- try:
- with open(self._enterprise_cert_file_path, "r") as f:
- enterprise_cert_json = json.load(f)
- libs = enterprise_cert_json["libs"]
- signer_library = libs["ecp_client"]
- offload_library = libs["tls_offload"]
- except (KeyError, ValueError) as caught_exc:
- new_exc = exceptions.MutualTLSChannelError(
- "enterprise cert file is invalid", caught_exc
- )
- raise new_exc from caught_exc
- self._offload_lib = load_offload_lib(offload_library)
- self._signer_lib = load_signer_lib(signer_library)
+ with open(self._enterprise_cert_file_path, "r") as f:
+ enterprise_cert_json = json.load(f)
+ libs = enterprise_cert_json.get("libs", {})
+
+ signer_library = libs.get("ecp_client", None)
+ offload_library = libs.get("tls_offload", None)
+ provider_library = libs.get("ecp_provider", None)
+
+ # Using newer provider implementation. This is mutually exclusive to the
+ # offload implementation.
+ if provider_library:
+ self._provider_lib = load_provider_lib(provider_library)
+ return
+
+ # Using old offload implementation
+ if offload_library and signer_library:
+ self._offload_lib = load_offload_lib(offload_library)
+ self._signer_lib = load_signer_lib(signer_library)
+ self.set_up_custom_key()
+ return
+
+ raise exceptions.MutualTLSChannelError("enterprise cert file is invalid")
def set_up_custom_key(self):
# We need to keep a reference of the cert and sign callback so it won't
@@ -224,11 +250,22 @@ class CustomTlsSigner(object):
)
def attach_to_ssl_context(self, ctx):
- # In the TLS handshake, the signing operation will be done by the
- # sign_callback.
- if not self._offload_lib.ConfigureSslContext(
- self._sign_callback,
- ctypes.c_char_p(self._cert),
- _cast_ssl_ctx_to_void_p(ctx._ctx._context),
- ):
- raise exceptions.MutualTLSChannelError("failed to configure SSL context")
+ if self._provider_lib:
+ if not self._provider_lib.ECP_attach_to_ctx(
+ _cast_ssl_ctx_to_void_p(ctx._ctx._context),
+ self._enterprise_cert_file_path.encode("ascii"),
+ ):
+ raise exceptions.MutualTLSChannelError(
+ "failed to configure ECP Provider SSL context"
+ )
+ elif self._offload_lib and self._signer_lib:
+ if not self._offload_lib.ConfigureSslContext(
+ self._sign_callback,
+ ctypes.c_char_p(self._cert),
+ _cast_ssl_ctx_to_void_p(ctx._ctx._context),
+ ):
+ raise exceptions.MutualTLSChannelError(
+ "failed to configure ECP Offload SSL context"
+ )
+ else:
+ raise exceptions.MutualTLSChannelError("Invalid ECP configuration.")
diff --git a/contrib/python/google-auth/py3/google/auth/transport/requests.py b/contrib/python/google-auth/py3/google/auth/transport/requests.py
index b9bcad359f..aa16113226 100644
--- a/contrib/python/google-auth/py3/google/auth/transport/requests.py
+++ b/contrib/python/google-auth/py3/google/auth/transport/requests.py
@@ -274,7 +274,6 @@ class _MutualTlsOffloadAdapter(requests.adapters.HTTPAdapter):
self.signer = _custom_tls_signer.CustomTlsSigner(enterprise_cert_file_path)
self.signer.load_libraries()
- self.signer.set_up_custom_key()
poolmanager = create_urllib3_context()
poolmanager.load_verify_locations(cafile=certifi.where())
diff --git a/contrib/python/google-auth/py3/google/auth/transport/urllib3.py b/contrib/python/google-auth/py3/google/auth/transport/urllib3.py
index 053d6f7b72..63144f5fff 100644
--- a/contrib/python/google-auth/py3/google/auth/transport/urllib3.py
+++ b/contrib/python/google-auth/py3/google/auth/transport/urllib3.py
@@ -40,11 +40,18 @@ except ImportError as caught_exc: # pragma: NO COVER
"urllib3 package to use the urllib3 transport."
) from caught_exc
+from packaging import version # type: ignore
+
from google.auth import environment_vars
from google.auth import exceptions
from google.auth import transport
from google.oauth2 import service_account
+if version.parse(urllib3.__version__) >= version.parse("2.0.0"): # pragma: NO COVER
+ RequestMethods = urllib3._request_methods.RequestMethods # type: ignore
+else: # pragma: NO COVER
+ RequestMethods = urllib3.request.RequestMethods # type: ignore
+
_LOGGER = logging.getLogger(__name__)
@@ -179,7 +186,7 @@ def _make_mutual_tls_http(cert, key):
return http
-class AuthorizedHttp(urllib3.request.RequestMethods):
+class AuthorizedHttp(RequestMethods): # type: ignore
"""A urllib3 HTTP class with credentials.
This class is used to perform requests to API endpoints that require
diff --git a/contrib/python/google-auth/py3/google/auth/version.py b/contrib/python/google-auth/py3/google/auth/version.py
index 491187e6d7..31cc30242a 100644
--- a/contrib/python/google-auth/py3/google/auth/version.py
+++ b/contrib/python/google-auth/py3/google/auth/version.py
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-__version__ = "2.23.0"
+__version__ = "2.25.2"