9Mj߄dZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z ddl m Zm Z ddl mZmZmZddlZddlmZddlmZmZddlmZmZdd lmZdd lmZdd lm Z dd l!m"Z#d dl$m%Z%d dl&m'Z'd dl(m)Z)d dl*m+Z+m,Z,m-Z-m.Z.m/Z/d dl0m1Z1d dl2m3Z3d dl4m5Z5d dl6m7Z7m8Z8m9Z9d dl:m;Z;d dlm?Z?m@Z@mAZAd dlBmCZCmDZDmEZEmFZFmGZGmHZHd dlImJZJmKZKmLZLmMZMmNZNe jOrd dlPmQZQejRdZSGddZTdS)zX This module contains classes implementing X-Ray Manager behaviour and helper functions N)datetime timedelta)escapeglob)IteratorOptionalTuple)Feature)is_panel_feature_supportedget_installed_php_versions)php_get_vhost_versionsis_wpos_supported)is_litespeed_running)drop_privileges) disable_quota)gettext) ClWposGetter) get_client)ContinuousManager) XRayAPIError XRayErrorXRayMissingDomainXRayManagerExitXRayManagerExitPHPUnsupported)FPMReloadController)open_local_storage)NginxUserCache) DomainInfoTask url_split)ManageUserAgent)AdvancedMetrics)get_xray_exec_useruser_mode_restrictednginx_user_cache)no_active_tasksswitch_schedstats ssa_disabled_cagefsctl_remountset_privilegesis_file_recently_modified)create_ini_filesremove_ini_filesis_global_ini_moderemove_global_ini_mode_markercreate_global_ini_mode_marker) APIClientz%^[A-Za-z0-9_][A-Za-z0-9@:._-]{0,127}$ceZdZdZdZddddddd d d d d ddddZdbdedefdZde e fdZ de fdZ dedefdZdedefdZdedefdZdedefdZdedefdZdedd fd!Zd"Zd#edefd$Zed%edeejfd&Zd'edd fd(Zd)edefd*Zd+edefd,Zdedefd-Z d.edefd/Z!d.edd fd0Z"ed#ede#ee ffd1Z$d2edd fd3Z%edefd4Z&defd5Z'e(ddd6d)ed7ed8ed9e d:ed;edefd<Z)d)edefd=Z*d>d?d)ed9e defd@Z+dAedefdBZ,dCZ-e(dAedefdDZ.dAedefdEZ/edFe defdGZ0defdHZ1edIe2dJdKfdLZ3dAedefdMZ4d)edNedefdOZ5d)edefdPZ6d)edefdQZ7d)edefdRZ8defdSZ9defdTZ:dcdUedVe dWe defdXZ;dUedefdYZdefd]Z?defd^Z@defd_ZAdefd`ZBdefdaZCd S)d BaseManagerz Basic manager abstract class. Implements methods common for all managers. Requires managers to implement their custom methods. z/var/run/xray-agent.pidz/opt/alt/php54/link/confz/opt/alt/php55/link/confz/opt/alt/php56/link/confz/opt/alt/php70/link/confz/opt/alt/php71/link/confz/opt/alt/php72/link/confz/opt/alt/php73/link/confz/opt/alt/php74/link/confz/opt/alt/php80/link/confz/opt/alt/php81/link/confz/opt/alt/php82/link/confz/opt/alt/php83/link/confz/opt/alt/php84/link/confz/opt/alt/php85/link/conf)z alt-php54z alt-php55z alt-php56z alt-php70z alt-php71z alt-php72z alt-php73z alt-php74z alt-php80z alt-php81z alt-php82z alt-php83z alt-php84z alt-php85F system_id phpinfo_modec t|_||_tjd|_t |_t|_ ||_ td|j|_ dS)Nmanagerlistsr5) rapi_client_classsys_idlogging getLoggerloggerrcontinuous_monitoringr"manage_user_agentr6 ui_api_client)selfr5r6s H/opt/cloudlinux/venv/lib64/python3.11/site-packages/xray/manager/base.py__init__zBaseManager.__init__ssr2< ' 22 %6%8%8"!0!2!2(0Z004;GGGreturnc t|j5}t|cdddS#1swxYwYdS#tt f$rt jdYdSwxYw)Nz'Unable to read daemon pid from pidfile.)openDAEMON_PIDFILEintreadOSErrorIOErrorr=warning)rCfs rD_get_daemon_pidzBaseManager._get_daemon_pid~s Gd)** %a16688}} % % % % % % % % % % % % % % % % % %! G G G OE F F F F F F Gs3A!A AAA A A%A:9A:c|jS)z\ Get supported PHP versions :return: a dict with supported versions )VERSIONSrCs rDsupported_versionszBaseManager.supported_versionss }rF php_versionc.||vS)z Check if given PHP version is supported :param php_version: PHP version, e.g. 'alt-phpXY' :return: True if version is supported, False otherwise )rU)rCrVs rDis_version_supportedz BaseManager.is_version_supporteds d557777rF domain_infocZ||jS)zh Get a path to directory for additional ini file for based on panel-set version )rUgetpanel_php_versionrCrYs rD _ini_pathzBaseManager._ini_paths' &&((,,[-JKKKrFc||} |jr|j}n&||r|j}n |jp|}n#t $rYnwxYw|jd||S)z Resolve a path to directory for additional ini file It depends on version set for domain and on selector :param domain_info: a DomainInfo object :return: path to directory for ini files zIni path resolved as %s)r^php_ini_scan_diris_selector_enabledselector_ini_pathphpd_location_ini_path ValueErrorr?info)rCrYini_paths rD get_ini_pathzBaseManager.get_ini_paths>>+.. + J&7))+66 J&8&=I    D  2H===s5A AAc|js=||r(|jd|j|j}n|j}|jd||S)a Get PHP version which serves given domain :param domain_info: a DomainInfo object, including user of domain and PHP version set in control panel environment :return: real php version of domain (selector or panel one) zSelector is enabled for user %szPHP version detected as %s)is_selector_appliedrar?reuserselector_php_versionr\)rCrYcurrent_versions rDget_php_versionzBaseManager.get_php_versionsq. <43K3KK3X3X < K  > @P Q Q Q)>OO);O 5GGGrFctttjsdS|jdS||S)a  Is selector enabled for given domain :param domain_info: a DomainInfo object, including user of domain and PHP version set in control panel :return: True if selector is enabled for domain, False otherwise F)r r PHP_SELECTORrkpanel_specific_selector_enabledr]s rDrazBaseManager.is_selector_enableds>*'*>?? 5  + 3533K@@@rFNc||j|jr||dSt r||jdS||jdS)z Reload FPM service or kill all *php* processes of user :param domain_info: a ready-to-use DomainInfo object N)reset_criu_imgsname panel_fpmrestart_fpm_servicergracefully_restart_litespeedrj kill_user_phpr]s rDphp_procs_reloadzBaseManager.php_procs_reloads [-...   1  $ $[ 1 1 1 1 1 ! # # 1  - -k.> ? ? ? ? ?   {/ 0 0 0 0 0rFct|5t5tj|} t t j|jdd n3#ttf$r|j ddYnwxYwdddn #1swxYwYddddS#1swxYwYdS)z Litespeed's graceful restart. https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:php:detached_mode#for_a_user z.lsphp_restart.txtwz$Unable to restart lsws after changesT)exc_infoN)rrpwdgetpwnamrIospathjoinpw_dircloseFileNotFoundErrorPermissionErrorr?rO)rCusernamepws rDrvz(BaseManager.gracefully_restart_litespeeds X & & [ [  [ [h''B [RW\\")-ABBCHHNNPPPP%7 [ [ [ ##$JUY#ZZZZZ [  [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [sXCB:AA;:B:;-B+(B:*B++B:. C:B> >CB> CCCrct}||D]P}d|jdvr?|tj||jdQ|S)z Kill all PHP processes, which belong to given username :param username: name of user :return: list of pids of successfully killed processes phprspid)list user_procsre send_signalsignalSIGHUPappend)rCr killed_procsprocs rDrwzBaseManager.kill_user_phpsr vv OOH-- 6 6D &)))  ///##DIe$4555rF user_namec#Ktj|j}gd}tj|D],}||jdj|jdjfvr|V-dS)z Generator yields processes, which belong to given user_name. Processes are checked using UID, not user_name :param user_name: user name :return: a generator object )rsruidsrN)r|r}pw_uidpsutil process_iterrereal effective)r uid_by_nameattrsps rDrzBaseManager.user_procssul9--4 '''$U++  Aqvf~2AF6N4LMMM  rFdomainc|sdStdt|d}|r=tj|d|jd|ddSdS)zt Reset criu images if any found for given domain in order to enable/disable X Ray correctly Nz/var/run/mod_lsapi/* _criu_imgsrzcriu images in %s dropped)r glob_escapeshutilrmtreer?re)rCr criu_imgs_dirs rDrrzBaseManager.reset_criu_imgss   FSK4G4GSSSTT  L M-* + + + K  8-:J K K K K K L LrFurlcPt|\}}||S)z4 DomainInfo retrieving based on url )r!get_domain_inforCr domain_name_s rD_domain_info_by_urlzBaseManager._domain_info_by_urls'#3 Q##K000rFrc:ttd)z Retrieve information about given domain from control panel environment Required to be implemented by child classes :param domain_name: name of domain :return: a DomainInfo object z0Manager should implement retrieving domain info!NotImplementedErrorr)rCrs rDrzBaseManager.get_domain_infos"!$V"W"WXXXrFc:ttd)z Check if selector is enabled specifically for panel Required to be implemented by child classes :param domain_info: a DomainInfo object :return: True if yes, False otherwise zCManager should implement specific panel check for selector enabled!rr]s rDrpz+BaseManager.panel_specific_selector_enableds"!$i"j"jkkkrFdom_infoc:ttd)z Get FPM service name for particular panel :param dom_info: DomainInfo object :return: name of FPM service z5Manager should implement FPM service name retrieving!r)rCrs rDfpm_service_namezBaseManager.fpm_service_name(s "!$["\"\]]]rFcF||}t|trt|s.|jdt||ddS tj d|dgddd|j d |t| dS#tttjf$r7}|jd t||d Yd}~dSd}~wwxYw) zg Restart FPM service for particular version :param dom_info: DomainInfo object z6Refusing to reload FPM service: name failed validation) fpm_servicereextraNz /sbin/servicereloadT)capture_outputtextcheckzService %s reloadedzFailed to reload FPM service)errre)r isinstancestr_FPM_SERVICE_NAME_REmatchr?errorrepr subprocessrunrersave_latest_reloadrMrdSubprocessError)rCrfpm_serves rDruzBaseManager.restart_fpm_service0sK ((22(C(( 0D0J0J80T0T  K  H&*8nnhGG     F ? NOXx@QU\`hl m m m m K  2H = = =  ) ) < < > > > > >Z%?@ g g g K   > >!!$G"H"H3|ObKcKc"cdd d  ) + +  . . 0 0 0#L$899 ]W33GD[3\\\ ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] 22<3CDDK  ) )+*: ; ; ; ;     K  J K K KKKK   q4e<<    !NOOO"   $ !!###'99;; Q   KK ( ( ( ( NN< 0 0 0  " ;+ , , 4 4 6 6 6  ! !+ . . .    - - e , , , ,}}FLDT@U@UVVV) 4 4I'' 22  L=s9M^C_?`?` a a a IIi 12 3 3 3 3}}$8}999rFt_taskrr2c||||jr|dSdS)z Common complete actions: - delete cron job, - erase request id file - send 'complete' status to mongo :param t_task: a tracing task object :param client: an APIClient object N)r$erase_request_id_storager:rshare)rLrs rDr&zBaseManager._completes^ '')))    LLNNNNN  rFc:||j|}|}|jdkr1t t dt |jz||d|j S)z Delete given task ID :param tracing_task_id: an ID of task to delete :return: JSON encoded result of delete action rrz#Cannot delete task with status '%s'deleter) r;r<rrrrrrQrrr;s rDrQzBaseManager.deletes &&o&^^((  ) + +!!$I"J"JSQ]QdMeMe"eff f }}Hl>R}SSSrFemailc||}|j|j|||d|S)z Enable continuous monitoring for given URL :param url: URL to monitor :param email: email to send reports to :return: JSON encoded result of enable action enablerr)rr@rTrsr)rCrrRd_infos rDenable_continuouszBaseManager.enable_continuoussM))#.. "))&+sEBBB''xS'AAArFct|\}}|j||d|S)z Disable continuous monitoring for given URL :param url: URL to monitor :return: JSON encoded result of disable action rrU)r!r@rrrs rDdisable_continuouszBaseManager.disable_continuoussC #3 Q "**;777''yc'BBBrFct|\}}|j||d|S)z Start continuous monitoring for given URL :param url: URL to monitor :return: JSON encoded result of start action rrU)r!r@rrrs rDstart_continuouszBaseManager.start_continuoussC #3 Q "((555''wC'@@@rFct|\}}|j||d|S)z Stop continuous monitoring for given URL :param url: URL to monitor :return: JSON encoded result of stop action rrU)r!r@rrrs rDstop_continuouszBaseManager.stop_continuoussC #3 Q "'' 444''v3'???rFcb|j}|d|S)zq Get list of continuous monitoring tasks :return: JSON encoded result of get list action zget continuous listrdata)r@get_tracing_listr)rC tracing_lists rDcontinuous_tracing_listz#BaseManager.continuous_tracing_lists/ 1BBDD }}$9 }MMMrFc^|d|jS)z# Get list of tasks z tasks-listr_)rrBrHrTs rD tasks_listzBaseManager.tasks_lists)}}Lt7I7W7W7Y7Y}ZZZrFr time_fromtime_toc||j|}|}|d|j|||S)z@ Get list of requests for given tracing task id rz requests-list)rfrgr_)r;r<rrrBget_request_list)rCrrfrgrrs rD requests_listzBaseManager.requests_listsg &&g&VV OO  }}"#44W [b4cc   rFc||j|}|}|d|j|S)zE Get hourly requests stats for given tracing task id rzrequests-stats-by-hourr_)r;r<rrrBget_requests_stats_by_hour)rCrrrs rDrequests_stats_by_hourz"BaseManager.requests_stats_by_hours_ &&g&VV OO  }}+$2D2_2_`g2h2h   rF request_idc||j|}|}|d|j||S)zO Get collected statistics for request ID of given tracing task rz request-datar_)r;r<rrrBget_request_data)rCrrnrrs rD request_datazBaseManager.request_datasX &&g&VV OO  }}N9K9\9\]dfp9q9q}rrrrFc`|j|dS)a Enable X-Ray User Agent: start or restart service if it is accidentally already running For systemd systems -- start socket unit only For SysV -- start the entire service :return: JSON encoded result of enable action zenable-user-agentrG)rArTrrTs rDenable_user_agentzBaseManager.enable_user_agents. %%'''}}$7}888rFc`|j|dS)a7 Disable X-Ray User Agent: stop the entire service or do nothing if it is accidentally not running For systemd systems -- also check if socket unit is running and stop it too :return: JSON encoded result of disable action zdisable-user-agentrG)rArrrTs rDdisable_user_agentzBaseManager.disable_user_agents. &&(((}}$8}999rFc||j}|d|tS)zn Get status of X-Ray User Agent service :return: JSON encoded result of status action zuser-agent-status)rruser_nginx_cache)rArrr&)rC agent_statuss rDuser_agent_statuszBaseManager.user_agent_statuss8 -4466 }}$7 _o_q_q}rrrrFc*t}|ddur|nS|ddur|n4|ddur*|}||S|S)] Advanced metrics tool :return: JSON encoded result of status action rTTrr)r)r#rTrrr)rCargsamrs rDadvanced_metricszBaseManager.advanced_metrics#s    >T ! ! IIKKKK )_ $ $ JJLLLL (^t # #YY[[F===// /}}rFcbtt|Sr{)r1r-rrCr|s rDenable_serverwide_modez"BaseManager.enable_serverwide_mode3s* &'''}}rFcbtt|Sr)r.r0rrs rDdisable_serverwide_modez#BaseManager.disable_serverwide_mode=s* %'''}}rF)F)NN)D__name__ __module__ __qualname____doc__rJrSrboolrErrKrQrrUrXrr^rgrmrarxrvrrw staticmethodrrProcessrrrrrrprrur rrrrr%rrrrrr8r:rErKr r&rQrWrYr[r]rcrerjrmrqrsruryr~rrrrFrDr4r4Ys /N0/////////////H" H H# HT H H H HG#GGGGD888888LZLCLLLL s* : #     Az Ad A A A A 1J 14 1 1 1 1 [ [ [ c d     c hv~&>   \  Lc Ld L L L L1s1z1111Y3Y:YYYYl:l$llll^^^^^^?J?4????,##sCx###\#UCUDUUUU, 9c 9 9 9\ 9's'''' !CSCSCSCS CS  CS  CSCSCS CSCSCSCSJiiiiiiCE    C     $GRCGRCGRGRGRGRRAAA2 V V V V V VD V V V V V V d t   \  :C : : : : $    \  Tc Tc T T T T BS B B B B B BCcCcCCCCACACAAAA@3@3@@@@NNNNN[C[[[[   S  S  #  Y\       c  c     sCsSsSssss 93 9 9 9 9 :C : : : :s3ssss csrFr4)Urrr=r~r|rerrrtypingrrrrrrrr rclcommon.constr clcommon.cpapir r !xray.internal.clwpos_safe_importsr rclcommon.utilsrclcommon.clpwdrsecureiorxrayrradviser.clwpos_getr apiclientrcontinuous.managerrinternal.exceptionsrrrrrinternal.fpm_utilsrinternal.local_countersrinternal.nginx_utilsrinternal.typesrr r!internal.user_managerr"internal.advanced_metricsr#internal.user_plugin_utilsr$r%r&internal.utilsr'r(r)r*r+r,reconfiguration.global_inir-r.r/r0r1 TYPE_CHECKINGapiclient.api_clientr2compilerr4rrFrDrs`    ((((((((,,,,,,,,,,,,,,,,,, """"""QQQQQQQQWWWWWWWW//////******""""""------""""""2222225444448888881111118888888888333333777777cccccccccc 1000000""rz"JKKl l l l l l l l l l rF