1# -*- coding: utf-8 -*- 
    2# Copyright 2025 Google LLC 
    3# 
    4# Licensed under the Apache License, Version 2.0 (the "License"); 
    5# you may not use this file except in compliance with the License. 
    6# You may obtain a copy of the License at 
    7# 
    8#     http://www.apache.org/licenses/LICENSE-2.0 
    9# 
    10# Unless required by applicable law or agreed to in writing, software 
    11# distributed under the License is distributed on an "AS IS" BASIS, 
    12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    13# See the License for the specific language governing permissions and 
    14# limitations under the License. 
    15# 
    16import json  # type: ignore 
    17import re 
    18from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union 
    19 
    20from google.api_core import gapic_v1, path_template 
    21from google.protobuf import json_format 
    22 
    23from google.cloud.iam_credentials_v1.types import common 
    24 
    25from .base import DEFAULT_CLIENT_INFO, IAMCredentialsTransport 
    26 
    27 
    28class _BaseIAMCredentialsRestTransport(IAMCredentialsTransport): 
    29    """Base REST backend transport for IAMCredentials. 
    30 
    31    Note: This class is not meant to be used directly. Use its sync and 
    32    async sub-classes instead. 
    33 
    34    This class defines the same methods as the primary client, so the 
    35    primary client can load the underlying transport implementation 
    36    and call it. 
    37 
    38    It sends JSON representations of protocol buffers over HTTP/1.1 
    39    """ 
    40 
    41    def __init__( 
    42        self, 
    43        *, 
    44        host: str = "iamcredentials.googleapis.com", 
    45        credentials: Optional[Any] = None, 
    46        client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, 
    47        always_use_jwt_access: Optional[bool] = False, 
    48        url_scheme: str = "https", 
    49        api_audience: Optional[str] = None, 
    50    ) -> None: 
    51        """Instantiate the transport. 
    52        Args: 
    53            host (Optional[str]): 
    54                 The hostname to connect to (default: 'iamcredentials.googleapis.com'). 
    55            credentials (Optional[Any]): The 
    56                authorization credentials to attach to requests. These 
    57                credentials identify the application to the service; if none 
    58                are specified, the client will attempt to ascertain the 
    59                credentials from the environment. 
    60            client_info (google.api_core.gapic_v1.client_info.ClientInfo): 
    61                The client info used to send a user-agent string along with 
    62                API requests. If ``None``, then default info will be used. 
    63                Generally, you only need to set this if you are developing 
    64                your own client library. 
    65            always_use_jwt_access (Optional[bool]): Whether self signed JWT should 
    66                be used for service account credentials. 
    67            url_scheme: the protocol scheme for the API endpoint.  Normally 
    68                "https", but for testing or local servers, 
    69                "http" can be specified. 
    70        """ 
    71        # Run the base constructor 
    72        maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host) 
    73        if maybe_url_match is None: 
    74            raise ValueError( 
    75                f"Unexpected hostname structure: {host}" 
    76            )  # pragma: NO COVER 
    77 
    78        url_match_items = maybe_url_match.groupdict() 
    79 
    80        host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host 
    81 
    82        super().__init__( 
    83            host=host, 
    84            credentials=credentials, 
    85            client_info=client_info, 
    86            always_use_jwt_access=always_use_jwt_access, 
    87            api_audience=api_audience, 
    88        ) 
    89 
    90    class _BaseGenerateAccessToken: 
    91        def __hash__(self):  # pragma: NO COVER 
    92            return NotImplementedError("__hash__ must be implemented.") 
    93 
    94        __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} 
    95 
    96        @classmethod 
    97        def _get_unset_required_fields(cls, message_dict): 
    98            return { 
    99                k: v 
    100                for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() 
    101                if k not in message_dict 
    102            } 
    103 
    104        @staticmethod 
    105        def _get_http_options(): 
    106            http_options: List[Dict[str, str]] = [ 
    107                { 
    108                    "method": "post", 
    109                    "uri": "/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken", 
    110                    "body": "*", 
    111                }, 
    112            ] 
    113            return http_options 
    114 
    115        @staticmethod 
    116        def _get_transcoded_request(http_options, request): 
    117            pb_request = common.GenerateAccessTokenRequest.pb(request) 
    118            transcoded_request = path_template.transcode(http_options, pb_request) 
    119            return transcoded_request 
    120 
    121        @staticmethod 
    122        def _get_request_body_json(transcoded_request): 
    123            # Jsonify the request body 
    124 
    125            body = json_format.MessageToJson( 
    126                transcoded_request["body"], use_integers_for_enums=True 
    127            ) 
    128            return body 
    129 
    130        @staticmethod 
    131        def _get_query_params_json(transcoded_request): 
    132            query_params = json.loads( 
    133                json_format.MessageToJson( 
    134                    transcoded_request["query_params"], 
    135                    use_integers_for_enums=True, 
    136                ) 
    137            ) 
    138            query_params.update( 
    139                _BaseIAMCredentialsRestTransport._BaseGenerateAccessToken._get_unset_required_fields( 
    140                    query_params 
    141                ) 
    142            ) 
    143 
    144            query_params["$alt"] = "json;enum-encoding=int" 
    145            return query_params 
    146 
    147    class _BaseGenerateIdToken: 
    148        def __hash__(self):  # pragma: NO COVER 
    149            return NotImplementedError("__hash__ must be implemented.") 
    150 
    151        __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} 
    152 
    153        @classmethod 
    154        def _get_unset_required_fields(cls, message_dict): 
    155            return { 
    156                k: v 
    157                for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() 
    158                if k not in message_dict 
    159            } 
    160 
    161        @staticmethod 
    162        def _get_http_options(): 
    163            http_options: List[Dict[str, str]] = [ 
    164                { 
    165                    "method": "post", 
    166                    "uri": "/v1/{name=projects/*/serviceAccounts/*}:generateIdToken", 
    167                    "body": "*", 
    168                }, 
    169            ] 
    170            return http_options 
    171 
    172        @staticmethod 
    173        def _get_transcoded_request(http_options, request): 
    174            pb_request = common.GenerateIdTokenRequest.pb(request) 
    175            transcoded_request = path_template.transcode(http_options, pb_request) 
    176            return transcoded_request 
    177 
    178        @staticmethod 
    179        def _get_request_body_json(transcoded_request): 
    180            # Jsonify the request body 
    181 
    182            body = json_format.MessageToJson( 
    183                transcoded_request["body"], use_integers_for_enums=True 
    184            ) 
    185            return body 
    186 
    187        @staticmethod 
    188        def _get_query_params_json(transcoded_request): 
    189            query_params = json.loads( 
    190                json_format.MessageToJson( 
    191                    transcoded_request["query_params"], 
    192                    use_integers_for_enums=True, 
    193                ) 
    194            ) 
    195            query_params.update( 
    196                _BaseIAMCredentialsRestTransport._BaseGenerateIdToken._get_unset_required_fields( 
    197                    query_params 
    198                ) 
    199            ) 
    200 
    201            query_params["$alt"] = "json;enum-encoding=int" 
    202            return query_params 
    203 
    204    class _BaseSignBlob: 
    205        def __hash__(self):  # pragma: NO COVER 
    206            return NotImplementedError("__hash__ must be implemented.") 
    207 
    208        __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} 
    209 
    210        @classmethod 
    211        def _get_unset_required_fields(cls, message_dict): 
    212            return { 
    213                k: v 
    214                for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() 
    215                if k not in message_dict 
    216            } 
    217 
    218        @staticmethod 
    219        def _get_http_options(): 
    220            http_options: List[Dict[str, str]] = [ 
    221                { 
    222                    "method": "post", 
    223                    "uri": "/v1/{name=projects/*/serviceAccounts/*}:signBlob", 
    224                    "body": "*", 
    225                }, 
    226            ] 
    227            return http_options 
    228 
    229        @staticmethod 
    230        def _get_transcoded_request(http_options, request): 
    231            pb_request = common.SignBlobRequest.pb(request) 
    232            transcoded_request = path_template.transcode(http_options, pb_request) 
    233            return transcoded_request 
    234 
    235        @staticmethod 
    236        def _get_request_body_json(transcoded_request): 
    237            # Jsonify the request body 
    238 
    239            body = json_format.MessageToJson( 
    240                transcoded_request["body"], use_integers_for_enums=True 
    241            ) 
    242            return body 
    243 
    244        @staticmethod 
    245        def _get_query_params_json(transcoded_request): 
    246            query_params = json.loads( 
    247                json_format.MessageToJson( 
    248                    transcoded_request["query_params"], 
    249                    use_integers_for_enums=True, 
    250                ) 
    251            ) 
    252            query_params.update( 
    253                _BaseIAMCredentialsRestTransport._BaseSignBlob._get_unset_required_fields( 
    254                    query_params 
    255                ) 
    256            ) 
    257 
    258            query_params["$alt"] = "json;enum-encoding=int" 
    259            return query_params 
    260 
    261    class _BaseSignJwt: 
    262        def __hash__(self):  # pragma: NO COVER 
    263            return NotImplementedError("__hash__ must be implemented.") 
    264 
    265        __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} 
    266 
    267        @classmethod 
    268        def _get_unset_required_fields(cls, message_dict): 
    269            return { 
    270                k: v 
    271                for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() 
    272                if k not in message_dict 
    273            } 
    274 
    275        @staticmethod 
    276        def _get_http_options(): 
    277            http_options: List[Dict[str, str]] = [ 
    278                { 
    279                    "method": "post", 
    280                    "uri": "/v1/{name=projects/*/serviceAccounts/*}:signJwt", 
    281                    "body": "*", 
    282                }, 
    283            ] 
    284            return http_options 
    285 
    286        @staticmethod 
    287        def _get_transcoded_request(http_options, request): 
    288            pb_request = common.SignJwtRequest.pb(request) 
    289            transcoded_request = path_template.transcode(http_options, pb_request) 
    290            return transcoded_request 
    291 
    292        @staticmethod 
    293        def _get_request_body_json(transcoded_request): 
    294            # Jsonify the request body 
    295 
    296            body = json_format.MessageToJson( 
    297                transcoded_request["body"], use_integers_for_enums=True 
    298            ) 
    299            return body 
    300 
    301        @staticmethod 
    302        def _get_query_params_json(transcoded_request): 
    303            query_params = json.loads( 
    304                json_format.MessageToJson( 
    305                    transcoded_request["query_params"], 
    306                    use_integers_for_enums=True, 
    307                ) 
    308            ) 
    309            query_params.update( 
    310                _BaseIAMCredentialsRestTransport._BaseSignJwt._get_unset_required_fields( 
    311                    query_params 
    312                ) 
    313            ) 
    314 
    315            query_params["$alt"] = "json;enum-encoding=int" 
    316            return query_params 
    317 
    318 
    319__all__ = ("_BaseIAMCredentialsRestTransport",)