
    P                       S 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rSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSK J!r!  SSK"J#r$  SSK"J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-J.r.  \	R^                  Ra                  SSS5      r1\	R^                  Ra                  SSS5      r2\	R^                  Ra                  SSS5      r3Sr4Sr5Sr6Sr7 " S S \Rp                  5      r9 " S! S"\Rp                  5      r: " S# S$\Rp                  5      r; " S% S&\Rp                  5      r< " S' S(\Rp                  5      r= " S) S*\R|                  5      r? " S+ S,\@5      rAS- rB " S. S/\R|                  5      rC " S0 S1\R|                  5      rD " S2 S3\@5      rES4 rFS5 rGS6 rHS7 rIS8 rJS9 rKS: rL     S^S; jrMS< rN " S= S>\@5      rOS_S? jrPS@ rQ S`SA jrRSB rS " SC SD\@5      rTS`SE jrUSF rVSG rWSH rX        SaSI jrYSJ rZSK r[SL r\ " SM SN\@5      r]SO r^SP r_SQ r`SR raSS rb " ST SU\@5      rc " SV SW\@5      rd " SX SY\@5      re " SZ S[\@5      rf " S\ S]\@5      rgg)bzJSSH client utilities for key-generation, dispatching the ssh commands etc.    )absolute_import)division)unicode_literalsN)
exceptions)client)base)oslogin_utils)gaia)config)execution_utils)log)
properties)
console_io)creds)store)files)	platforms)retry)quote~.sshr   google_compute_engine_skgoogle_compute_engine_certzenable-osloginzenable-oslogin-2fazenable-oslogin-skzenable-oslogin-certificatesc                       \ rS rSrSrSrg)InvalidKeyError?   z#Indicates a key file was not found. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       .lib/googlecloudsdk/command_lib/util/ssh/ssh.pyr   r   ?   s    +r%   r   c                       \ rS rSrSrSrg)MissingCommandErrorC   z8Indicates that an external executable couldn't be found.r   Nr   r   r%   r&   r(   r(   C   s    @r%   r(   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )CommandErrorG   z7Raise for a failure when invoking ssh, scp, or similar.c                 d  > U(       d  U(       d  [        S5      eXl        U(       a  SR                  U5      OS nU(       a  SR                  U5      OS nSR                  XE4 Vs/ s H  of(       d  M  UPM     sn5      n[        [
        U ]  SR                  U R                  U5      US9  g s  snf )Nz*One of message or return_code is required.z[{0}]zreturn code [{0}]z and z[{0}] exited with {1}.)	exit_code)
ValueErrorcmdformatjoinsuperr+   __init__)	selfr0   messagereturn_codemessage_textreturn_code_textf
why_failed	__class__s	           r&   r4   CommandError.__init__J   s    {CDDH.57>>'*4L3>"";/D  !4:4q4:J 
,& ''*= '  	;s   %
B-3B-)r0   NNr   r    r!   r"   r#   r4   r$   __classcell__r<   s   @r&   r+   r+   G   s    ? r%   r+   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidConfigurationError^   z@When arguments provided have misconfigured sources/destinations.c                 P   > [         [        U ]  USR                  X#5      -   5        g )Nz"  Got sources: {}, destination: {})r3   rC   r4   r1   )r5   msgsourcesdestinationr<   s       r&   r4   "InvalidConfigurationError.__init__a   s'    	
#T3299'OOr%   r   r?   rA   s   @r&   rC   rC   ^   s    H r%   rC   c                       \ rS rSrSrSrg)BadCharacterErrorg   z9Indicates a character was found that couldn't be escaped.r   Nr   r   r%   r&   rK   rK   g   s    Ar%   rK   c                        \ rS rSrSrSrSrSrg)Suitek   z'Represents an SSH implementation suite.OpenSSHPuTTYr   N)r   r    r!   r"   r#   OPENSSHPUTTYr$   r   r%   r&   rN   rN   k   s    /'
%r%   rN   c                       \ rS rSrSr\R                  SSSSS.\R                  SSS	S
S.0r\R                  S\R                  S0r	SS jr
S rS r\S 5       rSrg)Environmentr   a  Environment maps SSH commands to executable location on file system.

  Recommended usage:

  env = Environment.Current()
  env.RequireSSH()
  cmd = [env.ssh, 'user@host']

An attribute which is None indicates that the executable couldn't be found.

Attributes:
  suite: Suite, The suite for this environment.
  bin_path: str, The path where the commands are located. If None, use
    standard `$PATH`.
  ssh: str, Location of ssh command (or None if not found).
  ssh_term: str, Location of ssh terminal command (or None if not found), for
    interactive sessions.
  scp: str, Location of scp command (or None if not found).
  keygen: str, Location of the keygen command (or None if not found).
  ssh_exit_code: int, Exit code indicating SSH command failure.
sshscpz
ssh-keygen)rW   ssh_termrX   keygenplinkputtypscp	winkeygen      Nc           
      $   Xl         X l        SU l        SU l        SU l        SU l        [        R                  " U R                  U   5       H-  u  p4[        X[        R                  " X@R                  S95        M/     U R                  U   U l        g)zCreate a new environment by supplying a suite and command directory.

Args:
  suite: Suite, the suite for this environment.
  bin_path: str, the path where the commands are located. If None, use
    standard $PATH.
Npath)suitebin_pathrW   rY   rX   rZ   six	iteritemsCOMMANDSsetattrr   FindExecutableOnPathSSH_EXIT_CODESssh_exit_code)r5   rd   re   keyr0   s        r&   r4   Environment.__init__   st     JMDHDMDHDKMM$--"67d33CmmLM 8,,U3Dr%   c                 p    [        U R                  U R                  U R                  U R                  45      $ )zpWhether all SSH commands are supported.

Returns:
  True if and only if all commands are supported, else False.
)allrW   rY   rX   rZ   r5   s    r&   SupportsSSHEnvironment.SupportsSSH   s(     $--4;;?@@r%   c                 D    U R                  5       (       d  [        S5      eg)zSimply raises an error if any SSH command is not supported.

Raises:
  MissingCommandError: One or more of the commands were not found.
z#Your platform does not support SSH.N)rr   r(   rq   s    r&   
RequireSSHEnvironment.RequireSSH   s$      EFF r%   c                     [         R                  R                  5       (       a  [        R                  n[        5       nO[        R                  nSn[        X5      $ )zoRetrieve the current environment.

Returns:
  Environment, the active and current environment on this machine.
N)r   OperatingSystem	IsWindowsrN   rS   _SdkHelperBinrR   rU   )clsrd   re   s      r&   CurrentEnvironment.Current   sB       **,,kkehmmehu''r%   )re   rZ   rX   rW   rl   rY   rd   N)r   r    r!   r"   r#   rN   rR   rS   rh   rk   r4   rr   ru   classmethodr|   r$   r   r%   r&   rU   rU   r   s    0 mm 	 kk	(" mmSkk1.
4$AG ( (r%   rU   c                 &    [        S U  5       5      $ )Nc              3   V   #    U  H  n[        U5      S :  =(       a    US:g  v   M!     g7f)    N)ord).0cs     r&   	<genexpr>&_IsValidSshUsername.<locals>.<genexpr>   s$     51SVc\&a3h&s   '))rp   users    r&   _IsValidSshUsernamer      s     
55	55r%   c                        \ rS rSrSrSrSrSrg)KeyFileStatus   OKz	NOT FOUNDBROKENr   N)r   r    r!   r"   PRESENTABSENTr   r$   r   r%   r&   r   r      s    '&&r%   r   c                   $    \ rS rSrSrSrSrSrSrg)_KeyFileKind   z-List of supported (by gcloud) key file kinds.privatepublicz	PuTTY PPKr   N)	r   r    r!   r"   r#   PRIVATEPUBLICPPKr$   r   r%   r&   r   r      s    5'&#r%   r   c                       \ rS rSrSr\R                  R                  SSS5      r " S S\	5      r
 " S S	\	5      rSS jr\SS j5       r\S 5       rS rS rSS jrS rS rSS jrSrg
)Keys   a  Manages private and public SSH key files.

This class manages the SSH public and private key files, and verifies
correctness of them. A Keys object is instantiated with a path to a
private key file. The public key locations are inferred by the private
key file by simply appending a different file ending (`.pub` and `.ppk`).

If the keys are broken or do not yet exist, the EnsureKeysExist method
can be utilized to shell out to the system SSH keygen and write new key
files.

By default, there is an SSH key for the gcloud installation,
`DEFAULT_KEY_FILE` which should likely be used. Note that SSH keys are
generated and managed on a per-installation basis. Strictly speaking,
there is no 1:1 relationship between installation and user account.

Verifies correctness of key files:
 - Populates list of SSH key files (key pair, ppk key on Windows).
 - Checks if files are present and (to basic extent) correct.
 - Can remove broken key (if permitted by user).
 - Provides status information.
r   r   google_compute_enginec                   <    \ rS rSrSrSS jr\S 5       rS	S jrSr	g)
Keys.PublicKeyi  zRepresents a public key.

Attributes:
  key_type: str, Key generation type, e.g. `ssh-rsa` or `ssh-dss`.
  key_data: str, Base64-encoded key data.
  comment: str, Non-semantic comment, may be empty string or contain spaces.
c                 (    Xl         X l        X0l        g r~   )key_typekey_datacomment)r5   r   r   r   s       r&   r4   Keys.PublicKey.__init__
  s    mmlr%   c                 b   UR                  5       n[        U[        R                  5      (       a  UR	                  SS5      nUR                  SS5      n[        U5      S:  a  [        SR                  U5      5      e[        U5      S:  a  US   R                  5       OSnU " US   US   U5      $ )	a/  Construct a public key from a typical OpenSSH-style key string.

Args:
  key_string: str, on the format `TYPE DATA [COMMENT]`. Example: `ssh-rsa
    ABCDEF me@host.com`.

Raises:
  InvalidKeyError: The public key file does not contain key (heuristic).

Returns:
  Keys.PublicKey, the parsed public key.
zutf-8replacer      zPublic key [{}] is invalid. r   r`   )	strip
isinstancerf   binary_typedecodesplitlenr   r1   )r{   
key_stringdecoded_keypartsr   s        r&   FromKeyStringKeys.PublicKey.FromKeyString  s    $ $$&k	J	0	0!(()<Q'e	Ua;BB:NOO$'JNa gq58W--r%   c                     SnU(       a  U R                   (       a  US-  nUR                  U R                  U R                  U R                   S9$ )zFormat this key into a text entry.

Args:
  include_comment: str, Include the comment part in this entry.

Returns:
  str, A key string on the form `TYPE DATA` or `TYPE DATA COMMENT`.
z{type} {data}z
 {comment})typedatar   )r   r1   r   r   )r5   include_comment
out_formats      r&   ToEntryKeys.PublicKey.ToEntry*  sG     #j	T\\l"
}}4==$,,   r%   )r   r   r   N)r   F)
r   r    r!   r"   r#   r4   r   r   r   r$   r   r%   r&   	PublicKeyr     s%    
 . .4r%   r   c                       \ rS rSrS rSrg)Keys.KeyFileDatai:  c                     Xl         S U l        g r~   filenamestatus)r5   r   s     r&   r4   Keys.KeyFileData.__init__<  s     mdkr%   r   N)r   r    r!   r"   r4   r$   r   r%   r&   KeyFileDatar   :  s    r%   r   Nc                 4   [         R                  R                  [        R                  " U5      5      n[         R                  R                  U5      U l        U=(       d    [        R                  5       U l	        [        R                  U R                  U5      [        R                  U R                  US-   5      0U l        U R                  R                  [         R"                  L a0  U R                  US-   5      U R                  [        R$                  '   gg)a"  Create a Keys object which manages the given files.

Args:
  key_file: str, The file path to the private SSH key file (other files are
    derived from this name). Automatically handles symlinks and user
    expansion.
  env: Environment, Current environment or None to infer from current.
z.pub.ppkN)osrc   realpathr   ExpandHomeDirdirnamedirrU   r|   envr   r   r   r   keysrd   rN   rS   r   )r5   key_filer   private_key_files       r&   r4   Keys.__init__C  s     ww''(;(;H(EFww/0DH+k))+DHd../?@T--.>.GHDI xx~~$$($4$45E5N$Odii  ! %r%   c                 B    U " U=(       d    [         R                  U5      $ )a  Create Keys object given a file name.

Args:
  filename: str or None, the name to the file or DEFAULT_KEY_FILE if None
  env: Environment, Current environment or None to infer from current.

Returns:
  Keys, an instance which manages the keys with the given name.
)r   DEFAULT_KEY_FILE)r{   r   r   s      r&   FromFilenameKeys.FromFilenameV  s     x0400#66r%   c                 P    U R                   [        R                     R                  $ )z!Filename of the private key file.)r   r   r   r   rq   s    r&   r   Keys.key_filec  s     99\))*333r%   c           
      V   / nSnSnU R                    HZ  nU R                   U   n[        U[        UR                  5      5      n[        U[        UR                  R                  5      5      nM\     U R                    H  nU R                   U   nUR                  SR                  UR                  S-   R                  US-   5      SUR                  R                  -   S-   R                  US-   5      UR                  5      5        M     UR                  5         SR                  U5      $ )	z3Prepares human readable SSH key status information.r   z{} {} [{}]
z key   ()r   r   )r   maxr   valuer   appendr1   ljustr   sortr2   )r5   messageskey_paddingstatus_paddingkindr   s         r&   _StatusMessageKeys._StatusMessageh  s    HKN		YYt_dS_5k>3t{{/@/@+ABn  		YYt_doo


zzF"))+/:T[[&&&,33NQ4FGmm  MMO778r%   c                 6  ^  U 4S jnT R                    H  nU" U5      T R                   U   l        M     T R                   [        R                     R                  [        R
                  L a   T R                  5         [        R                  " T R                   5       Vs/ s H  o3R                  PM     nn[        S U 5       5      (       a  [        R                  $ [        S U 5       5      (       a  [        R
                  $ [        R                  $ ! [         at    [        R                  " SR                  T R                   [        R                     5      5        [        R                  T R                   [        R                     l         GNf = fs  snf )a  Performs minimum key files validation.

Note that this is a simple best-effort parser intended for machine
generated keys. If the file has been user modified, there's a risk
of both false positives and false negatives.

Returns:
  KeyFileStatus.PRESENT if key files meet minimum requirements.
  KeyFileStatus.ABSENT if neither private nor public keys exist.
  KeyFileStatus.BROKEN if there is some key, but it is broken or incomplete.
c                    > TR                  TR                  U    R                  U R                  5      n[	        U[
        5      (       a  U$ UTR                  U    l        [
        R                  $ r~   )_WarnOrReadFirstKeyLiner   r   r   r   r   
first_liner   )r   status_or_liner5   s     r&   ValidateFile#Keys.Validate.<locals>.ValidateFile  s[    33
))D/
"
"DJJn 
NM	2	2%3		$"$$$r%   z(The public SSH key file [{}] is corrupt.c              3   F   #    U  H  o[         R                  :H  v   M     g 7fr~   )r   r   r   xs     r&   r    Keys.Validate.<locals>.<genexpr>  s     
?.>$$$.>   !c              3   F   #    U  H  o[         R                  :H  v   M     g 7fr~   )r   r   r   s     r&   r   r     s     B1AA-'''1Ar   )r   r   r   r   r   r   GetPublicKeyr   r   warningr1   r   rf   
itervaluesrp   r   )r5   r   	file_kindr   collected_valuess   `    r&   ValidateKeys.Validate}  s8   % YY	$0$;dii	!  yy$$%,,0E0EEE +...*CD*CQ*CD

?.>
???!!!	B1AB	B	B"""!!!  E6==		,--.	

 1>0D0D		,%%&-E Es   .D  FA:FFc                    SU R                  5       -   nUSL a  [        R                  " US-   5      eUS-  n[        R                  " U5        Uc  [        R
                  " SSS9  [        R                  " U R                  5       H$  n [        R                  " UR                  5        M&     g! [         a*  nUR                  [        R                  :X  a  e  SnAMX  SnAff = f)a  Removes all SSH key files if user permitted this behavior.

Precondition: The SSH key files are currently in a broken state.

Depending on `force_key_file_overwrite`, delete all SSH key files:

- If True, delete key files.
- If False, cancel immediately.
- If None and
  - interactive, prompt the user.
  - non-interactive, cancel.

Args:
  force_key_file_overwrite: bool or None, overwrite broken key files.

Raises:
  console_io.OperationCancelledError: Operation intentionally cancelled.
  OSError: Error deleting the broken file(s).
zYour SSH key files are broken.
FzOperation aborted.z*We are going to overwrite all above files.NT)defaultcancel_on_no)r   r   OperationCancelledErrorr   r   PromptContinuerf   
viewvaluesr   r   remover   OSErrorerrnoEISDIR)r5   force_key_file_overwriter6   r   es        r&   RemoveKeyFilesIfPermittedOrFail$Keys.RemoveKeyFilesIfPermittedOrFail  s    ( 143F3F3HHG5(..w9M/MNN;;GKK' DA NN499-
		(##$ .  77ell"
 #s   	 B..
C"8CC"c                     [         R                  " U5       nUR                  5       R                  5       nU(       a  UsSSS5        $ Sn[        R
                  nSSS5        [        R                  " SUW5        W$ ! , (       d  f       N(= f! [         R                   a    Sn[        R                  n NS[         R                   a    Sn[        R
                  n Nzf = f)a  Returns the first line from the key file path.

A None return indicates an error and is always accompanied by a log.warning
message.

Args:
  path: The path of the file to read from.
  kind: The kind of key file, 'private' or 'public'.

Returns:
  None (and prints a log.warning message) if the file does not exist, is not
  readable, or is empty. Otherwise returns the first line utf8 decoded.
Nzis emptyzdoes not existzis not readablez"The %s SSH key file for gcloud %s.)r   
FileReaderreadliner   r   r   MissingFileErrorr   Errorr   r   )r5   rc   r   r:   linerF   r   s          r&   r   Keys._WarnOrReadFirstKeyLine  s    $D!Qzz|!!# "! %% " KK4dC@M "! !! $c##f;; $c##f$s?   B 'A=	B 	A=B =
BB B &C6%CCc                    U R                   [        R                     R                  n[        R
                  " U5       nUR                  5       nU R                  R                  U5      sSSS5        $ ! , (       d  f       g= f)a%  Returns the public key verbatim from file as a string.

Precondition: The public key must exist. Run Keys.EnsureKeysExist() prior.

Raises:
  InvalidKeyError: If the public key file does not contain key (heuristic).

Returns:
  Keys.PublicKey, a public key (that passed primitive validation).
N)	r   r   r   r   r   r
  r  r   r   )r5   filepathr:   r   s       r&   r   Keys.GetPublicKey  sY     yy,,-66H			(	#q ::<j^^))*5	 
$	#	#s   +A33
Bc                    U R                  5       nU[        R                  L a  U R                  U5        U[        R                  La  U[        R
                  L a,  [        R                  " S5        [        R                  " S5        [        R                  R                  U R                  5      (       dR  SR                  U R                  5      n[        R                  " USSS9  [        R                   " U R                  S5        [#        U R$                  US9nUR'                  U R(                  5        U R(                  R*                  [,        R.                  L a  [0        R2                  " 5       R4                  n[        R                  R                  U5      (       d\  U[        R                  L a0  [#        U R$                  S	SS
9nUR'                  U R(                  5         [        R6                  " US5        ggg! [        R8                   a/  n[        R:                  " SR                  U5      5         SnAgSnAff = f)a  Generate ssh key files if they do not yet exist.

Precondition: Environment.SupportsSSH()

Args:
  overwrite: bool or None, overwrite key files if they are broken.
  allow_passphrase: bool, if keygeneration occurs, let the user specify a
    passphrase for private key encryption. See `ssh.KeygenCommand` for
    details on when this is possible.

Raises:
  console_io.OperationCancelledError: if interrupted by user
  CommandError: if the ssh-keygen command failed.
z&You do not have an SSH key for gcloud.z.SSH keygen will be executed to generate a key.zUThis tool needs to create the directory [{0}] before being able to generate SSH keys.Tz#SSH key generation aborted by user.)r6   r   cancel_string  )allow_passphraseF)r  reencode_ppkr   z$Failed to create sentinel file: [{}]N)r   r   r   r  r   r   r   r   r   rc   existsr   r1   r   r   r   MakeDirKeygenCommandr   Runr   rd   rN   rS   r   Pathsvalid_ppk_sentinel_fileWriteFileContentsr  debug)r5   	overwriter  key_files_validityrF   r0   valid_ppk_sentinelr  s           r&   EnsureKeysExistKeys.EnsureKeysExist  s    ]111
**95!6!66	}33	3<=DEWW^^DHH%%))/)9 	 	!!?	

 	dhh&$--:JKc	ggdhhxx~~$ "<<>AAWW^^.//!6!66mme$# ''$((
	F

!
!"4b
9 0 % {{ 	F
 )):AA!D
E
E	Fs   $G> >I%H<<I)r   r   r   r~   r>   )T)r   r    r!   r"   r#   r   rc   r2   r   objectr   r   r4   r   r   propertyr   r   r   r  r   r   r#  r$   r   r%   r&   r   r      s    . WW\\#v/FG7& 7rF P& 
7 
7 4 4*/"b&P<6$=Fr%   r   c                     [         R                  R                  [        R                  " [
        5      5      n[         R                  R                  USR                  XU5      5      $ Nz{}_{}_{}-cert.pubr   rc   r   r   r   CERTIFICATE_DIRr2   r1   )projectregion
deploymentcert_dirs       r&   CertFileFromCloudRunDeploymentr/  F  sI    WWe11/BC(	  *=
 r%   c           	          [         R                  R                  [        R                  " [
        5      5      n[         R                  R                  USR                  XX#5      5      $ )Nz{}_{}_{}_{}-cert.pubr)  )r+  serviceversioninstancer.  s        r&   CertFileFromAppEngineInstancer4  N  sI    WWe11/BC(	##GgH
 r%   c                     [         R                  R                  [        R                  " [
        5      5      n[         R                  R                  USR                  XU5      5      $ r(  r)  )
project_idzoneinstance_idr.  s       r&   CertFileFromComputeInstancer9  V  sI    WWe11/BC(	#**:[I
 r%   c                 n   [         R                  R                  [        R                  " [
        5      5      n[        R                  " USS9  [        XU5      n [        R                  " XP5        g! [        R                   a/  n[        R                  " SR                  XV5      5         SnAgSnAff = f)a   Writes a certificate associated with the key pair for Cloud Run.

Args:
  cert: string, The SSH certificate data.
  project: string, The project ID of the instance.
  region: string, The region of the deployment.
  deployment: string, The deployment name.
r  mode)Failed to update the certificate {}: [{}]N)r   rc   r   r   r   r*  r  r/  r  r  r   r  r1   )certr+  r,  r-  r.  r  r  s          r&   WriteCloudRunCertificater?  ]  s     WWe11/BC(--u%+GZH(O	H+	 OII9@@MNNO   A1 1B4%B//B4c                 n   [         R                  R                  [        R                  " [
        5      5      n[        R                  " USS9  [        XX45      n [        R                  " X`5        g! [        R                   a/  n[        R                  " SR                  Xg5      5         SnAgSnAff = f)a+  Writes a certificate associated with the key pair for App Engine.

Args:
  cert: string, The SSH certificate data.
  project: string, The project ID of the instance.
  service: string, The service of the instance.
  version: string, The version of the instance.
  instance: string, The instance ID.
r  r;  r=  N)r   rc   r   r   r   r*  r  r4  r  r  r   r  r1   )r>  r+  r1  r2  r3  r.  r  r  s           r&   WriteAppEngineCertificaterB  p  s     WWe11/BC(--u%*7WO(O	H+	 OII9@@MNNOr@  c                 n   [         R                  R                  [        R                  " [
        5      5      n[        R                  " USS9  [        XU5      n [        R                  " XP5        g! [        R                   a/  n[        R                  " SR                  XV5      5         SnAgSnAff = f)zWrites a certificate associated with the key pair.

Args:
  cert: string, The SSH certificate data.
  project_id: string, The project ID of the instance.
  zone: string, The zone of the instance.
  instance_id: string, The instance ID.
r  r;  r=  N)r   rc   r   r   r   r*  r  r9  r  r  r   r  r1   )r>  r6  r7  r8  r.  r  r  s          r&   WriteComputeCertificaterD    s     WWe11/BC(--u%(;G(O	H+	 OII9@@MNNOr@  c                     [        XU5      n[        R                  R                  U5      (       a  [        R                  " U5        gg)zDeletes an OS Login certificate file.

Args:
  project_id: string, The project ID of the instance.
  zone: string, The zone of the instance.
  instance_id: string, The instance ID.
N)r9  r   rc   r  r  )r6  r7  r8  r  s       r&   DeleteCertificateFilerF    s4     );G(WW^^HIIh r%   c                   ^  U 4S jnU(       a  [        US   US   US   US   5      nO'U(       a  [        UUS   US   5      nO[        XU5      n[        USS	9n [        R
                  R                  U5      (       a  UR                  US
9  gg! [         a/  n	[        R                  " SR                  Xy5      5         Sn	A	gSn	A	ff = f)a  Checks if the certificate is currently valid for a given instance.

Args:
  oslogin_state: An OsloginState object.
  project_id: string, The project ID of the instance.
  zone: string, The zone of the instance.
  instance_id: string, The instance ID.
  app_engine_params: dict, values of (appsId, servicesId, versionId,
    instanceId, serviceAccount, region) for App Engine instances.
  cloud_run_params: dict, values of (region, deployment_name, project_id) for
    Cloud Run deployments.
c                 8  > Sn[         R                  " SU 5      nU(       d  g [        R                  R                  US   U5      n[        R                  R                  US   U5      n[        R                  R	                  5       nXS:  =(       a    XT:  Tl        g )Nz%Y-%m-%dT%H:%M:%Sz#\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}r   r`   )refindalldatetimestrptimenowsigned_ssh_key)r>  time_formatmatchstartendrM  oslogin_states         r&   IsCertValid(ValidateCertificate.<locals>.IsCertValid  s|    %KJJ=tDE&&uQx=E



$
$U1X{
;C





!C#&;#<39M r%   appsId
servicesId
versionsIdinstancesIdr,  deployment_nameT)
print_cert)out_funcz(Cert File [{0}] could not be opened: {1}N)r4  r/  r9  r  r   rc   r  r  r+   r   r  r1   )
rS  r6  r7  r8  app_engine_paramscloud_run_paramsrT  	cert_filer0   r  s
   `         r&   ValidateCertificater`    s    (= -(#,','-(	I ."*+I ,JkJIiD1#O	ww~~i  	gg{g# !	 OII8??	MNNOs   3B 
C
%CC
c                    U R                   S:X  a  gU R                  nU(       d  g[        R                  R	                  [
        R                  " [        5      5      n[
        R                  " USS9  / n[        R                  " U5       HP  nUR                  S5      (       d  M  [        R                  R                  X$5      n[        R                  " U5        MR     [        U5       H[  u  pgSR                  U5      n[        R                  R                  X$5      n[
        R                  " XWSS9  UR!                  U5        M]     U$ )	zWrites temporary files from a list of key data.

Args:
  oslogin_state: An OsloginState object.

Returns:
  List of file paths for security keys or None if security keys are not
  supported.
r\   Nr  r;  tmp_skz
tmp_sk_{0}Tr   )environmentsecurity_keysr   rc   r   r   r   SECURITY_KEY_DIRr  listdir
startswithr2   r  	enumerater1   r  r   )rS  re  key_dir	key_filesr   	file_pathnumrm   s           r&   WriteSecurityKeysrn    s     ')--- 
GGU001ABC'--e$) **W%h8$$'',,w1iii	 & M*hc""3'HW/I	ID9Y	 + 
r%   c            	           \ rS rSrSr\R                  R                  \R                  " \R                  R                  SSS5      5      5      rS r\S 5       r\S 5       rS	 rSS
 jrSS jrS rSrg)
KnownHostsi  zRepresents known hosts file, supports read, write and basic key management.

Currently a very naive, but sufficient, implementation where each entry is
simply a string, and all entries are list of those strings.
r   r   google_compute_known_hostsc                     Xl         X l        g)zConstruct a known hosts representation based on a list of key strings.

Args:
  known_hosts: str, list each corresponding to a line in known_hosts_file.
  file_path: str, path to the known_hosts_file.
N)known_hostsrl  )r5   rs  rl  s      r&   r4   KnownHosts.__init__  s     #Nr%   c                      [         R                  " U5      R                  5       n[        X!5      $ ! [         R                   a1  n/ n[        R
                  " SR                  X5      5         SnANKSnAff = f)zCreate a KnownHosts object given a known_hosts_file.

Args:
  file_path: str, path to the known_hosts_file.

Returns:
  KnownHosts object corresponding to the file. If the file could not be
  opened, the KnownHosts object will have no entries.
z3SSH Known Hosts File [{0}] could not be opened: {1}N)r   ReadFileContents
splitlinesr  r   r  r1   rp  )r{   rl  rs  r  s       r&   FromFileKnownHosts.FromFile  sj    **95@@Bk k-- ;; k	ii
?
F
F s   $1 A6'A11A6c                 H    [         R                  [         R                  5      $ )zCreate a KnownHosts object from the default known_hosts_file.

Returns:
  KnownHosts object corresponding to the default known_hosts_file.
)rp  rx  DEFAULT_PATH)r{   s    r&   FromDefaultFileKnownHosts.FromDefaultFile0  s     z6677r%   c                 B   ^ [        U4S jU R                   5       5      $ )a  Check if a host key alias exists in one of the known hosts.

Args:
  host_key_alias: str, the host key alias

Returns:
  bool, True if host_key_alias is in the known hosts file. If the known
  hosts file couldn't be opened it will be treated as if empty and False
  returned.
c              3   .   >#    U  H
  nTU;   v   M     g 7fr~   r   )r   r  host_key_aliass     r&   r   +KnownHosts.ContainsAlias.<locals>.<genexpr>D  s     C2B$~%2Bs   )anyrs  )r5   r  s    `r&   ContainsAliasKnownHosts.ContainsAlias9  s     C$2B2BCCCr%   c                     SR                  X5      n[        U R                  5       H2  u  pVUR                  U5      (       d  M  U(       a  X@R                  U'     g   U R                  R	                  U5        g)ao  Add or update the entry for the given hostname.

If there is no entry for the given hostname, it will be added. If there is
an entry already and overwrite_keys is False, nothing will be changed. If
there is an entry and overwrite_keys is True, the key will be updated if it
has changed.

Args:
  hostname: str, The hostname for the known_hosts entry.
  host_key: str, The host key for the given hostname.
  overwrite: bool, If true, will overwrite the entry corresponding to
    hostname with the new host_key if it already exists. If false and an
    entry already exists for hostname, will ignore the new host_key value.
{0} {1}N)r1   ri  rs  rh  r   )r5   hostnamehost_keyr   new_key_entryirm   s          r&   AddKnownHosts.AddF  sd     $$X8MD,,-		!	! -

1
	 . m,r%   c                    SnU Vs/ s H  nSR                  X5      PM     nnU(       d  U$ U R                   Vs/ s H  owR                  U5      (       d  M  UPM     nnU(       a_  U(       aV  U R                   Vs/ s H  owR                  U5      (       a  M  UPM     snU l        U R                  R                  U5        SnU$ U R                  R                  U5        SnU$ s  snf s  snf s  snf )a  Add or update multiple entries for the given hostname.

If there is no entry for the given hostname, the keys will be added. If
there is an entry already, and overwrite keys is False, nothing will be
changed. If there is an entry and overwrite_keys is True, all  current
entries for the given hostname will be removed and the new keys added.

Args:
  hostname: str, The hostname for the known_hosts entry.
  host_keys: list, A list of host keys for the given hostname.
  overwrite: bool, If true, will overwrite the entries corresponding to
    hostname with the new host_key if it already exists. If false and an
    entry already exists for hostname, will ignore the new host_key values.

Returns:
  bool, True if new keys were added.
Fr  T)r1   rs  rh  extend)	r5   r  	host_keysr   new_keys_addedr  new_key_entriesrm   existing_entriess	            r&   AddMultipleKnownHosts.AddMultiple^  s    $ N=F=F	,Y   '''>>(+C'   	++
+C>>(3KC+
 	0
  o.n'


s   C%C*C*<C/C/c                 |    [         R                  " U R                  SR                  U R                  5      S-   SS9  g)zWrites the file to disk.
Trc  N)r   r  rl  r2   rs  rq   s    r&   WriteKnownHosts.Write  s/    			$"2"23d:Dr%   )rl  rs  Nr   )r   r    r!   r"   r#   r   rc   r   r   r   r2   r{  r4   r   rx  r|  r  r  r  r  r$   r   r%   r&   rp  rp    s     !!
'',,sF$@
A, . .* 8 8D-0&Pr%   rp  c                 :   [         R                  " 5       n[        U5      (       du  [        R                  R
                  R                  R                  SS9n[        R                  " U5      nU (       a%  [        R                  " SR                  X5      5        UnU$ )a  Returns the default username for ssh.

The default username is the local username, unless that username is invalid.
In that case, the default username is the username portion of the current
account.

Emits a warning if it's not using the local account username.

Args:
  warn_on_account_user: bool, whether to warn if using the current account
    instead of the local username.

Returns:
  str, the default SSH username.
T)requiredzaInvalid characters in local username [{0}]. Using username corresponding to active account: [{1}])getpassgetuserr   r   VALUEScoreaccountGetr
    MapGaiaEmailToDefaultAccountNamer   r   r1   )warn_on_account_userr   full_accountaccount_users       r&   GetDefaultSshUsernamer    s      
	$	T	"	"$$))1155t5DL88FL	kkBBH&C D	+r%   c                     U (       a  U R                   (       d  gU R                    Vs/ s H   o"R                  U:X  d  M  UR                  PM"     nnU(       d  gUS   R                  5       S:H  $ s  snf )a  Return true if the metadata has the supplied key and it is set to 'true'.

Args:
  metadata: Instance or Project metadata.
  key_name: The name of the metadata key to check. e.g. 'oslogin-enable'.

Returns:
  True if Enabled, False if Disabled, None if key is not presesnt.
Nr   true)itemsrm   r   lower)metadatakey_nameitemmatching_valuess       r&   MetadataHasEnabler    se     x~~%^^+Txx8/Cjdjj^   
			!	!	#v	--s
   A/A/c                 |    SnU b  [        U R                  U5      nOUb  UnUc  UR                  n[        XR5      nU$ )a  Return True if the feature associated with the supplied key is enabled.

If the key is set to 'true' in instance metadata, will return True.
If the key is set to 'false' in instance metadata, will return False.
If key is not set in instance metadata, will return the value in project
metadata unless instance_override is not None (set to True or False).

Args:
  instance: The current instance object.
  project: The current project object.
  key_name: The name of metadata key to check. e.g. 'oslogin-enable'.
  instance_override: The value of the instance metadata key. Used if the
    instance object cannot be passed in. None if not set.

Returns:
  bool, True if the feature associated with the supplied key is enabled
    in instance/project metadata.
N)r  r  commonInstanceMetadata)r3  r+  r  instance_overridefeature_enabledproject_metadatas         r&   FeatureEnabledInMetadatar    sO    * /'(9(98DO$'O55'(8CO	r%   c                     [         R                  5       n U R                  [        R                  :X  a  gSS/n[        SUSS9nUR                  5       n[        R                  " U5         [        R                  " [        R                  " U[        R                  S95      n[        R                  " U5        UR#                  5       n[        R                  " S	R                  U5      5        U H  nUR%                  S
5      (       d  M    g   g! [        R                   a7    [        R                  " SR                  SR!                  U5      5      5         gf = f)a  Check the local SSH installation for security key support.

Runs 'ssh -Q key' and looks for keys starting with 'sk-'.
PuTTY on Windows will return False.

Returns:
  True if SSH supports security keys, False if not, and None if support
  cannot be determined.
Fz-Qrm   N)extra_flagstty)stderrz;Cannot determine SSH supported key types using command: {0}r   zSupported SSH key types: {0}zsk-T)rU   r|   rd   rN   rS   
SSHCommandBuildr   r  rf   
ensure_str
subprocesscheck_outputSTDOUTCalledProcessErrorr1   r2   rw  rh  )r   	ssh_flagsr0   cmd_listoutputkeys_supportedrm   s          r&   CheckSshSecurityKeySupportr    s    	# 	YY%++Um)4YE:#YY[())H^^1B1BCF IIf $$&.))*11.ABc
~~e 
 
! 
	&	& IIELLHHX	

 s   *AD AEEc                   B    \ rS rSrSr          SS jrS rS rSrg)	OsloginStatei  a]  Class for holding OS Login State.

Attributes:
  oslogin_enabled: bool, True if OS Login is enabled on the instance.
  oslogin_2fa_enabled: bool, True if OS Login 2FA is enabled on the instance.
  security_keys_enabled: bool, True if Security Keys should be used for SSH
    authentication.
  user: str, The username that SSH should use for connecting.
  third_party_user: bool, True if the authenticated user is an external
    account user.
  ssh_security_key_support: bool, True if the SSH client supports security
    keys.
  environment: str, A hint about the current environment. ('ssh' or 'putty')
  security_keys: list, A list of 'private' keys associated with the security
    keys configured in the user's account.
  signed_ssh_key: bool, True if a valid signed ssh key exists.
  require_certificates: bool, True if passing a certificate is required.
Nc                     Xl         X l        X0l        X@l        XPl        X`l        Xpl        Uc  / U l        OXl        Xl        Xl	        g r~   )
oslogin_enabledoslogin_2fa_enabledsecurity_keys_enabledr   third_party_userssh_security_key_supportrd  re  rN  require_certificates)r5   r  r  r  r   r  r  rd  re  rN  r  s              r&   r4   OsloginState.__init__#  sM     +2!6I,$<!"d(( 4r%   c                 D   [         R                  " S5      R                  U R                  U R                  U R
                  U R                  U R                  U R                  U R                  SR                  U R                  5      U R                  U R                  5
      $ )Na6          OS Login Enabled: {0}
        2FA Enabled: {1}
        Security Keys Enabled: {2}
        Username: {3}
        Third Party User: {4}
        SSH Security Key Support: {5}
        Environment: {6}
        Security Keys:
        {7}
        Signed SSH Key: {8}
        Require Certificates: {9}
        r  )textwrapdedentr1   r  r  r  r   r  r  rd  r2   re  rN  r  rq   s    r&   __str__OsloginState.__str__>  s    ??   V  ""		%%		$$$%!!r%   c                     SR                  U R                  U R                  U R                  U R                  U R
                  U R                  U R                  U R                  U R                  U R                  5
      $ )NzOsloginState(oslogin_enabled={0}, oslogin_2fa_enabled={1}, security_keys_enabled={2}, user={3}, third_party_user={4}ssh_security_key_support={5}, environment={6}, security_keys={7}, signed_ssh_key={8}, require_certificates={9}))r1   r  r  r  r   r  r  rd  re  rN  r  rq   s    r&   __repr__OsloginState.__repr__X  sp    	$ %+F  $$&&II!!))%%%
r%   )
rd  r  r  r  re  r  rN  r  r  r   )
FFFNFNNNFF)	r   r    r!   r"   r#   r4   r  r  r$   r   r%   r&   r  r    s6    * !# 564r%   r  c                 j   U (       a  U R                   (       a  U(       d  g[        [        [        S U R                   5      5      S 5      nU(       a  UR                  O/ nU=(       d    /  Vs/ s H  oDR
                  PM     nnU=(       a#    UR                  R                  R                  U;   $ s  snf )NFc                     U R                   $ r~   )boot)disks    r&   <lambda>$_IsInstanceWindows.<locals>.<lambda>q  s    DIIr%   )	disksnextiterfilterguestOsFeaturesr   GuestOsFeatureTypeValueValuesEnumWINDOWS)r3  r   	boot_diskguest_os_featuresfeaturefeaturess         r&   _IsInstanceWindowsr  m  s    	x45x~~FGN)3<i//"*;*Ar*AB*Awll*A(B J

!
!
5
5
=
=
I Cs   -B0c                     US   nUS   nUS   nU R                  UUUSU SU SU 3S9n[        UR                  UUU5        g)	z?Signs and writes a certificate for the given Cloud Run service.r6  r,  rZ  	projects/z/locations/
/services/)cloud_run_deploymentN)SignSshPublicKeyForInstancer?  signedSshPublicKey)oslogin
public_keyr^  r6  r,  rZ  sign_responses          r&    _SignAndWriteCloudRunCertificater  z  st      -*H%&$%67/55j\VHJ>O
P 6 - &&	r%   c                     U R                  UUR                  UUS   SUS    SUS    SUS    SUS	    3S
9n[        UR                  US   US   US   US	   5        g)zASigns and writes a certificate for the given App Engine instance.serviceAccountzapps/rV  r  rW  z
/versions/rX  /instances/rY  )service_accountapp_engine_instanceN)r  namerB  r  )r  r  r+  r,  r]  r  s         r&   !_SignAndWriteAppEngineCertificater    s     55ll'(89#H-.j9J<9X8YYcdu  wC  eD  dE  EP  Qb  cp  Qq  Pr  s 6 - &&!%%&r%   c                 "   U R                  UUR                  UUR                  (       a  UR                  S   R                  OSSUR                   SU SUR                   3S9n[        UR                  UR                  XER                  5        g)z>Signs and writes a certificate for the given Compute instance.r   r   r  z/zones/r  )r  compute_instanceN)r  r  serviceAccountsemailidrD  r  )r  r  r+  r,  r7  r3  r  s          r&   _SignAndWriteComputeCertificater     s     55ll		!	! ..q177gll^74&HKK=
I 6 
- &&dKKr%   c           	         [        US9nU(       a  SnO[        U U[        U	S9nU(       d  U$ [        XS9(       a!  [        R
                  R                  S5        U$ Xl        [        5       Ul	        U(       a  SUl
        SUl        SUl        O?[        U U[        U
S9Ul
        [        U U[        US9Ul        [        U U[        US9Ul        [         R#                  5       nUR$                  [&        R(                  :X  a  SUl        OSUl        UR                  (       a  [-        5       Ul        [0        R2                  " U5      n[4        R6                  R8                  R:                  R=                  5       =(       d2    [4        R6                  R>                  R@                  R=                  5       nS	nS	nU (       aO  U RB                  (       a>  U RB                  RE                  S
5      RG                  5       nUS	URI                  S5       nOU(       a  US   nU[J        RL                  RN                  [J        RL                  RP                  4;   a  UR                  (       d  UR                  (       a  [S        USS9nU(       a  [U        X5        O7U(       a  [U        UUUS   S9  O![U        XRV                  UU RX                  5        URZ                  (       d<   U(       a  []        UX1UU5        O%U(       a  [_        UUU5        O[a        UX1UUU 5         URk                  UU(       a  US   OURV                  UR                  S9nGOGUR                  (       a  [m        S5      eUR                  (       a  [m        S5      eURk                  UU(       a  US   OURV                  UR                  S9nUR                  (       aK  [n        Rp                  " UUUS9Ul9        URt                  (       d  URw                  US5      nURx                  nO[n        Rz                  " UUUS9n[n        R|                  " UU5      nU(       a  URt                  (       d   URw                  UUUSUS9nURx                  nOU(       a  UR                  UUUU   SUS9  S	nURt                   HK  nU=(       d    UR                  nUR                  U:X  a  Us  $ UR                  (       d  M?  UR                  nMM     UUlB        U(       a1  [        R
                  R                  SRg                  UU5      5        U$ [        R                  " SRg                  UU5      5        U$ ! [b        Rd                   a    [        R
                  R                  SRg                  UURV                  5      5        URi                  UURV                  U5        U(       a  []        UX1UU5         GNU(       a  [_        UX75         GN[a        UX1UUU 5         GNf = f)a
  Check instance/project metadata for oslogin and return updated username.

Check to see if OS Login is enabled in metadata and if it is, return
the OS Login user and a boolean value indicating if OS Login is being used.

Args:
  instance: instance, The object representing the instance we are connecting
    to. If None, instance metadata will be ignored.
  project: project, The object representing the current project.
  requested_user: str, The default or requested username to connect as.
  public_key: str, The public key of the user connecting.
  expiration_time: int, Microseconds after epoch when the ssh key should
    expire. If None, an existing key will not be modified and a new key will
    not be set to expire.  If not None, an existing key may be modified with
    the new expiry.
  release_track: release_track, The object representing the release track.
  app_engine_params: dict, The fields required to identify an App Engine
    instance. This should be None for Compute instances and Cloud Run
    deployments. If present, this should contain fields for 'appsId',
    'servicesId', 'versionsId', 'instancesId', and 'serviceAccount'.
  cloud_run_params: dict, The fields required to identify a Cloud Run
    deployment. This should be None for Compute and App Engine instances. If
    present, this should contain fields for 'deployment_name', 'project_id',
    and 'region'.
  username_requested: bool, True if the user has passed a specific username in
    the args.
  instance_enable_oslogin: True if the instance's metadata indicates that OS
    Login is enabled, and False if not enabled. Used when the instance cannot
    be passed through the instance argument. None if not specified.
  instance_enable_2fa: True if the instance's metadata indicates that OS Login
    2FA is enabled, and False if not enabled. Used when the instance cannot be
    passed through the instance argument. None if not specified.
  instance_enable_security_keys: True if the instance's metadata indicates
    that OS Login security keys are enabled, and False if not enabled. Used
    when the instance cannot be passed through the instance argument. None if
    not specified.
  instance_require_certificates: True if the instance's metadata indicates
    that OS Login SSH certificates are to be used exclusively, False
    otherwise. An override to be used when the instance cannot be passed
    through the "instance" argument. None if not specified.
  messages: API messages class, The compute API messages.

Returns:
  object, An object containing the OS Login state, with values indicating
    whether OS Login is enabled, Security Keys are enabled, the username to
    connect as and a list of security keys.
r   T)r  )r   z=OS Login is not available on Windows VMs.
Using ssh metadata.Fr\   rW   N/-r,  z:@)safer6  )r^  r6  zSNo OS Login profile found for user [{0}] for project [{1}]. Creating POSIX account.)include_security_keyszSSH using federated workforce identities is not yet generally available (GA). Please use `gcloud beta compute ssh` to SSH using a third-party identity.zSSH using certificates is not yet generally available (GA). Please use `gcloud beta compute ssh` to SSH to VMs that require certificate authentication.)profiler   )expiration_timer  r,  expirationTimeUsec)r  z9Using OS Login user [{0}] instead of requested user [{1}]z7Using OS Login user [{0}] instead of default user [{1}])Dr  r  OSLOGIN_ENABLE_METADATA_KEYr  r   r   Printr  IsThirdPartyUserr  r  r  r  OSLOGIN_ENABLE_2FA_METADATA_KEYOSLOGIN_ENABLE_SK_METADATA_KEY(OSLOGIN_ENABLE_CERTIFICATES_METADATA_KEYrU   r|   rd   rN   rS   rd  r  r  oslogin_clientOsloginClientr   r  authimpersonate_service_accountr  r  r  r7  r   poprindexr   ReleaseTrackALPHABETAr   r`  r  r  rN  r  r  r   r   HttpNotFoundErrorr1   ProvisionPosixAccountGetLoginProfileNotImplementedErrorr	   GetSecurityKeysFromProfilere  posixAccountsImportSshPublicKeyloginProfileGetKeyDictionaryFromProfileFindKeyInKeyListUpdateSshPublicKeyusernameprimaryr   info)r3  r+  requested_userr  r  release_trackr]  r^  username_requestedinstance_enable_oslogininstance_enable_2fainstance_enable_security_keysinstance_require_certificatesr   rS  r  r   r  
user_emailr7  r,  login_profileimport_responser   fingerprintoslogin_userpas                              r&   GetOsloginStater3    s]   ~ N3-O.#1	O 
4JJH "1#3#5- (-M%*/M')-M&(@'-	)M% +C&7	+M' *B07	*M& 	#YY%++ 'M %M((-G-IM*((7'88<<> .						'	'	+	+	- 
 
$&(--==s#'')D$DKK$%Fx(F

  
	'	'=+M+Mz-J-;	
+%l3 -tX[[I'' 
+zF4E 
* *zFD(* ++*:&+AA , M %%$ 
 ))) 
 ++*:&+AA , M
 **$1$L$L
g}%m! ((!44ZD'4466
g}d "22:tDk ; ;!44+"' 5 
 (44"" + 	# 	
 ,''b.2;;L	{{n$	[[l ( $- JJCJJ.	
 
 HHAHH.	

 
K )) 

''-vj',,'G	
 	%%j',,G
+zF4E 
*z *zFD(s+   U +U  U A?W9W9&W98W9c                  j    [         R                  " SS9n [        R                  R                  U 5      nU[        R                  R                  [        R                  R                  [        R                  R                  4;   $ ! [        R                   a    [        R
                  " S5         gf = f)z1Checks if the Authenticated User is a BYOID User.T)use_google_authz!Failed to load fresh credentials.F)c_storeLoadFreshCredentialcreds_exceptionsr  r   r  c_credsCredentialTypeGoogleAuthFromCredentialsEXTERNAL_ACCOUNTEXTERNAL_ACCOUNT_USER EXTERNAL_ACCOUNT_AUTHORIZED_USER)r   
creds_types     r&   r  r    s    ''=E //??F*	&&77&&<<&&GG 
 	 
		 II12s   B *B21B2c                 l   / nU R                   (       a  U R                    H  nU(       d  M  US:w  d  M  UR                  5        Hh  nUnSU;   a  UR                  SUR                  5      nSU;   a  UR                  SU5      nSU;   a  UR                  SU5      nUR	                  U5        Mj     M     U$ )z.Obtain extra flags from the command arguments.--z%USER%z
%INSTANCE%z
%INTERNAL%)ssh_flagr   r   r   r   )argsremoteinstance_addressinternal_addressr  flag	flag_part
deref_flags           r&   ParseAndSubstituteSSHFlagsrJ    s     +	]]	$$,I *
 ##++HfkkBJZ'#++L:JKJZ'#++L:JKJ


Z
( & $ 
r%   c                  ~    [         R                  R                  [        R                  " 5       R
                  SS5      $ )z0Returns the SDK helper executable bin directory.binsdk)r   rc   r2   r   r  sdk_rootr   r%   r&   rz   rz     s'     
flln--ue	<<r%   c                   t    \ rS rSrSr\R                  " S5      rSS jrS r	\
S 5       rS rS	 rS
 rS rSrg)Remotei  a	  A reference to an SSH remote, consisting of a host and user.

Hashing and equality methods are implemented for this class,
so remotes can be put in sets for de-duplication.

Attributes:
  user: str or None, SSH user name (optional).
  host: str or None, Host name.
z$^(?:([^:@]+)@)?([^.:/\\@][^:/\\@]*)$Nc                     Xl         X l        g)zjConstructor for FileReference.

Args:
  host: str or None, Host name.
  user: str or None, SSH user name.
Nhostr   )r5   rS  r   s      r&   r4   Remote.__init__  s     IIr%   c                 t    U R                   (       a  U R                   S-   U R                  -   $ U R                  $ )z~Convert to a positional argument, in the form expected by `ssh`/`plink`.

Returns:
  str, A string on the form `[user@]host`.
@)r   rS  rq   s    r&   ToArgRemote.ToArg$  s*     +/))499s?TYY&BBr%   c                 x    U R                   R                  U5      nU(       a  UR                  5       u  p4U " XCS9$ g)zConvert an SSH-style positional argument to a remote.

Args:
  arg: str, A path on the canonical ssh form `[user@]host`.

Returns:
  Remote, the constructed object or None if arg is malformed.
r   N)_REMOTE_REGEXrP  groups)r{   argrP  r   rS  s        r&   FromArgRemote.FromArg,  s8     ##C(E<<>jd!!r%   c                 4    [        U R                  5       5      $ r~   )hashrW  rq   s    r&   __hash__Remote.__hash__=  s    

r%   c                 ~    [        U 5      [        U5      L =(       a!    U R                  5       UR                  5       :H  $ r~   r   rW  r5   others     r&   __eq__Remote.__eq__@  +    :e$F)FFr%   c                 .    U R                  U5      (       + $ r~   rg  re  s     r&   __ne__Remote.__ne__C      {{5!!!r%   c                 "    U R                  5       $ r~   rW  rq   s    r&   r  Remote.__repr__F      ::<r%   rR  r~   )r   r    r!   r"   r#   rI  compilerZ  r4   rW  r   r]  ra  rg  rl  r  r$   r   r%   r&   rP  rP    sL    & **DE-C   G"r%   rP  c                    U  H/  nS[        U5      s=::  a  S:  a  M  O  [        SU< SU < S35      e   UR                  [        R                  L a  [        U 5      n [        U 5      n U $ [        U 5      R                  SS5      $ )zReturns s escaped such that it can be a ProxyCommand arg.

Args:
  s: str, Argument to escape. Must be non-empty.
  env: Environment, data about the ssh client.

Raises:
  BadCharacterError: If s contains a bad character.
       zSpecial character z
 (part of z&) couldn't be escaped for ProxyCommand%%%)	r   rK   rd   rN   rS   _EscapeWindowsArgvElement_EscapePuttyBackslashPercent_EscapeForBashr   )sr   r   s      r&   _EscapeProxyCommandArgr}  J  s     a3q6 D 
 	   	YY%++ 	"!$A$Q'AH
 
		"	"3	--r%   c                 $   / nSnU SSS2    Hd  nUS:X  a  UR                  S5        SnM  US:X  a-  U(       a  UR                  S5        M>  UR                  S5        MQ  UR                  U5        SnMf     SS	R                  U5      SSS2   -   S-   $ )
zReturns s escaped such that it can be passed to a windows executable.

Args:
  s: str, What to escape. Must be ASCII and non-control.
TN"z"\\\\Fr   )r   r2   )r|  resultfollowing_quoter   s       r&   ry  ry  q  s      &
 /TrT7aCxmmEo	
d	fdmmAo  
rwwvtt$	$s	**r%   c                 F    U R                  SS5      R                  SS5      $ )Nr  r  rw  rx  )r   )r|  s    r&   rz  rz    s"     
4	 	(	(d	33r%   c                     [        [        R                  [        R                  -   S-   5      n/ nU  H/  nX1;   a  UR	                  U5        M  UR	                  SU-   5        M1     SR                  U5      $ )zReturns s escaped so it can be used as a single bash argument.

Args:
  s: str, What to escape. Must be ASCII, non-control, and non-empty.
z	%+-./:=@_r  r   )setstringascii_lettersdigitsr   r2   )r|  
good_charsr  r   s       r&   r{  r{    sb     6''&--7+EF*&ammAmmD1H	 
 
r%   c           
         U (       d  / $ U R                   (       a>  1 SknU R                    H*  nUR                  5       (       a  M  X2;  d  M!  [        S5      e   [        R                  " 5       nU Vs/ s H  n[        XQ5      PM     nnU R                  (       a  UR                  U R                  5        UR                  [        R                  L a  SOSu  pgU R                  (       a  UR                  SSS[        U R                  S   5      -   S	U R                  -   S
U R                  S   R                  -   SU R                  S   -   SU R                   -   /5        U R                  S   (       a!  UR                  SU R                  S   -   5        U R                  S   (       a!  UR                  SU R                  S   -   5        OU R                   (       a  UR                  SSXpR                   -   U-   Xv-   U-   SSU R                  -   /5        U R"                  (       a  UR                  SU R"                  -   5        U R                   (       a  UR                  SU R                   -   5        U R$                  (       a  UR                  SU R$                  -   5        O['        S5      eU R(                   H  nUR                  [        X5      5        M     [*        R,                  " 5       n	U	(       a  UR                  SU	-   5        UR                  [        R                  L a  SSR/                  U5      /$ SSR/                  S/U-   5      SS/$ s  snf )a  Calculate the ProxyCommand flags for IAP Tunnel if necessary.

IAP Tunnel with ssh runs an second inner version of gcloud by passing a
command to do so as a ProxyCommand argument to OpenSSH/Putty.

Args:
  iap_tunnel_args: iap_tunnel.SshTunnelArgs or None, options about IAP Tunnel.
  env: Environment, data about the ssh client.

Raises:
  BadCharacterError: If instance arg contains any invalid characters.
  ValueError: If no instance or cloud run args are provided.

Returns:
  [str], the additional arguments for OpenSSH or Putty.
>   r  ._z6Instance name/IP/hostname contains illegal characters.)z%portr  )z%p'runzstart-iap-tunnelz--project_number=project_numberz--project_id=z--workload_type=workload_typez--deployment_name=rZ  z	--region=r8  z--instance=container_idz--container=computez--listen-on-stdinz
--project=z--zone=z
--network=z'No instance or cloud run args provided.z--verbosity=z	-proxycmdr   -oProxyCommandzProxyUseFdpass=no)r3  isalnumrK   r   ArgsForGcloudr}  trackr   rd   rN   rS   cloud_run_argsr  strr+  r   r,  r7  networkr/   pass_through_argsr   GetVerbosityNamer2   )
iap_tunnel_argsr   allowed_non_alnum_charschargcloud_commandr   
port_token	quotationr\  	verbositys
             r&   _BuildIapTunnelProxyCommandArgsr    s   " 
I
 -((\\^^ CD
 	
 ) #002. =KKNq*12N.K ///0 ekk1o| * ##
o,,-=>
?	@

!
!	"

(
(
9
?
?	@

(
():
;	<o,,,  %%m4
/88G
G %%n5
?99.I
I ,,,y8*...  I(<(<<=K/*@*@@AL?+B+BBC
>
??..c0:; /""$).945YY%++.122 	.!N23	 u Ls   2Mc                   :    \ rS rSrSr  SS jrS	S jrS
S jrSrg)r  i  a  Platform independent SSH client key generation command.

For OpenSSH, we use `ssh-keygen(1)`. For PuTTY, we use a custom binary.
Currently, the only supported algorithm is 'rsa'. The command generates the
following files:
- `<identity_file>`: Private key, on OpenSSH format (possibly encrypted).
- `<identity_file>.pub`: Public key, on OpenSSH format.
- `<identity_file>.ppk`: Unencrypted PPK key-pair, on PuTTY format.

The PPK-file is only generated from a PuTTY environment, and encodes the same
private- and public keys as the other files.

Attributes:
  identity_file: str, path to private key file.
  allow_passphrase: bool, If True, attempt at prompting the user for a
    passphrase for private key encryption, given that the following conditions
    are also true: - Running in an OpenSSH environment (Linux and Mac) -
    Running in interactive mode (from an actual TTY) - Prompts are enabled in
    gcloud
  reencode_ppk: bool, If True, reencode the PPK file if it was generated with
    a bad encoding, instead of generating a new key. This is only valid for
    PuTTY.
  print_cert: bool, If True, ssh-keygen will print certificate information.
c                 4    Xl         X l        X0l        X@l        g)z3Construct a suite independent `ssh-keygen` command.N)identity_filer  r  r[  )r5   r  r  r  r[  s        r&   r4   KeygenCommand.__init__/  s     ',$ Or%   Nc                 p   U=(       d    [         R                  5       nUR                  (       d  [        S5      eUR                  /nUR                  [
        R                  L a  U R                  (       a   UR                  SSU R                  /5        U$ U R                  =(       a    [        R                  " 5       nU(       d  UR                  SS/5        UR                  SSSU R                  /5         U$ U R                  (       a  UR                  S5        UR                  U R                  5        U$ )	a!  Construct the actual command according to the given environment.

Args:
  env: Environment, to construct the command for (or current if None).

Raises:
  MissingCommandError: If keygen command was not found.

Returns:
  [str], the command args (where the first arg is the command itself).
z4Keygen command not found in the current environment.z-Lz-fz-Nr   -trsaz--reencode-ppk)rU   r|   rZ   r(   rd   rN   rR   r[  r  r  r  r   	CanPromptr  r   )r5   r   rC  prompt_passphrases       r&   r  KeygenCommand.Build7  s     
&$$&C::
@  JJ<D
yyEMM!	T4!3!345 K !11Lj6J6J6L 
++tRj
!T5$(:(:;< K	 
		$%
kk$$$%Kr%   c                     U R                  U5      n[        R                  " SR                  SR	                  U5      5      5        [
        R                  " USUS9nU(       a  [        US   US9eg)a  Run the keygen command in the given environment.

Args:
  env: Environment, environment to run in (or current if None).
  out_func: str->None: A function call with the stdout of ssh-keygen.

Raises:
  MissingCommandError: Keygen command not found.
  CommandError: Keygen command failed.
Running command [{}].r   T)no_exitr\  r   r7   N)r  r   r  r1   r2   r   Execr+   )r5   r   r\  rC  r   s        r&   r  KeygenCommand.RunX  s^     ::c?DII%,,SXXd^<=!!$xHFaf55 r%   )r  r  r[  r  )TFFr~   r>   	r   r    r!   r"   r#   r4   r  r  r$   r   r%   r&   r  r    s!    2 IN!B6r%   r  c                   T    \ rS rSrSr          SS jrS	S jr     S
S jrSrg)r  ij  a  Represents a platform independent SSH command.

This class is intended to manage the most important suite- and platform
specifics. We manage the following data:
- The executable to call, either `ssh`, `putty` or `plink`.
- User and host, through the `remote` arg.
- Potential remote command to execute, `remote_command` arg.

In addition, it manages these flags:
-t, -T      Pseudo-terminal allocation
-p, -P      Port
-i          Identity file (private key)
-o Key=Val  OpenSSH specific options that should be added, `options` arg.

For flexibility, SSHCommand also accepts `extra_flags`. Always use these
with caution -- they will be added as-is to the command invocation without
validation. Specifically, do not add any of the above mentioned flags.
Nc                     Xl         X l        X0l        X@l        Xl        U=(       d    0 U l        U=(       d    / U l        U=(       d    / U l        Xl        Xl	        Xl
        SU l        g)a  Construct a suite independent SSH command.

Note that `extra_flags` and `remote_command` arguments are lists of strings:
`remote_command=['echo', '-e', 'hello']` is different from
`remote_command=['echo', '-e hello']` -- the former is likely desired.
For the same reason, `extra_flags` should be passed like `['-k', 'v']`.

Args:
  remote: Remote, the remote to connect to.
  port: str, port.
  identity_file: str, path to private key file.
  cert_file: str, path to certificate file.
  options: {str: str}, options (`-o`) for OpenSSH, see `ssh_config(5)`.
  extra_flags: [str], extra flags to append to ssh invocation. Both binary
    style flags `['-b']` and flags with values `['-k', 'v']` are accepted.
  remote_command: [str], command to run remotely.
  tty: bool, launch a terminal. If None, determine automatically based on
    presence of remote command.
  iap_tunnel_args: iap_tunnel.SshTunnelArgs or None, options about IAP
    Tunnel.
  remainder: [str], NOT RECOMMENDED. Arguments to be appended directly to
    the native tool invocation, after the `[user@]host` part but prior to
    the remote command. On PuTTY, this can only be a remote command. On
    OpenSSH, this can be flags followed by a remote command. Cannot be
    combined with `remote_command`. Use `extra_flags` and `remote_command`
    instead.
  identity_list: list, A list of paths to private key files. Overrides the
    identity_file argument, and sets multiple `['-i']` flags.
N)rD  portr  r_  identity_listoptionsr  remote_commandr  r  	remainder_remote_command_file)r5   rD  r  r  r_  r  r  r  r  r  r  r  s               r&   r4   SSHCommand.__init__~  s]    V KI&N&=bDL"(bD(.BDH*N $Dr%   c           	         U=(       d    [         R                  5       nUR                  (       a  UR                  (       d  [	        S5      eU R
                  S;   a  U R
                  OU R                  (       + nU(       a  UR                  S/OUR                  S/nU R                  (       a=  UR                  [        R                  L a  SOSnUR                  X@R                  /5        U R                  (       a+  UR                  SR                  U R                  5      /5        U R                  (       a'  U R                   H  nUR                  SU/5        M     OhU R                  (       aW  U R                  nUR                  [        R                  L a  UR!                  S	5      (       d  US	-  nUR                  SU/5        UR                  [        R"                  L aR  [%        [&        R(                  " U R*                  5      5       H%  u  pgUR                  S
SR                  XgS9/5        M'     UR                  [-        U R.                  U5      5        UR                  U R0                  5        U R2                  (       a)  UR5                  U R2                  R7                  5       5        U R8                  (       a  UR                  U R8                  5        U R                  (       a  UR                  [        R"                  L a.  UR5                  S5        UR                  U R                  5        U$ U(       a  [:        R<                  " SSS9 U l        U R>                  RA                  SRC                  U R                  5      5        SSS5        UR                  SU R>                  RD                  /5        U$ UR                  U R                  5        U$ ! , (       d  f       NT= f)a+  Construct the actual command according to the given environment.

Args:
  env: Environment, to construct the command for (or current if None).

Raises:
  MissingCommandError: If SSH command(s) required were not found.

Returns:
  [str], the command args (where the first arg is the command itself).
z"The current environment lacks SSH.)TFr  z-T-Pz-pz-o CertificateFile={}-ir   r  {k}={v}kvrA  zw+tF)r<  deleter   Nz-m)#rU   r|   rW   rY   r(   r  r  r  rd   rN   rS   r  r_  r1   r  r  endswithrR   sortedrf   rg   r  r  r  r  rD  r   rW  r  tempfileNamedTemporaryFiler  writer2   r  )r5   r   r  rC  	port_flagr  rm   r   s           r&   r  SSHCommand.Build  s    
&$$&CGG DEEhh-/$((9L9L5LC#&CLL$SWWdODyy))u{{2$i
kk9ii()~~
kk*11$..ABC---T=)* .			((m	ekk	!-*@*@*H*H
kk4'(
yyEMM!s}}T\\:;*#T9++c+;<= < 	KK/0D0DcJKKK  !{{
kk$++##%& ~~
kk$..!	emm	#DD''( K  ((u
&

#
#
)
)#((43F3F*G
H
 	T44499:; K 	D''(K
 
s   :O
O(c                    U=(       d    [         R                  5       nU R                  U5      n[        R                  " SR                  SR                  U5      5      5        UR                  [        R                  L a
  U(       a  SnOSn0 nU(       a  X8S'   U(       a  XHS'   U(       a  XXS'   [        R                  " U4SUS	.UD6n	U R                  (       a+   [        R                  " U R                  R                  5        XR"                  :X  a  [%        US   U	S9eU	$ ! [          a<    [        R                  " S
R                  U R                  R                  5      5         Ncf = f)a  Run the SSH command using the given environment.

Args:
  env: Environment, environment to run in (or current if None).
  putty_force_connect: bool, whether to inject 'y' into the prompts for
    `plink`, which is insecure and not recommended. It serves legacy
    compatibility purposes for existing usages only; DO NOT SET THIS IN NEW
    CODE.
  explicit_output_file: Pipe stdout into this file-like object
  explicit_error_file: Pipe stderr into this file-like object
  explicit_input_file: Pipe stdin from this file-like object

Raises:
  MissingCommandError: If SSH command(s) not found.
  CommandError: SSH command failed (not to be confused with the eventual
    failure of the remote command).

Returns:
  int, The exit code of the remote command, forwarded from the client.
r  r   y
Nstdoutr  stdinTr  in_strz)Failed to delete remote command file [{}]r   r  )rU   r|   r  r   r  r1   r2   rd   rN   rS   r   r  r  r   r  r  r  rl   r+   )
r5   r   putty_force_connectexplicit_output_fileexplicit_error_fileexplicit_input_filerC  r  extra_popen_kwargsr   s
             r&   r  SSHCommand.Run  s:   8 
&$$&C::c?DII%,,SXXd^<=
yyEKK$7ff %9"%8"$7!!!6-?F   	
		$++001 """af55M  		7>>))..	

 	s   *D# #AE)(E))r  r_  r  r  r  r  r  r  r  rD  r  r  )
NNNNNNNNNNr~   )NFNNNr  r   r%   r&   r  r  j  sK    , 
6%pAJ Cr%   r  c                   \    \ rS rSrSr         S	S jr\S
S j5       rSS jrSS jr	Sr
g)
SCPCommandi?  az  Represents a platform independent SCP command.

This class is intended to manage the most important suite- and platform
specifics. We manage the following data:
- The executable to call, either `scp` or `pscp`.
- User and host, through either `sources` or `destination` arg. Multiple
  remote sources are allowed but not supported under PuTTY. Multiple local
  sources are always allowed.
- Potential remote command to execute, `remote_command` arg.

In addition, it manages these flags:
-r          Recursive copy
-C          Compression
-P          Port
-i          Identity file (private key)
-o Key=Val  OpenSSH specific options that should be added, `options` arg.

For flexibility, SCPCommand also accepts `extra_flags`. Always use these
with caution -- they will be added as-is to the command invocation without
validation. Specifically, do not add any of the above mentioned flags.
Nc                     [        U[        5      (       a  U/OUU l        X l        X0l        X@l        XPl        X`l        Xpl        Xl	        U=(       d    0 U l
        U	=(       d    / U l        Xl        g)a  Construct a suite independent SCP command.

Args:
  sources: [FileReference] or FileReference, the source(s) for this copy. At
    least one source is required. NOTE: Multiple remote sources are not
    supported in PuTTY and is discouraged for consistency.
  destination: FileReference, the destination file or directory. If remote
    source, this must be local, and vice versa.
  recursive: bool, recursive directory copy.
  compress: bool, enable compression.
  port: str, port.
  identity_file: str, path to private key file.
  cert_file: str, path to OpenSSH certificate file.
  options: {str: str}, options (`-o`) for OpenSSH, see `ssh_config(5)`.
  extra_flags: [str], extra flags to append to scp invocation. Both binary
    style flags `['-b']` and flags with values `['-k', 'v']` are accepted.
  iap_tunnel_args: iap_tunnel.SshTunnelArgs or None, options about IAP
    Tunnel.
  identity_list: list, A list of paths to private key files. Overrides the
    identity_file argument, and sets multiple `['-i']` flags.
N)r   FileReferencerG   rH   	recursivecompressr  r  r_  r  r  r  r  )r5   rG   rH   r  r  r  r  r_  r  r  r  r  s               r&   r4   SCPCommand.__init__V  s`    F !+7M B BG9DL"NMI&N&=bDL"(bD*r%   c                    U=(       d    [         R                  5       nU(       d  [        SX5      eUR                  (       a8  [	        U Vs/ s H  oUR                  PM     sn5      (       a  [        SUU5      egUR
                  [        R                  L a  [        U5      S:w  a  [        SUU5      e[        U Vs/ s H  oUR                  PM     sn5      (       d  [        SUU5      eU(       a@  [        [        U Vs/ s H  oUR                  PM     sn5      5      S:w  a  [        SUU5      eggs  snf s  snf s  snf )aF  Verify that the source- and destination config is sound.

Checks that sources are remote if destination is local and vice versa,
plus raises error for multiple remote sources in PuTTY, which is not
supported by `pscp`.

Args:
  sources: [FileReference], see SCPCommand.sources.
  destination: FileReference, see SCPCommand.destination.
  single_remote: bool, if True, enforce that all remote sources refer to the
    same Remote (user and host).
  env: Environment, the current environment.

Raises:
  InvalidConfigurationError: The source/destination configuration is
    invalid.
zNo sources provided.z;All sources must be local files when destination is remote.r`   z/Multiple remote sources not supported by PuTTY.z3Source(s) must be remote when destination is local.zDAll sources must refer to the same remote when destination is local.N)rU   r|   rC   rD  r  rd   rN   rS   r   rp   r  )r{   rG   rH   single_remoter   srcs         r&   VerifySCPCommand.Verify  s,   & 
&$$&C%
 '  	G,GSjjG,	-	-'I
 	
 
. 
ekk	!c'la&7'=
 	

 0**011'A
 	

 
3s'#B'3JJ'#BCDI'	
 	
 J' - 1 $Cs   D2<D7?D<c           	         U=(       d    [         R                  5       nUR                  (       d  [        S5      eU R	                  U R
                  U R                  US9  UR                  /nU R                  (       a  UR                  S5        U R                  (       a  UR                  S5        U R                  (       a  UR                  SU R                  /5        U R                  (       a6  UR                  [        R                  L a  U R                  U R                   S'   U R"                  (       a'  U R"                   H  nUR                  SU/5        M     OhU R$                  (       aW  U R$                  nUR                  [        R&                  L a  UR)                  S5      (       d  US-  nUR                  SU/5        UR                  [        R                  L aR  [+        [,        R.                  " U R                   5      5       H%  u  pEUR                  S	S
R1                  XES9/5        M'     UR                  [3        U R4                  U5      5        UR                  U R6                  5        UR                  U R
                   Vs/ s H  ofR9                  5       PM     sn5        UR                  U R                  R9                  5       5        U$ s  snf )a}  Construct the actual command according to the given environment.

Args:
  env: Environment, to construct the command for (or current if None).

Raises:
  InvalidConfigurationError: The source/destination configuration is
    invalid.
  MissingCommandError: If SCP command(s) required were not found.

Returns:
  [str], the command args (where the first arg is the command itself).
z:The current environment lacks an SCP (secure copy) client.)r   z-rz-Cr  CertificateFiler  r   r  r  r  )rU   r|   rX   r(   r  rG   rH   r  r   r  r  r  r_  rd   rN   rR   r  r  r  rS   r  r  rf   rg   r1   r  r  r  rW  )r5   r   rC  r  rm   r   sources          r&   r  SCPCommand.Build  s    
&$$&C77
F  	KKd..CK8GG9D~~
kk$}}
kk$yy
kk4#$~~#))u}}4(,dll$%---T=)* .			((m	ekk	!-*@*@*H*H
kk4'( yyEMM!s}}T\\:;*#T9++c+;<= < 	KK/0D0DcJKKK  ! 	KKdll;lFl;<KK  &&()K <s   Kc                 n   U=(       d    [         R                  5       nU R                  U5      n[        R                  " SR                  SR                  U5      5      5        UR                  [        R                  L a
  U(       a  SnOSn[        R                  " USUS9nU(       a  [        US   US9eg)	a!  Run the SCP command using the given environment.

Args:
  env: Environment, environment to run in (or current if None).
  putty_force_connect: bool, whether to inject 'y' into the prompts for
    `pscp`, which is insecure and not recommended. It serves legacy
    compatibility purposes for existing usages only; DO NOT SET THIS IN NEW
    CODE.

Raises:
  InvalidConfigurationError: The source/destination configuration is
    invalid.
  MissingCommandError: If SCP command(s) not found.
  CommandError: SCP command failed to copy the file(s).
r  r   r  NTr  r   r  )rU   r|   r  r   r  r1   r2   rd   rN   rS   r   r  r+   )r5   r   r  rC  r  r   s         r&   r  SCPCommand.Run  s      
&$$&C::c?DII%,,SXXd^<= yyEKK$7ff!!$VDFaf55 r%   )r_  r  rH   r  r  r  r  r  r  r  rG   )	FFNNNNNNN)FNr~   NF)r   r    r!   r"   r#   r4   r   r  r  r  r$   r   r%   r&   r  r  ?  sJ    4 -+^ 3
 3
j8t6r%   r  c                   :    \ rS rSrSr       SS jrSS jrSrg)		SSHPolleri	  a  Represents an SSH command that polls for connectivity.

Using a poller is not ideal, because each attempt is a separate connection
attempt, meaning that the user might be prompted for a passphrase or to
approve a server identity by the underlying ssh tool that we do not control.
Always assume that polling for connectivity using this method is an operation
that requires user action.
Nc	                 p    [        UUUUUS/SUS9U l        Xpl        [        R                  " USS9U l        g)a6  Construct a poller for an SSH connection.

Args:
  remote: Remote, the remote to poll.
  port: str, port to poll.
  identity_file: str, path to private key file.
  options: {str: str}, options (`-o`) for OpenSSH, see `ssh_config(5)`.
  extra_flags: [str], extra flags to append to ssh invocation. Both binary
    style flags `['-b']` and flags with values `['-k', 'v']` are accepted.
  max_wait_ms: int, number of ms to wait before raising.
  sleep_ms: int, time between trials.
  iap_tunnel_args: iap_tunnel.SshTunnelArgs or None, information about IAP
    Tunnel.
:F)r  r  r  r  r  r  r  r   )max_wait_ms	jitter_msN)r  ssh_command	_sleep_msr   Retryer_retryer)	r5   rD  r  r  r  r  r  sleep_msr  s	            r&   r4   SSHPoller.__init__	  sD    2 "#u'	D NMMkQGDMr%   c                    U=(       d    [         R                  5       nUUS.nUR                  [        R                  L a  [
        R                  US'   U R                  R                  U R                  R                  US U R                  S9  g)a  Poll a remote for connectivity within the given timeout.

The SSH command may prompt the user. It is recommended to wrap this call in
a progress tracker. If this method returns, a connection was successfully
established. If not, this method will raise.

Args:
  env: Environment, environment to run in (or current if None).
  putty_force_connect: bool, whether to inject 'y' into the prompts for
    `plink`, which is insecure and not recommended. It serves legacy
    compatibility purposes for existing usages only; DO NOT SET THIS IN NEW
    CODE.

Raises:
  MissingCommandError: If SSH command(s) not found.
  core.retry.WaitException: SSH command failed, possibly due to short
    timeout. There is no way to distinguish between a timeout error and a
    misconfigured connection.
)r   r  r  c                     U [         L $ r~   )r+   )exc_typerC  s     r&   r   SSHPoller.Poll.<locals>.<lambda>i	  s	    L0Hr%   )kwargsshould_retry_ifr  N)rU   r|   rd   rN   rR   r  DEVNULLr  RetryOnExceptionr  r  r  )r5   r   r  run_argss       r&   PollSSHPoller.PollD	  sz    ( 
&$$&C2H yyEMM!(2(:(:h$%MM""H	 # r%   )r  r  r  )NNNNi`  i  Nr  )r   r    r!   r"   r#   r4   r  r$   r   r%   r&   r  r  	  s*     $HL'r%   r  c                   J    \ rS rSrSrSS jrS r\S 5       rS r	S r
S	 rS
rg)r  in	  zA reference to a local or remote file (or directory) for SCP.

Attributes:
  path: str, The path to the file.
  remote: Remote or None, the remote referred or None if local.
Nc                     Xl         X l        g)zConstructor for FileReference.

Args:
  path: str, The path to the file.
  remote: Remote or None, the remote referred or None if local.
Nrc   rD  )r5   rc   rD  s      r&   r4   FileReference.__init__v	  s     IKr%   c                     U R                   (       d  U R                  $ SR                  U R                   R                  5       U R                  S9$ )zConvert to a positional argument, in the form expected by `scp`/`pscp`.

Returns:
  str, A string on the form `remote:path` if remote or `path` if local.
z{remote}:{path})rD  rc   )rD  rc   r1   rW  rq   s    r&   rW  FileReference.ToArg	  s<     ;;YY##4;;+<+<+>TYY#OOr%   c                     [         R                  R                  U5      S   nUR                  S5      u  p4nU(       a  [        R                  U5      OSnU(       a  U(       d  U " XVS9$ U " US9$ )aM  Convert an SCP-style positional argument to a file reference.

Note that this method does not raise. No lookup of either local or remote
file presence exists.

Args:
  path: str, A path on the canonical scp form `[remote:]path`. If remote,
    `path` can be empty, e.g. `me@host:`.

Returns:
  FileReference, the constructed object.
r   r  Nr  rb   )r   rc   
splitdrive	partitionrP  r]  )r{   rc   local_drive
remote_argseprl  rD  s          r&   FromPathFileReference.FromPath	  s\     ''$$T*1-K!%!4JY+.V^^J'DFki//d^r%   c                 ~    [        U 5      [        U5      L =(       a!    U R                  5       UR                  5       :H  $ r~   rd  re  s     r&   rg  FileReference.__eq__	  ri  r%   c                 .    U R                  U5      (       + $ r~   rk  re  s     r&   rl  FileReference.__ne__	  rn  r%   c                 "    U R                  5       $ r~   rp  rq   s    r&   r  FileReference.__repr__	  rr  r%   r  r~   )r   r    r!   r"   r#   r4   rW  r   r  rg  rl  r  r$   r   r%   r&   r  r  n	  s6    P  ,G"r%   r  )NNNNNr   r~   )NNFNNNNN)hr#   
__future__r   r   r   rK  enumr  r  r   rI  r  r  r  r  apitools.base.pyr   googlecloudsdk.api_lib.osloginr   r  googlecloudsdk.callioper   "googlecloudsdk.command_lib.osloginr	   googlecloudsdk.command_lib.utilr
   googlecloudsdk.corer   core_exceptionsr   r   r   googlecloudsdk.core.consoler   googlecloudsdk.core.credentialsr   r9  r8  r   r6  googlecloudsdk.core.utilr   r   r   rf   six.moves.urllib.parser   rc   r2   PER_USER_SSH_CONFIG_FILErf  r*  r	  r  r  r  r  r   r(   r+   rC   rK   EnumrN   r%  rU   r   r   r   r   r/  r4  r9  r?  rB  rD  rF  r`  rn  rp  r  r  r  r  r  r  r  r  r   r3  r  rJ  rz   rP  r}  ry  rz  r{  r  r  r  r  r  r  r   r%   r&   <module>r)     s    Q &  '     	 	     ' C ( < 0 & = / # * 2 < J < * . * 
 ( 77<<VX> 77<<V-GH '',,sF,HI. "6 !4 +H (,o++ ,A/// A?(( . 5 5 B-- BDII ](& ](@6DII 499 \F6 \F~
O&O(O&
 	2Oj&RH HV>.* 48B+\[6 [|
24@  "&"&K\6=CV CL$.N"+J4"dNR6F R6jR RjR6 R6jW Wt:F :r%   