
    :                        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	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\R4                  " \R6                  \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.    )absolute_import)division)unicode_literalsN)
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$ )BadPatternException4   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__7   s<    $L	
t-077LL	r   )r,   r+   r$   r&   s   @r   r(   r(   4   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	   r2   r"   s      r   r   %InvalidKeyExceptionNoContext.__init__C   s9    HJ	
&6"))HHJJ	r   )r2   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$ )InvalidKeyExceptionL   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_idr2   r   r5   r   r   )r    r	   r8   r2   r"   s       r   r   InvalidKeyException.__init__O   sE    HKJ	
t-,33HHKKJJ	r   )r2   r	   r8   r$   r&   s   @r   r5   r5   L   s    > r   r5   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   ValidateKeyrM   Z   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)rJ   )rM   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rT   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   rR   CsekKeyBase.GetKeyLength   s    
B
CCr   c                     A[        S5      e)NzToMessage() must be overridden.ra   r    compute_clients     r   	ToMessageCsekKeyBase.ToMessage   s    
?
@@r   c                     U R                   $ NrS   rc   s    r   rT   CsekKeyBase.key_material   s    r   rl   NF)r   r   r   r   r   r   staticmethodr^   abcabstractmethodrR   rh   propertyrT   r   r   r   r   rO   rO      sj    +& ( (: D D A A  r   rO   c                   $    \ rS rSrSrS rS rSrg)rX      z!Class representing raw CSEK keys.c                     [         $ rk   )BASE64_RAW_KEY_LENGTH_IN_CHARSrc   s    r   rR   CsekRawKey.GetKeyLength   s    ))r   c                 Z    UR                   R                  [        U R                  5      S9$ )N)rawKeyMESSAGES_MODULECustomerEncryptionKeystrrT   rf   s     r   rh   CsekRawKey.ToMessage   s/    ))??4$$% @ ' 'r   r   Nr   r   r   r   r   rR   rh   r   r   r   r   rX   rX      s    )*'r   rX   c                   $    \ rS rSrSrS rS rSrg)rY      z+Class representing rsa encrypted CSEK keys.c                     [         $ rk   )(BASE64_RSA_ENCRYPTED_KEY_LENGTH_IN_CHARSrc   s    r   rR    CsekRsaEncryptedKey.GetKeyLength   s    33r   c                 Z    UR                   R                  [        U R                  5      S9$ )N)rsaEncryptedKeyrz   rf   s     r   rh   CsekRsaEncryptedKey.ToMessage   s/    ))??D--. @ 0 0r   r   Nr   r   r   r   rY   rY      s    340r   rY   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )rZ      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: .)r\   r   r   rZ   r   )r    r\   explanationmsgr"   s       r   r   BadKeyTypeException.__init__   sG    M
"
)
)$--
8C	TKc3JC	
t-c2r   )r\   ) r$   r&   s   @r   rZ   rZ      s    "3 3r   rZ   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   rc   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fnamer]   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   )argsr]   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   r[   )r	   r8   r2   N)
isinstancesixstring_typesjsonloadslistr   dictr   dumpssetkeysEXPECTED_RECORD_KEY_KEYSjoinr   rO   r^   r/   r5   r	   r2   r?   r   )sr]   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      $ rk   )r@   r   rc   s    r   __len__CsekKeyStore.__len__s  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.r;   )
r   r   r   r   	iteritemsr   r   r   r}   r   )r    r   raise_if_missingsearch_statepatr	   s         r   	LookupKeyCsekKeyStore.LookupKeyv  s      djj$''''LMM$**-	X		?'..4fq/3H/78 8
 z . \!_4 **?r   c                 :    [         R                  UU5      U l        g rk   )r   r   r   )r    json_stringr]   s      r   r   CsekKeyStore.__init__  s    //0CEDJr   )r   Nrn   )r   r   r   r   r   classmethodr   ro   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 $ rk   )rh   )csek_key_or_nonecomputes     r   MaybeToMessager     s    0@		#	#G	,JdJr   c                 B    U (       a  U(       a  U R                  U5      $ g rk   )r   )csek_keys_or_noner   s     r   MaybeLookupKeyr     s    8&&x00	r   c                 .    [        X5      n[        X25      $ rk   )r   r   )r   r   rg   	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 rk   )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 rk   )r   r   )r   r   rg   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 rk   )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 rk   )r   r   )r   r   r   rg   r   s        r   MaybeLookupKeyMessagesByUrir     s:     0$
?
A
? 12.
+
?
A A 
As   ')Tr   ),r   
__future__r   r   r   rp   rE   r   rC   googlecloudsdk.api_lib.computer   googlecloudsdk.corer   googlecloudsdk.core.consoler   r   r   r   rv   r   r   r   r(   r/   r5   rM   with_metaclassABCMetaobjectrO   rX   rY   rZ   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   