
    p!                     l   S r SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSK	J
r
  SSKrSSKJr  SS	KJr  SS
KJr  Sq\R"                  R%                  \R"                  R'                  SSS5      5      rSrSr " S S\5      r " S S\5      rS rS rS rS rS r " S S\5      r S r!S r"g)z)Manages device context mTLS certificates.    )absolute_import)print_function)division)unicode_literalsN)config)	exception)	boto_util)execution_util~z.secureConnectzcontext_aware_metadata.jsoncert_provider_commandz--with_passphrasec                       \ rS rSrSrSrg)CertProvisionError+   z9Represents errors when provisioning a client certificate. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       'platform/gsutil/gslib/context_config.pyr   r   +   s    Ar   r   c                       \ rS rSrSrSrg)(ContextConfigSingletonAlreadyExistsError0   z>Error for when create_context_config is called multiple times.r   Nr   r   r   r   r   r   0   s    Fr   r   c                     U R                  S5      (       a  U R                  S5      (       a  SSU SS 4$ U R                  S5      (       a  U R                  S5      (       a  SSU SS 4$ g	)
z)Returns (begin:bool, end:bool, name:str).z-----BEGIN z-----TF   z	-----END 	   )FF )
startswithendswith)lines    r   _is_pem_section_markerr%   5   se    	__]##g(>(>R##{##g(>(>$Qr
""r   c                 \   0 n/ nSnU R                  5        H  nUR                  5       nU(       d  M  [        U5      u  pgnU(       aG  U(       a  UR                  SU-  5        XR	                  5       ;   a  UR                  SU-  5        Un/ nOCU(       a<  U(       d  UR                  SU-  5        O XH:w  a  UR                  SU< SU< 35        SnU(       d  M  UR                  U5        U(       d  M  SR                  U5      S-   X('   SnM     U(       a  UR                  SU-  5        U$ )	a  Returns dict with {name: section} by parsing contents in PEM format.

A simple parser for PEM file. Please see RFC 7468 for the format of PEM
file. Not using regex to improve performance catching nested matches.
Note: This parser requires the post-encapsulation label of a section to
match its pre-encapsulation label. It ignores a section without a
matching label.

Args:
  contents (str): Contents of a PEM file.
  logger (logging.logger): gsutil logger.

Returns:
  A dict of the PEM file sections.
Nz0Section %s missing end line and will be ignored.zASection %s already exists, and the older section will be ignored.z8Section %s missing a beginning line and will be ignored.zSection z% missing a matching end line. Found: 
zSection %s missing an end line.)
splitlinesstripr%   warningkeysappendjoin)	contentsloggerresult	pem_linespem_section_namer$   beginendnames	            r   _split_pem_into_sectionsr6   ?   s"     &)!!#d::<D-d3E	I'( 	)		 %'+, 	-i	FM	O#($0 	1t	yy+d29 $< 
NN47GGH	-r   c                      [         R                  R                  [        5      n [         R                  R	                  U 5      (       d  gU $ )zChecks for content aware metadata.

If content aware metadata exists, return its absolute path;
otherwise, returns None.

Returns:
  str: Absolute path if exists. Otherwise, None.
N)ospath
expanduser_DEFAULT_METADATA_PATHexists)metadata_paths    r   _check_pathr>   w   s5     ''$$%;<-		&	&	r   c                      [        U 5       n[        R                  " U5      sSSS5        $ ! , (       d  f       g= f! [         a  n[	        U5      eSnAff = f)zLoads context aware metadata from the given path.

Returns:
    dict: The metadata JSON.

Raises:
    CertProvisionError: If failed to parse metadata as JSON.
N)openjsonload
ValueErrorr   )r=   fes      r   _read_metadata_filerF      sB     	m	YYq\ 
			  
Q
 s)   > -	> 
;> > 
AAAc                      [        5       n U (       d  [        S5      e[        U 5      n[        U;  a  [        S5      eU[           n[        U;  a  UR                  [        5        U$ )zLoads default cert provider command.

Returns:
    str: The default command.

Raises:
    CertProvisionError: If command cannot be found.
z+Client certificate provider file not found.z.Client certificate provider command not found.)r>   r   rF   _CERT_PROVIDER_COMMAND(_CERT_PROVIDER_COMMAND_PASSPHRASE_OPTIONr,   )r=   metadata_jsoncommands      r   _default_commandrL      s]     --	
J
KK%m4-=0
M
NN01'.g=NN;<	.r   c                   *    \ rS rSrSrS rS rS rSrg)_ContextConfig   zRepresents the configurations associated with context aware access.

Only one instance of Config can be created for the program.
c                    Xl         [        R                  " SS5      U l        SU l        U R                  (       d  g[
        R                  " U R                  5        [        R                  R                  [        R                  " 5       S5      U l         U R                  U R                  5        g! [         a(  nU R                   R                  SU-  5         SnAgSnAff = f)zEInitializes config.

Args:
  logger (logging.logger): gsutil logger.
Credentialsuse_client_certificateNzcaa_cert.pemz*Failed to provision client certificate: %s)r/   r   getboolrR   client_cert_pathatexitregister_unprovision_client_certr8   r9   r-   r	   GetGsutilStateDir_provision_client_certr   error)selfr/   rE   s      r   __init___ContextConfig.__init__   s     K"(..1I#KD D&& OOD112GGLL)D)D)F)79DJ !!$"7"78 J
kkDqHIIJs   B1 1
C#;CC#c                 |   [         R                  " SSS5      nU(       a  UR                  S5      nO
[        5       n [        R
                  " U5      u  pE[        X@R                  5      n[        US5       nUR                  US   5        SU;   a0  UR                  US   5        US   R                  5       S	   U l        OUR                  US
   5        SU l        SSS5        g! , (       d  f       g= f! [        R                  [        4 a  n[        U5      eSnAf[          a  n[        SU-  5      eSnAff = f)zDExecutes certificate provider to obtain client certificate and keys.rQ   r   N zw+CERTIFICATEzENCRYPTED PRIVATE KEY
PASSPHRASE   zPRIVATE KEYz6Invalid output format from certificate provider, no %s)r   getsplitrL   r
   ExecuteExternalCommandr6   r/   r@   writer(   client_cert_passwordr   ExternalBinaryErrorOSErrorr   KeyError)	r[   	cert_pathcert_command_stringcert_commandcommand_stdout_string_sectionsrD   rE   s	            r   rY   %_ContextConfig._provision_client_cert   s$    **]4K%)+(..s3l &'lH!/!F!F
" **?Mh	4 A	'("h.
''(23
4&.|&<&G&G&I!&L$
#
''(=)
*&*$
# !   ))73 "q!! H
BQ
FH HHsB   9C6 6A&C%C6 %
C3/C6 3C6 6D;DD;(D66D;c                    U R                   bJ   [        R                  " U R                   5        U R                  R	                  SU R                   -  5        gg! [
         a(  nU R                  R                  SU-  5         SnAgSnAff = f)z@Cleans up any files or resources provisioned during config init.NzUnprovisioned client cert: %sz'Failed to remove client certificate: %s)rT   r8   remover/   debugri   rZ   )r[   rE   s     r   rW   '_ContextConfig._unprovision_client_cert   s}    (I
		$''(9//0 	1 )
  ICaGHHIs   AA 
B#BB)rg   rT   r/   rR   N)	r   r   r   r   r   r\   rY   rW   r   r   r   r   rN   rN      s    
J4H:Ir   rN   c                 F    [         (       d  [        U 5      q [         $ [        e)zShould be run once at gsutil startup. Creates global singleton.

Args:
  logger (logging.logger): For logging during config functions.

Returns:
  New ContextConfig singleton.

Raises:
  Exception if singleton already exists.
)_singleton_configrN   r   )r/   s    r   create_context_configrx      s!     
	&v.00r   c                      [         $ )zoRetrieves ContextConfig global singleton.

Returns:
  ContextConfig or None if global singleton doesn't exist.
)rw   r   r   r   get_context_configrz   
  s
     
r   )#r   
__future__r   r   r   r   rU   rA   r8   botor   gslibr   gslib.utilsr	   r
   rw   r9   r:   r-   r;   rH   rI   	Exceptionr   r   r%   r6   r>   rF   rL   objectrN   rx   rz   r   r   r   <module>r      s    0 & %  '   	    ! &   ++GGLL&(EFH 0 +> ( 
y 
5p  2EIV EIP1&r   