
    9                        S 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rSr1 SkrSrS	r " S
 S\R                   5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rS r " S S\R,                  " \R.                  \5      5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rS+S jr " S  S!\5      r " S" S#\5      r S$ r!S% r"S& r#S' r$S( r%S) r&S* r'g),zAUtility functions for managing customer supplied encryption keys.    N)
exceptions)	resources)
console_iozHhttps://cloud.google.com/compute/docs/disks/customer-supplied-encryption>   keyurikey-type,   iX  c                       \ rS rSrSrSrg)Error#   zFBase exception for Csek(customer supplied encryption keys) exceptions. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       0lib/googlecloudsdk/api_lib/compute/csek_utils.pyr   r   #   s    Nr   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidKeyFileException'   z!There's a problem in a CSEK file.c                 J   > [         [        U ]  SR                  U5      5        g )Nz{0}
For information on proper key file format see: https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#key_file)superr   __init__format)selfbase_message	__class__s     r   r    InvalidKeyFileException.__init__*   s#    	
!41	006|0DFr   r   r   r   r   r   r   r   r   __classcell__r   s   @r   r   r   '   s    )F Fr   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )BadPatternException1   z$A (e.g.) url pattern is bad and why.c                    > Xl         X l        [        [        U ]  SR                  U R                   U R                  5      5        g )Nz&Invalid value for [{0}] pattern: [{1}])pattern_typepatternr   r%   r   r   )r   r(   r)   r   s      r   r   BadPatternException.__init__4   s<    $L	
t-077LL	r   )r)   r(   r!   r#   s   @r   r%   r%   1   s    , r   r%   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidKeyExceptionNoContext=   z.Indicate that a particular key is bad and why.c                    > Xl         X l        [        [        U ]  SR                  U R                   U R                  5      5        g )NzInvalid key, [{0}] : {1})r   issuer   r,   r   r   )r   r   r/   r   s      r   r   %InvalidKeyExceptionNoContext.__init__@   s9    HJ	
&6"))HHJJ	r   )r/   r   r!   r#   s   @r   r,   r,   =   s    6 r   r,   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidKeyExceptionI   z6Indicate that a particular key is bad, why, and where.c                    > Xl         X l        X0l        [        [        U ]  SR                  U R                   U R                  U R                  5      5        g )Nz"Invalid key, [{0}], for [{1}]: {2})r   key_idr/   r   r2   r   r   )r   r   r5   r/   r   s       r   r   InvalidKeyException.__init__L   sE    HKJ	
t-,33HHKKJJ	r   )r/   r   r5   r!   r#   s   @r   r2   r2   I   s    > r   r2   c           	         US:  a  [        SR                  U5      5      e[        U 5      U:w  a%  [        U SR                  U[        U 5      5      5      eU S   S:w  a  [        U S5      e U R	                  S5      n[        R                  " S	U 5      (       d  [        US
5      e [        R                  " U5        g! [
         a    [        U S5      ef = f! [         a*  n[        U SR                  UR                  5      5      eSnAff = f)zFValidateKey(s, k) returns None or raises InvalidKeyExceptionNoContext.   z6ValidateKey requires expected_key_length > 1.  Got {0}zTKey should contain {0} characters (including padding), but is [{1}] characters long.=z4Bad padding.  Keys should end with an '=' character.asciiz"Key contains non-ascii characters.z^[a-zA-Z0-9+/=]*$zKey contains unexpected characters. Base64 encoded strings contain only letters (upper or lower case), numbers, plusses '+', slashes '/', or equality signs '='.zKey is not valid base64: [{0}].N)
ValueErrorr   lenr,   encodeUnicodeDecodeErrorrematchbase64	b64decode	TypeErrormessage)base64_encoded_stringexpected_key_lengthbase64_encoded_string_as_strts       r   ValidateKeyrJ   W   s5    1
Mf013 3 		#66
&	((.%&)() ) 2#%
&@B B.#8#?#?#H  
&(=	>	>
&$	AB B=
12 
 .
&,. .. 
 =
&)00;= ==s$   +B< %C <C
D
 %DD
c                       \ rS rSrSrS r\S
S j5       r\R                  S 5       r
\R                  S 5       r\S 5       rSrg	)CsekKeyBase   z#A class representing for CSEK keys.c                 >    [        XR                  5       S9  Xl        g )N)rG   )rJ   GetKeyLength_key_material)r   key_materials     r   r   CsekKeyBase.__init__   s    2C2C2EF%r   c                     US:X  a  [        U 5      $ US:X  a  U(       a  [        U 5      $ [        US5      e[        U5      e)a\  Make a CSEK key.

Args:
  key_material: str, the key material for this key
  key_type: str, the type of this key
  allow_rsa_encrypted: bool, whether the key is allowed to be RSA-wrapped

Returns:
  CsekRawKey or CsekRsaEncryptedKey derived from the given key material and
  type.

Raises:
  BadKeyTypeException: if the key is not a valid key type
rawzrsa-encryptedzLthis feature is only allowed in the alpha and beta versions of this command.)
CsekRawKeyCsekRsaEncryptedKeyBadKeyTypeExceptionrQ   key_typeallow_rsa_encrypteds      r   MakeKeyCsekKeyBase.MakeKey   sO    " 5%%?"	"<00
 
 h
''r   c                     [        S5      e)Nz"GetKeyLength() must be overridden.NotImplementedErrorr   s    r   rO   CsekKeyBase.GetKeyLength   s    
B
CCr   c                     A[        S5      e)NzToMessage() must be overridden.r^   r   compute_clients     r   	ToMessageCsekKeyBase.ToMessage   s    
?
@@r   c                     U R                   $ NrP   r`   s    r   rQ   CsekKeyBase.key_material   s    r   ri   NF)r   r   r   r   r   r   staticmethodr[   abcabstractmethodrO   re   propertyrQ   r   r   r   r   rL   rL      sj    +& ( (: D D A A  r   rL   c                   $    \ rS rSrSrS rS rSrg)rU      z!Class representing raw CSEK keys.c                     [         $ rh   )BASE64_RAW_KEY_LENGTH_IN_CHARSr`   s    r   rO   CsekRawKey.GetKeyLength   s    ))r   c                 Z    UR                   R                  [        U R                  5      S9$ )N)rawKeyMESSAGES_MODULECustomerEncryptionKeystrrQ   rc   s     r   re   CsekRawKey.ToMessage   s/    ))??4$$% @ ' 'r   r   Nr   r   r   r   r   rO   re   r   r   r   r   rU   rU      s    )*'r   rU   c                   $    \ rS rSrSrS rS rSrg)rV      z+Class representing rsa encrypted CSEK keys.c                     [         $ rh   )(BASE64_RSA_ENCRYPTED_KEY_LENGTH_IN_CHARSr`   s    r   rO    CsekRsaEncryptedKey.GetKeyLength   s    33r   c                 Z    UR                   R                  [        U R                  5      S9$ )N)rsaEncryptedKeyrw   rc   s     r   re   CsekRsaEncryptedKey.ToMessage   s/    ))??D--. @ 0 0r   r   Nr|   r   r   r   rV   rV      s    340r   rV   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )rW      zA key type is bad and why.c                    > Xl         SR                  U R                   5      nU(       a  USU-   -  nUS-  n[        [        U ]  U5        g )NzInvalid key type [{0}]z: .)rY   r   r   rW   r   )r   rY   explanationmsgr   s       r   r   BadKeyTypeException.__init__   sG    M
"
)
)$--
8C	TKc3JC	
t-c2r   )rY   ) r!   r#   s   @r   rW   rW      s    "3 3r   rW   c                   (   ^  \ rS rSrU 4S jrSrU =r$ )MissingCsekException   c                 J   > [         [        U ]  SR                  U5      5        g )Nz0Key required for resource [{0}], but none found.)r   r   r   r   )r   resourcer   s     r   r   MissingCsekException.__init__   s"    	
.:AA(KMr   r   )r   r   r   r   r   r   r"   r#   s   @r   r   r      s    M Mr   r   c           
          U R                  SSSR                  U[        S9S9  U(       a%  U R                  SSSS	R                  U[        S9S
9  gg)z$Adds arguments related to csek keys.z--csek-key-fileFILEaA        Path to a Customer-Supplied Encryption Key (CSEK) key file that maps
      Compute Engine {resource}s to user managed keys to be used when
      creating, mounting, or taking snapshots of disks.

      If you pass `-` as value of the flag, the CSEK is read from stdin.
      See {csek_help} for more details.
      )r   	csek_help)metavarhelpz--require-csek-key-create
store_trueTa          Refuse to create {resource}s not protected by a user managed key in
        the key file when --csek-key-file is given. This behavior is enabled
        by default to prevent incorrect gcloud invocations from accidentally
        creating {resource}s with no user managed key. Disabling the check
        allows creation of some {resource}s without a matching
        Customer-Supplied Encryption Key in the supplied --csek-key-file.
        See {csek_help} for more details.
        )actiondefaultr   N)add_argumentr   CSEK_HELP_URL)parserflags_about_creationresource_types      r   AddCsekKeyArgsr      sm    
 &-=&
A  
C 
# FM]FC  E r   c                   *    \ rS rSrSrS rS rS rSrg)
UriPattern   zCA uri-based pattern that maybe be matched against resource objects.c                     UR                  S5      (       d  [        SU5      e[        R                  R	                  U5      R                  5       U l        g )Nhttpr   )
startswithr%   r   REGISTRYParseURLRelativeName_path_as_string)r   path_as_strings     r   r   UriPattern.__init__   sF    $$V,,~66$--66$ 	r   c                 <    U R                   UR                  5       :H  $ )z*Tests if its argument matches the pattern.)r   r   )r   r   s     r   MatchesUriPattern.Matches  s    8#8#8#:::r   c                      SU R                   -   $ )NzUri Pattern: r   r`   s    r   __str__UriPattern.__str__  s    T1111r   r   N)	r   r   r   r   r   r   r   r   r   r   r   r   r   r      s    K';2r   r   c                   j    \ rS rSrSr\S 5       r\SS j5       r\SS j5       r	S r
SS jrSS jrS	rg
)CsekKeyStorei  z0Represents a map from resource patterns to keys.c                 <    [         R                  " USS9nU " X25      $ )a  FromFile loads a CsekKeyStore from a file.

Args:
  fname: str, the name of a file intended to contain a well-formed key file
  allow_rsa_encrypted: bool, whether to allow keys of type 'rsa-encrypted'

Returns:
  A CsekKeyStore, if found

Raises:
  googlecloudsdk.core.util.files.Error: If the file cannot be read or is
                                        larger than max_bytes.
F)binary)r   ReadFromFileOrStdin)clsfnamerZ   contents       r   FromFileCsekKeyStore.FromFile  s!      ,,U5AGw,,r   c                 ^    U R                   c  g[        R                  U R                   U5      $ )a  FromFile attempts to load a CsekKeyStore from a command's args.

Args:
  args: CLI args with a csek_key_file field set
  allow_rsa_encrypted: bool, whether to allow keys of type 'rsa-encrypted'

Returns:
  A CsekKeyStore, if a valid key file name is provided as csek_key_file
  None, if args.csek_key_file is None

Raises:
  exceptions.BadFileException: there's a problem reading fname
  exceptions.InvalidKeyFileException: the key file failed to parse
    or was otherwise invalid
N)csek_key_filer   r   )argsrZ   s     r   FromArgsCsekKeyStore.FromArgs&  s-    " !  !3!35HIIr   c           	      F   [        U [        R                  5      (       d   e0 n [        R                  " U 5      n[        U[
        5      (       d  [        S5      eU H  n[        U[        5      (       d.  [        SR                  [        R                  " U5      5      5      e[        UR                  5       5      [        :w  aB  [        SR                  [        R                  " U5      SR                  [        5      5      5      e[        US   5      n [        R!                  US   US   US9X%'   M     [        U[        5      (       d   eU$ ! ["         a#  n[%        UR&                  XVR(                  S	9eS
nAff = f! [*         a  n[        UR,                  6 eS
nAff = f)a  _ParseAndValidate(s) inteprets s as a csek key file.

Args:
  s: str, an input to parse
  allow_rsa_encrypted: bool, whether to allow RSA-wrapped keys

Returns:
  a valid state object

Raises:
  InvalidKeyFileException: if the input doesn't parse or is not well-formed.
z1Key file's top-level element must be a JSON list.z7Key file records must be JSON objects, but [{0}] found.z4Record [{0}] has incorrect json keys; [{1}] expected,r   r   r   rX   )r   r5   r/   N)
isinstancesixstring_typesjsonloadslistr   dictr   dumpssetkeysEXPECTED_RECORD_KEY_KEYSjoinr   rL   r[   r,   r2   r   r/   r<   r   )srZ   staterecords
key_recordr)   es          r   _ParseAndValidateCsekKeyStore._ParseAndValidate<  s    a))****E-

1g&&%@B 	B  **d++'GNN**Z(*+ + z !%=='DKK**Z(((3467 7
 Z./	N&..%e,z*7M"5 / 7%.  0 eT""""L , 	N#gWWM
M	N  -#QVV,,-s<   C/E? E2E? 
E<E77E<<E? ?
F 	FF c                 ,    [        U R                  5      $ rh   )r=   r   r`   s    r   __len__CsekKeyStore.__len__p  s    tzz?r   c           
      n   [        U R                  [        5      (       d   eSn[        R                  " U R                  5       HR  u  pEUR                  U5      (       d  M  US   (       a(  [        SR                  US   U[        U5      5      5      eXE4nMT     U(       a  US   c  [        U5      eUS   $ )a  Search for the unique key corresponding to a given resource.

Args:
  resource: the resource to find a key for.
  raise_if_missing: bool, raise an exception if the resource is not found.

Returns: CsekKeyBase, corresponding to the resource, or None if not found
  and not raise_if_missing.

Raises:
  InvalidKeyFileException: if there are two records matching the resource.
  MissingCsekException: if raise_if_missing and no key is found
    for the provided resource.
)NNr   zEUri patterns [{0}] and [{1}] both match resource [{2}].  Bailing out.r8   )
r   r   r   r   	iteritemsr   r   r   rz   r   )r   r   raise_if_missingsearch_statepatr   s         r   	LookupKeyCsekKeyStore.LookupKeys  s      djj$''''LMM$**-	X		?'..4fq/3H/78 8
 z . \!_4 **?r   c                 :    [         R                  UU5      U l        g rh   )r   r   r   )r   json_stringrZ   s      r   r   CsekKeyStore.__init__  s    //0CEDJr   )r   Nrk   )r   r   r   r   r   classmethodr   rl   r   r   r   r   r   r   r   r   r   r   r     sU    8 - -$ J J* 1 1f DEr   r   c                 6    U (       a  U R                  U5      $ S $ rh   )re   )csek_key_or_nonecomputes     r   MaybeToMessager     s    0@		#	#G	,JdJr   c                 B    U (       a  U(       a  U R                  U5      $ g rh   )r   )csek_keys_or_noner   s     r   MaybeLookupKeyr     s    8&&x00	r   c                 .    [        X5      n[        X25      $ rh   )r   r   )r   r   rd   	maybe_keys       r   MaybeLookupKeyMessager     s    .9)			22r   c                 D    U Vs/ s H  n[        X5      PM     sn$ s  snf rh   )r   )r   resource_collectionrs      r   MaybeLookupKeysr     s"    8K	L8K1.*
.8K	LL	Ls   c                 V    [        X5       Vs/ s H  n[        X25      PM     sn$ s  snf rh   )r   r   )r   r   rd   ks       r   MaybeLookupKeyMessagesr     s8     +
A
C
A 12.
+
A
C C 
Cs   &c           	      t    [        U U Vs/ s H  o3(       a  UR                  U5      OS PM     sn5      $ s  snf rh   )r   Parse)r   r   urisus       r   MaybeLookupKeysByUrir     s6    	156A1Q$&6
8 86s   #5
c                 X    [        XU5       Vs/ s H  n[        XC5      PM     sn$ s  snf rh   )r   r   )r   r   r   rd   r   s        r   MaybeLookupKeyMessagesByUrir     s:     0$
?
A
? 12.
+
?
A A 
As   ')Tr   )(r   rm   rB   r   r@   googlecloudsdk.api_lib.computer   googlecloudsdk.corer   googlecloudsdk.core.consoler   r   r   r   rs   r   r   r   r%   r,   r2   rJ   with_metaclassABCMetaobjectrL   rU   rV   rW   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r     s(   H    	 5 ) 2 
05 !# +. (OJ OFe F	1 		#: 	1 '=T0#$$S[[&9 0f' '0+ 0	31 	3M5 ME<2 2"KE6 KEbK3
MC8Ar   