o
    id                     @   s  U d dl mZ d dlZd dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$  m%Z& d dl'm(Z) erd dlm*Z* d dlm+Z+ e&,e-Z%G dd deZ.G dd dedZ/e/D ]\Z0Z1e&2e1e&j3 qd d!d!d"Z4d#Z5e
d# e6d$< d%Z7e
d% e6d&< d'Z8e
d' e6d(< d)Z9e
d) e6d*< d+Z:e
d+ e6d,< d-Z;e
d- e6d.< e:g iZ<e=e>e?e	 f e6d/< d0e>d1e>d2dfd3d4Z@G d5d6 d6ZAd2eeA fd7d8ZBd2eeA fd9d:ZCd2eDfd;d<ZEd2eDfd=d>ZFd2ee fd?d@ZGd2ee fdAdBZHdCZIeJe6dD< dEZKeJe6dF< G dGdH dHZLdIeAd2eDfdJdKZMd2e>fdLdMZNdNed2eDfdOdPZOdQed2dfdRdSZPdTed2dfdUdVZQd-ee=e>ef edf d2dfdWdXZRdYedZe>d[eeSeJf d2dfd\d]ZTdIeAd2dfd^d_ZUdIeAd2dfd`daZVdbe>dce>d[ed2dfdddeZWdNed2dfdfdgZXdhed2dfdidjZYdce>d[ed2dfdkdlZZddbe>dce>dmed2efdndoZ[ddce>dmed2efdpdqZ\ddse	eAgef dteDd2dfdudvZ]ddse	eAgef dteDd2dfdwdxZ^dye	g dzf d2dfd{d|Z_				rdd}ee=e>ef  d~ee> dee> deDd2ed f
ddZ`dddZadee> d2dfddZbd2ee> fddZcdNed2dfddZdd2ee fddZedeDd2dfddZfd2eDfddZgdee	g ef  ded2dfddZhdddZid2eje> fddZk			r	ddee> dNedeDdee	 d2df
ddZlde>d>eDdddee> deDd2dfddZmd2ee fddZnde?e=e>ef  d2dfddZodee. dYede>d2dfddZpdYed2dfddZqdedereeset  eet ee f d2dfddZudedNeded2dfddZvdeded2dfddZwdeded2dfddZxd2ee fddZyh dZzh dZ{e{|ez ddYedNede>deDd2df
ddĄZ}dddƄZ~dS )    )MappingN)TracebackType)TYPE_CHECKING)Any)Callable)Literal)Optional)Protocol)Union)parse)Span)APPSEC)SPAN_DATA_NAMES)Constant_Class)_set_waf_request_metrics)Block_config)Telemetry_result)get_triggers)is_inferred_span)_normalize_tag_name)core)BlockingException)config)
DDWaf_info)DDWaf_resultc                   @   sL   e Zd Z				ddeeeef  dee dee deded f
d	d
ZdS )WafCallableNFcustom_data
crop_trace	rule_type
force_sentreturnr   c                 C   s   d S N )selfr   r   r   r   r"   r"   W/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/appsec/_asm_request_context.py__call__&   s   zWafCallable.__call__NNNF)	__name__
__module____qualname__r   dictstrr   boolr%   r"   r"   r"   r$   r   %   s     r   c                   @   s(   e Zd ZdZdZdZdZdZdZdZ	dS )	WARNING_TAGSz%asm_context::ASM_Environment::no_spanz+asm_context::set_blocked::no_active_contextz,asm_context::set_waf_info::no_active_contextz'asm_context::call_waf_callback::not_setz(asm_context::block_request::not_callablez-asm_context::get_data_sent::no_active_contextz6asm_context::store_waf_results_data::no_active_contextN)
r'   r(   r)   ASM_ENV_NO_SPANSET_BLOCKED_NO_ASM_CONTEXTSET_WAF_INFO_NO_ASM_CONTEXTCALL_WAF_CALLBACK_NOT_SETBLOCK_REQUEST_NOT_CALLABLEGET_DATA_SENT_NO_ASM_CONTEXT STORE_WAF_RESULTS_NO_ASM_CONTEXTr"   r"   r"   r$   r-   /   s    r-   )	metaclassappsec   )productstack_limit
exec_limit_asm_env_ASM_CONTEXTwaf_addresses_WAF_ADDRESSES	callbacks
_CALLBACKS	telemetry
_TELEMETRYcontext_CONTEXT_CALLblock_BLOCK_CALLGLOBAL_CALLBACKSerrormessager    c                 C   s.   t  }|sd S |tj|  |tj| d S r!   )get_entry_span_set_tag_strr   
ERROR_TYPEERROR_MESSAGE)rH   rI   
entry_spanr"   r"   r$   report_error_on_entry_spanN   s
   rO   c                   @   s4   e Zd ZdZ		d	dee dee defddZdS )
ASM_Environmentz
    an object of this class contains all asm data (waf and telemetry)
    for a single request. It is bound to a single asm request context.
    It is contained into a ContextVar.
    N waf_callablespanrc_productsc                 C   s   t   | _| jrtt |pt }|d u r$tjtj	t
dd td|| _| jj| _| jjdr=| jjd d | _n| jj| _| j dd| _d | _i | _|| _i | _t | _t | _g | _d | _d| _d	| _|| _ d	| _!d S )
NTextra
stack_infozASM_Environment requires a spanz.requesti _Fr   )"in_asm_contextrootr   add_suppress_exceptionr   get_root_spanloggerwarningr-   r.   	log_extra	TypeErrorrS   _service_entry_spanrN   nameendswith	frameworklowerreplacewaf_infor=   rR   r?   r   rA   setaddresses_sentwaf_triggersblocked	finalizedapi_security_reportedrT   downstream_requests)r#   rR   rS   rT   context_spanr"   r"   r$   __init__]   s2   




zASM_Environment.__init__NrQ   )	r'   r(   r)   __doc__r   r   r   r+   rq   r"   r"   r"   r$   rP   V   s    	rP   c                   C   s
   t tS r!   r   	find_itemr<   r"   r"   r"   r$   _get_asm_context   s   
rv   c                  C   s6   t  } | d u s
| jrddd}tjd|dd d S | S )Nr6   r7   )r8   r9   z)asm_context::get_value::no_active_contextTrU   )rv   rm   r^   debug)envrV   r"   r"   r$   get_active_asm_context   s   
ry   c                   C   s   t td uS r!   rt   r"   r"   r"   r$   rZ         rZ   c                  C   s   t  } | d u r	dS | jd uS NFrv   rl   rx   r"   r"   r$   
is_blocked      
r~   c                  C   s   t  } | d u r	d S | jpd S r!   r|   r}   r"   r"   r$   get_blocked   r   r   c                  C   s.   t  } | d u rt }|r|jS t S | jS r!   )rv   r   get_spanrb   r]   rN   )rx   rS   r"   r"   r$   rJ      s   rJ   l     ~fq	 KNUTH_FACTORl    
UINT64_MAXc                   @   s0   e Zd ZU dZeed< eeje Z	eed< dS )DownstreamRequestsr   countersampling_rateN)
r'   r(   r)   r   int__annotations__
asm_config_dr_sample_rater   r   r"   r"   r"   r$   r      s   
 r   rx   c                 C   s.   t  jd7  _| jtjk ot jt t t jkS )z*Check if we should analyze body for API10.   )r   r   ro   r   _dr_body_limit_per_requestr   r   r   r}   r"   r"   r$   should_analyze_body_response   s   r   c                  C   s   t  } | d u r	dS | jS rr   )rv   re   r}   r"   r"   r$   get_framework   s   r   headersc              	   C   sP  |  d|  dd}|sdS d}d}|d}|D ]}t|dkr"qtd| }|r|d	d
krJt|tdt	|ddu rAdn|d}q|d	dkrht|tdt	|ddu r_dn|d}q|d	dkrt|tdt	|ddu r}dn|d}q|d	dkrt|tdt	|ddu rdn|d}q||kS )zmdecide if the response should be html or json.

    Add support for quality values in the Accept header.
    AcceptacceptrQ   F        ,   z'([^/;]+/[^/;]+)(?:;q=([01](?:\.\d*)?))?r   	text/htmlg      ?   Nztext/*g?zapplication/jsonzapplication/*)
getsplitlenrematchstripgroupmaxminfloat)r   ctype
html_score
json_scorectypesctmr"   r"   r$   	_use_html   s*   
...,r   block_configc                 C   s<   t  }|du r	dS | jdkrt|s| jdkrd| _dS dS )zJcompute MIME type of the blocked response and store it in the block configNautohtmlr   )get_headerstyper   content_type)r   r   r"   r"   r$   _ctype_from_headers   s   
r   rl   c                 C   s6   t  }|d u rtjtjtdd d S t|  | |_d S NTrU   )rv   r^   r_   r-   r/   r`   r   rl   )rl   rx   r"   r"   r$   set_blocked   s   
r   c                 C   s:   t | trtdi | }n
| d u rt }n| }t| d S )Nr"   )
isinstancer*   r   r   )rE   rl   r"   r"   r$   set_blocked_dict   s   
r   rS   rc   valuec                 C   s   |  ||| |p
d  d S )Nr   )
set_metric
get_metric)rS   rc   r   r"   r"   r$   update_span_metrics   s   r   c                 C   s  ddl m} | j}| jrbt|}|d ur|| j n| j}tjr+|t	j
d|i n|t	jtjd|idd |j}|d ur_t|r_tjrQ|t	j
d|i n|t	jtjd|idd g | _| j}|t	j| | jrwt|t	j| j |jrt|t	j|j d|_t|t	j|j d|_|jrt|t	j|j t|jj }|rt|t	j | |jj!rt|t	j"|jj t|t	j#|jj t|t	j$|jj! |j%j&r|'t	j(t)|j%j& |j%j*r|'t	j+t)|j%j* |j%j,r|'t	j-t)|j%j, d S d S )Nr   )ddwaf_versiontriggers)r   :)
separatorsr   ).ddtrace.appsec._metricsr   rN   rk   r   extendr   _use_metastruct_for_triggers_set_struct_tagr   STRUCTset_tagJSONjsondumps_parentr   rA   rK   WAF_VERSIONro   r   DOWNSTREAM_REQUESTStotal_durationWAF_DURATIONdurationWAF_DURATION_EXTtimeoutWAF_TIMEOUTSsumraspvaluesRASP_TIMEOUTSsum_evalRASP_DURATIONRASP_DURATION_EXTRASP_RULE_EVAL
truncationstring_lengthr   TRUNCATION_STRING_LENGTHr   container_sizeTRUNCATION_CONTAINER_SIZEcontainer_depthTRUNCATION_CONTAINER_DEPTH)rx   r   rN   report_listparenttelemetry_resultsrasp_timeoutsr"   r"   r$   flush_waf_triggers   sR   r   c                 C   sp  | j rd S d| _ tt D ]}||  qt|  t| j | j}|r| jrn|  }z4|jrC|	t
j|j d|jdd}tjd|dd |	t
j|j |t
j|j |t
j|j W n tym   tjdtdd Y nw tjd ur{|t
jtj | j}|tji }|rt||d	d
 |tj i }|rt||dd
 | j!r|	t
j"| j! | j#$  d | _%t&'t( d S )NTr6   r7   r8   	more_infor9   z)asm_context::finalize_asm_env::waf_errorsrU   z(asm_context::finalize_asm_env::exception)rV   exc_inforequest)kindresponse))rm   rG   rD   r   r   rA   rN   rh   errorsrK   r   EVENT_RULE_ERRORSr^   rw   EVENT_RULE_VERSIONversionr   EVENT_RULE_LOADEDloadedEVENT_RULE_ERROR_COUNTfailed	Exceptionr`   r   _rc_client_idr   RC_CLIENT_IDr=   r   r   REQUEST_HEADERS_NO_COOKIES_set_headersRESPONSE_HEADERS_NO_COOKIESrT   RC_PRODUCTSr?   clearrR   r   discard_local_itemr<   )rx   functionrN   inforV   waf_adressesreq_headersres_headersr"   r"   r$   finalize_asm_env1  sH   



r   categoryaddressc                 C   s^   t  }|d u rdd|  d| dd}tjd|dd d S t|| d }|d ur-|||< d S d S )Nr6   z::r7   r   z)asm_context::set_value::no_active_contextTrU   )rv   r^   rw   getattr)r   r   r   rx   rV   asm_context_attrr"   r"   r$   	set_valueY  s   r  c                 C      | d urt tj|  d S d S r!   )set_waf_addressr   r   r   r"   r"   r$   set_headers_responsed     r  body_responsec                    sV   ddl m t d u rdddd}tjd|dd	 d S ttj fd
d d S )Nr   )parse_response_bodyr6   z::set_body_responser7   r   z1asm_context::set_body_response::no_active_contextTrU   c                      s    j tjd S r!   )r=   r   r   r   r"   r  rx   r	  r"   r$   <lambda>u  s    z#set_body_response.<locals>.<lambda>)ddtrace.appsec._utilsr	  rv   r^   rw   r  r   RESPONSE_BODY)r  rV   r"   r
  r$   set_body_responsei  s   r  c                 C   sx   | t jkr$t|}tjddg|dd  R  }t|}tt| | ntt| | | t jt j	fv r:t
| | d S d S )NrQ   r   )r   REQUEST_URI_RAWr   urlparseParseResult
urlunparser  r>   REQUEST_HTTP_IPREQUEST_HEADERS_NO_COOKIES_CASEr   set_item)r   r   parse_address	no_scheme	waf_valuer"   r"   r$   r  |  s   


r  defaultc                 C   s6   t  }|d u r	|S t|| d }|d ur|||S |S r!   )ry   r   r   )r   r   r  rx   r  r"   r"   r$   	get_value  s   r  c                 C   s   t t| |dS )N)r  )r  r>   )r   r  r"   r"   r$   get_waf_address  rz   r  Fr   global_callbackc                 C   s"   |rt tg }||  d S d S r!   )rG   
setdefaultrD   appendr   r  r?   r"   r"   r$   add_context_callback  s   r   c                    s<   |rt t}|rt fdd|D |d d < d S d S d S )Nc                    s   g | ]}| kr|qS r"   r"   ).0cbr   r"   r$   
<listcomp>  s    z+remove_context_callback.<locals>.<listcomp>)rG   r   rD   listr  r"   r#  r$   remove_context_callback  s   
"r&  r   r   c                 C   s.   t  }|d u rtjtjtdd d S | |_d S r   )rv   r^   r_   r-   r0   r`   rh   )r   rx   r"   r"   r$   set_waf_info  s
   
r'  r   r   r   r   r   c                 C   sT   t jsd S t }|d ur|jd ur|| |||S tjtjtdd t	dtj d S )NTrU   z#appsec::instrumentation::diagnostic)
r   _asm_enabledry   rR   r^   r_   r-   r1   r`   rO   )r   r   r   r   rx   r"   r"   r$   call_waf_callback  s   r)  c                  C   s<   t jrt } | r| jjs| j}|r|  dS dS dS dS dS )z.call the waf once if it was not already calledN)r   r(  rv   rA   	triggeredrR   )rx   rR   r"   r"   r$   $call_waf_callback_no_instrumentation  s   
r+  ipc                 C   r  r!   )r  r   r  )r,  r"   r"   r$   set_ip  r  r-  c                   C   s   t ttjS r!   )r  r>   r   r  r"   r"   r"   r$   get_ip  s   r.  c                 C   r  r!   )r  r   r   r  r"   r"   r$   set_headers  r  r/  c                   C   s   t ttji S r!   )r  r>   r   r   r"   r"   r"   r$   r     rz   r   case_sensitivec                 C   s   t tj|  d S r!   )r  r   r  )r0  r"   r"   r$   set_headers_case_sensitive  s   r1  c                   C   s   t ttjdS r{   )r  r>   r   r  r"   r"   r"   r$   get_headers_case_sensitive  rz   r2  	_callablerY   c                 G   s"   t jr| rttt|  dS dS dS )z
    Sets a callable that could be use to do a best-effort to block the request. If
    the callable need any params, like headers, they should be curried with
    functools.partial.
    N)r   r(  r  r@   rF   )r3  rY   r"   r"   r$   set_block_request_callable  s   
r4  c                  C   s.   t tt} | r|   dS tjtjtdd dS )zE
    Calls or returns the stored block request callable, if set.
    TrU   N)r  r@   rF   r^   r_   r-   r2   r`   )r3  r"   r"   r$   block_request  s   

r5  c                  C   s,   t  } | d u rtjtjtdd t S | jS r   )rv   r^   r_   r-   r3   r`   ri   rj   r}   r"   r"   r$   get_data_sent  s
   r6  	remote_ipheaders_case_sensitiveblock_request_callablec                 C   s$   t |  t| t| t| d S r!   )r-  r/  r1  r4  )r7  r   r8  r9  r"   r"   r$   asm_request_context_set  s   r:  rules_versionwaf_results
is_sampledc                 C   s  t  }|d u r	d S |j}t|j}ddlm} | j|O  _|jdk r@|jr/t	|j|j|_n|j|_ddlm
}	 |	|j| | ||j dD ]}
t|j|
}t|tr]t|j|
| qG|d u r| j|O  _| j|O  _| j|j7  _| r}| |_| j|j7  _| j|j7  _d S |j j|O  _|j jd7  _|jj|  d7  < |jj|  t|7  < |jj|  t|j7  < |jj|  |j7  < |j j|j7  _|j j|j7  _d S )Nr   )_report_waf_truncations)_report_waf_run_error)r   r   r   r   )rv   rA   r,   datar   r>  rate_limitedreturn_coderH   r   r?  r   r   r   r   r  r*  rl   r   r   r   runtimer   total_runtimer   r   evalr   	durations)r;  r~   r<  r   r=  rx   resultis_triggeredr>  r?  keyresr"   r"   r$   set_waf_telemetry_results  sF   



rK  c                  C   s   t  } | r| jS d S r!   )rv   rA   r}   r"   r"   r$   get_waf_telemetry_results?  s   rL  r@  c                 C   sR   | sd S t  }|d u rtjtjtdd d S | D ]}|jj|d< q|j	|  d S )NTrU   span_id)
rv   r^   r_   r-   r4   r`   rS   rM  rk   r   )r@  rx   dr"   r"   r$   store_waf_results_dataF  s   rO  rR   rT   c                 C   sJ   t jr#ttt| ||d ttdtdtdtd d S d S )NrR   rS   rT   remote_addrr   r8  r9  )r   r(  r   r  r<   rP   r:  get_itemrP  r"   r"   r$   start_contextR  s    rS  c                 C   s,   t  }|d ur|j| u rt| d S d S d S r!   )rv   rS   r   )rS   rx   r"   r"   r$   end_contexte  s   rT  ctx	_exc_infoc                 C   s"   |  t}|d urt| d S d S r!   )rR  r<   r   )rU  rV  rx   r"   r"   r$   _on_context_endedk  s   
rW  r   c                 G   s^   t jsd S t jr)|rt|trt| }nt|}t| | r+t jr-t	|  d S d S d S d S r!   )
r   r(  _api_security_feature_activer   r*   r%  itemsr  !_api_security_parse_response_bodyr  )r   r   rY   list_headersr"   r"   r$   _set_headers_and_responset  s   

r\  integrationc                 G   ,   t jsd S |  d}tj|td t  d S )Nz::srb_on_requestrV   r   r(  r^   rw   r`   r)  r]  rY   r   r"   r"   r$   _call_waf_first  
   

rb  c                 G   r^  )Nz::srb_on_responser_  r`  ra  r"   r"   r$   	_call_waf  rc  rd  c                   C   s   t jrt S d S r!   )r   r(  r   r"   r"   r"   r$   _get_headers_if_appsec  s   re  >   cf-ray
user-agentcontent-typex-sigsci-tagsx-amzn-trace-idakamai-user-riskx-appgw-trace-idx-sigsci-requestidx-cloud-trace-context!cloudfront-viewer-ja3-fingerprintr   >   	x-real-ipx-client-ipx-forwardedforwarded-forcontent-lengthtrue-client-ipaccept-encodingaccept-languagex-forwarded-forcf-connecting-ipcontent-encodingcontent-languagefastly-client-ipcf-connecting-ipv6x-cluster-client-ipviahost	forwardedr   only_asm_enabledc                 C   sz   |D ]8}t |tr|\}}n||| }}t |tr| }t |tr'| }| |r.tntv r:| t||| qd S r!   )	r   tuplebytesdecoderf   &_COLLECTED_REQUEST_HEADERS_ASM_ENABLED_COLLECTED_REQUEST_HEADERSr   r   )rS   r   r   r  krI  r   r"   r"   r$   r     s   



r   c                   C   s   t dt t dtd d S )Nzasm.set_blockedzasm.get_blockedr   )r   onr   r   r"   r"   r"   r$   
asm_listen  s   r  r!   )Fr&   )r    N)NNFN)collections.abcr   r   r   typesr   typingr   r   r   r   r   r	   r
   urllibr   ddtrace._trace.spanr   ddtrace.appsec._constantsr   r   r   r   r   r  r   r   r   r   )ddtrace.contrib.internal.trace_utils_baser   ddtrace.internalr   ddtrace.internal._exceptionsr   ddtrace.internal.loggerinternalr^   ddloggerddtrace.internal.settings.asmr   r   r   r   
get_loggerr'   r   r-   rY   tagset_tag_rate_limitDAYr`   r<   r   r>   r@   rB   rD   rF   rG   r*   r+   r%  rO   rP   rv   ry   r,   rZ   r~   r   rJ   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r   r&  r'  r)  r+  r-  r.  r/  r   r1  r2  r4  r5  ri   r6  r:  rK  rL  rO  rS  rT  r  r   BaseExceptionrW  r\  rb  rd  re  r  r  updater   r  r"   r"   r"   r$   <module>   s    

*			$	"
2(
""	


	"

	

1
	
 