Ë
    ÛJêjJ)  ã                  ó¾   — d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
mZ ddlmZ ddlZddlmZmZ ddlmZ ddlmZmZmZmZmZmZ ddlmZ d	Zdd
„Z G d„ d«      Z y)zïProperty-based tests for the EgressGate with hypothesis.

Every property is a fail-closed guarantee: for ANY combination of
provider, classifications and destination, the gate never grants egress
that the policy does not explicitly allow.
é    )ÚannotationsN)ÚPath)ÚgivenÚsettings)ÚSQLiteDatabase)ÚAuditLogÚDataClassificationÚ
EgressGateÚEgressPolicyÚEgressRequestÚSecurityError)ÚEgressPermissionGatei,  c                óZ  — t        | j                  «      xs t        | j                  «      }|sddg}t        j                  |«      }t        j
                  t        j                  t        t        «      «      d¬«      }t        j                  g d¢«      }t        j                  |||«      S )zBStrategy that can emit any realistic request for the given policy.Úunknown_providerÚremoteT)Úunique)úhttp://localhostzhttps://example.comzhttp://127.0.0.1:9000zhttps://example.com?q=1#frag)ÚlistÚallowed_remote_providersÚlocal_provider_idsÚstÚsampled_fromÚlistsr	   Útuples)ÚpolicyÚprovider_namesÚ	providersÚclassificationsÚdestinationss        úA/home/oem/CyberBrain26-unified/tests/test_egress_gate_property.pyÚegress_requests_for_policyr!       s…   € ä˜&×9Ñ9Ó:Ò]¼dÀ6×C\ÑC\Ó>]€NÙð -¨hÐ7ˆÜ—‘ Ó/€IÜ—h‘hœrŸ™¬tÔ4FÓ/GÓHÐQUÔV€OÜ—?‘?Úló€Lô �9‰9�Y °Ó>Ð>ó    c                  ó€  — e Zd ZdZ eed¬«       e e e«       «      «      	 	 	 	 dd„«       «       Z	 eed¬«       e e
j                   ee«      «      «      dd„«       «       Z eed¬«       e e
j                   e
j                   ee«      «      ddd¬	«      «      	 	 	 	 dd
„«       «       Z eed¬«       e e
j                  ddg«       e
j                   e
j                   ee«      «      ddd¬	«      «      	 	 	 	 	 	 dd„«       «       Z eed¬«       e e
j                   ee«      «      «      dd„«       «       Zy)ÚTestEgressGatePropertyzDFail-closed guarantees for ANY request, not just pre-selected cases.iˆ  )Úmax_examplesÚdeadlinec                ó€  — |\  }}}t        j                  «       5 }t        t        t	        |«      dz  «      ¬«      }t        «       }t        ||d¬«      }t        j                  t        «      5  |j                  t        d|dt        |«      |¬«      «       ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)	z?A gate with no provider allowlist denies EVERY request, always.zegress.sqlite3©ÚdatabaseT©Ú	audit_logÚbase_decisionúagent-0Ú@0000000000000000000000000000000000000000000000000000000000000000©Úagent_idÚprovider_idÚpayload_sha256r   ÚdestinationN)ÚtempfileÚTemporaryDirectoryr   r   r   r   r
   ÚpytestÚraisesr   Ú	authorizer   Ú	frozenset)	ÚselfÚparamsÚproviderr   r3   Útmp_dirÚauditr   Úgates	            r    Ú test_no_bypass_when_no_allowlistz7TestEgressGateProperty.test_no_bypass_when_no_allowlist2   s¯   € ð 28Ñ.ˆ�/ ;Ü×(Ñ(Ó*ð 	¨gÜ¤n´T¸'³]ÐEUÑ5UÓ&VÔWˆEÜ!“^ˆFÜ˜f°ÀTÔJˆDÜ—‘œ}Ó-ñ 	Ø—‘Ü!Ø!*Ø$,Ø'/Ü(1°/Ó(BØ$/ôô÷	÷		ð 	÷	ð 	ú÷		ð 	ús$   ›AB4Á.)B(ÂB4Â(B1	Â-B4Â4B=c                ó>  — t        j                  «       5 }t        t        j                  t        j
                  h«      }t        t        t        |«      dz  «      ¬«      }t        t        dh«      |¬«      }t        ||d¬«      }||v r*|j                  t        dddt        |h«      d	¬
«      «       nKt        j                  t        «      5  |j                  t        dddt        |h«      d	¬
«      «       ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)zKFor ANY classification, it is accepted iff the policy explicitly allows it.zclassification_boundary.dbr(   r   ©r   Úallowed_remote_classificationsTr*   r-   r.   r   r/   N)r4   r5   r9   r	   ÚPUBLICÚPERSONALr   r   r   r   r
   r8   r   r6   r7   r   )r:   Úclsr=   Úallowedr>   r   r?   s          r    Ú(test_classification_boundary_is_enforcedz?TestEgressGateProperty.test_classification_boundary_is_enforcedH   s  € ô ×(Ñ(Ó*ð 	¨gÜÔ!3×!:Ñ!:Ô<N×<WÑ<WÐ XÓYˆGÜ¤n´T¸'³]ÐEaÑ5aÓ&bÔcˆEÜ!Ü)2°H°:Ó)>Ø/6ôˆFô ˜f°ÀTÔJˆDØ�g‰~Ø—‘Ü!Ø!*Ø$,Ø'/Ü(1°3°%Ó(8Ø$6ôõô —]‘]¤=Ó1ñ 	Ø—N‘NÜ%Ø%.Ø(0Ø+3Ü,5°s°eÓ,<Ø(:ôô÷	÷'	ð 	÷&	ð 	ú÷'	ð 	ús$   •B7DÃ*DÃ6DÄD	ÄDÄDTé   é   )r   Úmin_sizeÚmax_sizec                ó8  — t        j                  «       5 }t        t        t	        |«      dz  «      ¬«      }t        t        dh«      t        t        j                  h«      ¬«      }t        ||d¬«      }t        d„ |D «       «      r)|j                  t        ddd	t        |«      d
¬«      «       nLt        j                  t        d¬«      5  |j                  t        ddd	t        |«      d
¬«      «       ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)zKFor ANY combination of classification sets, a disallowed class is rejected.zdisallowed_combinations.dbr(   r   rB   Tr*   c              3  óB   K  — | ]  }|t         j                  hv –— Œ y ­w©N)r	   rD   )Ú.0Úcs     r    ú	<genexpr>zbTestEgressGateProperty.test_disallowed_classification_combinations_are_rejected.<locals>.<genexpr>w   s   è ø€ ÒE¸�1Ô+×2Ñ2Ð3Ô3ÑEùs   ‚r-   r.   r   r/   zremote classifications denied©ÚmatchN)r4   r5   r   r   r   r   r9   r	   rD   r
   Úallr8   r   r6   r7   r   )r:   Úclassesr=   r>   r   r?   s         r    Ú8test_disallowed_classification_combinations_are_rejectedzOTestEgressGateProperty.test_disallowed_classification_combinations_are_rejectedj   sÿ   € ô ×(Ñ(Ó*ð 	¨gÜ¤n´T¸'³]ÐEaÑ5aÓ&bÔcˆEÜ!Ü)2°H°:Ó)>Ü/8Ô:L×:SÑ:SÐ9TÓ/UôˆFô ˜f°ÀTÔJˆDÜÑE¸WÔEÔEØ—‘Ü!Ø!*Ø$,Ø'/Ü(1°'Ó(:Ø$6ôõô —]‘]¤=Ð8WÔXñ 	Ø—N‘NÜ%Ø%.Ø(0Ø+3Ü,5°gÓ,>Ø(:ôô÷	÷%	ð 	÷$	ð 	ú÷%	ð 	ús$   •B5DÃ
)DÃ3DÄD	Ä	DÄDFc                óö  ‡— t        j                  «       5 }t        t        t	        |«      dz  «      ¬«      }t        t        dh«      t        t        j                  h«      t        dh«      t        t        j                  t        j                  t        j                  h«      ¬«      }t        ||¬«      }t        |¬«      |_        |r¹t        j                  t        j                  t        j                  hŠt        ˆfd„|D «       «      r)|j                  t!        d	dd
t        |«      d¬«      «       n™t#        j$                  t&        d¬«      5  |j                  t!        d	dd
t        |«      d¬«      «       d d d «       nLt#        j$                  t&        d¬«      5  |j                  t!        d	dd
t        |«      d¬«      «       d d d «       d d d «       y # 1 sw Y   ŒxY w# 1 sw Y   ŒxY w# 1 sw Y   y xY w)Nzfail_closed_overrides.dbr(   r   Úlocal)r   rC   r   Úallowed_local_classifications)r+   )r,   c              3  ó&   •K  — | ]  }|‰v –— Œ
 y ­wrO   © )rP   rQ   Úallowed_locals     €r    rR   zXTestEgressGateProperty.test_fail_closed_overrides_all_classifications.<locals>.<genexpr>¤   s   øè ø€ Ò;¨a�q˜MÔ)Ñ;ùs   ƒr-   r.   r   r/   zlocal classifications deniedrS   zegress permission denied)r4   r5   r   r   r   r   r9   r	   rD   rE   Ú	SENSITIVEr
   r   Úegress_permission_gaterU   r8   r   r6   r7   r   )r:   r,   rV   r=   r>   r   r?   r]   s          @r    Ú.test_fail_closed_overrides_all_classificationszETestEgressGateProperty.test_fail_closed_overrides_all_classifications�   s·  ø€ ô
 ×(Ñ(Ó*ð 1	¨gÜ¤n´T¸'³]ÐE_Ñ5_Ó&`ÔaˆEÜ!Ü)2°H°:Ó)>Ü/8Ô:L×:SÑ:SÐ9TÓ/UÜ#,¨g¨YÓ#7Ü.7Ü'×.Ñ.Ô0B×0KÑ0KÔM_×MiÑMiÐjó/ô	ˆFô ˜f°Ô6ˆDÜ*>È]Ô*[ˆDÔ'Ùä&×-Ñ-Ü&×/Ñ/Ü&×0Ñ0ð!�ô
 Ó;°7Ô;Ô;Ø—N‘NÜ%Ø%.Ø(/Ø+3Ü,5°gÓ,>Ø(:ôõô  Ÿ™¤}Ð<ZÔ[ñ 	ØŸ™Ü)Ø)2Ø,3Ø/7Ü09¸'Ó0BØ,>ôô÷	ð 	ô —]‘]¤=Ð8RÔSñ 	Ø—N‘NÜ%Ø%.Ø(/Ø+3Ü,5°gÓ,>Ø(:ôô÷	÷Q1	ð 1	÷:	ð 	ú÷	ð 	ú÷Q1	ð 1	ús<   –D:G/Å)GÅ9$G/Æ)G#ÇG/ÇG 	ÇG/Ç#G,	Ç(G/Ç/G8c                ó:  — t        j                  «       5 }t        t        t	        |«      dz  «      ¬«      }t        t        j                  h«      }t        t        t        dh«      |¬«      |d¬«      }|t        j                  k(  r*|j                  t        dddt        |h«      d	¬
«      «       nKt        j                  t        «      5  |j                  t        dddt        |h«      d	¬
«      «       ddd«       ddd«       y# 1 sw Y   ŒxY w# 1 sw Y   yxY w)zBLocal and remote classification gates are evaluated independently.zlocal_vs_remote.dbr(   rY   )r   rZ   Tr*   r-   r.   r   r/   N)r4   r5   r   r   r   r9   r	   rD   r
   r   r8   r   r6   r7   r   )r:   rF   r=   r>   Úlocal_allowedr?   s         r    Ú6test_local_classification_gate_independent_from_remotezMTestEgressGateProperty.test_local_classification_gate_independent_from_remoteÅ   s  € ô ×(Ñ(Ó*ð 	¨gÜ¤n´T¸'³]ÐEYÑ5YÓ&ZÔ[ˆEÜ%Ô'9×'@Ñ'@Ð&AÓBˆMÜÜÜ'0°'°Ó';Ø2?ôð  Ø"ôˆDð Ô(×/Ñ/Ò/Ø—‘Ü!Ø!*Ø$+Ø'/Ü(1°3°%Ó(8Ø$6ôõô —]‘]¤=Ó1ñ 	Ø—N‘NÜ%Ø%.Ø(/Ø+3Ü,5°s°eÓ,<Ø(:ôô÷	÷-	ð 	÷,	ð 	ú÷-	ð 	ús$   •B5DÃ
*DÃ4DÄD	Ä
DÄDN)r;   z)tuple[str, list[DataClassification], str]ÚreturnÚNone)rF   r	   rd   re   )rV   úlist[DataClassification]rd   re   )r,   ÚboolrV   rf   rd   re   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚMAX_EXAMPLESr   r!   r   r@   r   r   r   r	   rH   r   rW   r`   rc   r\   r"   r    r$   r$   /   s–  „ ÙNá˜<°$Ô7Ù
Ñ%¡l£nÓ5Ó6ðØ?ðà	òó 7ó 8ðñ( ˜<°$Ô7Ù
ˆ?ˆ2�?‰?™4Ð 2Ó3Ó4Ó5òó 6ó 8ðñ@ ˜<°$Ô7Ù
ˆ8ˆ2�8‰8�O�B—O‘O¡DÐ);Ó$<Ó=ÀdÐUVÐabÔcÓdðØ/ðà	òó eó 8ðñB ˜<°$Ô7Ù
ˆ?ˆ2�?‰?˜D %˜=Ó)¨8¨2¯8©8°O°B·O±OÁDÐI[ÓD\Ó4]ÐfjÐuvð  BCô  ,Dó  Eð4Ø!ð4Ø,Dð4à	ò4ó Eó 8ð4ñl ˜<°$Ô7Ù
ˆ?ˆ2�?‰?™4Ð 2Ó3Ó4Ó5ò!ó 6ó 8ñ!r"   r$   )r   r   )!rk   Ú
__future__r   ÚbuiltinsÚ@py_builtinsÚ_pytest.assertion.rewriteÚ	assertionÚrewriteÚ
@pytest_arr4   Úpathlibr   Úhypothesis.strategiesÚ
strategiesr   r6   Ú
hypothesisr   r   Úcyberbrain26.data_planer   Úcyberbrain26.security_planer   r	   r
   r   r   r   Ú,cyberbrain26.security_plane.extension_pointsr   rl   r!   r$   r\   r"   r    ú<module>r{      sM   ðñõ #ç  „ ƒÝ å "Û ß &å 2÷÷ õ Nð €ó?÷yò yr"   