2626from google .cloud .sql .connector .connection_info import ConnectionInfo
2727from google .cloud .sql .connector .connection_info import ConnectionInfoCache
2828from google .cloud .sql .connector .connection_name import ConnectionName
29- from google .cloud .sql .connector .enums import IPTypes
3029from google .cloud .sql .connector .exceptions import RefreshNotValidError
3130from google .cloud .sql .connector .rate_limiter import AsyncRateLimiter
3231from google .cloud .sql .connector .refresh_utils import _is_valid
3534logger = logging .getLogger (name = __name__ )
3635
3736APPLICATION_NAME = "cloud-sql-python-connector"
38- SERVER_PROXY_PORT = 3307
39- DEFAULT_CONNECT_TIMEOUT = 30
4037
4138
4239class RefreshAheadCache (ConnectionInfoCache ):
@@ -53,8 +50,6 @@ def __init__(
5350 client : CloudSQLClient ,
5451 keys : asyncio .Future ,
5552 enable_iam_auth : bool = False ,
56- ip_type : IPTypes | str = IPTypes .PUBLIC ,
57- timeout : int = DEFAULT_CONNECT_TIMEOUT ,
5853 ) -> None :
5954 """Initializes a RefreshAheadCache instance.
6055
@@ -67,32 +62,21 @@ def __init__(
6762 enable_iam_auth (bool): Enables automatic IAM database authentication
6863 (Postgres and MySQL) as the default authentication method for all
6964 connections.
70- ip_type (IPTypes | str): Preferred IP type used to connect to the instance.
71- timeout (int): Connect timeout in seconds.
7265 """
7366 self ._conn_name = conn_name
7467
7568 self ._enable_iam_auth = enable_iam_auth
76- if isinstance (ip_type , str ):
77- ip_type = IPTypes ._from_str (ip_type )
78- self ._ip_type = ip_type
79- self ._timeout = timeout
8069 self ._keys = keys
8170 self ._client = client
8271 self ._refresh_rate_limiter = AsyncRateLimiter (
8372 max_capacity = 2 ,
8473 rate = 1 / 30 ,
8574 )
8675 self ._refresh_in_progress = asyncio .locks .Event ()
87- self ._iam_principals : list [tuple [str , str ]] = []
8876 self ._current : asyncio .Task = self ._schedule_refresh (0 )
8977 self ._next : asyncio .Task = self ._current
9078 self ._closed = False
9179
92- def record_principal (self , user : str , database : str ) -> None :
93- """Records a PostgreSQL (user, database) pair observed on an IAM connection."""
94- _append_iam_principal (self ._iam_principals , user , database )
95-
9680 @property
9781 def conn_name (self ) -> ConnectionName :
9882 return self ._conn_name
@@ -135,8 +119,6 @@ async def _perform_refresh(self) -> ConnectionInfo:
135119 self ._keys ,
136120 self ._enable_iam_auth ,
137121 )
138- if self ._enable_iam_auth :
139- await self ._probe_connection (connection_info )
140122 logger .debug (
141123 f"['{ self ._conn_name } ']: Connection info refresh operation complete"
142124 )
@@ -156,17 +138,6 @@ async def _perform_refresh(self) -> ConnectionInfo:
156138 self ._refresh_in_progress .clear ()
157139 return connection_info
158140
159- async def _probe_connection (self , conn_info : ConnectionInfo ) -> None :
160- """Proactively probes the database to refresh IAM tokens on server-side MCP."""
161- await _probe_instance_connection (
162- self ._conn_name ,
163- conn_info ,
164- self ._enable_iam_auth ,
165- self ._ip_type ,
166- self ._timeout ,
167- self ._iam_principals ,
168- )
169-
170141 def _schedule_refresh (self , delay : int ) -> asyncio .Task :
171142 """
172143 Schedule task to sleep and then perform refresh to get ConnectionInfo.
@@ -252,124 +223,3 @@ async def close(self) -> None:
252223 tasks = asyncio .gather (self ._current , self ._next , return_exceptions = True )
253224 await asyncio .wait_for (tasks , timeout = 2.0 )
254225 self ._closed = True
255-
256-
257- def _append_iam_principal (
258- principals : list [tuple [str , str ]], user : str , database : str
259- ) -> None :
260- """Appends (user, database) to principals if not already present."""
261- if not user :
262- return
263- if not database :
264- database = user
265- pair = (user , database )
266- if pair not in principals :
267- principals .append (pair )
268-
269-
270- async def _probe_instance_connection (
271- conn_name : ConnectionName ,
272- conn_info : ConnectionInfo ,
273- enable_iam_auth : bool ,
274- ip_type : IPTypes ,
275- timeout : int ,
276- iam_principals : list [tuple [str , str ]],
277- ) -> None :
278- """Proactively probes the database to refresh IAM tokens on server-side MCP."""
279- targets : list [str ] = []
280- if conn_name .domain_name :
281- targets .append (conn_name .domain_name )
282- else :
283- if ip_type .value in conn_info .ip_addrs :
284- targets .extend (conn_info .ip_addrs [ip_type .value ])
285-
286- if not targets :
287- logger .debug (
288- f"['{ conn_name } ']: Proactive IAM token refresh probe skipped: no target IP addresses"
289- )
290- return
291-
292- port = SERVER_PROXY_PORT
293- try :
294- ssl_context = await conn_info .create_ssl_context (enable_iam_auth )
295- except Exception as e : # noqa: BLE001
296- logger .debug (
297- f"['{ conn_name } ']: Failed to create SSL context for probe: { e !s} "
298- )
299- return
300-
301- principals : list [tuple [str , str ] | None ] = []
302- if conn_info .database_version .startswith ("POSTGRES" ) and iam_principals :
303- principals .extend (iam_principals )
304- else :
305- principals .append (None )
306-
307- all_succeeded = True
308- for principal in principals :
309- probed_principal = False
310- for target in targets :
311- try :
312- logger .debug (
313- f"['{ conn_name } ']: Probing IAM token refresh on { target } :{ port } "
314- )
315- reader , writer = await asyncio .wait_for (
316- asyncio .open_connection (
317- host = target ,
318- port = port ,
319- ssl = ssl_context ,
320- server_hostname = (
321- conn_name .domain_name
322- if conn_name .domain_name
323- else None
324- ),
325- ),
326- timeout = float (timeout ),
327- )
328- try :
329- if principal is not None :
330- user , database = principal
331- writer .write (
332- _build_postgres_startup_packet (user , database )
333- )
334- await writer .drain ()
335- await asyncio .wait_for (
336- reader .read (1024 ),
337- timeout = float (timeout ),
338- )
339- writer .write (b"X\x00 \x00 \x00 \x04 " )
340- await writer .drain ()
341- finally :
342- writer .close ()
343- await writer .wait_closed ()
344- probed_principal = True
345- break
346- except Exception as e : # noqa: BLE001
347- logger .debug (
348- f"['{ conn_name } ']: Probing IAM token refresh on { target } :{ port } failed: { e !s} "
349- )
350- if not probed_principal :
351- all_succeeded = False
352-
353- if all_succeeded :
354- logger .debug (
355- f"['{ conn_name } ']: Proactive IAM token refresh probe successful"
356- )
357- else :
358- logger .debug (
359- f"['{ conn_name } ']: Proactive IAM token refresh probe encountered error across all targets"
360- )
361-
362-
363- def _build_postgres_startup_packet (user : str , database : str ) -> bytes :
364- """Builds a PostgreSQL v3.0 StartupMessage for (user, database)."""
365- if not database :
366- database = user
367- body = (
368- b"user\x00 "
369- + user .encode ("utf-8" )
370- + b"\x00 database\x00 "
371- + database .encode ("utf-8" )
372- + b"\x00 \x00 "
373- )
374- total_len = 8 + len (body )
375- return total_len .to_bytes (4 , byteorder = "big" ) + b"\x00 \x03 \x00 \x00 " + body
0 commit comments