
    |ƂjS0              	      <   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZ dZdZdZd	Zd
ddddddddZ G d de      Zd"dZd#dZd$dZd%dZd&dZd'dZd(dZd)dZd*dZ d+dZ!d,dZ"d-d Z#e$d!k(  r e% e#             y).zKCreate and verify the local immutable Task26 strict-rerun retention object.    )annotationsN)Path)Anyz#task26-local-immutable-retention-v1z3root-owned-ext4-immutable-content-addressed-copy-v1l   f     @9f5d72840b4cc1fcb57720a61ebc53529fa00202d9201615e4ebdbb3e047a635   @4a6c7ee54cf9526a30de8bb576c1d71b411938beba33a04914738f6e1b6ed1cb@fdcfb1efd1f2d4a2b95f22f7311827d197898a6d480cb572956e87bd66d20361@50e7556e58a876d8136fbfb2023ede8bcb46ac816d97d4b85e1d0559f463d008@84d937ef67c1517bfdbca4cabce9fb4bfbe39aa1165458bb3aedd14decc4bff0@188e9e630b53e9329ae185fc8c007aecb7988c16d174d325d68e8e004edb38e9z task26-current-4a6c7ee5-20260817)archive_root_sha256archive_entry_countcandidate_digestlifecycle_root_sha256lifecycle_seal_sha256v3_seal_sha256v4_seal_sha256run_idc                      e Zd Zy)RetentionErrorN)__name__
__module____qualname__     }/home/cube/projects/richard/traning coach/.omo/evidence/task26/task26-strict-rerun-retention-st_01a00ed5/retention_control.pyr   r   #   s    r   r   c                T    t        j                  | dd      dz   j                         S )NT),:)	sort_keys
separators
)jsondumpsencode)values    r   canonr(   '   s#    JJuDtKSSUUr   c                H    t        j                  |       j                         S N)hashlibsha256	hexdigest)raws    r   shar/   +   s    >>#((**r   c                4    t        | j                               S r*   )r/   
read_bytes)paths    r   file_shar3   /   s    t !!r   c           	        t        j                  | t         j                  t         j                  z  t	        t         dd      z        }	 t        d      }t        j                  |t        |d       t        t        j                  |d      t        z        t        j                  |       S # t        j                  |       w xY w)N
O_NOFOLLOWr      Tlittle)osopenO_RDONLY	O_CLOEXECgetattr	bytearrayfcntlioctlFS_IOC_GETFLAGSboolint
from_bytesFS_IMMUTABLE_FLclose)r2   fdflagss      r   	immutablerH   3   s|    	r{{R\\1GBa4PP	QB!B5CNN5(3oEF
s   	AB+ +Cc                   g }t        j                  | d      D ]3  \  }}}|j                          |j                          |D ]  }t        |      |z  }|j	                         }t        j                  |j                        st        d|       |j                  |j                  |       j                         dt        j                  |j                        dd        |D ]c  }t        |      |z  }|j	                         }t        j                  |j                        r|j                  dk7  rt        d|       |j                         }|j	                         }	|j                   |j"                  |j$                  |j&                  |j(                  f|	j                   |	j"                  |	j$                  |	j&                  |	j(                  fk7  rt        d	|       |j                  |j                  |       j                         d
t        j                  |j                        dt+        |      t-        |      d       f 6 |S )NF)followlinksznon-directory archive entry: D04o)r2   typemode   zunsafe archive file: zarchive changed while reading: F)r2   rM   rN   sizer,   )r8   walksortr   lstatstatS_ISDIRst_moder   appendrelative_toas_posixS_IMODES_ISREGst_nlinkr1   st_devst_inost_sizest_mtime_nsst_ctime_nslenr/   )
rootrowsbasedirsfilesnamer2   str.   afters
             r   source_inventoryrl   =   s   !#DWWTu==dE		

D:$DB<<

+$'DTF%KLLKK!1!1$!7!@!@!BC\`\h\hikisis\tux[y{|  D:$DB<<

+r{{a/?$'<TF%CDD//#CJJLE		299bjj".."..QellEMM5;L;LeN_N_V  %'Ftf%MNNKK((.779<<

3C8Cc(   >6 Kr   c           
         | D cg c]  }dD ci c]  }||v s|||    c} }}}t        t        |            S c c}w c c}}w )N)r2   rM   rN   r,   )r/   r(   )re   rowkeysealed_rowss       r   inventory_rootrq   ]   sa     C #ES"D3s
c#h"DS   u[!"" 	Ts   	A	==AAc                "   | j                         s| j                         st        d      t        |      t        d   k7  rt        d      t        |      t        d   k7  rt        d      t        j                  |j                               }dD ],  }|j                  |      t        |   k7  st        d| d       t        |       }t        |      t        d	   k7  st        |      t        d
   k7  rt        d      t        j                  | dz  j                               }|j                  di       }dD ],  }|j                  |      t        |   k7  st        d| d       |j                  d      t        d   k7  rt        d      |S )Nz&source archive is not a real directoryr   zv3 seal hash mismatchr   zv4 seal hash mismatch)r   r   r   zv3 seal 	 mismatchr   r   z!source archive inventory mismatchzmanifest.jsonbindings)r   r   r   zarchive manifest r   zarchive run_id mismatch)
is_symlinkis_dirr   r3   EXPECTEDr$   loadsr1   getrl   rc   rq   )sourcev3_sealv4_sealsealro   re   manifestrt   s           r   validate_sourcer   e   sp   &--/EFFH%566455H%566455::g((*+DQ88C=HSM) 8C5	!:;; R F#D
4yH233~d7KxXmOn7n@AAzz6O3??ABH||J+HU<<- #4SE!CDD V ||H(!33677Kr   c                    | j                         } ddddddddd	|  d
|dddg}t        j                  |ddd      }|j                  dk7  r3t	        d|j                   d|j
                  j                                y )Nz/usr/bin/dockerrunz--rmz--pullneverz	--networknonez--privilegedz-vz:/retentionshz-ceuzfind /retention -xdev -type f -exec chmod 0444 {} +; find /retention -xdev -depth -type d -exec chmod 0555 {} +; chown -R 0:0 /retention; find /retention -xdev -type f -exec chattr +i {} +; find /retention -xdev -depth -type d -exec chattr +i {} +TF)textcapture_outputcheckr   zimmutable seal failed (z): )resolve
subprocessr   
returncoder   stderrstrip)
object_dirimagecommandresults       r   seal_with_dockerr   }   s    ##%J5&(G[&R`K(%v	DG ^^G$t5QFA6v7H7H6IV]]M`M`MbLcdee r   c           
        t        | j                  | j                  | j                        }| j                  dz  }|t
        d   z  }|j                         rt        |dz         |dz  S |j                  ddd       t        t        j                  d|            }	 |d	z  }t        j                  | j                  |d
t        j                         |D ]+  }t        j                   ||d   z  t#        |d   d             - t%        |      }||k7  rt'        d      i dt(        dddt*        dt
        d   dt
        d   dt
        d   dt
        d   dt
        d   dt
        d   dt
        d   dt
        d   dt
        d   ddd d!d"d#d$|}t-        |      }	|d%z  j/                  |	       d&d't*        t
        d   t1        |	      t
        d   t
        d   t
        d   |d    d(	}
|dz  j/                  t-        |
             t        j2                  ||       t5        || j6                         t        |dz         |dz  S # t8        $ r' |j                         rt        j:                  |        w xY w))Nobjectsr   zretention-proof.jsonTi  )parentsexist_okrN   z.pending-retention-)prefixdirarchiveF)symlinkscopy_functionr2   rN      z4copied archive is not byte/mode exact before sealingschemastatusRETAIN_UNTIL	mechanism	object_idsource_archive_root_sha256source_archive_entry_countr   r   r   r   r   r   r   retention_started_utcz2026-08-17T00:00:00Zretain_until_utc2033-08-17T00:00:00Zretention_basisz.strict-rerun-audit-and-incident-reconstructionarchive_objectsretention-metadata.json)task26-local-immutable-retention-proof-v1SEALED	r   r   r   r   metadata_sha256r   r   r   r   )r   rz   r{   r|   storerw   existsverifymkdirr   tempfilemkdtempshutilcopytreecopyfiler8   chmodrB   rl   r   SCHEMA	MECHANISMr(   write_bytesr/   renamer   docker_image	Exceptionrmtree)argsre   r   finalstager   rn   copiedmetadatametadata_rawproofs              r   creater      s   4;;dllCDjj9$Gh455E||~u--.---MM$EM:!!)>GLME/)#WuFOO\CHHWs6{*CFQ,?@ !'*T> !WXX
f
n
 
 "78	

 )(3H*I
 )(3H*I
 ); <
 $X.E%F
 $X.E%F
 h'78
 h'78
 hx(
 $%;
  6
 O
  t!
$ X	*	*77EA"!"78"<0 (); <%-.E%F%-.E%F (); <

 
'	'44U5\B
		% 1 12u--.--- <<>MM% s   F,I 0I<c                   | j                   }t        j                  | j                               }|dz  j                         }t        j                  |      }ddt        t
        d   t        |      t
        d   t
        d   t
        d   dd		}||k7  rt        d
      |j                  d      t        k7  s|j                  d      t        k7  rt        d      dD ],  }|j                  |      t
        |   k7  st        d| d       |j                  d      }t        |t              r*t        |      t
        d   k7  st        |      t
        d   k7  rt        d      |D ch c]  }|d   	 }	}t        |dz        D ch c]  }|d   	 }
}|
|	k7  rt        d      |D ]X  }|dz  |d   z  }|d   dk(  s|j                         j                   |d   k7  st#        |      |d   k7  sIt        d|d           d}t%        j&                  |      D ]  \  }}}||z   D ]  }t)        |      |z  }|j+                         }t        j,                  |j.                        rdnd}|j0                  dk7  s<|j2                  dk7  s-t        j4                  |j.                        |k7  st7        |      st        d|       |d z  }  |j+                         }|j0                  dk7  s-t        j4                  |j.                        dk7  st7        |      st        d!      d"d#t
        d   |d z   t        |D cg c]  }|d   dk(  s| c}      d$S c c}w c c}w c c}w )%Nr   r   r   r   r   r   r   r   r   zretention proof mismatchr   r   z$retention metadata contract mismatch)r   r   r   r   r   r   zretention metadata rs   r   r   z+retention object inventory binding mismatchr2   r   z"retention object path set mismatchrM   rP   rQ   r,   z retention object hash mismatch: r   im  i$  z&retention prevention control missing: rO   z1retention object root is not root-owned immutablez0task26-local-immutable-retention-verification-v1PASS)r   r   r   checked_inodesverified_reads)parentr$   rx   r1   r   rw   r/   r   ry   r   
isinstancelistrc   rq   rl   rU   r`   r3   r8   rR   r   rT   rV   rW   st_uidst_gidr[   rH   )
proof_pathr   r   r   r   expected_proofro   re   rn   expected_pathsactual_pathsr2   checkedrf   rg   rh   ri   rj   required_moderoot_strs                        r   r   r      s   ""JJJz,,./E!::FFHLzz,'H=34|,$%78!)*A!B!)*A!B2
N 788||H'8<<+D	+QCDD D<<- #6se9!EFF D <<)*DdD!SY(;P2Q%QUcdhUimu  wL  nM  VMJKK-12Tcc&kTN2+;J<R+ST+SCCK+SLT~%ABBI%F3v;#499;#6#6#f+#ERV[^_g[hIh #CCK=!QRR  GWWZ0dE5LD:$DB%)\\"**%=E5MyyA~a4<<

3K}3\dmnrds$'MdV%TUUqLG ! 1  G~~dll7??;uDIV`LaPQQHTZiq  sH  jI  ]d  gh  ]h  |  LP  @e  LP  GH  TU  V\  T]  ad  Td  AB  LP  @e  |f  g  g) 3T& @es   #MM3MMc                    t        j                         } | j                  dd      }|j                  d      }|j	                  dt
        d       |j	                  dt
        d       |j	                  dt
        d       |j	                  d	t
        d       |j	                  d
d       |j                  d      }|j	                  dt
        d       | S )Nr   T)destrequiredr   z--source)rM   r   z	--v3-sealz	--v4-sealz--storez--docker-imagezubuntu:24.04)defaultr   z--proof)argparseArgumentParseradd_subparsers
add_parseradd_argumentr   )psubcreate_pverify_ps       r   parserr      s    !A


	D

9C~~h'H*4$?+D4@+D4@)$>*NC~~h'H)$>Hr   c                    t               j                         } 	 | j                  dk(  r%t        |       }t	        |      }t        |      |d<   nt	        | j                        }t        t        |      j                         d       y# t        t        t        t        t        t        j                   f$ r(}t        d| t"        j$                         Y d }~yd }~ww xY w)	Nr   r    )endr   z	BLOCKED: )file   )r   
parse_argsr   r   r   strr   printr(   decoder   OSError
ValueErrorKeyError	TypeErrorr$   JSONDecodeErrorsysr   )r   r   r   excs       r   mainr     s    8 D<<8#4LEE]F!%jF7ODJJ'FeFm""$"-GZ9dFZFZ[ 	#cjj1s   A-B -C5CC__main__)r'   r   returnbytes)r.   r   r   r   )r2   r   r   r   )r2   r   r   rA   )rd   r   r   list[dict[str, Any]])re   r   r   r   )rz   r   r{   r   r|   r   r   r   )r   r   r   r   r   None)r   zargparse.Namespacer   r   )r   r   r   zdict[str, Any])r   zargparse.ArgumentParser)r   rB   )&__doc__
__future__r   r   r>   r+   r$   r8   r   rU   r   r   r   pathlibr   typingr   r   r   r@   rD   rw   RuntimeErrorr   r(   r/   r3   rH   rl   rq   r   r   r   r   r   r   r   
SystemExitr   r   r   <module>r     s    Q "     	    
   	.A	]Z__XX0		\ 	V+"@#0f 8v.gb  z
TV
 r   