fj)dZddlZddlZddlZddlmZddlmZddlm Z ddl m Z ddl mZmZdd lmZmZmZejeZ dd lmZmZmZdd lmZn#e$rd Zd ZdZdZYnwxYwdedefdZdedededeefdZ dededdfdZ! d dee"de#dedefdZ$ d!dede#de#dede#dee"deddfdZ%dededdfdZ&dS)"z Website isolation support for X-Ray INI files. This module provides functions to manage xray.ini files in per-website directories when CageFS website isolation is enabled. N)iglob)Optional) disable_quota)docroot) user_contextcagefsctl_get_prefix)is_excluded_path$get_domain_php_version_from_selectorINI_USER_LOCATIONS)(is_website_isolation_allowed_server_wideis_isolation_enabled#get_websites_with_enabled_isolation)get_website_idcdSNFr]/opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/reconfiguration/website_isolation.pyr r +urcdSrrusers rrr/rrcgSNrrs rrr3s rrdomaincDtsdS|t|vSr)r r)rrs ris_per_website_php_selectorr:s) 3 5 5u 8>> >>r website_id php_ver_dirreturnc Ft|}|dSd|d|d|d|d S)a Build path to xray.ini in per-website directory. :param user: Username :param website_id: Website ID hash :param php_ver_dir: PHP version directory (e.g., 'alt-php80') :return: Full path to xray.ini or None if cagefs prefix not available Nz /var/cagefs//z/etc/cl.php.d/z /xray.ini)r)rrr prefixs r_get_per_website_ini_pathr%@sD"$ ' 'F ~t Z& Z Z4 Z Zz Z ZK Z Z ZZrc t||sdSi}d}d}tD][}t|dD]A}t|r |d|}|j|kr1|j}|j}n"#td|Y_xYwtj |d}tj |s t|5} tj |} | || <dddn #1swxYwY#t $r4} td|t%| Yd} ~ ;d} ~ wwxYw]|r|dSt'|} | d} t)| }t+||}||}|s/t/t1|d}t5|||}tj |}tj |std|dS t;||5t=5t|d 5} | |dddn #1swxYwYdddn #1swxYwYdddn #1swxYwYtd ||dS#t@$r'} td || Yd} ~ dSd} ~ wwxYw) a Copy xray.ini files from base user locations to per-website directories. This function is called by cagefsctl when enabling website isolation for a user. If xray.ini exists in base location (meaning user has active tasks), copy it to per-website directories. Overwrites existing files for consistency. Each domain may have a different PHP version set via cloudlinux-selector, so we determine the domain's actual PHP version from cl.selector symlinks. :param user: Username to regenerate ini files for Npathrz!Cannot get pw_record for path: %szxray.iniz+Cannot read xray.ini for path: %s, error=%srz*Per-website ini directory does not exist: wzCreated %s for domain %szFailed to create %s: %s)!rr rr pw_namepw_uidpw_gidloggerdebugosr'joinexistsopenbasenamereadOSErrorerrorstr get_docrootrr getnextitervaluesr%dirnameinforrwrite Exception)rrbase_ini_filesuidgidlocationdir_path pw_recordini_filefr edocroot_result document_rootrdomain_php_vercontentini_pathini_dirs r$regenerate_ini_for_website_isolationrONsV 'tV 4 4N C C&hv.//  H))  ,HV,X66 $,,&&  @(KKKw||Hj99H7>>(++  (^^;q"$'"2"28"<"JJHgooh''G 7>>' " " JJJKKK= #s # #  ]__  d8S6I6I Q GGG                                                 /6BBBBB === .!<<<<<<<<<=s A8)A88BD:*7D-! D:-D1 1D:4D1 5D:: E8)E33E8.L>K. KK4 KK KK K K.K K.K K." L.K22L5K26L M!MMexisting_contentscounter php_versionc|t|dkrd}nd|d} d|ddSfd }d t|S) a: Generate xray.ini content with a specific task counter value. :param existing_contents: Existing ini file lines or None for new file :param counter: Task counter value to set :param php_version: PHP version for extension path (used only for new files) :return: Generated ini file content Nzxray.soz /opt/alt/phpz/usr/lib64/php/modules/xray.soz extension=z ;xray.tasks= c3>KD]}d|vr ddV|dzVdS)Nz xray.tasksz ;xray.tasks=rUr)linerQrPs r update_linez/_generate_ini_with_counter..update_linesX% " "Dt##0W0000000Tk!!!!  " "r)lenr/list)rPrQrRso_pathrXs`` r_generate_ini_with_counterr]sc+..22LLLL g  """""" 774 && ' ''rrArBdomain_task_countcDt||sdS t|}|std|dS|d}t |} n4#t $r'} td|| Yd} ~ dSd} ~ wwxYw| sdSt|| } | std|dSt|| | } | sdStj | } tj | std| dSt|||} t||5t5t!| d5}||dddn #1swxYwYdddn #1swxYwYdddn #1swxYwYtd| || |dS#t$$r'} td | | Yd} ~ dSd} ~ wwxYw) aT Update xray.ini file in per-website directory for a SPECIFIC domain. This function is called when a tracing task is added/updated for a domain. The ini file is placed in the directory matching the domain's PHP version as configured via cloudlinux-selector. Generates the ini content with domain-specific task counter, which may differ from the per-user counter when a user has tasks for multiple domains. :param user: Username :param uid: User ID for file ownership :param gid: Group ID for file ownership :param domain: Domain name (e.g., 'example.com') - REQUIRED :param domain_task_count: Number of tasks for this specific domain :param existing_contents: Existing per-user ini file lines (to preserve settings) :param php_version: PHP version for extension path (used only for new files) N#Failed to get docroot for domain %sr*Failed to get website_id for domain %s: %s3No specific PHP version set for domain %s, skippingz,Per-website ini directory does not exist: %sr(z+Updated %s for domain %s (PHP %s, tasks=%d)zFailed to update %s: %s)rr7r,r-rr?r5r r%r.r'r<isdirr]rrr1r>r4)rrArBrr^rPrRrIrJrrHrKrMrNrLrGs rupdate_website_isolation_inirds6 'tV 4 4 $V,,  LL> G G G F&q) #M22  A61MMM :$ KKN  JFSSS(z>JJH gooh''G 7== ! ! CWMMM)): G G G F&q) #M22  A61MMM :$ KKN  JFSSS(z>JJH  7>>( # #=L&& )*I,< = =  Ih                   8(FN[[[[[ === .!<<<<<<<<<=sY,AA B $BB 8.E1&E; E1E  E1E  E11 F";FF"r)NN)'__doc__loggingr.rfglobrtypingrsecureiorclcommon.cpapirr7xray.internal.utilsrrxray_inir r r getLogger__name__r,clcagefslib.domainr rr#clcagefslib.webisolation.jail_utilsr ImportErrorr6rr%rOr[intr]rdrirrrrxs """"""111111BBBBBBBB  8 $ $ CBBBBBB   NNN  ?c?3???? [C [S [s [xX[} [ [ [ [I=sI=CI=DI=I=I=I=^ ((#D>((( ((((P-1H=H=H= H=H= H=  H= $D> H=H= H=H=H=H=V0=s0=C0=D0=0=0=0=0=0=s AA.-A.