
                            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
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  \	R&                  " S5      rSr " S S\R,                  5      r\R0                  " S/ SQ5      r " S S5      r\" 5       rS rS r\R<                  " SS9S 5       rS r S r!SS jr"SS jr#SS jr$g) z1Utilities that support customer encryption flows.    )absolute_import)division)unicode_literalsN)errors)	hash_util)user_request_args_factory)
properties)yaml)function_result_cachezqprojects/([^/]+)/locations/([a-zA-Z0-9_-]{1,63})/keyRings/([a-zA-Z0-9_-]{1,63})/cryptoKeys/([a-zA-Z0-9_-]{1,63})$AES256c                       \ rS rSrSrSrSrg)KeyType*   CMEKCSEK N)__name__
__module____qualname____firstlineno__r   r   __static_attributes__r       9lib/googlecloudsdk/command_lib/storage/encryption_util.pyr   r   *   s    	$	$r   r   EncryptionKey)keytypesha256c                   .    \ rS rSrSr   SS jrS rSrg)	_KeyStore8   au  Holds encryption key information.

Attributes:
  encryption_key (Optional[EncryptionKey]): The key for encryption.
  decryption_key_index (Dict[EncryptionKey.sha256, EncryptionKey]): Indexes
    keys that can be used for decryption.
  initialized (bool): True if encryption_key and decryption_key_index
    reflect the values they should based on flag and key file values.
Nc                 <    Xl         U=(       d    0 U l        X0l        g N)encryption_keydecryption_key_indexinitialized)selfr#   r$   r%   s       r   __init___KeyStore.__init__C   s     ) 4 :D"r   c                     [        XR                  5      (       d  [        $ U R                  UR                  :H  =(       a9    U R                  UR                  :H  =(       a    U R
                  UR
                  :H  $ r"   )
isinstance	__class__NotImplementedr#   r$   r%   )r&   others     r   __eq___KeyStore.__eq__K   sb    e^^,,u333 	.!!U%?%??	.E---r   )r$   r#   r%   )NNF)r   r   r   r   __doc__r'   r.   r   r   r   r   r   r   8   s     #$( #r   r   c                    U (       d  [         R                  " S5      eU R                  S5      (       a  [         R                  " SU -   5      e[        R	                  U 5      (       d%  [         R                  " SR                  U 5      5      eg )NzKey is empty./z1KMS key should not start with leading slash (/): zInvalid KMS key name: {}.
KMS keys should follow the format "projects/<project-id>/locations/<location>/keyRings/<keyring>/cryptoKeys/<key-name>")r   Error
startswith_CMEK_REGEXmatchformat)raw_keys    r   validate_cmekr9   X   sx    	
,,
''
,,J     
		7	#	#
,,	!!'2 2 
$r   c                 d   U R                  S5      n [        U 5        [        R                  nSn[        XUS9$ ! [        R
                   aa    [        U 5      S:w  a  e [        R                  n[        R                  " [        R                  " [        R                  " U5      5      5      n N~f = f)zAReturns an EncryptionKey populated with information from raw_key.asciiN,   )r   r   r   )encoder9   r   r   r   r3   lenr   r   get_base64_hash_digest_stringhashlibr   base64	b64decoder   )r8   raw_key_byteskey_typer   s       r   	parse_keyrE   g   s    ..)-	9'||HF 
7	AA 
 9
7|r||H44v''679F	9s   : A2B/.B/   )maxsizec                     U =(       d2    [         R                  R                  R                  R	                  5       nU(       d  0 $ [
        R                  " U5      $ )zReads the key store file, if it exists.

Args:
  key_path: str | None, only provided for unit tests.

Returns:
  The contents of the key store file, or an empty dict if the file does not
  exist.
)r	   VALUESstoragekey_store_pathGetr
   	load_path)key_pathrK   s     r   _read_key_store_filerO   w   s@     Mz0088GGKKM.	I		''r   c                 X    [        XS5      nUb  U$ [        U5      R                  U5      $ )a  Searches for key values in flags, falling back to a file if necessary.

Args:
  args: An object containing flag values from the command surface.
  key_field_name (str): Corresponds to a flag name or field name in the key
      file.
  key_store_path (str | None): The path to the key store file. Only provided
    if testing.

Returns:
  The flag value associated with key_field_name, or the value contained in the
  key file.
N)getattrrO   get)argskey_field_namerK   flag_keys       r   _get_raw_keyrV      s1     T40(O	n	-	1	1.	AAr   c                     0 nU (       aK  U  HE  nU(       d  M  [        U5      nUR                  [        R                  :X  d  M7  X1UR                  '   MG     U$ )zParses and indexes raw keys.

Args:
  raw_keys (list[str]): The keys to index.

Returns:
  A dict mapping key hashes to keys in raw_keys. Falsy elements of raw_keys
  and non-CSEKs are skipped.
)rE   r   r   r   r   )raw_keysindexr8   r   s       r   _index_decryption_keysrZ      sI     %gc	W\\	!cjj  
,r   c                 L   [         R                  (       a  g[        U SU5      n[        U SS5      (       a  [        R
                  [         l        OU(       a  [        U5      [         l        U/n[        U SU5      nU(       a  X4-  n[        U5      [         l	        S[         l        g)a  Loads appropriate encryption and decryption keys into memory.

Prefers values from flags over those from the user's key file. If _key_store
  is not already initialized, creates a _KeyStore instance and stores it in a
  global variable.

Args:
  args: An object containing flag values from the command surface.
  key_store_path (str | None): The path to the key store file. Only provided
    if testing.
Nr#   clear_encryption_keydecryption_keysT)

_key_storer%   rV   rQ   r   CLEARr#   rE   rZ   r$   )rS   rK   raw_encryption_keyrX   raw_decryption_keyss        r   initialize_key_storerb      s     
#D*:NKT)400 9 ? ?J )*< =J !($T+<nM#H$:8$D*!*r   c                     [         R                  (       a   [         R                  R                  U 5      nOSnU(       d,  U(       a%  [        R
                  " SR                  X5      5      eU$ )zCReturns a key that matches sha256_hash, or None if no key is found.NzPMissing decryption key with SHA256 hash {}. No decryption key matches object {}.)r^   r%   r$   rR   r   r3   r7   )sha256_hashurl_for_missing_key_errordecryption_keys      r   get_decryption_keyrg      sV    4488ENN	5
,,	#VKKM M 
r   c                 r    [         R                  (       a"  U (       a  [        X5      $ [         R                  $ g)a  Returns an EncryptionKey, None, or a CLEAR string constant.

Args:
  sha256_hash (str): Attempts to return a CSEK key that matches this hash.
    Used for encrypting with a non-default key.
  url_for_missing_key_error (StorageUrl): If a key matching sha256_hash can
    not be found, raise an error adding this object URL to the error text.

Returns:
  EncryptionKey: Custom or default key depending on presence of sha256_hash.
  None: Matching key to sha256_hash could not be found and
    url_for_missing_key_error was None. Or, no sha256_hash and no default key.
  user_request_args_factory.CLEAR (str): Value indicating that the
    user requested to clear an existing encryption.
N)r^   r%   rg   r#   )rd   re   s     r   get_encryption_keyri      s,      GG$$$ r   r"   )NN)%r0   
__future__r   r   r   rA   collectionsenumr@   re"googlecloudsdk.command_lib.storager   r   r   googlecloudsdk.corer	   r
   googlecloudsdk.core.cacher   compiler5   ENCRYPTION_ALGORITHMEnumr   
namedtupler   r   r^   r9   rE   lrurO   rV   rZ   rb   rg   ri   r   r   r   <module>rv      s    8 &  '     	 5 8 H * $ ; jj = >   dii 
 && : [
2B  1%( &( B(* <
%r   