o
    q\j                     @  s   d Z ddlm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 G dd	 d	eZG d
d deZe	ddG dd dZG dd dZdS )z:Versioned authenticated encryption for tenant credentials.    )annotationsN)Path)	dataclass)
InvalidTag)AESGCMc                   @     e Zd ZdS )SecretConfigurationErrorN__name__
__module____qualname__ r   r   platform/secrets/encryption.pyr          r   c                   @  r   )SecretIntegrityErrorNr	   r   r   r   r   r      r   r   T)frozenc                   @  s   e Zd ZU ded< ded< dS )EncryptedSecretstr
ciphertextkey_versionN)r
   r   r   __annotations__r   r   r   r   r      s   
 r   c                   @  s@   e Zd ZdZdZdd	d
ZedddZdddZdddZ	dS )VersionedAESCipherz5AES-256-GCM keyring with explicit active-key version.aesgcm1keysdict[str, bytes]active_versionr   returnNonec                 C  sJ   ||vrt d| D ]\}}|rt|dkrt dq|| _|| _d S )Nz7Active secret key version is not present in the keyring    z2Every platform secret key must be exactly 32 bytes)r   itemslenr   r   )selfr   r   versionkeyr   r   r   __init__"   s   
zVersionedAESCipher.__init__'VersionedAESCipher'c              
   C  s   t tdd}tdd }tdd }|sH| rHzt|jdd}t|d }t	|d	 }W n t
yG } ztd
|d }~ww |rL|sPtdzt|}dd | D }W n t
yq } ztd|d }~ww | ||S )NPLATFORM_SECRETS_KEYRING_FILEz4/var/www/html/.platform-secrets/secrets-keyring.jsonPLATFORM_SECRETS_KEYS #PLATFORM_SECRETS_ACTIVE_KEY_VERSIONutf-8)encodingr   r   z'External secret keyring file is invalidz/An external platform secret keyring is requiredc                 S  s*   i | ]\}}t |tt |d qS )ascii)r   base64urlsafe_b64decodeencode).0r"   encodedr   r   r   
<dictcomp>@   s    z7VersionedAESCipher.from_environment.<locals>.<dictcomp>z,PLATFORM_SECRETS_KEYS is not a valid keyring)r   osgetenvstripis_filejsonloads	read_textdumpsr   	Exceptionr   r   )clskeyring_fileraw_keyringr   file_payloadexcencoded_keysr   r   r   r   from_environment+   s:   




z#VersionedAESCipher.from_environment	plaintextaadbytesr   c                C  s`   t d}t| j| j ||d|}t|| 	d}t
| j d| j d| | jdS )N   r*   r,   :)r   r   )r3   urandomr   r   r   encryptr/   r-   urlsafe_b64encodedecoder   FORMAT_VERSION)r!   rC   rD   nonce	encryptedpayloadr   r   r   rI   H   s   
zVersionedAESCipher.encryptr   c                C  s   z9| dd\}}}|| jkrtd| j| }t|d}|d d |dd  }}	t|||	|	dW S  t
tttfyT }
 zt|
trK td|
d }
~
ww )NrG      z#Unsupported encrypted secret formatr,   rF   r*   z,Encrypted secret failed integrity validation)splitrL   r   r   r-   r.   r/   r   decryptrK   KeyErrorr   UnicodeDecodeError
ValueError
isinstance)r!   r   rD   format_versionr   r1   r#   rO   rM   rN   r@   r   r   r   rR   S   s   



zVersionedAESCipher.decryptN)r   r   r   r   r   r   )r   r%   )rC   r   rD   rE   r   r   )r   r   rD   rE   r   r   )
r
   r   r   __doc__rL   r$   classmethodrB   rI   rR   r   r   r   r   r      s    
	
r   )rX   
__future__r   r-   r7   r3   pathlibr   dataclassesr   cryptography.exceptionsr   +cryptography.hazmat.primitives.ciphers.aeadr   RuntimeErrorr   rU   r   r   r   r   r   r   r   <module>   s    