
    j4N                         d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ dZdZd	Zd
ZdZdZdZ ej        e          Z G d d          ZdS )    N)datetimetimezone)Optional)urlparse)	ZTSClient)set_cert_expiry_metriczF^(?:flava-)?(?P<product>[\w-]+)\.(?P<env>[\w-]+)\.(?P<project>[\w-]+)$z$http://lypwg01-001.yahoo-net.jp:8080zapj.zts.athenz.yahoo.co.jpi[  z.https://apj.zts.athenz.yahoo.co.jp:4443/zts/v1   i,  c                   X    e Zd Z	 	 	 ddZd Zd Zd Zd Zd Zd	 Z	d
 Z
d Zd Zd ZdS )AthenzClientNTc                    || _         || _        t          j        t          |          }|st          d| d          |                    d          | _        |                    d          | _        |                    d          | _	        ||st          d          t          j                            d| j        | j	                  }t          j                            || d	          }|#t          j                            || d
          }t          j                            |          st          d|           t          j        |t          j                  st#          d|           || _        || _        |rt          j        dt*                    nd| _        |                                  t1          t          j        dt3          t4                                        | _        d| _        t;          j                    | _        |                                  }tC          j!                    | _        tD          #                    d|           | $                                 dS )a  
        Initialize Athenz client with flexible path and proxy configuration.

        Args:
            account_name: Account name for authentication.
            provider_domain: Provider domain (e.g., flava-faas.stage.flava-qa or servicemap.stage.flava-api-test).
            key_path: Optional custom path to private key file.
            cert_path: Optional custom path to certificate file.
            use_proxy: Whether to use proxy for connections (default: True).
        z Invalid provider_domain format: z@. Expected: [flava-]{product-abbr}.{environment}.{flava-project}productenvprojectNz6account_name is required when key_path is not provided/z.key.pem	.cert.pemzPrivate key not found: $No read permission for private key: 	PROXY_URLCERT_CHECK_INTERVAL_SECONDSg        z6Initial certificate preparation completed (renewed=%s))%provider_domainaccount_namere	fullmatchSERVICE_PROVIDER_PATTERN
ValueErrorgroupproduct_abbrenvironmentproject_nameospathjoinexistsFileNotFoundErroraccessR_OKPermissionErrorkey_path	cert_pathgetenvDEFAULT_PROXY_URL	proxy_url_init_zts_configintstr#DEFAULT_CERT_CHECK_INTERVAL_SECONDS_cert_check_interval_last_cert_check_ts	threadingLock
_cert_lock_check_and_renewtimeloggerdebug_init_zts_client)	selfr   r   r'   r(   	use_proxymatchsecret_mount_pathreneweds	            A/Users/user/workspace/sujinbaek/cqa-test-app/lib/athenz_client.py__init__zAthenzClient.__init__    sb   $  /( 5GG 	X? X X X  
 "KK	22 ;;u--!KK	22   L   !#S$2BDDU V Vw||$5,7P7P7PQQH GLL):|<V<V<VWW	 w~~h'' 	J#$Hh$H$HIIIy27++ 	U!"S"S"STTT " :CLBIk#4555 	 	 %(I-788 %
 %
! $' #.** ''))#'9;; MwWWW 	    c                    t          j        d          }t          j        d          }t          j        d          }|rBt          |          }|j        pt          }|j        pt          }|| _        || _        || _	        dS |pt          }|rt          |          nt          }|| _        || _        |t          k    r|t          k    rt          | _	        dS d| d| d| _	        dS )zGInitialize ZTS host/port/endpoint from environment in a consistent way.ZTS_ENDPOINTZTS_HOSTZTS_PORTzhttps://:z/zts/v1N)r   r)   r   hostnameDEFAULT_ZTS_HOSTportDEFAULT_ZTS_PORTzts_hostzts_portzts_endpointr-   DEFAULT_ZTS_ENDPOINT)r:   zts_endpoint_envzts_host_envzts_port_envparsedhostrI   s          r?   r,   zAthenzClient._init_zts_configr   s    9^44y,,y,, 	D.//F?6&6D;2"2D DM DM 0D3#3D(4J3|$$$:JD DM DM'''D4D,D,D$8!!!$Ct$C$Cd$C$C$C!!!rA   c                    	 t          | j        | j        d          }| j        r
| j        |d<   t	          j        | j        | j        fi || _        dS # t          $ ry}t                              d| j        | j        | j        | j        | j        |           t          d| j         d| j         d| j         d| j         d	| j         d
|           |d}~ww xY w)zE(Re)initialize ZTSClient with current cert/key and ZTS configuration.i0*  )rS   rI   token_refresh_offsetr+   z^Failed to initialize ZTSClient (cert_path=%s, key_path=%s, proxy_url=%s, host=%s, port=%s): %sz*Failed to initialize ZTSClient (cert_path=z, key_path=z, proxy_url=z, host=z, port=z): N)dictrK   rL   r+   r   	with_certr(   r'   
zts_client	Exceptionr7   errorRuntimeError)r:   zts_client_kwargses      r?   r9   zAthenzClient._init_zts_client   sP   	 $]]%0! ! !
 ~ @15!+.'1  $ DOOO
  	 	 	LLR	 	 	 `"n` `9=` `!^` `48M` `JN-` `\]` `  		s   AA 
CA4CCc                    |                                   t                              d| j                   	 | j                            | j                  }t                              d| j                   |j        S # t          $ rA}t                              d| j        |           t          d| j         d|           |d}~ww xY w)z4Get access token for the configured provider domain.z?[AthenzClient] get_access_token() called for provider_domain=%szG[AthenzClient] access_token fetched successfully for provider_domain=%szD[AthenzClient] Failed to get access token for provider_domain=%s: %sz/Failed to get access token for provider_domain=z: N)
_ensure_cert_readyr7   r8   r   rX   get_access_tokenaccess_tokenrY   rZ   r[   )r:   ra   r]   s      r?   r`   zAthenzClient.get_access_token   s     	!!!M 	
 	
 	
	?;;D<PQQLLLY$    ,, 	 	 	LLV$  
 ]$BV]]Z[]] 	s   AA< <
C<CCc                    t          j                     }|| j        z
  | j        k     rdS | j        5  t          j                     }|| j        z
  | j        k     r	 ddd           dS t                              d| j        | j                   |                                 }|| _        |r.t                              d           |                                  ddd           dS # 1 swxY w Y   dS )z
        Periodically check and renew the certificate when access tokens are requested.

        This method is called on each access token request but throttles the
        actual check/renewal using CERT_CHECK_INTERVAL_SECONDS.
        Nz?Running periodic certificate check (interval=%s, last_check=%s)z8Certificate renewed/generated. Reinitializing ZTSClient.)	r6   r1   r0   r4   r7   r8   r5   infor9   )r:   nowr>   s      r?   r_   zAthenzClient._ensure_cert_ready   sS    ikk))D,EEEF_ 	( 	()++CT--0III		( 	( 	( 	( 	( 	( 	( 	( LLQ)(   ++--G'*D$  (VWWW%%'''%	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	(s   (C#%A1C##C'*C'c                 n   d}	 t                               d           d}t                               d|           t          j        |d           t          j        |d           |                                 }| j        }t                               d|           t                               d	|           |Pt          j        	                    |          r1t          j
        |t          j                  st          d|           t          j        	                    | j                  st          d| j                   t          j
        | j        t          j                  st          d| j                   t          j        	                    |          rt                               d           || _        |                                 rUt                               d           |                                  d}|                                 st%          d          nt                               d           n|1t          j        	                    |          rt                               d||           	 t'          j        ||           t          j        |d           t                               d           n%# t          $ r}t%          d|           |d
}~ww xY w|| _        |                                 rTt                               d           |                                  d}|                                 st%          d          nut                               d           nZt                               d           || _        |                                  d}|                                 st%          d          || _        t                               d           |                                  |S # t,          $ r!}t                               d|            d
}~ww xY w)z
        Check certificate expiry and renew if needed.

        Returns:
            True if certificate was newly generated or renewed, False otherwise.
        Fz.Starting certificate check and renewal process/tmp/athenzz$Ensuring athenz directory exists: %sT)exist_oki  zLatest cert path: %szOrigin cert path: %sNz+No read permission for origin certificate: zPrivate key not found at r   z-Latest certificate exists, checking expiry...z0Certificate needs renewal, attempting renewal...z+Certificate validation failed after renewalz!Latest certificate is still validz;Latest certificate not found, copying from origin: %s -> %si  z&Certificate copied and permissions setz/Failed to copy certificate due to permissions: z7Copied certificate needs renewal, attempting renewal...z!Copied certificate is still validz<No existing certificate found, generating new certificate...z.Certificate validation failed after generationz<Certificate check and renewal process completed successfullyz(Certificate check and renewal failed: %s)r7   rc   r8   r   makedirschmod_get_latest_cert_pathr(   r    r"   r$   r%   r&   r'   r#   _needs_renewal_renew_cert_validate_certr[   shutilcopy2_update_cert_expiry_metricrY   rZ   )r:   r>   
athenz_dirlatest_cert_pathorigin_cert_pathr]   s         r?   r5   zAthenzClient._check_and_renew   s;    `	KKHIII&JLL?LLLK
T2222HZ'''#99;;#~LL/1ABBBLL/1ABBB  +?O0P0P+y!127;; )XFVXX  
 7>>$-00 U'(SDM(S(STTT9T]BG44 %J4=JJ   w~~.// 6LMMM!1&&(( 	FKK RSSS$$&&&"G..00 *I  
 LL!DEEEE#/BGNNCS4T4T/KKU((  
!%57GHHH!15999%MNNNN* ! ! !*QaQQ  !!
 &6DN**,, JU   ((***"&#2244 ". M# # 
 %HIIIIKKV   &6DN$$&&&"G..00 *L   .DNKKVWWW ++---N 	 	 	LLCQGGG	s>   I?P	 AK	 P	 	
K+K&&K++DP	 	
P4P//P4c                 j   | j         pd| j        pd| j        pd| j        pdf}| j        r$t
          j                            | j                  s*t          	                    d           t          g |dR   dS 	 ddd| j        dd	g}t          j        |d
d
          }d}|j        dk    r|j                                        }|                    d          r|t#          d          d                                         }	 t%          j        |d          }|                    t*          j                  }t%          j                                        t*          j                  }t1          ||z
                                            }|dk     rd}n3# t4          $ r&}	t                              d||	           Y d}	~	nd}	~	ww xY wt          g ||R   t          	                    d|           dS # t4          $ r4}	t                              d|	           t          g |dR   Y d}	~	dS d}	~	ww xY w)zP
        Update certificate expiry metric based on current certificate.
        unknownz6Certificate does not exist, setting expiry metric to 0r   Nopensslx509-in-nooutz-enddateTcapture_outputtextz	notAfter=z%b %d %H:%M:%S %Y GMT)tzinfoz*Failed to parse cert notAfter date: %s, %sz0Updated cert expiry metric: %s seconds remainingz'Failed to update cert expiry metric: %s)r   r   r   r   r(   r   r    r"   r7   r8   r   
subprocessrun
returncodestdoutstrip
startswithlenr   strptimereplacer   utcutcnowr-   total_secondsrY   warningrZ   )
r:   labelscmdresultremaining_secondsline	not_afterdtrd   r]   s
             r?   rp   z'AthenzClient._update_cert_expiry_metricT  s   
 *)	**	
 ~ 	RW^^DN%C%C 	LLQRRR".F.A....F	/feT^XzRC^C4HHHF ! A%%}**,,??;//  $S%5%5%7%7 8 > > @ @I%.y:QRRZZx|Z<<&o//77x|7LL,/c0H0H0J0J,K,K),q0001-$   H%        #>F>,=>>>>LLBDU      	/ 	/ 	/LLBAFFF".F.A..........	/sD   9B	G4 BF G4 
G G<G4 G,G4 4
H2>)H--H2c                 "   | j         r$t          j                            | j                   st                              d           dS 	 t          t          j        dt          t                                        }|dz  }ddd| j         dt          |          d	g}t          j        |dd
          }|j        dk    }|rt                              d|           |S # t          $ r&}t                              d|           Y d}~dS d}~ww xY w)z
        Check if certificate needs renewal based on expiry time.

        Uses openssl -checkend to decide whether renewal is required.
        z,Certificate does not exist, renewal requiredTCERT_RENEWAL_THRESHOLD_HOURSi  rv   rw   rx   z	-checkendry   rz   r   z#Certificate expires within %s hoursz&Failed to check certificate expiry: %sN)r(   r   r    r"   r7   rc   r-   r)   r.   $DEFAULT_CERT_RENEWAL_THRESHOLD_HOURSr~   r   r   rY   rZ   )r:   threshold_hoursthreshold_secondsr   r   needs_renewalr]   s          r?   rk   zAthenzClient._needs_renewal  s/    ~ 	RW^^DN%C%C 	KKFGGG4	!	2<==  O !0$ 6 %&&C  ^C4HHHF"-2M TA?SSS   	 	 	LLA1EEE44444	s   	BC 
D(D		Dc                    t          j        d          st          d          d| j         d| j         }| j        }| j        }t          j        dt          j	                              }t                              d|||           dd| j        d|d	|d
| j        d|d| j        ddddddd|g}t                              dd                    |                     	 t#          j        |ddd          }t                              d           t                              d|j                   dS # t"          j        $ rS}t                              d|           t                              d|j                   t          d|           |d}~wt.          $ r3}t                              d|           t          d|           |d}~ww xY w)z$Renew certificate using zts-svccert.zzts-svccertzFzts-svccert command not found. Make sure athenz_tools_jp is installed.z
flava-iam..POD_UIDz:Renewing certificate for domain=%s, service=%s, pod_uid=%sz-ztsz-domainz-servicez-private-keyz-key-versionz
-cert-filez-hdrzYahoo-Principal-Authz-dns-domainzzts.athenz.cloudz	-providerzsys.auth.ztsz	-instancezExecuting: %s Tr{   r|   checkz*Certificate renewal completed successfullyzzts-svccert output: %szzts-svccert failed: %szError output: %szCertificate renewal failed: NzCertificate renewal error: %s)rn   whichr[   r   r   r   r   r)   socketgethostnamer7   rc   rM   r'   r(   r8   r!   r~   r   r   CalledProcessErrorrZ   stderrrY   )r:   domainservicekey_versionpod_uidr   r   r]   s           r?   rl   zAthenzClient._renew_cert  s   |M** 	X   Ed.DD1BDD#')Iv'9';';<<H		
 	
 	
 MN"+
0 	_chhsmm444
	J^C4tTTTFKKDEEELL16=AAAAA, 	J 	J 	JLL11555LL+QX666AaAABBI 	J 	J 	JLL8!<<<AaAABBI	Js&   AD0 0G?AFG.GGc                    | j         r$t          j                            | j                   s"t                              d| j                    dS 	 ddd| j         ddg}t          j        |ddd	          }d
|j        v rt          	                    d           dS t                              d           dS # t          $ r&}t                              d|           Y d}~dS d}~ww xY w)z=Validate that certificate is properly formatted and readable.z Certificate file not found at %sFrv   rw   rx   ry   z-textTr   zCertificate:z!Certificate validation successfulz.Certificate validation failed - invalid formatz Certificate validation error: %sN)r(   r   r    r"   r7   rZ   r~   r   r   r8   rY   )r:   r   r   r]   s       r?   rm   zAthenzClient._validate_cert  s    ~ 	RW^^DN%C%C 	LL;T^LLL5	feT^XwOC^C4tTTTF..@AAAtLLIJJJ5 	 	 	LL;Q???55555	s   AB5 B5 5
C%?C  C%c                     | j          d| j         d| j         d}t          j                            d|          }t                              d|           |S )zRCalculate latest certificate path: /tmp/athenz/{project}.{env}.{account}.cert.pem.r   r   rf   zGenerated latest cert path: %s)r   r   r   r   r    r!   r7   r8   )r:   filenamerr   s      r?   rj   z"AthenzClient._get_latest_cert_path  sb      RR4#3RRd6GRRR 	 7<<x@@57GHHHrA   )NNT)__name__
__module____qualname__r@   r,   r9   r`   r_   r5   rp   rk   rl   rm   rj    rA   r?   r   r      s        
 M  M  M  M dD D D.  H  :( ( (@h h hT// // //b( ( (T6J 6J 6Jp  *         rA   r   )r   r   r~   rn   loggingr   r2   r6   r   r   typingr   urllib.parser   yj.athenz.clientr   common.cert_metricsr   r   r*   rH   rJ   rN   r   r/   	getLoggerr   r7   r   r   rA   r?   <module>r      s2   				 				             ' ' ' ' ' ' ' '       ! ! ! ! ! ! & & & & & & 6 6 6 6 6 6 N  ; /  G '- $&) #		8	$	$d  d  d  d  d  d  d  d  d  d rA   