Ë
    ÛJêjÞ:  ã                  ón  — U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZ ddlmZmZ  ej4                  e«      Z G d„ dee«      Z G d„ dee«      Ze	 G d„ d«      «       Z e	 G d„ d«      «       Z!e	 G d„ d«      «       Z" G d„ de#«      Z$dZ%dZ& e'h d£«      Z( e'dh«      Z)ejT                  ejV                  ejX                  ejZ                  ej\                  ej^                  ej`                  ejb                  ejd                  ejf                  ejh                  ejj                  ejl                  d„ ejn                  d„ ejp                  ejr                  ejt                  ejv                  i
Z<de=d<   ej|                  ej~                  ej€                  ej‚                  ej„                  ej†                  ejˆ                  ejŠ                  ejŒ                  ejŽ                  ej�                  f eIe<«      z   ZJd&d „ZKd'd!„ZLd(d"„ZM G d#„ d$«      ZNg d%¢ZOy))u  Policy Engine â€” Default Deny policy evaluation for CyberBrain26.

Core principle: DEFAULT DENY. Nothing sensitive is allowed just because an agent wants it.

Policy modes:
- SAFE: no risky automatic execution, sensitive operations require approval, limited tools
- FULL: higher automation, read-only operations may be automatic, risky write/execute require control
- RESEARCH: experimental models, detailed logging, sandbox, limited network
- RED_TEAM_LAB: isolated test environment, synthetic credentials, no production access
é    )ÚannotationsN)ÚCallable)Ú	dataclassÚfield)ÚEnum)ÚAny)ÚSENSITIVE_ACTIONS)Úis_registered_actionÚnormalize_action)ÚAuditEventTypeÚAuditLog)ÚAgentIdentityÚ
TrustLevelc                  ó   — e Zd ZdZdZdZdZy)ÚPolicyDecisionzOutcome of a policy evaluation.ÚallowÚdenyÚrequire_approvalN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚALLOWÚDENYÚREQUIRE_APPROVAL© ó    úQ/home/oem/CyberBrain26-unified/src/cyberbrain26/security_plane/policy/__init__.pyr   r   #   s   „ Ù)à€EØ€DØ)Ñr   r   c                  ó    — e Zd ZdZdZdZdZdZy)Ú
PolicyModezSystem-wide policy modes.ÚsafeÚfullÚresearchÚred_team_labN)r   r   r   r   ÚSAFEÚFULLÚRESEARCHÚRED_TEAM_LABr   r   r   r    r    +   s   „ Ù#à€DØ€DØ€HØ!�Lr   r    c                  ó„   — e Zd ZU dZded<   dZded<    ee¬«      Zded	<   d
Z	ded<   e
j                  Zded<   dZded<   y)ÚPolicyContextz1Context in which a policy decision is being made.ÚstrÚactionNú
str | NoneÚresource)Údefault_factoryzdict[str, Any]Úenvironmentg        ÚfloatÚ
risk_scorer    Úmodezfloat | NoneÚ	timestamp)r   r   r   r   Ú__annotations__r.   r   Údictr0   r2   r    r%   r3   r4   r   r   r   r*   r*   4   sE   … á;àƒKØ€HˆjÓÙ"'¸Ô"=€K�Ó=Ø€J�ÓØ!—‘€Dˆ*Ó&Ø"€Iˆ|Ô"r   r*   c                  óZ   — e Zd ZU dZded<   ded<   ded<   dZded	<   d
Zded<   d
Zded<   y)Ú
PolicyRulezA single policy rule.r+   ÚnameÚaction_patternr   ÚdecisionNr-   Ú	conditionÚ ÚdescriptionÚreason)r   r   r   r   r5   r<   r>   r?   r   r   r   r8   r8   @   s4   … áà
ƒIØÓØÓØ €IˆzÓ Ø€K�ÓØ€FˆCÔr   r8   c                  óT   — e Zd ZU dZded<   dZded<   dZded	<   d
Zded<   dZded<   y)ÚPolicyEvaluationzResult of a policy evaluation.r   r;   Nr-   Úruler=   r+   r?   FÚboolÚrequires_approvalúPolicyContext | NoneÚcontext)	r   r   r   r   r5   rB   r?   rD   rF   r   r   r   rA   rA   L   s5   … á(àÓØ€Dˆ*ÓØ€FˆCÓØ#Ð�tÓ#Ø$(€GÐ!Ô(r   rA   c                  ó   — e Zd ZdZy)ÚPolicyConditionErroru3   NeplatnÃ½ nebo nedovolenÃ½ vÃ½raz policy podmÃ­nky.N)r   r   r   r   r   r   r   rH   rH   W   s   „ Ú=r   rH   é   é2   >   r3   r,   rF   Úidentityr2   Úis_sensitiver	   rL   c                ó.   — t        j                  || «      S ©N©ÚoperatorÚcontains©ÚaÚbs     r   ú<lambda>rU   j   s   € œ×*Ñ*¨1¨aÓ0€ r   c                ó0   — t        j                  || «       S rN   rO   rR   s     r   rU   rU   k   s   € ¤× 1Ñ 1°!°QÓ 7Ð7€ r   z/dict[type[ast.AST], Callable[[Any, Any], bool]]Ú_COMPARATORSc                óš   — t        j                  | «      D ]3  }t        |t        «      rŒt	        dt        |«      j                  › �«      ‚ y)uI   AllowlistovÃ¡ kontrola AST â€” cokoliv mimo povolenÃ© uzly je odmÃ­tnuto.údisallowed expression node: N)ÚastÚwalkÚ
isinstanceÚ_ALLOWED_NODESrH   Útyper   )ÚtreeÚnodes     r   Ú_validate_condition_astra   v   sC   € ä—‘˜“ò ]ˆÜ˜$¤Õ/Ü&Ð)EÄdÈ4Ãj×FYÑFYÐEZÐ'[Ó\Ð\ñ]r   c           	     ó  — t        | t        j                  «      r| j                  S t        | t        j                  «      rG| j
                  t        vs| j
                  |vrt        d| j
                  › �«      ‚|| j
                     S t        | t        j                  «      rÅt        | j                  t        j                  «      r| j                  j
                  t        vrt        d«      ‚| j                  st        | dd «      rt        d«      ‚|| j                  j
                     }t        |«      st        d«      ‚ || j                  D �cg c]  }t        ||«      ‘Œ c}Ž S t        | t        j                   «      r]| j"                  D �cg c]  }t        ||«      ‘Œ }}t        | j$                  t        j&                  «      rt)        |«      S t+        |«      S t        | t        j,                  «      rFt        | j$                  t        j.                  «      st        d«      ‚t        | j0                  |«       S t        | t        j2                  «      rƒt        | j4                  |«      }t7        | j8                  | j:                  «      D ]I  \  }}t<        j?                  tA        |«      «      }	|	€t        d«      ‚t        ||«      }
 |	||
«      s y|
}ŒK y	t        d
tA        | «      jB                  › �«      ‚c c}w c c}w )Nzname not allowed: zcall not allowedÚstarargszcall arguments not allowedzcallable not allowedzunary operator not allowedzcomparison not allowedFTrY   )"r\   rZ   ÚConstantÚvalueÚNameÚidÚALLOWED_CONDITION_NAMESrH   ÚCallÚfuncÚALLOWED_CONDITION_CALLABLESÚkeywordsÚgetattrÚcallableÚargsÚ_eval_ast_nodeÚBoolOpÚvaluesÚopÚAndÚallÚanyÚUnaryOpÚNotÚoperandÚCompareÚleftÚzipÚopsÚcomparatorsrW   Úgetr^   r   )r`   ÚenvÚtargetrS   Úvrr   r{   rs   Ú
comparatorrj   Úrights              r   rp   rp   }   sG  € Ü�$œŸ™Ô%Ø�z‰zÐÜ�$œŸ™Ô!Ø�7‰7Ô1Ñ1°T·W±WÀCÑ5GÜ&Ð);¸D¿G¹G¸9Ð'EÓFÐFØ�4—7‘7‰|ÐÜ�$œŸ™Ô!Ü˜$Ÿ)™)¤S§X¡XÔ.°$·)±)·,±,ÔFaÑ2aÜ&Ð'9Ó:Ð:Ø�=Š=œG D¨*°dÔ;Ü&Ð'CÓDÐDØ�T—Y‘Y—\‘\Ñ"ˆÜ˜ÔÜ&Ð'=Ó>Ð>Ù¸¿	¹	ÖB°1œ q¨#Õ.ÒBÐCÐCÜ�$œŸ
™
Ô#Ø26·+±+Ö>¨Q”.  CÕ(Ð>ˆÐ>Ü(¨¯©´#·'±'Ô:Œs�6‹{ÐKÄÀFÃÐKÜ�$œŸ™Ô$Ü˜$Ÿ'™'¤3§7¡7Ô+Ü&Ð'CÓDÐDÜ! $§,¡,°Ó4Ð4Ð4Ü�$œŸ™Ô$Ü˜dŸi™i¨Ó-ˆÜ! $§(¡(¨D×,<Ñ,<Ó=ò 	‰NˆB�
Ü×#Ñ#¤D¨£HÓ-ˆDØˆ|Ü*Ð+CÓDÐDÜ" :¨sÓ3ˆEÙ˜˜eÔ$ÙØ‰Dð	ð Ü
Ð!=¼dÀ4»j×>QÑ>QÐ=RÐSÓ
TÐTùò' Cùâ>s   ÅK<ÆLc                óV  — t        | «      t        kD  rt        d«      ‚	 t        j                  | d¬«      }t        d„ t        j                  |«      D «       «      t        kD  rt        d«      ‚t        |«       t        |j                  |«      S # t
        $ r}t        d«      |‚d}~ww xY w)u=   BezpeÄ�nÃ© vyhodnocenÃ­ policy podmÃ­nky nad allowlistou AST.zcondition too longÚeval)r3   zinvalid condition syntaxNc              3  ó    K  — | ]  }d –— Œ y­w)é   Nr   )Ú.0Ú_s     r   ú	<genexpr>z%evaluate_condition.<locals>.<genexpr>ª   s   è ø€ Ò
%�Œ1Ñ
%ùs   ‚zcondition too complex)ÚlenÚMAX_CONDITION_LENGTHrH   rZ   ÚparseÚSyntaxErrorÚsumr[   ÚMAX_CONDITION_NODESra   rp   Úbody)r<   r€   r_   Úexcs       r   Úevaluate_conditionr”   ¢   s–   € ä
ˆ9ƒ~Ô,Ò,Ü"Ð#7Ó8Ð8ðHÜ�y‰y˜¨Ô0ˆô Ñ
%”c—h‘h˜t“nÔ
%Ó%Ô(;Ò;Ü"Ð#:Ó;Ð;Ü˜DÔ!Ü˜$Ÿ)™) SÓ)Ð)øô ò HÜ"Ð#=Ó>ÀCÐGûðHús   ŸB Â	B(ÂB#Â#B(c                  óÞ   — e Zd ZU dZeZded<   ej                  dfdd„Z	dd„Z
dd„Zdd„Zdd	„Z	 	 d	 	 	 	 	 	 	 	 	 dd
„Z	 	 	 	 	 	 	 	 	 	 dd„Zdd„Z	 	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 	 	 dd„Zy)ÚPolicyEnginea  Default Deny Policy Engine.

    Evaluates whether an agent identity is permitted to perform an action
    in a given context. Defaults to DENY unless an explicit rule allows it.

    Usage:
        engine = PolicyEngine()
        engine.add_rule(PolicyRule("allow_read", "read_file", PolicyDecision.ALLOW))
        result = engine.evaluate(identity, "read_file", "/etc/passwd")
    zfrozenset[str]r	   Nc                óN   — || _         || _        g | _        | j                  «        y rN   )r3   Ú	audit_logÚ_rulesÚ_load_default_rules)Úselfr3   r˜   s      r   Ú__init__zPolicyEngine.__init__À   s#   € ØˆŒ	Ø"ˆŒØ(*ˆŒØ× Ñ Õ"r   c           
     óf  — t        ddt        j                  d¬«      g| _        | j                  t
        j                  k(  rq| j                  j                  dt        ddt        j                  dd¬	«      «       | j                  j                  dt        d
dt        j                  dd¬	«      «       yy)z/Load the default rule set for the current mode.Údefault_denyÚ*u-   No matching allow rule found â€” default deny)r9   r:   r;   r?   r   Úsafe_mode_non_sensitive_allowedznot is_sensitive(action)z7SAFE mode: non-sensitive actions are allowed by default)r9   r:   r;   r<   r>   Ú%safe_mode_sensitive_requires_approvalzis_sensitive(action)z7SAFE mode: all sensitive actions require human approvalN)
r8   r   r   r™   r3   r    r%   Úinsertr   r   ©r›   s    r   rš   z PolicyEngine._load_default_rulesÆ   s¤   € ô Ø#Ø"Ü'×,Ñ,ØFô	ð
ˆŒð �9‰9œ
Ÿ™Ò'Ø�K‰K×ÑØÜØ:Ø#&Ü+×1Ñ1Ø8Ø Yôô	ð �K‰K×ÑØÜØ@Ø#&Ü+×<Ñ<Ø4Ø Yôõ	ð r   c                ó<   — | j                   j                  d|«       y)zBAdd a policy rule. Rules are evaluated in order; first match wins.r   N)r™   r¢   )r›   rB   s     r   Úadd_rulezPolicyEngine.add_ruleê   s   € à�‰×Ñ˜1˜dÕ#r   c                ó–   — t        | j                  «      D ]1  \  }}|j                  |k(  sŒ| j                  j                  |«        y y)z-Remove a rule by name. Returns True if found.TF)Ú	enumerater™   r9   Úpop)r›   r9   ÚirB   s       r   Úremove_rulezPolicyEngine.remove_ruleî   sB   € ä  §¡Ó-ò 	‰GˆAˆtØ�y‰y˜DÓ Ø—‘—‘ Ô"Ùð	ð r   c                ó,   — t        | j                  «      S )zReturn all registered rules.)Úlistr™   r£   s    r   Ú
list_ruleszPolicyEngine.list_rulesö   s   € ä�D—K‘KÓ Ð r   c                ó*  — t        |«      }|xs t        ||| j                  ¬«      }t        |«      s;t	        t
        j                  dd|xs d› d�|¬«      }| j                  ||||«       |S |j                  t        j                  k(  rAt	        t
        j                  dd|j                  › d	�|¬«      }| j                  ||||«       |S | j                  D ]‡  }| j                  ||||«      sŒ|j                  t
        j                  k(  }	t	        |j                  |j                   |j"                  xs |j$                  |	|¬
«      }| j                  ||||«       |c S  t	        t
        j                  dd|¬«      }| j                  ||||«       |S )a{  Evaluate whether an identity can perform an action.

        Args:
            identity: The agent identity requesting the action.
            action: The action being requested (e.g. "read_file", "execute_shell").
            resource: Optional resource being accessed.
            context: Optional evaluation context (mode, risk_score, environment).

        Returns:
            PolicyEvaluation with decision, rule, reason, and approval flag.

        Security rationale: an unregistered action is denied before any rule is
        evaluated. Rules such as SAFE's ``not is_sensitive(action)`` and
        non-SAFE's describe the *known* vocabulary; applied to
        a name outside it they would turn an invented action into an allowed one.
        The action is canonicalized first so a cosmetic variant cannot select a
        different rule than the action it claims to be.
        )r,   r.   r3   Úunregistered_actionzAction 'z<empty>u2   ' is not a registered action â€” denied by default)r;   rB   r?   rF   Útrust_checkzAgent u(    is UNTRUSTED â€” denied by trust policy)r;   rB   r?   rD   rF   rž   u)   No matching rule â€” default deny applied)r   r*   r3   r
   rA   r   r   Ú_audit_decisionÚtrust_levelr   Ú	UNTRUSTEDÚagent_idr™   Ú_rule_matchesr;   r   r9   r?   r>   )
r›   rK   r,   r.   rF   Úcanonical_actionÚctxÚ
evaluationrB   rD   s
             r   ÚevaluatezPolicyEngine.evaluateú   s¬  € ô2 ,¨FÓ3ÐØÒbœÐ.>ÈÐX\×XaÑXaÔbˆô $Ð$4Ô5Ü)Ü'×,Ñ,Ø*àÐ/Ò<°9Ð=ð >,ð ,ð ôˆJð × Ñ  Ð+;¸XÀzÔRØÐð ×Ñ¤:×#7Ñ#7Ò7Ü)Ü'×,Ñ,Ø"Ø × 1Ñ 1Ð2Ð2ZÐ[Øô	ˆJð × Ñ  Ð+;¸XÀzÔRØÐð —K‘Kò 	"ˆDØ×!Ñ! $Ð(8¸(ÀCÕHØ$(§M¡M´^×5TÑ5TÑ$TÐ!Ü-Ø!Ÿ]™]ØŸ™ØŸ;™;Ò:¨$×*:Ñ*:Ø&7Øô�
ð ×$Ñ$ XÐ/?ÀÈ:ÔVØ!Ò!ð	"ô &Ü#×(Ñ(ØØ>Øô	
ˆ
ð 	×Ñ˜XÐ'7¸À:ÔNØÐr   c           
     óŽ  — | j                   €y| j                  t        j                  k(  xs, |j                  t
        j                  t
        j                  fv }|sy| j                   j                  t        j                  |j                  |j                  ||xs d|j                  j                  |j                  xs d¬«       y)z¢Record a POLICY_DECISION audit event.

        RED_TEAM_LAB mode always logs every decision.
        Other modes log DENY and REQUIRE_APPROVAL decisions.
        Nr=   )Úactorr´   r,   r.   Úpolicy_decisionÚresult)r˜   r3   r    r(   r;   r   r   r   Úrecordr   ÚPOLICY_DECISIONr´   re   rB   )r›   rK   r,   r.   r¸   Ú
should_logs         r   r±   zPolicyEngine._audit_decisionG  s®   € ð �>‰>Ð!Øà—Y‘Y¤*×"9Ñ"9Ñ9ò 
¸Z×=PÑ=PÜ×ÑÜ×+Ñ+ðU
ð >
ˆ
ñ Øà�‰×ÑÜ×*Ñ*Ø×#Ñ#Ø×&Ñ&ØØ’^ Ø&×/Ñ/×5Ñ5Ø—?‘?Ò( bð 	õ 	
r   c                ó0   — t        |«      | j                  v S )a!  Check whether an action is classified as sensitive.

        The name is canonicalized first, because this predicate is reachable
        from policy conditions; without normalization a whitespace or case
        variant would evaluate as non-sensitive and skip the approval gate.
        )r   r	   )r›   r,   s     r   rL   zPolicyEngine.is_sensitiveg  s   € ô   Ó'¨4×+AÑ+AÐAÐAr   c           	     ó.  — |j                   d|fvry|j                  r"	 | j                  |j                  |||«      }|syy# t        t        t
        t        t        t        t        f$ r+}t        j                  d|j                  |«       Y d}~yd}~ww xY w)z=Check whether a rule applies to the given action and context.rŸ   Fz"Condition %r evaluation failed: %sNT)r:   r<   Ú_eval_conditionr�   Ú	NameErrorÚ	TypeErrorÚ
ValueErrorÚAttributeErrorÚMemoryErrorÚRecursionErrorÚloggerÚwarning)r›   rB   r,   rK   rF   Úcond_resultr“   s          r   rµ   zPolicyEngine._rule_matchesp  s‰   € ð ×Ñ s¨F mÑ3Øð �>Š>ðØ"×2Ñ2°4·>±>À6È8ÐU\Ó]�ñ Øàøô  ¤¬I´zÄ>ÔS^Ô`nÐoò Ü—‘ÐCÀTÇ^Á^ÐUXÔYÜûðús   ŸA Á(BÁ)!BÂBc                ó¸   — ||||j                   |j                  | j                  | j                  dœ}t	        ||«      }t        |t        «      st        d«      ‚|S )z'Evaluate a simple condition expression.)r,   rK   rF   r2   r3   rL   r	   zcondition must evaluate to bool)r2   r3   rL   r	   r”   r\   rC   rH   )r›   r<   r,   rK   rF   Ú
local_varsre   s          r   rÃ   zPolicyEngine._eval_condition‡  s_   € ð Ø ØØ!×,Ñ,Ø—L‘LØ ×-Ñ-Ø!%×!7Ñ!7ñ)
ˆ
ô # 9¨jÓ9ˆÜ˜%¤Ô&Ü&Ð'HÓIÐIØˆr   )r3   r    r˜   zAuditLog | NoneÚreturnÚNone)rÏ   rÐ   )rB   r8   rÏ   rÐ   )r9   r+   rÏ   rC   )rÏ   zlist[PolicyRule])NN)
rK   r   r,   r+   r.   r-   rF   rE   rÏ   rA   )
rK   r   r,   r+   r.   r-   r¸   rA   rÏ   rÐ   )r,   r+   rÏ   rC   )
rB   r8   r,   r+   rK   r   rF   r*   rÏ   rC   )
r<   r+   r,   r+   rK   r   rF   r*   rÏ   rC   )r   r   r   r   ÚCANONICAL_SENSITIVE_ACTIONSr	   r5   r    r%   rœ   rš   r¥   rª   r­   r¹   r±   rL   rµ   rÃ   r   r   r   r–   r–   °   s#  … ñ	ð )DÐ�~ÓCà*4¯/©/ÐX\ô #ó"óH$óó!ð  $Ø(,ðKàðKð ðKð ð	Kð
 &ðKð 
óKðZ
àð
ð ð
ð ð	
ð
 %ð
ð 
ó
ó@Bðàðð ðð  ð	ð
 ðð 
óð.àðð ðð  ð	ð
 ðð 
ôr   r–   )r*   r   r–   rA   r    r8   )r_   úast.ASTrÏ   rÐ   )r`   rÒ   r€   údict[str, object]rÏ   Úobject)r<   r+   r€   rÓ   rÏ   rÔ   )Pr   Ú
__future__r   rZ   ÚloggingrP   Úcollections.abcr   Údataclassesr   r   Úenumr   Útypingr   Ú#cyberbrain26.security_plane.actionsr	   rÑ   r
   r   Ú!cyberbrain26.security_plane.auditr   r   Ú$cyberbrain26.security_plane.identityr   r   Ú	getLoggerr   rÊ   r+   r   r    r*   r8   rA   rÆ   rH   r�   r‘   Ú	frozensetrh   rk   ÚEqÚeqÚNotEqÚneÚLtÚltÚLtEÚleÚGtÚgtÚGtEÚgeÚInÚNotInÚIsÚis_ÚIsNotÚis_notrW   r5   Ú
Expressionrq   rt   ÚOrrw   rx   rz   rd   rf   ÚLoadri   Útupler]   ra   rp   r”   r–   Ú__all__r   r   r   ú<module>r÷      sú  ðò	õ #ã 
Û Û Ý $ß (Ý Ý õ÷÷ Gß Jà	ˆ×	Ñ	˜8Ó	$€ô*�S˜$ô *ô"��dô "ð ÷#ð #ó ð#ð ÷ð ó ðð ÷)ð )ó ð)ô>˜:ô >ð Ð ØÐ Ù#ò*óÐ ñ (¨Ð(8Ó9Ð ð ‡F�FˆH�K‰KØ‡I�Iˆx�{‰{Ø‡F�FˆH�K‰KØ‡G�GˆX�[‰[Ø‡F�FˆH�K‰KØ‡G�GˆX�[‰[Ø‡F�FÑ0Ø‡I�IÑ7Ø‡F�FˆH�L‰LØ‡I�Iˆx�‰ðA€Ð=ó ð ‡N�N�C—J‘J §¡¨¯©°·±¸c¿g¹gØ‡K�K�—‘˜sŸx™x¨¯©°3·8±8ðñ 
ˆ,Óñ€ó]ó"UóJ*÷kñ kò\�r   