eJ ddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m cm Z ddlmZddlmZddlmZddlmZddlmZddlmZmZmZmZddlmZmZm Z m!Z!m"Z"m#Z#m$Z$ddl%Z%dd l&m'Z'dd l(m)Z)m*Z*dd l+m,Z,dd l-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5dd l6m7Z7e8ej9:ddZ; dZ<edZ=dZ>dZ?dZ@dZAdZBejCdZDeEdeFe jGDZHdZIejJeKZLGddeMZNGddeMZOGddZPd ZQd!ZRd"e!eSfd#ZTd"eUfd$ZVeWd%d&ZXd'ZYd(ZZd)Z[ dVd+egefd,e8fd-Z\d.Z]d"e eSfd/Z^d"e!e$eSfd0Z_d1Z`ejad23d"ebfd4Zcd5ebd"e eSfd6ZddWd5ebd"e$eSfd8Zed"ebfd9Zfd"e!eSfd:ZgdXd5ebd"e$eSfd<Zhd"e$eSfd=Zied>Zjd?eSd"ebfd@ZkdYdAZle7jme;dYdBZndYdCZodDZpdEZqd"ebfdFZrd"ebfdGZsdZdHZtd"ebfdIZudWdJZvdKZwdLeUd"e eUfdMZxdNZydOZze.d23dPZ{e4ee8ej9:dQdRSTdUZ|dS)[N)suppress) ContextVar) timedelta)Version)Path)CalledProcessError check_call check_outputDEVNULL)AnyCallableListOptionalSetTupleIterable)IntegrationConfig)is_generic_panel_installedis_plesk_installed)g)async_lru_cacheatomic_rewrite check_runget_system_user_names OsReleaseInfo CheckRunError TimedCacheBACKUP_EXTENSION)webserver_gracefull_restart!IM360_GRACEFUL_RESTART_MIN_PERIODi,z*/usr/local/cpanel/scripts/restartsrv_httpdz/tmp/lshttpd/lshttpd.pid)/usr/local/lsws/bin/lswsctrl condrestart)r!restartz%/usr/local/lsws/conf/httpd_config.xmlz/usr/sbin/apache2z/usr/sbin/httpdz Server version:.*(\d+\.\d+\.\d+)c#>K|]}|VdSN)encode).0xs V/opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/subsys/web_server.py r*9s*@@1AHHJJ@@@@@@apacheceZdZdZdS)NotRunningErrorz[ Error for cases when the web server is expected to be running but it is not. N__name__ __module__ __qualname____doc__r+r)r.r.?sr+r.ceZdZdZdS)ConfigInvalidErrorzO Error used to indicate that the web server config is having error(s). Nr/r4r+r)r6r6Gsr+r6ceZdZdZdZdZdZdZdZdZ dZ d Z d e fd Z d e fd Zd eeeeffdZdZd efdZdS)LiteSpeedConfiguseIpInProxyHeadersecurity accessControlallowdenyrc8tj||_dSr%)ET fromstringconfig)selfcontents r)__init__zLiteSpeedConfig.__init__WsmG,, r+returnc|j|j}||js|jSt |jSr%)rCfindCLIENT_IP_IN_HEADER_TAGtextCLIENT_IP_IN_HEADER_DISABLEDintrDelements r)client_ip_in_headerz#LiteSpeedConfig.client_ip_in_headerZs>+""4#?@@ ?',?4 47<   r+valuec|j|j}|3tj|j}|j|t ||_dSr%)rCrIrJrAElementappendstrrK)rDrQrOs r)set_client_ip_in_headerz'LiteSpeedConfig.set_client_ip_in_header`sX+""4#?@@ ?j!=>>G K  w ' ' '5zz r+c|jdd|j|j|jg}|*|jr#d|jDStS)N/.ch|]R}|dD]:}||dr |ddn||df;SS),TN)splitendswith)r'sitems r) z>LiteSpeedConfig.access_control_allowed_list..ss}GGCLL "mmC00:crcdDMM#rr\r4)r'ras r) zCLiteSpeedConfig.set_access_control_allowed_list..|s1KKK4$q'6a3tAwKKKr+r[rXrY) rcrCrIrdrerfrArSrTrK)rDalloweditemsrQrOaccess_controlr:s r)set_access_control_allowed_listz/LiteSpeedConfig.set_access_control_allowed_list{sLKK7KKK+"" HH%+3       ?j!@AAG![--)/N%!#D,C!D!D;++D,=>>#!z$*;<.is_generic_panel_on_apaches. % ' ' P$(}EEO Our+exeNrz#Can't determine apache bin path: %s)rrrrAPACHE2_BIN_PATHHTTPD_BIN_PATHrgr_apache_running_process_infoospathsamefilerrr)rrr sys_usersrhttpd_process_exeexcs r)rrs#" -"66## : : < <#% " )++,,}|jVHdS)rN)z/httpdz/apache2usernamerr_)r'prs r)r*z/_apache_running_process_info..sp  u 1F5M223IJJ2F:.);;F<;;;  r+)namerruidsgidsattrsN)ranger IndexErrornextr process_iter)r_s` r)rrs 1XX j ! !      #0III                        s1A''A+ .A+ ctdh}|stdtj||dd|dddS)z&Make web server user/group own *path*.rootrz5Can't find running apache process without root owner.rrrN)rr.rchown)rrs r)rrs] "& : : :D   C   HT4<?DLO44444r+c`tdtjgdDdS)z;Return path to a running nginx binary or None if not found.c3K|]i}|jdZ|jddr:|jd-d|jdvr|jddvZ|jdVjdS)rNnginxrr)rzwww-datar)r'rs r)r*z%find_running_nginx..$s v*F6N++G44+F5M-qve},,F:&*??? F5M@??? r+)rrrrN)rrrr4r+r)find_running_nginxr!sJ  (/J/J/JKKK     r+ webserver_running_cb granularitycK|dksJt|D]/}|}|r|cStj||z d{V0|S)Nr)rasynciosleep)r timeout_secrrresults r)check_with_timeoutr3sz ???? ;  %%''  MMMmK+56666666666 r+c@tjdS)z8 though, available != running :return bool: z/etc/cpanel/ea4/is_ea4)rrisfiler4r+r)is_EA4_availablerCs 7>>2 3 33r+ctjt}|r|gStjtjzr#dddt j|gS|ddgS)a{ :return list: command which can be passed to check_call(..., shell=False) 'apache2 -k graceful' will not work for Ubuntu and will produce 'Invalid Mutex directory in argument file:${APACHE_LOCK_DIR}' error. https://serverfault.com/questions/558283/apache2-config-variable-is-not-defined That is why this specialization for Ubuntu graceful restart. systemctlreloadz--job-mode=replace-irreversiblyz-kgraceful) shutilwhichCPANEL_RESTART_APACHE_SCRIPTrrrrrbasename) apachectlrestartsrv_httpds r)_apache_graceful_restart_cmdrKsv|$@AA" !!!55 -   - G  Y ' '   4,,r+ctjr tjdd}|stddS|}t j|dr|Std|n*#t$rtdYnwxYwdS)Nrgraceful_restart_scriptz'graceful_restart_script option is emptyrz,Web server restart script does not exist: %sz;Integration config is missing graceful_restart_script field) rrto_dictrrr^rrKeyError)restart_scriptcmds r)+_graceful_restart_cmd_from_integration_confres!! .688F)N" =t &&((Cw~~c!f%%  NN>        NNM      " 4sB))$CCr>)maxsizecBtjd}|sdS t|dgt}n#t t f$rYdSwxYwtjd|}|duo*t| dtkS)N systemd-runFz --version)stderrzsystemd\s+(\d+)r>) rrr r decoderrresearchrMgroup_SYSTEMD_RUN_WAIT_MIN_VERSION) systemd_runoutmatchs r)_systemd_run_supports_waitrs,}--K uK5gFFFMMOO ' (uu I(# . .E    EKKNN<<s*AAAwaitcg}tjdx}rC||dddgz }|r#tr|d|d|S)Nrz-pzSendSIGKILL=noz--slice=graceful_restartz--waitz--)rrrrT)rprefixrs r)_systemd_run_prefixrs|Fl=111{     &     $.00 $ MM( # # # d Mr+Fct|}t}||t|zStr|ttzSt x}r|t |zStd)z Gracefully restart a web server.NCould not detect a web server)rrlistrLITESPEED_RESTART_CMDrr RuntimeError)rrrrs r)_graceful_restart_cmdrs  & &F 5 7 7C S !!423333"$$$y@4Y???? 6 7 77r+cJtjtSr%)rrrLITESPEED_CONF_PATHr4r+r)_litespeed_installedrs 7>>- . ..r+cd}tr7 tjdd}n#t$rYdSwxYw|tkrdSd}t jt jzr4ts|r$tj tStj tS)usystemd unit for this host's Apache, or None when the host is not Apache-based. Derived from OS/panel, not a running process — recovery runs precisely when the server is not alive.FrrNT)rrrrrrrrrrrrrr)on_generic_apachers r)_apache_systemd_unitrs!##! +/ mLLKK   44  & 4 -"6622 12w 0111 7  N + ++s ( 66Tct|}tr|ttzSt jt x}r||dgzSt}|td|dd|gzS)a-Full (non-graceful) restart to bring a web server back up after a reload left it down. Detects the server by install/config presence (not a running process, which may be down) and raises when no safe command is known (e.g. generic nginx, which has only a graceful integration script). z --restartNz0No safe hard-restart command for this web serverrr#) rrrLITESPEED_HARD_RESTART_CMDrrrrr)rrrunits r)_hard_restart_cmdrs ! & &F978888!<(DEEE8);777  ! !D |MNNN [)T2 22r+crtr= tjdd}|r|Sn#t$rYnwxYwt x}r(t jt jzrddgS|dgStrddgStx}r|dgStd)Nrconfig_test_scriptr configtest-t litespeedr) rrrr^rrrrrrrr)r apache_bin nginx_bins r)_configtest_cmdrs!## #' 6JKKC #yy{{" #    D $%%%z!  " "]%9 9 /. .D!!   !T""(** *!4  6 7 77s*< A A graceful_restart_caller new_configc Ktjtzfd tj}t ||sdSfd t dd{V t n=#t$r0}t d| Yd}~dSd}~wwxYwtj fd }tjt| t }t#jd }t&|j} | d{Vt&|n#t&|wxYwtd dS#t0$r/}t d | Yd}~nd}~wwxYwdS)a Update Web-server config with fallback in case of an error happens. It tries to do all the best but because of graceful_restart() the faulty config might still be applied but in practice it is barely probable (because of premature config check). 1. The new config is checked before to be applied. 2. The new config (if checked valid) is atomically applied. 3. The graceful Web-server restart is scheduled. It may hold the actual restart for some time, but it is a required workaround of a litespeed issue. 4. If the Web-server failed to restart the config is reverted. Return value: True if no errors (at least up to the server restart), False if There was an error and config was reverted. Note: It is possible that the config may be reverted even when return value is True. It is because the graceful_restart may delay the actual restart and config may be reverted on that (delayed) stage. ctt5tjddddS#1swxYwYdSr%)rFileNotFoundErrorrunlink)config_backup_pathsr) remove_backupz)safe_update_config..remove_backups ' ( ( * * I( ) ) ) * * * * * * * * * * * * * * * * * *s 8<<)backupTc tjdS#t$r&tdYdSwxYw)Nw)rrenameropenclose)r config_pathsr)revertz"safe_update_config..revertsa + I(+ 6 6 6 6 6  + + + c " " ( ( * * * * * * +s,A  A raise_exceptionNz*Failed to get graceful restart command: %sFcd}d}|s|td|t d}||t}||dSdS)Nc|sD|2td|dSdSdS)Nz'The reverted config seems to be invalidexc_info cancelled exceptionrcriticalfuts r)log_config_errorzFsafe_update_config..restart_callback..log_config_error2sb}}3==??+FOOA!$$+F+Fr+c|sD|2td|dSdSdS)Nzuncaught exceptionr$r&r*s r)log_uncaught_exceptionzLsafe_update_config..restart_callback..log_uncaught_exception9sa}}3==??+FOO,s}}$+F+Fr+z7Web server failed to start... Revert changes back. (%s)Tr )r'r(rerror create_taskr add_done_callback_graceful_restart)taskr,r.loopr restart_cmdrs r)restart_callbackz,safe_update_config..restart_callback1s       >>## (8(8(D MNN$$'' 4(H(H(HII&&'7888''(9+(F(FGG&&'=>>>>> r+) done_callbackr>z)Successfully scheduled web server restartz Web server config is invalid: %s)rfspathrrrrr rrrr/rget_running_looprcoalesce_callsGRACEFUL_RESTART_MIN_PERIODr2inspectstack_graceful_restart_callerrgfunctionresetrr6) rr make_backuper6graceful_restart caller_frame context_tokenrr4rr5rs ` @@@@@r)safe_update_configrFsh*;//2BB*****'..--K +z+ F F Ft++++++6..........  /11KK    LLEq I I I FHHH55555  '))        8 6E '7G   }q) 044\5JKK  :"";// / / / / / / / $ * *= 9 9 9 9 $ * *= 9 9 9 9 ?@@@ti  7;;;j 5s<$F+;B C%B??CE00F + G$5%GG$cKt t|p td{VtddS#t $r&}td|Yd}~dSd}~wwxYw)] Gracefully restart a web server. If web server cannot be detected, do nothing. N!Successfully restarted web server"Could not restart a Web server: %s)_log_graceful_restart_startrrrrrr)r5errs r)r2r2\s  !!!9 >'<'>'>?????????  788888 BBB;SAAAAAAAAABs#A BA<<BcKt|}|t_ |d{V tjdS#tjdwxYw)Nweb_server_restart_task)r2rrNpop)r5r3s r)_graceful_restart_coalescedrPks] [ ) )D $A)zzzzzz '(((('((((s <AcKtjd}t|j} t |d{V}t|n#t|wxYw|S)rHr>N)r<r=r>rgr?rPr@)r5rDrErs r)rCrCus=??1%L,001FGGM62;???????? &&}5555 &&}5555 Ms A,,Bcptd}td|dS)Nunknownz/Performing web server graceful restart, from %s)r>rrr)callers r)rKrKs0 % ) )) 4 4F KKA6JJJJJr+ctjd}t|j} t t|n#t|wxYw ttttt ddS#t$r&}t d|Yd}~dSd}~wwxYw)zk Gracefully restart a web server synchronously. If web server cannot be detected, do nothing. r>)rrrIrJN)r<r=r>rgr?rKr@r rr rrrr)rDrErLs r)graceful_restart_syncrVs =??1%L,001FGGM6#%%% &&}5555 &&}55559(**77KKKK  788888 BBB;SAAAAAAAAABs#A##A?(C C7C22C7cKtjd}t|j} t t|n#t|wxYw td}n3#t$r&}t d|Yd}~dSd}~wwxYwt|d{Vrt ddSt dtd{Vt|d{Vrt d dStd{VS) ayGraceful web-server restart that confirms the reload actually completed and recovers the server if it did not. Unlike graceful_restart() it bypasses the coalesce throttle (the post-update reload must never be dropped); unlike graceful_restart_sync() it observes the reload outcome instead of returning as soon as systemd-run queues the transient unit. r>TrrJNFrIzLWeb server reload after update did not complete cleanly; attempting recoveryz-Web server recovered on graceful reload retry)r<r=r>rgr?rKr@rrrr_reload_confirmedrr/_log_failed_configtest _hard_restart)rDrErrLs r)graceful_restart_confirmedr\s=??1%L,001FGGM6#%%% &&}5555 &&}5555#... ;SAAAuuuuus # ####### 7888t LL  ! " """""""" s # ####### CDDDt  s#A%%BB C CCcK t|d{Vn:#ttf$r&}td|Yd}~dSd}~wwxYwt rdS t dd{Vn#t$rYdSwxYwdS)aRun *cmd* and report whether the reload truly succeeded. With systemd-run --wait the exit code already reflects completion; on older systemd (no --wait) the reload is fire-and-forget, so fall back to a config test to detect a broken reload. Nz'Web server reload returned an error: %sFTr )rrrrrrr r6rrLs r)rYrYsnn < (@#FFFuuuuu"##t........... uu 4s&AA  A%A<< B  B cK tdd{VdS#t$r&}td|Yd}~dSd}~wwxYw)NTr z.Web server config test failed after update: %s)r r6rr/)rLs r)rZrZsL............ LLL EsKKKKKKKKKLs A AA cjK td}n3#t$r&}td|Yd}~dSd}~wwxYw t |d{Vn:#t tf$r&}td|Yd}~dSd}~wwxYwtddS)NTrXzCannot recover web server: %sFz"Web server hard restart failed: %sz-Web server hard-restarted after failed reload)rrrr/rrrr^s r)r[r[sT***  4c:::uuuuunn < ( 93???uuuuu KK?@@@ 4s, AAA AB0BBcKtd tttd{VdS#t $r8}td||rt d|Yd}~dSd}~wwxYw)z\ Check web server's config file. If web server cannot be detected, do nothing. z!Performing web server config test) raise_excNzCould not run configtest: %szFailed to check config)rrrrr6rr)r!rLs r)r r s  KK3444H))5GHHHHHHHHHHHH HHH5s;;;  H$%=>>C G H H H H H HHs(A B -BB ct|}|"t|dSt d|)Nr>z)Failed to parse apache version string: {})apache_version_regexprrrrr)outputrs r)_parse_apache_version_outputrfsV ! ( ( 0 0E u{{1~~&&& 7 > >v F F   r+rec>d|DS)a: Parse response of httpd -M :param output: stdout of httpd -M (with spaces before module name) Output example: Loaded Modules: core_module (static) so_module (static) http_module (static) mpm_prefork_module (shared) :return: list with installed modules cg|]H}|t|dIS)r) startswith BYTE_SPACESstripr^)r'lines r)rkz-_parse_apache_module_list..sS     ??; ' '  Q   r+) splitlines)res r)_parse_apache_module_listrns/  %%''   r+cg}|dD]L}|d}|dkr/|||dM|S)N rXr)rr^rIrTrk)dumpincludesrlindexs r)_parse_includesrt!spH ##D))22 # 199 OODL..00 1 1 1 Or+ctK ttgdd{VS#t$rgcYSwxYw)N)rr z-D DUMP_INCLUDES)rtrrr4r+r) dump_includesrw*sgFFFGG G G G G G G     s #( 77cKt}|tdt|dgd{V}t|}t d||S)Nrz-vzApache %s version detected)rr.rrfrrr)r rversions r)apache_versionrz3sy!!J5666:t,-- - - - - - -C*3::<<88G KK,g666 Nr+'IMUNIFY360_APACHE_MODULES_CACHE_TIMEOUTiX)seconds) expirationcNKtdd{V}t|S)Nz-M)rrn)rs r)apache_modulesr>s5&d++ + + + + + +F $V , ,,r+)rr)F)Tr%)rGN)}r functoolsr<rsloggingrrrrstringxml.etree.ElementTreeetreerurA contextlibr contextvarsrdatetimerpackaging.versionrpathlibr subprocessrr r r typingr r rrrrrr$defence360agent.api.integration_confr3defence360agent.application.determine_hosting_panelrr&defence360agent.internals.global_scoperdefence360agent.utilsrrrrrrrrdefence360agent.utils.commonrrMenvironrr;rrrrrrrcompilerdtupler whitespacerjr getLoggerr0rrr.r6r8rrrUrrr frozensetrrrrrrrrr lru_cacher~rrrrrrrr>rFr2r:rPrCrKrVr\rYrZr[r rfrnrtrwrzrr4r+r)rs  """""""""""""""%%%%%%LLLLLLLLLLLLFFFFFFFFFFFFFFFFFF BBBBBB544444                    EDDDDD!cJNN6?? L$9::GI=&"" #FGGe@@V->(?(?@@@@@   8 $ $l TTTTTTTTn999   / ////u2.7Y[['''''T(555(  "2s7+      444-tCy----4Xhsm5L>!$Q D     dtCy"888#8888"/d////,hsm,,,,(33D3HSM3333(8#8888(&:&?@@^c^d^^^^B 9 9 9 9,+,GHH)))IH)     KKK 999*$!$$!$!$!$!ND.LLLL T     H H H H   eU & y JNNDc J J  -----r+