Ur,dZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z mZmZmZmZmZmZddlmZmZddlmZmZejeZdZd ed ed efd Z e!hd Z"e!hdZ#d ed e$d e$fdZ%e ddZ&e ddZ'e ddZ(e%ddZ)dZ*ded efdZ+Gdde Z,dS)u3 Feature flags synchronisation plugin (AV mode only). In IM360 mode the Go resident-agent handles feature-flag sync. In AV mode there is no resident-agent, so this plugin takes over. Periodically POSTs the local file checksum to the API and writes back any updated flags to ``/var/imunify360/feature_flags.json`` (legacy map ``{flag: true}`` on disk) and ``/var/imunify360/feature_flags`` (plain names, one per line). The POSTed checksum is over the canonical JSON **array** of enabled names, matching the correlation sync API—not over the on-disk map bytes. N)Core) MessageSource) FLAGS_PATHFLAGS_PLAIN_PATHenabled_flag_names_sorted$plain_text_payload_for_enabled_flags$serialize_feature_flags_file_payload!sync_checksum_hex_from_flags_filesync_response_file_bytes)IAIDTokenErrorIndependentAgentIDAPI)Scopeatomic_rewritez/api/sync/v1/feature-flagsnamedefaultreturnctj|}|s|S t|S#t$r"t d||||cYSwxYw)uRead an int env var tolerantly. A non-numeric value (empty string, typo, etc.) must NOT raise at import time — the plugin lives in the AV agent entry point and a bad env var would otherwise kill the whole agent. z4feature-flags: %s=%r is not an int, using default %d)osenvirongetint ValueErrorloggerwarning)rrraws Z/opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/plugins/feature_flags.py_env_intr+s| *..  C  3xx  B       s4)A A >1onyestrue>0noofffalsectj|}|s|S|}|t vrdS|t vrdStd||||S)NTFz4feature-flags: %s=%r is not a bool, using default %s) rrrstriplower _TRUE_VALUES _FALSE_VALUESrr)rrr normalizeds r _env_boolr,Es *..  C ""$$J\!!t]""u NN>    N I360_FEATURE_FLAGS_SYNC_INTERVALiI360_FEATURE_FLAGS_INIT_DELAY I360_FEATURE_FLAGS_UNREG_DELAY#I360_FEATURE_FLAGS_USE_SERVER_DELAYT server_delayc.tr|dkr|StS)Nr)_USE_SERVER_DELAY_SYNC_INTERVAL)r4s r _next_delayr8^s \A-- r-ceZdZejZdZdZdefdZ dZ de fdZ e dejjdefdZe d d d Zd S) FeatureFlagsSyncc~K||_||_|||_dSN)_loop_sink create_task _sync_loop_task)selfloopsinks r create_sourcezFeatureFlagsSync.create_sourcegs7  %%doo&7&788 r-cK|j?|j |jd{VdS#tj$rYdSwxYwdSr<)rAcancelasyncioCancelledErrorrBs rshutdownzFeatureFlagsSync.shutdownlst : ! J      j         )     " !s 3AArc*ttSr<)r rrJs r_local_checksumz FeatureFlagsSync._local_checksumts0<<>E)    K K K:TJJJJJ K-&& & & & & & & & 'sAA..5B&%B&cK tjd{V}n+#t$rtdYdSwxYwt j}|d|jd{V}tj d|i }tj dtj}|dt"z}t$j||d|dd } |d|j|d{V}n#t$jj$rq} d | jcxkrd kr-nn*td | j|| j| n'td | j|| jYd} ~ dSd} ~ wt$jj$r,} td|| jYd} ~ dSd} ~ wt6$r!td|d YdSwxYw tj|} n0#tj$rtdYdSwxYw| dd} | ddurtd| S| d} | dpi} | #|d|j | | d{V| S)Nz*no IAID token, skipping feature flags syncrchecksumI360_FEATURE_FLAGS_API_URL/zapplication/json)z Content-TypezX-AuthPOST)dataheadersmethodiiXz$feature flags sync HTTP %s on %s: %srOz.feature flags sync connection failed on %s: %sz'feature flags sync request failed on %sTz&failed to parse feature flags responserWchangedFz'feature flags unchanged, skipping writeflagsparams)!r get_tokenr rrrHget_event_looprun_in_executorrMjsondumpsencodergetenvr API_BASE_URLrstrip _SYNC_URLurllibrequestRequest_blocking_requesterror HTTPErrorcodereasonURLErrorrVloadsJSONDecodeErrorrdebug _write_flags)rBtokenrCrYpayloadbase_urlurlreq resp_bodyeresultr4rarbs rrUzFeatureFlagsSync._do_syncs /9;;;;;;;;EE    NNG H H H11 %''--dD4HIIIIIIII*j(344;;==994;LMMooc""Y.n$$  2%  ' "22d,cII|%   af""""s""""" :FH :FH  11111|$    NN@    11111    LL9     11   Z **FF#    LLA B B B11 zz'1-- ::i E ) ) LLB C C C  7##H%%+  &&tT->vNN N N N N N N NsL$AA"D++H?A&F++H!G))*HHH00)IIr~ctj|t5}|cdddS#1swxYwYdS)N)timeout)rmrnurlopen _HTTP_TIMEOUTread)r~resps rrpz"FeatureFlagsSync._blocking_requests ^ # #C # ? ? 499;;                  sAA A Nc|pi} t|tr;d|D}d|D}t||}nt |}n>#t $r1t dt|j YdSwxYwtt|} tj tjt dt#t |dt%|}t#t&|dt d |dS#t*$r t d d YdSwxYw) u^Persist flags + params on disk in the canonical sync-response shape so the next sync's checksum matches what the server returned. Falls back to the legacy ``{name: true}`` map when ``flags`` is not a list (response shape we don't recognise) — keeps the long-standing on-disk contract from older code paths. c<g|]}t|t|S isinstancestr).0ns r z1FeatureFlagsSync._write_flags..s'@@@qZ3-?-?@@@@r-ci|]<\}}t|tt|t/|d|D=S)c<g|]}t|t|Srr)rvs rrz..s'AAAjC.@.@A1AAAr-)rrlist)rrvalss r z1FeatureFlagsSync._write_flags..sa"d!$,,2rs_    111111;;;;;;87777777  8 $ $ ( 3,y33344  55566 C$4$>h?DDICTJJ cc _F_F_F_F_F}_F_F_F_F_Fr-