
                            d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddlZddl	Z	ddl
mZ ddl
mZ ddl
mZ dd	lmZ dd
lmZ ddlmZ  e	j&                  d      ZdZ G d dej,                        Z ej0                  dg d      Z G d d      Z e       Zd Zd Z ej<                  d      d        Zd Z d Z!ddZ"ddZ#ddZ$y) 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                       e Zd ZdZdZy)KeyTypeCMEKCSEKN)__name__
__module____qualname__r   r        9lib/googlecloudsdk/command_lib/storage/encryption_util.pyr   r   *   s    	$	$r   r   EncryptionKey)keytypesha256c                   $    e Zd ZdZ	 	 	 ddZd Zy)	_KeyStorea  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                 6    || _         |xs i | _        || _        y N)encryption_keydecryption_key_indexinitialized)selfr   r    r!   s       r   __init__z_KeyStore.__init__C   s!     )D 4 :D"Dr   c                     t        || j                        st        S | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j
                  |j
                  k(  S r   )
isinstance	__class__NotImplementedr   r    r!   )r"   others     r   __eq__z_KeyStore.__eq__K   sa    eT^^,u333 	.!!U%?%??	.E---r   )NNF)r   r   r   __doc__r#   r)   r   r   r   r   r   8   s     #$( #r   r   c                     | st        j                  d      | j                  d      rt        j                  d| z         t        j	                  |       s$t        j                  dj                  |             y )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_cmekr3   X   sr    	
,,
''
,,J     
		7	#
,,	!!'2 2 
$r   c                 b   | j                  d      }	 t        |        t        j                  }d}t        | ||      S # t        j
                  $ r] t        |       dk7  r t        j                  }t        j                  t        j                  t        j                  |                  }Y }w xY w)zAReturns an EncryptionKey populated with information from raw_key.asciiN,   )r   r   r   )encoder3   r   r   r   r-   lenr   r   get_base64_hash_digest_stringhashlibr   base64	b64decoder   )r2   raw_key_byteskey_typer   s       r   	parse_keyr?   g   s    ..)-	9'||HF 
76	AA 
 9
7|r||H44v''679F	9s   > A-B.-B.   )maxsizec                     | xs2 t         j                  j                  j                  j	                         }|si S t        j                  |      S )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_pathrE   s     r   _read_key_store_filerI   w   s@     Mz0088GGKKM.	I		''r   c                 X    t        | |d      }||S t        |      j                  |      S )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)getattrrI   get)argskey_field_namerE   flag_keys       r   _get_raw_keyrP      s3     T>40(O	n	-	1	1.	AAr   c                     i }| rB| D ]=  }|st        |      }|j                  t        j                  k(  s/|||j                  <   ? |S )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.
  )r?   r   r   r   r   )raw_keysindexr2   r   s       r   _index_decryption_keysrT      sK     %gc	W\\	!cjj  
,r   c                 &   t         j                  ryt        | d|      }t        | dd      rt        j
                  t         _        n|rt        |      t         _        |g}t        | d|      }|r||z  }t        |      t         _	        dt         _        y)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!   rP   rK   r   CLEARr   r?   rT   r    )rM   rE   raw_encryption_keyrR   raw_decryption_keyss        r   initialize_key_storer\      s     
#D*:NKT)40 9 ? ?J )*< =J !($T+<nM##H$:8$D*!*r   c                     t         j                  r t         j                  j                  |       }nd}|s'|r%t	        j
                  dj                  | |            |S )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 {}.)rX   r!   r    rL   r   r-   r1   )sha256_hashurl_for_missing_key_errordecryption_keys      r   get_decryption_keyra      sY    4488ENN	5
,,	#VK1JKM M 
r   c                 `    t         j                  r| rt        | |      S t         j                  S y)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)rX   r!   ra   r   )r^   r_   s     r   get_encryption_keyrc      s/      -FGG$$$ r   r   )NN)%r*   
__future__r   r   r   r;   collectionsenumr:   re"googlecloudsdk.command_lib.storager   r   r   googlecloudsdk.corer	   r
   googlecloudsdk.core.cacher   compiler/   ENCRYPTION_ALGORITHMEnumr   
namedtupler   r   rX   r3   r?   lrurI   rP   rT   r\   ra   rc   r   r   r   <module>rp      s    8 &  '     	 5 8 H * $ ; bjj = >   dii 
 '&& : [
2B  1%( &( B(* <
%r   