Ӌ9~o ddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlmZddlmZmZddlmZmZddlmZmZmZddlmZddl m!Z!ddl"m#Z#m$Z$m%Z%m&Z&dd lm'Z'dd lm(Z(dd l)m*Z*dd l+m,Z,dd l-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5ddl6Z6ddl7Z7ddl8Z8ddl9m:Z:m;Z;ddlej?e@ZAdZBdZCdaDdZEe*dZFdZGe*dZHe*dZIe*dZJeKejLMddZNGdde!ZOejPd d!ZQedd"ZReAddfd#ZSGd$d%ZTdejUejUd&dfd'e4eKeVeVffd(ZWddd)d*ZXGd+d,ejYZZeZfd'eVfd-Z[eZfdd.Z\dd'e]fd0Z^d1Z_Gd2d3Z`d4ZaGd5d6ebZcd7Zdd8Ze dd:Zfd/ddd/ddd;dZiejPdd?Zjdd'e]fd@ZkGdAdBZlejmdCfdDe]dEeKd'e]fdFZn ddDe]dEeKd'e4e]eKffdGZodHZpdIZqddKZr ddMZsdNZtejPdOeKfdPZuejve6jwdQd/RZxdSZydDejhdTeVd'dfdUZzdVZ{dDejhdWeVd'egfdXZ|dYZ}GdZd[Z~eCfd\Zd]Zed^eKfd_Zddae]d'e*fdbZdce]dae]d'egfddZdeZddgedheKd'efdiZdjZGdkdleZejPd9 dmZdnZdd'egfdoZGdpdqZeZdrdsdtZduZdvZejPd d'egfdwZdxZdyZddze]d'e]fd{Zdd|Zdd}d~Zdd}dZdd}dZGddejZdZ ddZdZebdfdZefdZdZdZd&ddZeddZdZdZdce*d'eVfdZdeVd'e*fdZdZdZddZde0de/ffdZdZdrZdrZdZdQddze3e]fdZddrddZddZGddZdWe]d'ee]e]fdzfdZdWe]d'ee]e]fdzfdZejPd d'eee]e0e]gee]e]fdzfffdZGddebZdZehdZdee]d'ee]e]dzffdZde]dee]de0e]gee]e]fdzfd'ee]e]dzffdZeAjfd'e]fdZdeKfdZde1e.e.fdeKfdZejPd dZde*d'eKfdZde*fdZdZdS)N)Future) OrderedDictdeque) GeneratorIterable) ExitStackcontextmanagersuppress) timedelta)Enum)LOCK_EXLOCK_NBLOCK_UNflockwraps)islice)Path)NamedTemporaryFile)Any AwaitableCallableDict FrozenSetListTupleTypeVar)is_safe_subdir_namermtree)atomic_rewrite_fdF)bounduser_id)z User-AgentzAccept-LanguagezAccept-Encoding ConnectionDNTz.i360bakz/run/systemd/systemz/etc/cloudlinux-edition-soloz/var/run/imunify-antivirus.pidz/var/run/imunify360-agent.pidz/var/run/imunify360.pid%IMUNIFY360_HTTP_REQUEST_RETRY_TIMEOUT<ceZdZdZdZdZdZdS)ScopezAV onlyz AV and IM360z IM360 onlyzIM360 resident onlyN)__name__ __module__ __qualname__AVAV_IM360IM360IM360_RESIDENTS/opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/utils/__init__.pyr+r+Gs" BH E*NNNr4r+)maxsizecto2tot S)zReturn True if /run/systemd/system folder exists: [sd_booted] (https://www.freedesktop.org/software/systemd/man/sd_booted.html) )_SYSTEMD_BOOTED_DIRexistsis_dir is_symlinkr3r4r5is_systemd_bootr<NsC ""$$ 1  & & ( ( 1#..00 0r4c#K|s|sJtj}|p|jd|dVtj}|p|jd|||z dS)z :param str: action name to log :param logging.Logger: logger you want action name and timing to be logged with :param func: log function to use (`log` has preference over `logger_`) z %s startedNz%s took %.2f second(s))time monotonicdebug)actionlogger_logstartstops r5timeitrF[sz c> N  ESGM<000 EEE >  DSGM3VTE\JJJJJr4cfd}|S)NcNtjfd}|S)NcKtpj5|i|d{VcdddS#1swxYwYdSN)rBrCrFr,argskwargsrAfunrCrBs r5wrapperz+timefun..decorator..wrapperms.#,SIII 2 2 S$1&11111111 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2s 8<< functoolsrrOrPrArCrBs` r5 decoratorztimefun..decoratorlsH    2 2 2 2 2 2 2   2r4r3rBrArCrTs``` r5timefunrVks0 r4c0eZdZdZeeddfdZdS)synczF the same timefun decorator variation but without async/await Ncfd}|S)z :param logging.Logger: logger you want action name and timing to be logged with :param str: action name to log cNtjfd}|S)Ncztpj5|i|cdddS#1swxYwYdSrJrKrLs r5rPz0sync.timefun..decorator..wrappersF2clGMMM003///000000000000000000s 044rQrSs` r5rTzsync.timefun..decoratorsH _S ! ! 0 0 0 0 0 0 0" ! 0Nr4r3rUs``` r5rVz sync.timefun|s0       r4)r,r-r.__doc__ staticmethodloggerrVr3r4r5rXrXwsEt\r4rXFreturnc $K||tdtj}|r't|tsJ|g}t j}n*t|ttfsJt j }ttdtd|||||dd|d{V}| |d{V\} } |d{V} td |||| | | f| | | fS) zYAsynchronous command executor. Returns a tuple (exit_code, stdout_data, stderr_data).Nz/stdin and input arguments may not both be used.r)seconds) max_trieson_errorTstdinstdoutstderrstart_new_sessionz run(%s, stdin=%s, shell=%s) = %s) ValueError _subprocessPIPE isinstancestrasynciocreate_subprocess_shelllisttuplecreate_subprocess_execretry_onBlockingIOError await_for communicatewaitr^r@) commandrfrgrhshellinputrNcreate_subprocessprocouterr exit_codes r5runrs   NOO O  ;'3''''')#;'D%=11111#:1y/C/C/C             D%%e,,,,,,,,HCiikk!!!!!!I LL*  C  c3 r4)looptimeoutc|rtdD]b} tj}|sn7n#t$rYnwxYwtjtjc|tjt|tj r|ntj ||S)zjRun coroutine from a blocking code (outside the event loop). Coroutine will be wrapped in Task. Nrar) rangeroget_event_loop is_closed RuntimeErrorset_event_loopnew_event_looprun_until_completewait_forrmrTask)cororr_s r5run_corors  |q = =A -//~~''E       "7#9#;#; < < < <  " "tW^44 LDD',t:L:L     s? A  A ceZdZdZdS) CheckRunErrorcd}||j|j|jpd|jpdS)Nz[Command {cmd!r} returned non-zero code {returncode}, Stdout: {output}, Stderr: {error} )cmd returncodeoutputerror)formatrrrdecoderh)self_MESSAGEs r5__str__zCheckRunError.__str__s_ $  ;%%''/4+$$&&.$    r4N)r,r-r.rr3r4r5rrs#      r4rc`Kt|fi|d{V\}}}|dkr||||||S)zJ Asynchronous command executor. Returns output as bytestring. Nr)r)ry raise_excrNrr~rs r5 check_runrsZ "%W!7!7!7!7777777JSQi GS#666 Jr4cKt|tjtjtjd{V\}}}|dkr |||dS)z Asynchronous command executor. Raises raise_exc if exit code is nonzero. Stdin, stdout and stderr of command are connected to /dev/null. )rfrgrhNr)rrkDEVNULL)ryrcoders r5check_exit_codersy !"" JD!Q qyyig&&&yr4TcK t|fi|d{V\}}}n,#t$rtd|YdSwxYw|r%|dkrtd|||dS |}n,#t $rtd|YdSwxYw|S)zGSafe run command. Returns stdout as string or empty string on errorNzCommand %s failed with OSErrorrz'Command %s failed with exit code %s: %sz#Command %s returned non-utf8 output)rOSErrorr^warningstriprUnicodeDecodeError)rycheck_returncoderNrcr~rresults r5safe_runrs 33F33333333 C 7AAArrB!GG 5wC   r##%% .wrapper s  %+--Kr4r3)rrPrs` @r5plainold_lazy_initrs.K Nr4ceZdZdZdZdZdS) PeriodicCheckz Invoke a callback with a certain period and return cached result in between. Raising an exception from the callback does not affect the next check schedule. c||_||_tj|z |_d|_t tj|_ dSr) _cb_coro_check_every_n_secondsr>r?_last_check_timestamp_last_check_resultrroLock_lock)rcb_corocheck_every_n_secondss r5__init__zPeriodicCheck.__init__2sD &;#%)^%5%58M%M""&' 55 r4cK|4d{Vtj|jz }||jkrVt d|j|jtj|_|j|i|d{V|_|jcdddd{VS#1d{VswxYwYdS)Nz3Timeout %d seconds has expired, doing the check: %s) rr>r?rrr^r@rr)rrMrNdeltas r5__call__zPeriodicCheck.__call__;s\::<< + + + + + + + +N$$t'AAE333 I/M .2^-=-=*0= t0Nv0N0N*N*N*N*N*N*N'* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sBB33 B=B=N)r,r-r.r\rrr3r4r5rr)s<666 + + + + +r4rcfd}|S)Nc$t|Sr)r)rnsecs r5decoratezcache_result..decorateJsT4(((r4r3)rrs` r5 cache_resultrIs#))))) Or4ceZdZdZdS)RecurringCheckStopz: raised by coroutine to stop recurring_check loop Nr,r-r.r\r3r4r5rrPs Dr4rcK t|r!tj|di|d{Vntj|d{VdS#tj$rYdSwxYw)NFTr3)callablerosleepCancelledError)period period_kwargss r5wait_for_periodrXs F   (- 7 7 7 788 8 8 8 8 8 8 8 8-'' ' ' ' ' ' ' 'u  !ttsA AA#"A#c8K|r|rt|fi|d{VndSNF)r)checkrrs r5should_stop_after_period_passedrcsG   of66 666666666 r4 c fd}|S)z run decorated corotine in a loop every :period: seconds. If more then consecutive_err_limit error occured, exit loop. :param period: :param consecutive_err_limit: :param check_period_first: default false :return: cFtfd}|S)NcKd} tfid{VrdS |i|d{Vd}n#t$rOd|vrG t|dtr|dn#t $rYnwxYwYdSt j$rYdSt$r}|dz }|kr t dYd}~dSt|tj r3t d|j |j|j|jnt dYd}~nd}~wwxYwt fid{VrdST)NrT lock_filerz-Error count exceeded limit,exiting check loopz+Failed to run %s (%s). stdout=%s, stderr=%szError executing %s)rrrmrunlinkFileNotFoundErrorror Exceptionr^ exceptionrkCalledProcessErrorrrrrh) rMrNconsecutive_err_cntexccheck_period_firstconsecutive_err_limitrOrrs r5wrappedz3recurring_check..decorator..wrappedxsH"# ' 8&2?E,#t.v.........:+,''9*"f,,!)&*=tDD= &{ 3 : : < < <0!!! D!EE-EE DDD'1,'*-BBB((K!#{'EFF D((IGNJJ (()=sCCC!D&9**F6CEO' sK0D?5A54D?5 B?D?BD?D? D?"%D: A(D::D?r)rOrrrrrs` r5rTz"recurring_check..decoratorwsI s) ) ) ) ) ) ) )  ) Vr4r3)rrrrrTs```` r5recurring_checkrks7--------^ r4)backupuidgidallow_empty_content permissionsdir_fdrrc t|tr|}|'|rtdt |||||||St t 5t|d5}|t|dz} dddn #1swxYwY| |kr ddddS dddn #1swxYwY|s |st d||dS|rt|ttj fr|} ntj|tz} t t 5t!j|| dddn #1swxYwY|k t%jtj|j}n>#t $r1tjd} tj| d | z}YnwxYwtj|\} } t1| st d | t55}t7d | d | d zdd5fd}||||*|(tj ||tj! |tj" dddn #1swxYwYtj#j$||%dddn #1swxYwYdS)aAtomically rewrites *filename* with given *data*. If *filename*'s content is *data* already, do nothing. If both *uid* and *gid* are given then resulting file is chowned to given user id and group id. Skip rewrite with empty content if *allow_empty_content* is False. Chmod to given access *permissions* else preserve *filename* 's permissions. Return True if *filename* file was updated, False otherwise When *dir_fd* is provided it must be an O_NOFOLLOW-opened file descriptor for the parent directory of *filename*. All file I/O is then performed relative to that descriptor, closing the TOCTOU symlink-attack window. *backup* is not supported with *dir_fd*. Nz/backup is not supported when dir_fd is provided)rrrrrrbrFzempty content: %r for file: %srizParent dir is missing: wbz .i360editr)modedirsuffixprefix bufferingdeletectt5tjjddddS#1swxYwYdSr)r rosremovename)tfsr5cleanupzatomic_rewrite..cleanups/00''Ibg&&&''''''''''''''''''s=AAT)&rmrnencoderjr!r ropenreadlenr^rrPathLikefspathBACKUP_EXTENSIONshutilcopystatS_IMODEst_modeumaskpathsplitrr9rrcallbackwriteflushchownfilenochmodfsyncrenamerpop_all)filenamedatarrrrrrfile old_contentbackup_filename current_umaskdirpathbasenamestackrrs @r5atomic_rewriters6${{}}   PNOO O   3#     # $ $ (D ! ! 3T))CIIM22K 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 $     t 5tXFFFu 3 fsBK0 1 1 E$OO i114DDO ' ( ( 3 3 K/ 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1,rwx'8'8'@AAKK  1 1 1HQKKM H] # # #=.0KKK  1  h//GX ==   ! !G E' E EFFF  c>     " ' ' ' ' ' NN7 # # # HHTNNN HHJJJ3?c3/// HRYY[[+ . . . HRYY[[ ! ! !- " " " " " " " " " " " " " " ". "'8$$$ 38 4s(C9&B+ C+B/ /C2B/ 3 CCCE<<FF +F668G10G1M>0B=L9- M>9L= =M>L= 1M>>NNc tdS#t$rYdSwxYw)Nz/etc/system-release)r read_textrstriprr3r4r5os_release_and_versionr!sP)**4466==??? tts25 AAc|p t}|r-tjd|}|r|dSntt d|z)z3Return os version, if can't get it raise ValueErrorz\s*(\d+\.\d+\S*)(\s|$)rz!Can't discover os version from %r)r!researchgroup cache_clearrj)release_and_versionrvmatchs r5 os_versionr*st  8 6 8 8B - 3R88  ";;q>> ! " **,,, 82= > >>r4ceZdZdZedZedZedZdZe dZ e de e e ffdZe dee fd Ze de fd Ze de fd Ze d Ze d Ze dZe dZe dZe dZe dZe dZe dZdS) OsReleaseInfoz/etc/os-release)debian)rhelfedoracentos)unknownNct|j5}|D]U} |d\}}|d||<F#t $rYRwxYw dddn #1swxYwYd|vr,t |d|d<dSt |ddf|d<dS)N="ID_LIKEIDlinux)rETC_OS_RELEASEr r rrj frozensetget)clsdict_flinekvs r5dict_from_filezOsReleaseInfo.dict_from_file-s3 #$ % %   ;;==..s33DAq wws||E!HH!D                    (y)9)?)?)A)ABBE)    )%))D'*B*B)DEEE)   s5A;AAA; A+(A;*A++A;;A?A?r_c\|jt}tj|jr||ntj}|r|dr|d d}|dkr d|dvrd}||d<d |d|d|d|d <|d vr |j |d <n.|d vr |j |d <n|j|d <nd |d<|j|d <d |d <||_|jS)NrredzRed Hat Enterprise Linuxr.r6z {} {} ({})rra PRETTY_NAME) cloudlinuxr0r.r5)ubuntur-r1)r<dictrr r9r8rAdistrolinux_distributionlowerr rRHEL_FEDORA_CENTOSDEBIANUNKNOWN)r;r<dosids r5to_dictzOsReleaseInfo.to_dict<sQ 9 $(FFEw~~c011 5""5))))-//515Q4::<<--//2Du}})Cqt)K)K%"&E$K+7+>+>!adAaD,,E-(???+.+Ai((!555+.:i((+.;i(("+E$K'*{E)$+4E-(CIyr4c6|dS)Nr5rPr;s r5id_likezOsReleaseInfo.id_like[s{{}}Y''r4c6|dS)NrDrRrSs r5 pretty_namezOsReleaseInfo.pretty_name_s{{}}]++r4cR|ddS)zi :return: OS name, like centos, ubuntu, debian, cloudlinux, redhat in lower case r6r1)rPr:rSs r5get_oszOsReleaseInfo.get_oscs" {{}}  y111r4c2|dkS)Nr.rXrSs r5is_rhelzOsReleaseInfo.is_rhelkszz||v%%r4c2|dkS)Nr0rZrSs r5 is_centoszOsReleaseInfo.is_centosozz||x''r4c2|dkS)NrFrZrSs r5 is_ubuntuzOsReleaseInfo.is_ubuntusr^r4c.|dvS)N)rEcloudlinuxserverrZrSs r5 is_cloudlinuxzOsReleaseInfo.is_cloudlinuxwszz||AAAr4cJtjtSr)rr r9_CL_SOLO_EDITION_FILErSs r5is_cloudlinux_soloz OsReleaseInfo.is_cloudlinux_solo{sw~~3444r4c2|dkS)Nr-rZrSs r5 is_debianzOsReleaseInfo.is_debianr^r4c2|dkS)NolrZrSs r5is_oracle_linuxzOsReleaseInfo.is_oracle_linuxszz||t##r4c2|dkS)N almalinuxrZrSs r5 is_almalinuxzOsReleaseInfo.is_almalinuxszz||{**r4c2|dkS)NrockyrZrSs r5 is_rockylinuxzOsReleaseInfo.is_rockylinuxszz||w&&r4)r,r-r.r8r9rLrKrMr< classmethodrArrnrrPrrTrVrXr[r]r`rcrfrhrkrnrqr3r4r5r,r,%s&N Y{ # #F"#?@@i %%G E F F[ FS#X[<( #((([(,C,,,[,2s222[2&&[&(([((([(BB[B55[5(([($$[$++[+''['''r4r,r chunksizec0t|||dS)zReturn hash of the file `filename`, reading it in chunks. * filename is a path to a file; * hash_func is a function that returns hash object (one of hashlib.md5 etc); * chunksize is a size of chunks to read, in bytes. r)file_hash_and_size)r hash_funcrts r5 file_hashrxs h 9 = =a @@r4c|}d}t|d5} ||}|sn(|||t|z }@ dddn #1swxYwY||fS)aCalculate hash and size of the file `filename`, reading it in chunks. * filename is a path to a file; * hash_func is a function that returns hash object (one of hashlib.md5 etc); * chunksize is a size of chunks to read, in bytes. Return tuple(hash, file size).rrTN)rrupdater hexdigest)rrwrthash_sizer=chunks r5rvrvs IKKE D h   FF9%%E  LL    CJJ D    ??  d ""sAA,,A03A0c|\}}||kr&tdjdit|S)z0Given login.defs line, return *varname*'s value.z"Expected {varname!r}, got {name!r}r3)r rjrvars)varname defs_linervalues r5_parse_name_valuersJ//##KD%$D=DNNtvvNNOOO Lr4cHtdkrt\a}tS)Nr')_MIN_UID_get_max_min_uid)rs r5 get_min_uidrs2~~&(( ! Or4/etc/login.defschd\}} t|5}|D]f}|drttd|}|drttd|}g dddn #1swxYwYn#tt f$rYnwxYw||fS)zGet UID_MIN, UID_MAX from the login.defs file specified as *path*. On error, return default for the current OS values. )ii`UID_MINUID_MAXN)r startswithintrrrj)r uid_minuid_maxrr>s r5rrs( #GW  $ZZ F4 F F??9--F!"3It"D"DEEG??9--F!"3It"D"DEEG  F F F F F F F F F F F F F F F F Z       G s5BA*B  B BBBBB-,B-zimunify360-captchazimunify360-webshieldclt\fdtjDS)z~ :param excludes: users to exclude in results :return: list: list of pwd.struct_passwd objects representing users cPg|]"}|jcxkrknn |jv |#Sr3pw_uidpw_name).0entryexcludesrrs r5 z(get_non_system_users..sS     el - - - -g - - - - -%-x2O2O 2O2O2Or4rpwdgetpwall)rrrs`@@r5get_non_system_usersrsR())GW      \^^   r4cdt\}fdtjDS)z; :return: list: list of str with system user names c4g|]}|jk |jSr3r)rrrs r5rz)get_system_user_names..s.   W 5L5L 5L5L5Lr4r)rrs @r5get_system_user_namesrsE"##JGQ    #&<>>   r4rc0t\}}||kSr)r)rrrs r5is_system_userrs'))GW =r4d)r6typedct|d5}|dd}|dkrF||dz |ddkr|d|||ds|dddddS#1swxYwYdS)Nzr+rrar rseekrr endswithrrr= last_char_poss r5append_with_newliners h   q! A   FF=1$ % % %vvayyD     }}T""  GGDMMM                  B"CCCrct|d5}|dd}|dkrF||dz |ddkr|d|||ds|dddddS#1swxYwYdS)z>Append *data* to *filename* making sure there is at the end.zr+brrar Nrrs r5append_with_newline_bytesrs h   !q! A   FF=1$ % % %vvayyE!!  }}U##  GGENNN                  rcd}t|d5}tfd|Dsd}dddn #1swxYwY|rt||S)zAdd *line* to *filename* if it is not present in the file Returns: True if the file was changed, False otherwise. Frc3HK|]}|kVdSrrr_liner>s r5 z&ensure_line_in_file..(088U5;;==D(888888r4TN)ranyrrr>changedr=s ` r5ensure_line_in_filer s G h  8888a88888 G,Hd+++ N>AAr>cd}t|d5}tfd|Dsd}dddn #1swxYwY|rt||S)zAdd *line* to *filename* if it is not present in the file. Returns: True if the file was changed, False otherwise. Frc3HK|]}|kVdSrrrs r5rz,ensure_line_in_file_bytes..7rr4TN)rrrrs ` r5ensure_line_in_file_bytesr/s G h  8888a88888 G2!(D111 Nrctj|}t|d5}t d|d5}|D]/}||kr||0tj|j|dddn #1swxYwYddddS#1swxYwYdS)NrwF)rrr) rr dirnamerrrr rr)rr>basedirsfrrs r5remove_line_from_filer>s5gooh''G Xs%!???%CE  E{{}}$$ "'8$$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%s6B4A B B4B B4#B $B44B8;B8c,eZdZdZdZefdZdZdZdS)FileLockz` Simple context manager to enable UNIX-specific file locking with flock system call rcZ||_d|_t|d|_||_dS)NFr)r lockedrrr)rr rs r5rzFileLock.__init__Rs*  sOO  r4cKtj} t|jttzd|_|S#t tf$r}|jtj kr|j tj|z kr&t d|j Yd}~dStjdd{VYd}~nd}~wwxYw)NTz)Failed to lock file %s. Timeout exceeded.r)r>rrr rrrIOErrorerrnoEAGAINrr^rr ror)rrDexs r5 __aenter__zFileLock.__aenter__Xs  ' 'di7!2333"  W% ' ' '8u|++\DIKK%$777NNCTYEEEEEmA&&&&&&&&&&&&&& ' 's*ACAC/CCcK|jrt|jtd|_|jdSr)rrrrclose)rexc_typeexc_valexc_tbs r5 __aexit__zFileLock.__aexit__psC ; & $)W % % %  r4N)r,r-r.r\_TIMEOUTrrrr3r4r5rrJsZ H%- '''0r4rc |g}|fdt|Dtj}|d|dd|S#ttf$r%}t d|Yd}~nd}~wwxYwdS)Nc3DK|]\}}|v t|VdSr)rn)rfieldrfieldss r5rz user_identity..s?  u JJ  r4rutf8surrogateescapez9Generation of user identity hash failed, invalid data: %s) extendsorteditemshashlibsha1rzjoinrr{rjUnicodeEncodeErrorr^r) attackers_ipsourceruid_datahash_alges ` r5 user_identityrzs  !>    &v||~~ 6 6      <>>))009JKKLLL!!### * +    G         4sB%B))C:CCc0tjdkS)Nr)rgetuidr3r4r5 is_root_userrs 9;;! r4maskc#Ktj|} dVtj|dS#tj|wxYwr)rr)r current_masks r5run_with_umaskrsM8D>>L  s 2Arusernamec~t|tstd|ztj|vrtd t j|}n0#t$r#td|wxYwtj |j |}t|S)z Returns user's home dir if `relpath` is not specified. Otherwise, returns absolute path of `relpath` build from `username`'s home dir :raise ValueError: when user home dir is not exists z#Invalid type for %s, should be str!zInvalid usernamezUser {!r} doesn't exist) rmrnrjrseprgetpwnamKeyErrorrr rpw_dirr)rrelpathpwabs_paths r5get_abspath_from_user_dirrs h $ $K>IJJJ v+,,,E \( # # EEE299(CCDDDEw||BIw//H >>s A-Br cd} t|}t||d}n>#t$r1}tt |Yd}~nd}~wwxYw|S)NFT)rr relative_torjr^rrn)r rstatus user_homers r5does_path_belong_to_userrs F-h77  T y))) s1vv Ms38 A3'A..A3ctj|std|z tj|rg t jtj|jj S#t$r)ttj|jcYSwxYwtj |})NzPath %s should be absolute!) rr abspathrjr9rgetpwuidrst_uidrrrnrr s r5get_path_ownerrs 7??4 ?6=>>>% 7>>$   1 1|BGDMM$899AA 1 1 1274==/00000 1wt$$ %s/B0B65B6iterable chunk_sizec#Kt|}tt||}|r%|Vtt||}|#dSdS)a Generator that splits iterable on N-parts by chunk_size items in each chunk >>> list(split_for_chunk([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], chunk_size=2)) [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]] :param iterable: :param int chunk_size: :return: generator: N)iterrqr)r r ipieces r5split_for_chunkrsp XA :&& ' 'E , VAz**++ ,,,,,r4ct|tr+td|DSt|trt d|DS|S)Nc3>K|]\}}|t|fVdSrfreeze)rkeyrs r5rzfreeze..s1JJ*#u#ve}}-JJJJJJr4c34K|]}t|VdSrr)rrs r5rzfreeze..s(22uVE]]222222r4)rmrGr9rrqrr)rNs r5rrsm!T3JJ JJJJJJ At  322222222 Hr4c&eZdZdZiZfdZxZS) Singletonzc Metaclass for creating only one instance of class, when providing the same arguments. c|t|t|f}|j|s(tt|j|i||j|<|j|Sr)r _instancesr:superrr)r;rMrNr __class__s r5rzSingleton.__call__srF4LL&..1~!!#&& "@% 3"7"7"@###CN3 ~c""r4)r,r-r.r\rr __classcell__)rs@r5rrsI J#########r4rctjdd5}|cdddS#1swxYwYdS)z3 :return str: server's external IP address zhttps://api.ipify.orgrarN)urllibrequesturlopenrr)rs r5get_external_ipr!s    7  C C!qvvxx  !!!!!!!!!!!!!!!!!!s&AAAc<d}|||}tj|st d|d|t |d5}|}dddn #1swxYwY|S)z Reads parameter of kernel module from /sys/module/{module_name}/parameters/{parameter} :return str: value of the parameter z(/sys/module/{mod}/parameters/{parameter})mod parameterzCannot find parameter z for module rN)rrr r9rjrrr) module_namer$ _MOD_PAR_PATH param_fileprs r5get_kernel_module_parameterr)s ?M%%+%KKJ 7>>* % % j8A ;; O    j#  !!  !!!!!!!!!!!!!!! Ls'BBBcd}|D][\}}t|tr%||vs|s|||<d}(t|||}?||vs|sJ|d||||<d}\|S)zPerforms deep update of dict dst with values from src. Does not overwrite subdicts in dst blindly with new dicts in src, but does a deep update of (sub)dict content recursivelyFTz already exists in )rrmrGdict_deep_update)dstsrcallow_overwriteupdatedr?r@s r5r+r+s G  1 a   ||1|A*3q6155  ---- /CFGG Nr4c8eZdZd dZdZdZdZdedefdZd S) TimedCacherct|tsJ||_||_t |_i|_dSr)rmr expirationr6rcache_locks)rr3r6s r5rzTimedCache.__init__)s<*i00000$  ]]  r4ct}|jD]J}|j|\}}tj|z |jkr||f||<K||_dS)zClear cache from expired valuesN)rr4r>r3 total_seconds)r tmp_cacherradded_ats r5_collectzTimedCache._collect0shMM : 1 1C"joOE8 h&$/*G*G*I*III!& # r4c:t|_i|_dSr)rr4r5rs r5r&zTimedCache.cache_clear9s ]]  r4c|}|r3t|}|t|z }t|S)z Generate key from call arguments :param args: call positional args :param kwargs: call keyword args :return: )rrrrhash)rrMrNseedkws r5 _make_keyzTimedCache._make_key=sB   ''B E"II DDzzr4funcr_ctfd}tfd}tjr|n|}j|_|S)a  Use it to cache calls to decorated function @TimedCache(expiration=timedelta(minutes=10)) async def func(*args, **kwargs): pass :param func: decorated function :return: NOTE: is not thread safe. chK||}j|}|tjx}j|< tj|jd{VnP#tj $r=|j|urtjx}j|<n j|}YnwxYw   j |\}}ns#t$rftj jkrj d|i|d{V}|t!jfj |<YnwxYw|n#|wxYw|S)NTFlast)rAr5r:rorracquirer3r7 TimeoutErrorr:r4rrr6popitemr>release)rMrNrlockrrrBrs r5 wrapper_asyncz*TimedCache.__call__..wrapper_asyncWs..v..C;??3''D|*1,..8t{3' 00!* (E(E(G(G+ 0 0 0 t{3///29,..@t{3//#{3/ 0  0  : $ 3IFAA:::4:$,66 ***666#'4#8#8#8888888F&,dikk&9DJsOOO :   MsEABA C&%C&+FDFA-F>FFFF/cZ||} j|\}}nm#t$r`t jjkrjd|i|}|tjfj|<YnwxYw|S)NFrE)r:rAr4rrr6rIr>)rMrNrrrrBrs r5 wrapper_syncz)TimedCache.__call__..wrapper_synczs MMOOO..v..C 6 JsO  6 6 6tz??dl22J&&E&222t.v.."($)++"5 3  6 Ms>A'B('B()rroiscoroutinefunctionr&)rrBrLrNrPs`` r5rzTimedCache.__call__Js t       D t       *400 MM  #.r4N)r) r,r-r.rr:r&rAr"rr3r4r5r1r1(s   CQC1CCCCCCr4r1rcK|r<|s& |n#t$rYnwxYwdS|t j|h|d{V\}}|rL|s|nd}|rt d||dSdS|st d||dSdS)uCancel *task* and wait up to *timeout* seconds for it to finish. Unlike the common ``task.cancel(); suppress(CancelledError); await task`` pattern, this function **always returns** within *timeout* seconds — even if the task catches ``CancelledError`` and continues running (see DEF-40570 / CPython #103486). Uses ``asyncio.wait`` (not ``wait_for``) because ``wait_for`` also hangs when the inner task survives cancellation. Nrz&Task %r raised during cancellation: %sz.Task %r did not finish within %ds after cancel) done cancelledrrcancelrorxrr^r)taskrrRrrs r5safe_cancel_taskrVs: yy{{~~       KKMMML$999999999GD!  &*nn&6&6@dnnD  P NNCT3 O O O O O P P YY[[  s r5_has_no_new_privsrns % & & 2! 2 2??=112::<<?c111 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2      5s@A19A% A1A% A1%A))A1,A)-A11 A>=A>)z systemd-runz--quietz--waitz--pipez --collectz--property=NoNewPrivileges=noz--property=ProtectSystem=noc`|sdStd|DS)Nr3c3,K|]\}}d|d|VdS)z --setenv=r3Nr3)rr?r@s r5rz+_systemd_run_setenv_args.. s7==A$Q$$$$======r4)rrrenvs r5_systemd_run_setenv_argsrss4 r ===== = ==r4rcts|Stt|zdd|fz}dd|DS)zWrap a shell command so it runs as a transient systemd unit outside the agent's NoNewPrivileges= sandbox. Returns the original command unchanged when this process is not under NNP.z/bin/shz-c c3>K|]}tj|VdSr)shlexquote)rr(s r5rz._wrap_outside_sandbox_shell..s*22qEKNN222222r4)rn_SYSTEMD_RUN_BASErsr)rrrpartss r5_wrap_outside_sandbox_shellr{sa     "3 ' ' ( dC  ! 8822E222 2 22r4ctst|Sttt|zdzt |zS)z5Argv-form counterpart of _wrap_outside_sandbox_shell.)z--)rnrqryrsrr)argvrrs r5_wrap_outside_sandbox_argvr~sY   Dzz  "3 ' ' (   ++   r4rqcLKtt|||fi|d{VS)urun_cmd_and_log variant that escapes the agent's systemd sandbox. Use for shell commands whose RPM/apt scriptlets perform LSM domain transitions on exec (e.g. kernelcare install, hardened-php groupinstall) — see the module-level NNP note above. rqN)rkr{)rrfrrrgs r5run_cmd_and_log_outside_sandboxr(sZ!#CS111       r4cJKtt||fi|d{VS)z7run() variant that escapes the agent's systemd sandbox.rqN)rr~r}rrrNs r5run_outside_sandboxr8s</#>>>II&II I I I I I IIr4cJKtt||fi|d{VS)z=check_run() variant that escapes the agent's systemd sandbox.rqN)rr~rs r5check_run_outside_sandboxr=s<5dDDDOOOO O O O O O OOr4ceZdZdZdS)rc `|jdkr7|jr0|dd}|jr |j|d<|j| t j|dS#t$rt|j ddpt|j dd}t|j ddpt|j dd}t|j d dpt|j d d}|j }|r|j p|j }td ||j||YdSwxYw) NPENDINGz%Task was destroyed but it is pending!)rUmessagesource_tracebackr.r,gi_codecr_codegi_framecr_framez+!> Finalizer error in {}() {} at {} line {})_state_log_destroy_pending_source_traceback_loopcall_exception_handlerr__del__AttributeErrorgetattr_coro co_filenamef_linenoco_firstlinenoprintr)rcontextrrframerlinenos r5rz Task.__del__Es{ ;) # #(A #BG% E.2.D*+ J - -g 6 6 6  N4    4:~t<< JAAD4:y$777 It<<DDJ D99W J>>E'H.F43FF =DD$+x       sACD-,D-N)r,r-r.rr3r4r5rrDs#r4rcfd}|S)zReturn async callback which waits for *seconds*. Usage: @retry_on(Error, on_error=await_for(seconds=PAUSE_INTERVAL), timeout=T) async def coro(): 'here's something that may raise Error.' c<Ktjd{VSr)ror)rMrbs r5pausezawait_for..pauseos)]7+++++++++r4r3)rbrs` r5rvrves#,,,,, Lr4cjtgstdfd}|S)a Retry the function call on exception (or exceptions, if given in tuple) at most *max_tries*. Await *on_error* (if set) for each exception. If *timeout* is set, stop all attempts in *timeout* seconds. If *silent* is set to True - don't raise exceptions after max If *should_retry* is set - await it and on False, stop auto-retry cycle tries or timeout. zSet any of max_tries, timeoutc tj fd}tj fd}tjr|S|S)Nc~Krtjz} stjdnt d dzD]} rg|tjz }|dkr$t j|i||d{VcS s t j r dn|i|d{VcS}#t jt j f$r$rX}  ||d{V}|s }| kr s r d|  ||d{VYd}~d}~wwxYwdS)Nrrr Timeout exceeded when calling %s0Max tries exceeded when calling %s with error %s) r>r? itertoolscountrrorrHrrrMrNend_timer remaining_timershould_retry_retrrBrCrcrd should_retrysilentrs r5rLz2retry_on..decorator..wrapper_asyncs, 6>++g5!- """1i!m,,( /( / #/;)1DN4D4D)D)A--)0)9 $d 5f 5 5~***$$$$$$$*"&-&: :!$" # $F!"!"!"&*T4%:6%:%::::::::::,g.DE ///#/1=c11E1E+E+E+E+E+E+E(/* )AI~~%! II!, $ #   +&hsA.........#//( /( /s?C 4C D:"AD55D:crtjz} stjdnt d dzD]} rH|tjz }|dkr |i|cS st  r dn |i|cSX#$rL}  ||}|s }| kr s r d|  ||Yd}~d}~wwxYwdS)Nrrrr)r>r?rrrrHrrs r5rNz1retry_on..decorator..wrapper_syncs 6>++g5!- """1i!m,,$ )$ ) ) 5)1DN4D4D)D)A--#'4#8#8#8888#)"&2 2!$" # $F!"!"!" $tT4V44444 )))#/+7<Q+?+?(/* )AI~~%! II!, $ #   + a(((#)'$ )$ )s%B.)BC, AC''C,rRrrorO) rBrLrNrrCrcrdrrrs ` r5rTzretry_on..decorators   + /+ /+ /+ /+ /+ /+ /+ /+ /+ /+ /  + /Z   ' )' )' )' )' )' )' )' )' )' )' )  ' )R  &t , ,   r4)rrj)rrdrcrrrCrrTs``````` r5rtrtusz$  7# $ $:8999\ \ \ \ \ \ \ \ \ \ \ | r4ctjfd}tjfd}tjr|n|S)zhIf func throws an exception it is catched, converted to a string and returned as a result of a call.crK |i|d{VS#t$r}t|cYd}~Sd}~wwxYwrrreprrMrNrrBs r5rLz,stub_unexpected_error..wrapper_asyncsg t.v........ .   77NNNNNN s  6166cb |i|S#t$r}t|cYd}~Sd}~wwxYwrrrs r5rNz+stub_unexpected_error..wrapper_syncsQ 4((( (   77NNNNNN s .)..r)rBrLrNs` r5stub_unexpected_errorrs_T _T $7== O==<Or4c2 tjfd}|S)zkA decorator that logs uncaught exceptions ignoring them otherwise. CancelledError is not handled. Nctjfd}tjfd}tjr|S|S)Nc K |i|d{VS#tj$r$r'}dtdd|Yd}~dSd}~wwxYwNzIgnoring exception from %s: %sr.r)rorrrMrNrrr log_handlers r5rLz>log_error_and_ignore..decorator..wrapper_async s !T426222222222)       4D.&99 s AA  Ac t |i|S#$r'}dtdd|Yd}~dSd}~wwxYwr)rrs r5rNz=log_error_and_ignore..decorator..wrapper_syncs tT,V,,,    4D.&99 s 727r)rrLrNrrs` r5rTz'log_error_and_ignore..decorators                          &t , ,   r4)r^r)rrrTs`` r5log_error_and_ignorers9 l       < r4cfd}|S)z'Abort the agent service on *exception*.cLtjfd}|S)NcK |i|d{VS#$r/}t|Yd}~dSd}~wwxYwr)r^r)rMrNrabortrrs r5rPz2abort_agent_on..decorator..wrapper-s !T426222222222     ###  s A$AArQ)rrPrrs` r5rTz!abort_agent_on..decorator,sC            r4r3)rrrTs`` r5abort_agent_onr)s*       r4cRtjdd|S)zPascalCase to snake_casez([a-z])([A-Z])z\1_\2)r#subrJ)strings r5 snake_caser<s# 6"Hf 5 5 ; ; = ==r4)exec_expr_with_empty_iterc'K|s|rdg}nt|t}ddlm}|j5|D]}||g|REd{V ddddS#1swxYwYdS)a] Get iterator over results of sql expression expr. Given iterable will be split for chunks and we will return iterator containing results of all split queries. Useful for sql selects with in_() in order to avoid too many sql variables error. If exec_expr_with_empty_iter is True and iterable is None(empty) we will process expression once, passing here chunk=None expr(None, *args) :param expr: :param iterable: :param exec_expr_with_empty_iter: if iterable is None(empty) process given expression once, passing here chunk=None expr(None, *args) :return: Nr rinstance)rCHUNK_SIZE_SQL_QUERYdefence360agent.modelrdb transaction)exprr rrMchunksrr~s r5get_results_iterable_expressionrDs& L1L 6JKKK......  " "** * *EtE)D))) ) ) ) ) ) ) ) ) *******************sA##A'*A'rcd}ddlm}|j5t ||D] }|||g|Rz }! dddn #1swxYwY|S)z Get number of results of sql expression expr. Given iterable will be split for chunks and we will return number of results of all split queries. Useful for sql delete with in_() in order to avoid too many sql variables error rrrN)rrrrrexecute)rr r rMrrr~s r5execute_iterable_expressionrcsG......  " "44$X*EEE 4 4E ttE)D)))1133 3GG 4444444444444444 Ns3A""A&)A&cXtj|dddzS)Nr\nr)rfsencoder_rs r5encode_filenamervs% ;t||D%00 1 1E 99r4cbtj|ddddS)Nr'rr)rfsdecoder_rs r5decode_filenamerzs+ ;t  SbS ! ) )% 6 66r4cNtjtj|Sr)base64 b64encoderrrs r5base64_encode_filenamer~s  BK-- . ..r4b64namechttjtj|Sr)rrrr b64decode)rs r5base64_decode_filenamers%  F,W5566 7 77r4cV tj|}n#t$rd}YnwxYw|S)zS Like pwd.getpwnam(username) but returns None instead of raising KeyError. N)rrr)rrs r5rrsAh''  Ms  &&c>tt|||S)zH Put the specified `value` inside the [`low`, `high`] interval. )maxmin)rlowhighs r5cliprs s5$ % %%r4Background task failedc| tj} |dS#tj$rYdSt $r}|d||Yd}~dSd}~wwxYw)a[ Callback for asyncio.Future that logs exceptions and ignores CancelledError. Use this as a done_callback for asyncio tasks/futures: future.add_done_callback(log_future_errors) Or with custom logging: future.add_done_callback( lambda f: log_future_errors(f, logger.warning, "Upload failed") ) Nz%s: %s)r^rrrorr)futrrrs r5log_future_errorsrsn *  !     *** Hgq)))))))))*s&A A AAr.crfd}||i|}|||S)z Use this function in plugin initialization instead of loop.create_task to be able to see the exceptions from the specified coroutine. c|sA|/d||ddSdSdS)Nz1Unhandled exception during plugin initialization!)rrrU)rSrr)rUrs r5_log_exceptionz6create_task_and_log_exceptions.._log_exceptionsv~~ DNN$4$4$@  ' 'L!%!1!1        $@$@r4) create_taskadd_done_callback)rrrMrNrnew_tasks` r5create_task_and_log_exceptionsrsY     d 5f 5 566H ~... Or4cfd}|S)a5 Create coroutine from regular function Useful to pass functions to APIs requiring coroutines Note: coroutine will still block event loop in main thread. For most blocking functions, run_in_executor should be considered instead :param function: :return: coroutine running function cK|i|Srr3)rMrNfunctions r5rzmake_coro..corosx((((r4r3)rrs` r5 make_corors#))))) Kr4cK|tkr tj}n tj}|dt |ddx}rd|dnd||t jtd{VdS)Nz7Failed to copy data%s to modsec ruleset dir %r, try: %srz ()r)COPY_TO_MODSEC_MAXTRIESr^rrrror_MODSEC_COPY_FAILURE_TIMEOUT)rr rCfns r5log_failed_to_copy_to_modsecrs ###lnCA$S*d;;;rD R "   -4 5 5555555555r4) err_buf_sizec 4Kd}t|}tj|dtjjtjjd|d{V} tj||j||j23d{V}|WV 6 |d{V}|dkr%t||dd |dS#|d{V}|dkr%t||dd |wxYw)z Start *cmd*, yield its stdout line by line [b' '] If *cmd* return nonzero exit status, raise CheckRunError with the last *err_buf_size* lines from stderr. cJK|23d{V}||6dSr)append)pipebufr>s r5read_pipe_intoz1readlines_from_cmd_output..read_pipe_intosL       $ JJt    $$s")maxlenT)rirgrhNrr4) rrorsr`rlrrhrgrxrr)rrrgr err_bufr}r>rs r5readlines_from_cmd_outputrs<(((G/ !&!&         D I NN4;@@AAA+       $JJJJJ&+ 99;;&&&&&& ?? Cchhw6G6GHH H ? 99;;&&&&&& ?? Cchhw6G6GHH H H H H Hs*C:BCADra)rcdelaycKtd|dzD]3}||d{V}|s!||krtj|d{V0|cSdS)z Retry *predicate_coro(*args)* until it becomes true, but no more than *max_tries* attempts. Sleep for *delay* seconds before the next *predicate_coro()* call. Return whether the predicate became true. rN)rror)predicate_cororcrrMattemptrs r5finally_happenedr sIM**%~t,,,,,,, 'I---&& & & & & & & &  r4'cKt|dD]-\}}|WV||zdkrtjdd{V.dS)z6Yield to the event loop every *chunk_size* iterations.r)rDrN) enumerateror)r r r items r5 nice_iteratorrsoXQ///##4 Nq -"" " " " " " " "##r4ceZdZdZdZdZdS)LazyLocka Descriptor object to share async Lock between client objects. Used in order to achieve lazy evaluation of the lock and share state between it's clients. Using asyncio.Lock in client code directly: >>> class Foo: >>> lock = asyncio.Lock() leads to an unclear error ([Errno 9] Bad file descriptor), when trying to move this Lock during demonization process. cd|_dSr)rr<s r5rzLazyLock.__init__6s  r4cN|jstj|_|jSr)rror)rrowners r5__get__zLazyLock.__get__9s!z ( DJzr4N)r,r-r.r\rrr3r4r5rr's<  r4rc|}|rd|vsd|vrdS|dd\}}||fS)zOParse RPM output line, return (package_name, version) or None if not installed.z not installed: Nr)rrJr )r>pkg_nameversions r5_parse_rpm_liner#?s[ ::<r!restr"s r5_parse_dpkg_liner&Hs ::<.wrappervs\ 7>>= > > +4 T4*6*********r4r)rBrPs` r5check_disabled_firewallr.us3 4[[++++[+ Nr4> imunify-ui imunify-coreimunify-antivirusimunify360-firewallpackagescKt\}}t|}t||zddd{V}t|||S)a Retrieves the version of the specified system packages using a command and regex specific to the current system. Parameters: packages (Iterable[str]): A set of package names to retrieve version for. Returns: A dictionary mapping package names to their corresponding version strings, or None if the package is not installed or version information cannot be retrieved. F)rrN)r)rqsafe_run_with_timeout_parse_package_info_output)r3r parse_line packages_listrs r5system_packages_infor:st-..OCNNM( mR%F &fmZ H HHr4rr8cnfd|Dfd|DS)NcXi|]&}|xdxdx#'S)rrr3)rr>r8pkgrvers r5 z._parse_package_info_output..sf  j&& &F1I S  1I S  Sr4c<i|]}||Sr3)r:)rr=parseds r5r?z._parse_package_info_output..s% 5 5 5SCC 5 5 5r4) splitlines)rr3r8rAr=rr>s `@@@@r5r7r7sf %%''F 6 5 5 5H 5 5 55r4cK tjt|fi||d{VS#tj$r|d|YdSwxYw)Nrz#Command %s failed: Timeout occurredr)rorrrH)ryrrCrNs r5r6r6s% W ' ' ' '              17;;;rrs&+A  A nc#K|dkrtdt|}tt||x}r%|Vtt||x}#dSdS)Nrzn must be at least one)rjr rqr)r rDitbatchs r5batchedrHs  1uu1222 hBr1 && &% r1 && &%r4rNc#RKt|D]}fd|DVdS)Nc"i|] }|| Sr3r3)rr?rNs r5r?z batched_dict..s&&&1q!A$&&&r4)rH)rNrDrGs` r5 batched_dictrKsKA''&&&&&&&&&&&''r4cn tjddgd}|d}|s?t drtjddgd}d|vrd}|S#t $r&}td |Yd}~d Sd}~wwxYw) Nhostnamez-fT)text)z.cloudwaysapps.comz.cloudwaysstagingapps.comz/usr/local/sbin/apminfo Cloudwaysz$Error while checking environment: %sF) rk check_outputrrrr9rr^r)rM _is_cloudwaysrrs r5 is_cloudwaysrSs+  T   %'' !)) ?   %&;!urllib.requestrr collectionsrrcollections.abcrr contextlibrr r datetimer enumr fcntlr rrrrrpathlibrtempfilertypingrrrrrrrr async_lrurHrb_shutilrr fd_opsr!r" getLoggerr,r^USER_IDENTITY_FIELDUSER_IDENTITY_HEADERSrrr8re AV_PID_PATHIM360_NON_RESIDENT_PID_PATHIM360_RESIDENT_PID_PATHrenvironr:HTTP_REQUEST_RETRY_TIMEOUTr+ lru_cacher<rFrVrXrlbytesrrrrrrrnrrrrrrrrrboolrrr!r*r,md5rxrvrrrrrrpartial alru_cacheasync_lru_cacherrrrrrrrrrrrrrtyperr!r)r+r1 timed_cacherVr\rkrnryrsr{r~rrrrrvrtrrrrrrrrrrrrrrrrrrrrrrrrrr#r&rqr)r+r.r9IMUNIFY_PACKAGE_NAMESrGr:r7rr6rHrKrSrWrYr[r3r4r5r|s  ********////////::::::::::222222222222''''''                     00000000%%%%%% GCx     8 $ $ d0116d344 "d#BCC$899 SJNN:B?? +++++D+++Q     K K K K4T    4        00 3u 0000f 0      K2    (5  5    .; ' ' ' ' ' ,   ++++++++@        :?;;;;F(,  ddd 3J $ d $Jd ddddNQ ? ?C ? ? ? ?h'h'h'h'h'h'h'h'X%[4 A A A58 A A A A A #### 38_ ####2.<     $)#         5 T         5 T     % % %--------`0E6D&3#$ % % % , ,h ,C ,) , , , ,    ########"R   !!! !"2eeeeeeeeP -.     >)))ZQ4 $>>> 3 3S 3s 3 3 3 3     $      ,0JJJJJ 26PPPPP7<B   $   sssslPPP*$-$&&&&R%7&>>> 6;*****@';&:::777//%////8E8d8888&&&****.i(4      6 6 6%(III cIIIID=>Q      ####0#%S/D"835c?T#9"Q $s)XseU38_t%;;< <= .FFFFF FFF   " IsmI #sTz/IIII, 6  63i 6#c3h$ 667 6 #sTz/ 6 6 6 6 !,           'DcN's'''' Q ( T c     t    &&&&&r4