+
    i                     R    R t ^ RIt^ RIt^ RIHt R tR tR	R ltR	R ltR t	R t
R# )
a  
vault_client.py
===============
Reusable vault credential retrieval for all SKG pipeline scripts.
Place this file in VAULT_DIR alongside vault.py.

Reads from environment (load_dotenv must be called before importing):
  OS env vars : VAULT_DIR  - folder containing vault.py
                VPATH      - path to vault.enc
                ID_ENC     - AES-encrypted master password
  .env file   : VAULT_KEY  - Fernet key that decrypts ID_ENC

Public API:
    from vault_client import get_vault_credentials, get_wallet_password

    db_user, db_password   = get_vault_credentials('MULBUILDDB1')
    wallet_pw              = get_wallet_password('C:/code/wallet/Wallet_MULBUILDDB1')

Author: M Dombaugh
Version: 1.0 - Initial implementation with encrypted master password support.
               Fernet symmetric encryption: ID_ENC (OS env) decrypted by
               VAULT_KEY (.env). Falls back to plain ID env var for
               backward compatibility.
N)Pathc                     ^ RI Hp  V #   \         d     Mi ; i. p\        P                  ! R4      pT'       d   TP                  \        T4      4       TP                  \        P                  ! 4       R,          \        R4      \        P                  ! 4       R,          .4       T F  pTP                  4       '       g   K  \        T4      \        P                  9  g   K;  \        P                  P                  ^ \        T4      4        ^ RI Hp  T u #   \         d$    \        P                  P                  ^ 4        K  i ; i	  R# )z
Attempt to import SecureVault. Searches VAULT_DIR env var first,
then a small set of conventional fallback locations.
Returns SecureVault class or None.
)SecureVault	VAULT_DIRz.secure_vaultzC:/Oracle/vaultvaultN)r   r   ImportErrorosgetenvappendr   extendhomecwdexistsstrsyspathinsertpop)r   search_pathsvault_dir_envfolders       %C:\code\desktop_vault\vault_client.py_import_secure_vaultr   "   s    %  LIIk*MD/0		o%
W  ==??s6{#((:HHOOAs6{+ -""  Q   s   
 D*EEc                    \         P                  ! R4      p \         P                  ! R4      pV '       d   V'       d    ^ RIHpHp \        V \        4      '       d   V P                  4       MT p\        V\        4      '       d   VP                  4       MTpV! V4      P                  V4      P                  4       # \         P                  ! R4      pV'       d   V# \        R4       R#   \         d   p\        RT 24        Rp?R# Rp?ii ; i)z
Decrypt master password from ID_ENC (OS env) using VAULT_KEY (.env).
Falls back to plain ID env var for backward compatibility.
Returns decrypted master password string or None.
	VAULT_KEYID_ENC)FernetInvalidTokenz+[VAULT] Failed to decrypt master password: NIDzD[VAULT] No master password available. Set ID_ENC + VAULT_KEY, or ID.)r   r	   cryptography.fernetr   r   
isinstancer   encodedecryptdecode	Exceptionprint)	vault_keyid_encr   r   keytokeneplains           r   _get_master_passwordr,   H   s     		+&I		(#FV	@(29c(B(B)""$	C'1&#'>'>FMMOFE#;&&u-4466 IIdOE	
PQ  	?sCD	s   A<C( (D3DDc                h   \        4       pVf   \        R4       R# \        P                  ! R4      pV'       d    \	        V4      P                  4       '       g   \        RV R24       R# \        4       pV'       g   R#  V! V4      pVP                  V4      '       g   \        R4       R# VP                  W4      pVP                  4        Vf   \        RV  R24       R# V'       d   V# \        \        VP                  4       4      4      #   \         d   p\        R	T 24        Rp?R# Rp?ii ; i)
zu
Open vault, retrieve credentials for service_name.
Returns the entry dict {username, password, notes, ...} or None.
Nz4[VAULT] vault.py not found. Set VAULT_DIR correctly.VPATHz'[VAULT] Vault file not found at VPATH=''z[VAULT] Failed to unlock vault.z[VAULT] Service 'z' not found in vault.z[VAULT] Error accessing vault: )r   r%   r   r	   r   r   r,   unlock_vaultget_password
lock_vaultnextitervaluesr$   )service_nameusernamer   vpathmaster_passwordr   service_entriesr*   s   &&      r   _get_from_vaultr;   h   s   
 '(KDEIIgEU**,,7wa@A*,OE"!!/2234,,\D"%l^3HIJ"" D//1233 /s34s6   ?D D +4D !D )D +!D D1D,,D1c                p    \        W4      pV'       d#   VP                  R4      VP                  R4      3# R# )a  
Retrieve database credentials from the vault.

Args:
    service_name : Vault service key, derived from wallet folder name
                   e.g. 'MULBUILDDB1' from Wallet_MULBUILDDB1
    username     : Optional - retrieve specific username entry.
                   If omitted, returns first entry for the service.

Returns:
    (username, password) tuple, or (None, None) on failure.

Example:
    db_user, db_pass = get_vault_credentials('MULBUILDDB1')
r7   password)NN)r;   get)r6   r7   entrys   && r   get_vault_credentialsr@      s4      L3Eyy$eii
&;;;    c                   \        V 4      P                  pVP                  RR4      P                  RR4      P                  4       R,           p\	        V4      pV'       d   VP                  R4      # \        RV 24       R# )a  
Retrieve wallet password from the vault.

Derives the vault service name from the wallet folder name by
appending '_WALLET'. e.g. Wallet_MULBUILDDB1 -> MULBUILDDB1_WALLET

Args:
    oracle_wallet_path : Path to the wallet folder (string or Path).
                         Matches ORACLE_WALLET_PATH in .env.

Returns:
    Wallet password string, or None on failure.

Example:
    wallet_pw = get_wallet_password('C:/code/wallet/Wallet_MULBUILDDB1')
Wallet_ wallet__WALLETr=   z.[VAULT] No wallet password found for service: N)r   namereplacestripr;   r>   r%   )oracle_wallet_pathwallet_folderr6   r?   s   &   r   get_wallet_passwordrL      su    " ,-22M	B		B		
		  L)Eyy$$	:<.
IJrA   c                    \        V 4      P                  pVP                  RR4      P                  RR4      P                  4       # )z}
Utility: derive the vault service name from a wallet folder path.
e.g. 'C:/code/wallet/Wallet_MULBUILDDB1' -> 'MULBUILDDB1'
rC   rD   rE   )r   rG   rH   rI   )rJ   rK   s   & r   !get_service_name_from_wallet_pathrN      s<    
 +,11M	B		B			rA   )N)__doc__r   r   pathlibr   r   r,   r;   r@   rL   rN    rA   r   <module>rR      s7   2 
 
 L@)`,@rA   