From 4235041f706c7a811b5ddf369e26549bdea0206f Mon Sep 17 00:00:00 2001 From: Behnaz Hassanshahi Date: Tue, 19 Nov 2024 09:43:31 +1000 Subject: [PATCH] refactor: accept provenance data in artifact pipeline check (#872) This PR renames `mcn_infer_artifact_pipeline_1` to `mcn_find_artifact_pipeline_1`. This check can support all the package registries now. When a verifiable provenance is found for an artifact, we use it to obtain the pipeline trigger. Otherwise, we use heuristics to find the triggering pipeline. Signed-off-by: behnazh-w --- ..._example_maven_app_report_dependencies.png | Bin 94328 -> 109681 bytes .../images/tutorial_guava_infer_pipeline.png | Bin 38579 -> 0 bytes .../images/tutorial_log4j_find_pipeline.png | Bin 0 -> 76748 bytes docs/source/index.rst | 2 +- .../tutorials/detect_malicious_java_dep.rst | 48 +-- .../tutorials/exclude_include_checks.rst | 2 +- src/macaron/config/defaults.ini | 18 +- src/macaron/json_tools.py | 29 +- .../repo_finder/provenance_extractor.py | 340 ++++++++++++++++++ .../repo_finder/repo_finder_deps_dev.py | 2 +- src/macaron/slsa_analyzer/analyze_context.py | 16 +- src/macaron/slsa_analyzer/analyzer.py | 1 + .../build_tool/base_build_tool.py | 66 +++- src/macaron/slsa_analyzer/build_tool/npm.py | 6 +- src/macaron/slsa_analyzer/build_tool/pip.py | 6 +- .../slsa_analyzer/build_tool/poetry.py | 6 +- src/macaron/slsa_analyzer/build_tool/yarn.py | 6 +- .../checks/build_as_code_check.py | 90 +++-- .../checks/build_service_check.py | 6 +- .../slsa_analyzer/checks/check_result.py | 2 +- .../checks/infer_artifact_pipeline_check.py | 330 +++++++++++------ .../checks/trusted_builder_l3_check.py | 4 +- .../ci_service/base_ci_service.py | 29 +- .../ci_service/github_actions/analyzer.py | 2 +- .../github_actions/github_actions_ci.py | 159 ++++++-- .../package_registry/jfrog_maven_registry.py | 33 ++ .../maven_central_registry.py | 92 +++-- .../package_registry/package_registry.py | 85 ++++- .../slsa_analyzer/provenance/slsa/__init__.py | 1 + src/macaron/slsa_analyzer/specs/ci_spec.py | 4 + .../maven.dl | 2 +- .../guava.dl | 2 +- .../maven.dl | 2 +- .../mockito.dl | 2 +- .../cases/apache_maven_local_repo/policy.dl | 2 +- .../apache_maven_purl_repo_path/policy.dl | 2 +- .../maven.dl | 2 +- .../maven.dl | 2 +- .../guava.dl | 2 +- .../maven.dl | 2 +- .../mockito.dl | 2 +- .../policy.dl | 17 + .../test.yaml | 24 ++ .../facebook_yoga_yarn_classic/policy.dl | 2 +- .../cases/gitlab_tinyMediaManager/policy.dl | 2 +- .../gitlab_tinyMediaManager_purl/policy.dl | 2 +- .../integration/cases/google_guava/policy.dl | 18 +- .../jackson-databind.dl | 2 +- .../cases/jenkinsci_plotplugin/policy.dl | 2 +- .../cases/log4j_release_pipeline/policy.dl | 23 ++ .../cases/log4j_release_pipeline/test.yaml | 21 ++ .../policy.dl | 38 ++ .../test.yaml | 20 ++ .../config.ini | 3 - .../micronaut-test.dl | 2 +- .../cases/onu-ui_onu-ui_pnpm/policy.dl | 2 +- .../purl_of_nonexistent_artifact/policy.dl | 2 +- tests/integration/cases/semver/policy.dl | 6 +- .../integration/cases/sigstore_mock/policy.dl | 21 +- .../integration/cases/sigstore_sget/policy.dl | 2 +- .../slsa-framework_slsa-verifier/policy.dl | 2 +- .../policy.dl | 2 +- .../policy.dl | 2 +- .../cases/timyarkov_docker_test/policy.dl | 2 +- .../timyarkov_multibuild_test_maven/policy.dl | 2 +- tests/integration/cases/uiv-lib_uiv/policy.dl | 2 +- .../cases/urllib3_expectation_dir/policy.dl | 21 +- .../cases/urllib3_expectation_file/policy.dl | 2 +- .../urllib3_invalid_expectation/policy.dl | 2 +- .../wojtekmaj_reactpdf_yarn_modern/policy.dl | 2 +- tests/repo_finder/test_provenance_finder.py | 4 + .../checks/test_build_as_code_check.py | 7 + .../checks/test_build_service_check.py | 5 + .../checks/test_infer_artifact_pipeline.py | 15 +- .../checks/test_provenance_l3_check.py | 3 + .../test_provenance_l3_content_check.py | 3 + .../checks/test_trusted_builder_l3_check.py | 3 + .../ci_service/test_github_actions.py | 61 ++++ .../empty_log4j-core@3.0.0-beta2-select.json | 1 + ...invalid_log4j-core@3.0.0-beta2-select.json | 1 + .../jackson-annotations@2.16.1-select.json | 1 + .../log4j-core@3.0.0-beta2-select.json | 1 + .../_sigstore.mock@0.7.5.json | 1 + .../empty_sigstore.mock@0.7.5.json | 0 .../invalid_sigstore.mock@0.7.5.json | 1 + .../test_maven_central_registry.py | 249 +++++++++++++ .../package_registry/test_npm_registry.py | 79 +++- tests/slsa_analyzer/test_analyze_context.py | 4 +- 88 files changed, 1780 insertions(+), 314 deletions(-) delete mode 100644 docs/source/_static/images/tutorial_guava_infer_pipeline.png create mode 100644 docs/source/_static/images/tutorial_log4j_find_pipeline.png create mode 100644 tests/integration/cases/behnazh-w_example-maven-app-tutorial/policy.dl create mode 100644 tests/integration/cases/behnazh-w_example-maven-app-tutorial/test.yaml create mode 100644 tests/integration/cases/log4j_release_pipeline/policy.dl create mode 100644 tests/integration/cases/log4j_release_pipeline/test.yaml create mode 100644 tests/integration/cases/log4j_release_pipeline_deleted_run/policy.dl create mode 100644 tests/integration/cases/log4j_release_pipeline_deleted_run/test.yaml create mode 100644 tests/slsa_analyzer/package_registry/resources/maven_central_files/empty_log4j-core@3.0.0-beta2-select.json create mode 100644 tests/slsa_analyzer/package_registry/resources/maven_central_files/invalid_log4j-core@3.0.0-beta2-select.json create mode 100644 tests/slsa_analyzer/package_registry/resources/maven_central_files/jackson-annotations@2.16.1-select.json create mode 100644 tests/slsa_analyzer/package_registry/resources/maven_central_files/log4j-core@3.0.0-beta2-select.json create mode 100644 tests/slsa_analyzer/package_registry/resources/npm_registry_files/_sigstore.mock@0.7.5.json create mode 100644 tests/slsa_analyzer/package_registry/resources/npm_registry_files/empty_sigstore.mock@0.7.5.json create mode 100644 tests/slsa_analyzer/package_registry/resources/npm_registry_files/invalid_sigstore.mock@0.7.5.json create mode 100644 tests/slsa_analyzer/package_registry/test_maven_central_registry.py diff --git a/docs/source/_static/images/tutorial_example_maven_app_report_dependencies.png b/docs/source/_static/images/tutorial_example_maven_app_report_dependencies.png index ee0c91775fb1a66769b602ad024948a3bab28579..0f8b8b135a4b8dec9a5b85c0a1782dfd0dbfc568 100644 GIT binary patch literal 109681 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%0AskETxRkSEDZ zV4$e%k`;D!j3y~~L?EVANS-CLlG&%WaFxm5TqIpZ=R{Xkol@uc__S(DjCPSGHd)Z- zBklQQMUJbJs3`nuPgHi+yy7JF$lK5BvC;mb0r=WTD0=c&b(z_v637b8$Y}G9eKLQ zo0cH#?q-a5?A9Efy&{%pX$X-W-4|uoc!-kk)`}~7sUUHcV=RdtReQZ-nv~PvTH}@&Y|)z^50P5bw7lH< z<-VvBgI)OMKQZJN5tc&O~~ie{UcT0Brb7dySnqDtA`p zmIq12^v>(Gp_|4R$dh@k`h=yodmamV#&lO z7;&K^DWtBLlVV*BB*>HnQZf%8FX(dTXd`GAB$+Oa2YMd073R5pseMs|*x8BcO_Q^;g}oo?4LeJ};K z_d35~>L}l~_G+SIQKiqoaXB53TZgBW(9fkMjI!8jj@{d|4%Mvtcoo;K=NBoj7F}^* z__VHpbE+2Q+9w1owNYPl#?OaR6uM+398asI|2i#a=Bn}tOYr7Y2=l4U^D%KbUFN|( zKQ(spfZ~}h_*vAD|C-_~OJe?f4`t(qXjXJrzFfcuR#a@VxpOnl^j7}0NOxO9XRTET zO8pArukrcnH+A;&g?5aEG*NZY>fSLH0RZUuNY5UTg@OvwqDz72#iXhyD zZ*ogY3n-qy#j>AI>odC?Cu@iDuE-1kb%0z;+0yinqZa=^)V+6HQ`@@lZCNh2)TL4c z1yq`Jr72xOKza!Y(p7pwQ96X;QURrEARxWBgb*pA7Zm|10VE_yC{cPsF98VzZq&8* zUi+SX&Ux>-@45GL=O6QvIcH{j#+=U><2!%PGn4}rZz(G2S6#X4dXonAm>&=`3l~4V z;Dfu9a-ku){gTyuzg;rf-tH?kloKPV)3wI|OSuhkO?apc@=x-pROWL94t3V{>|s&V zb3Rz#OKPTaxtNyp za%@YiSndwWMg>XR6&jt%h!j%Q?n-3??F4F!P#pSu#jdo)aL5RqOk}}NqP%w=HV48m z%Tj?iL|KG|MJ6^b7-vlNe-Nk6a47UE&3f-u�oAcecJ5|1j2L-S(+z32$MFZN8B? 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 diff --git a/docs/source/_static/images/tutorial_guava_infer_pipeline.png b/docs/source/_static/images/tutorial_guava_infer_pipeline.png deleted file mode 100644 index 3cee17c0cc7b913af05d03fe84eff0b052397a04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38579 zcmeFYWmg>C*X|3!f`{OZ1$TGt1b26b#@*cl1ef6M?%p^AcXxMpcR0E4=lsX>>@&{( z0(dUR2F7*Q&X$-!((!WyO#Y00$6eF-`}`SBI-^`wkA%l1`fs$rZ%?L#`KOL2V-L!M>AWe3#d+kzZX&b zbCHmPv4NAht<5)Ob8BM=Wi#h*%xvG3jP1U$FtMW4}N(88kU1;zX#yQs{mPOolmsHjNIgFkx> zElutsmFvs`WB>l~pF_w8M@l`$|93Q>_Wut4Cqn-Q z?Ej>I9ElIKyLTj0BS^9U_vf&#HiyZE)v*kFkCJa?Zz+!*87?+tF0*VwzR}Afo|K3d zudf*F_fUN6{K>=Ir!@>bu}bE#P6W{t@7?E0sFM_TF%#1<0<#O8+-)!4)bt9iX#@~C z`<@~zT(LA-Y8Vkhmc<(BupY--gBfI$Qoqv3`Bwfc&@#OjCcjGwJd)MuXdu?BMiwE; zPHHv&YHTLH{$7&%)NaZ_S2lX^L-AL6kmF%1VAr{tL@RnDBQ8oL{?0{vtf{}?K^qe!{KY%j zr%@fzeAcO?+0YQUkRonF@L9j-{iIF8dHSn1qY`>Ac1vN1FUtQi368`AK#|Pl z$e+J``{w88=NwV76%wN)(_is&*$6Qob=#vWaZyh}vd;o^wi?`|gh2B=BSmWMaC zQX}}CW6=&wko1E1S{Iy){OmP_0b@1hGUktKkg@pBGRaX+xvi}~JCHjK`Xb4S)MhAF zeZ_q~Tt4Q!K6;8LIGB%G^=pwA$D?vGlV8uMCpT4VIh^_GepBd3e>D_LoXRs+^Wn+L zM2$-RJy*uiAk{Lo+mD^F$&(j!vl6IU4`@v*D#>`0ach_U#po=9_JOZgi~7$x@t+)L z3{S^2|9#VAJH_=b05Mjet!yl&1s}^RJ>A7_}iHX4XSE*2$1(ReF?k57x3jdgxOzP(P(F?tTnOv2K$)sJjE4kr^ z57IjV+w~)0%yAiZTQ9s^)-}eE)hFK<3q|zdTaCV?O8Br8ToZuf=ootZ(8jWu`WCAd zfq<`=a*2t4X8|Kd1yc@sNzw@VZ06$fiHn9qd%GQ?Q75oCuFDhT~gBLzSoUJyF*}*gyo6 z`o7iKPjC;4Z1~L?D^nN1FW!E-=NxQWo(W?CmWotb&OS}`{vP1H6#EnU;Af+Owp-!K zwlyJB&XL749@56C{$}VM#UmTDG4B^8kYoG;C0j;l%(0a48B^n=mUS{w5BQT8}6Z?suCJgwa=4S(ym#{_M8I_%s(**|*tiy9+k} z=0srRFHDA~x1*X{KD1Es*E+Axt>M)7S%wsJY&=W+TFkD_7Z!$&DBt7`4h(lkR#HGB zSy=}8{CG3wr9S;-IWBNOu355f7z2J5j4q`oT@zuzu1;hm#$F zyclS3HMv%_PP)!I@&@0MSOfwA_h3pZ;}2U~mWp)l$_yWg ze0=3hn27?VJ+CJ96wqFLnnML;-9-*o$kyzoV6yRX_d4p48>aXO5=$R&-#^(AwhfJcI``+!5_}zu6n^ma?n@0yvdE?sN5Z;U40L=1MHei^Ks9%7AGEV!qn`0;*o9Z0TW!xXr8VhFdNPlUnnL}pRU<}C zoM1AF*VuM&yY|!59m`Z-tVELIaV2%o-Nbg55C#3Oe`=C{r>XFAsQd6Qz4>aVKCGy< zw@*Dkms{y<79xB4L~BhhWU=ap{!B?!9ARJ5xqMf9feY7C&Y5YUDvi<@?@vHCGiy%z zIcLfAzT4W{qb#Jc(7@2%Xju$2U|(^CWvcV07?(DeXv9R_LAoBWv-g0bSfw8Loz+of zzD_~cS(CtUzV8+Z?8?ydh~qq0l&mWqZEs8Rc^aeU*@bZR7gLxX^lO?GgLb;jo7*l@ z#sLTZxtlRJc%y}~1RHIgl{+oD1Q{i-5fRAFC+tTHbC1U2}XW4`9t}P7C38@QyS1y5ZbabH!xlxUd3znoq)$m16H%7$e zMRdLrOz(MtF0vXsbTa<^QDFc_R@a?>`;+|)1DKvbq(BYtaLJHQ41Ls?ET2m`&xag2 zxbd}nfE)RY{S(yqmV6O+$Gk-RbtKF!A)f!hCb^Y1XE1|%<(1IMvC~Fs?L%1U1k~Y- z3)KEtQMK2eRm*;7pBzEil+PJdyB19cFI#$x9wTX6_ZKV}*z23@=|F}P>F^=bM=smk zBIJ^sv?Ij=+?$IelRt8J>b!OQ8WYmlnR_*W1tTfb-Ko|Y zEp^)p*VNJswic2jI&m;W8(zYM{DVW{5cIzI{QW`|QPp|D&G=AXdVXc+wKS$*QF1({e zpEn|3p?KL=b>SNb7*OcvqtP(?;%^PUEwXsKl7z%9e^S00EA^GvlUrfi^&<12 zupXK5@uKu%X}fT|y+aF{ejn-{=jYyCPgyEUym?b&NKc(lKlXn3Qdx9WJi$3rCoAWI zGiSVdJqA7c5~NMcYBuL1&?sO+5)`ha#j-8SUI_g@Ja670?~1ZhHuWO0U3!Tdu&m1R zmKc`v7CSt{9&qUS4N>O+uG*jrg0Dw)rb3f8adqCn%(t>*Q8Ie|#Qv-~dCfC%hWA0m z=X5dQm+v8j&b9Rqd%0a6kYLWU_u)pd+4c(2No&+Ho9w%X`FC#1_ilFbif7ZSy`lT+ z|4iP%FC^B&I)=LZz~|TN5FAX5w693Z_ju^EOGRt;Jpat8!^L`!Z2WvWJwhsYcgruUu`-2tW zP-ad?>FLTs7nWdckSlu8JXKR=&0VJ&a%LYt|AbF3ouGnQA)>~`scWb|+4bcvi-;Ct zjTT?a26Q&~aL{~!VP)f~cEsXNC&DLpCH} zmOfa9992|Wqw8|nd#Lb&&zsJLpkTljB%=1PXm^}20FH(0DWWINKbo94xe(Jl$LH=Q zX!RIPSxq@M@$=}c_3@r^VxTq+|g__p$9s6Z@26U^w?6*EDwVUhm8KPc=NoI zUl7Hq!Bb;sPlSLAg~^BGsm~wDsJ9cB(`V-koYv@jk3wM#Rr1$WemCcS6w2{^N z?1SsBP>rtS%O{cs&wY1$fK?*`DA?pRAVA0C%7!p5)HAi5O3`k?gwmK`(X-XEdwS(j zDul|2r6b{AP#`CDVSukpqNX=hT2a&<70wBYthm9Dq^6AKhtTBmj#hP%b!MZmHbYc)lx2xibfsnH57`(@7W4h!|F z6PqcoT3$R|&yj`Ykg8NFBNf)cD>}KvnU2iU-|BT|u1+@I!lDICRc<`Es>xe@wL0m< zNGIz188)|_ZrTTF3Wr>3F_?-2Gr*&?h{lCuJ0qUC(LQ>mx4`P@&Qzs>`SydVX|`C- z{p`Z(=?*4)@47!ydw9`re~&&^V01RT5V_8m2iWg!{^ktBh1YvE0gjgmD&dp?n7q*8 z?_D#?wo9LXCuPB;j@Y?DMtb$YmvYV8w+ZCd-5AyH=hUr<>-z15H_gBK=lzRx`zv)t zpf{h`mdoBHZSmgf5MpneK-X5CeC62!2GbLU>%9p*RhC_-LD+TTwF4)$#;-7r1$drU z9GzQ@sC1Trmo!;rCZN=04QDahz-Jy)LGF+1%h$vl&$bN02A;aBOyq)-r#RB7J(JLo=HZw;1Fi)t=>o1Ykugb*T;0kA ze4s-NPTBQi0{ix8m%eUE6*rn!XnBI?RJk3e)QW2DTjJJRtbI-p8^iO_Dm5`>OkdS`YA#?Z5*JT?NB-Pp-0Nb^C+;(AyCJ>M{kH?O*J*qu zsH9h#O7@Zqf+1V2`x};h56h)~4JD0@=*>WSSTV`-cTU7YpL7>Jy! zr(fa4u)D(5hJrylAlTL9)S`sZ`znu8xq82DNcu4vBT%j=+Av$KjOwJ`(~m~9!ba9|@!$8PxxAT@lQ^Rs z_*MfPFliKWjK~I1vi8POzC{hhcW+QaSv)%G{)XgCdi-g=%CcpGF?4fK1x$?T??X<4 z)(CBGOS<_L%v$Y$p(W}w^8Ohq50UZ|hO4#tOI3;4>fmYN|5Am?BHKr6nKPmGQrL<&PA!9;Y4kQ7{q$Zlgbw`{G=p{)KQqP@c90NgD0a(rc*iZ0*utof3Vy01kPdQHl-b{-@4KQO$!ot# zyPm);vtHOkSia}Nv z7W*xl+;&B=GCV3GoEEPYkhU~FooJ8IiuyHGFPJTV!N#-28ewZGoN|@N)$i_Y#L(O< zI}EP@5Wjb}PXCI9|EIr<+ibOb)bxTTLMjqv&t84CF7GSab6_Jt>(n|nmCS1>Jme8- z|9EA9&j$^do|Gf!X1N_w*Pi)Yw5WJnCSk?rlTBlNp^fUDIWTGO$$3HpG#y zZU8bC-nV%PQAW=sC9vh>=o#*Zgo~ph1R{j%Vds&CxFva=&89WRC$<{OiFC#a!xHIl zY>{e@s3fwCSGpxl^yF;{o$|ZI7s0$?FEu`U;{9?bay2hNX1o5S$JRd-A|NqXUbpK*_^UKYE`u$7OWSZ*#qIgR#u|wXr=C_h^oHFc+2*?1!WatgxAp-O8(!GxF^%nuPOfjBuM5cIWwF z<~0@D`)>X}@i&aF3+O-$fu*df99_4M3N}FH>U2fpchE8M7)cy$!f1qe-=^4uZK&9N zrtf(nw>~7z>^;FUbi3v{ooQyx2g*^jQd=OxN)9=*X~5naTmY>u*~wMj>cp`fIQ|j= zy?Sii3xlv+Dk5JtQIkbux)9r!lGEn6=`&;}K7kj+RyqF7IvwkG|KiqxrMHt`a*T;` zoO%?#S;2VYVJ%pT4eMb!rr-8gal$k(K%>nVd?`uakU5JIdPvlOC`I~WU)yuJgIF3z-R4E;}n7&X!CT7+A>8i{;akt#*!uldRM z0!0&nhI)B$?Ou+CmPpwNpUYq~%b7>V!!H;9;{ z8c&Z^;{9cOw!tXU1UCvfLlFB&*L}P1#)7&yzuoij-P~KQjXoG;+uv?Y@0L_O+&m_I zbf`*=&4=Bo@O8odWkhm$!#iVTOJ!Alcl-1OdzHj>(Tq=7r>6JU=;}$-Qo5v|>jXxr zAjFmA2G&5j4wXR=bSj;$TeH}e=jJ$JMR+RpL%t@LZ{*G zU*=FxPpD9udGt{agpK-uQ#H8E8gVwzP$y5zo7lgF9j!E#Qaj&cCjVfmp8)?r z&@etk6mDIXTXod^E`45qxD@dYeI>`Lgx6?4R$Q4rv-Q#x?V@oNIetFqy9yV1cI`Dt z9(-fPtr<$@fb5*A^Utwu`M{oPQp`2c$!tw~pED)>cZT$08w*o>Y?WUTW!g|zSMmGl z{_?_6s-i{#3DY1+))>51#0G9?D+d40r6RXM$eqi9X7!!y^jWdO9;cN++O64H1p z#Ggq$7zn{(1CZ9cPM~{@qelyJ+e_NSPjC^5tY%%U#oOH09Lu!}-V1AMPxK;h?VcZ} z-SYBaf=Iyk**4LXw^a$hF0+YnU*1$4oYF)cc;I_)$LSPtOLy4XTgg0tO_F_{Z#$4;B)JP1Pv)PLYm&}cby~|Uh z^ylI4an5IhrqE5;-?EmFu#n%Qwn3I#&u+jvxQV?~1mkU(+thZb<4FNSDw%6hdygeI z3c|6$1ue~;%AYS16n`QFf2}rg`m$vN{c!zQRTtpzinV>nre=@2MnT}4NwQ?6xdjOK z&Apka>KThu`d+8JbmOoEXLv@iz&1Y;faE2Bl{}Gq%*wmrP{Tg zDY6=8<69LvXq3mf5|4t%iq~qO3;h&pNpy!leUfXMa@V$(hKP`wv9?o5bb1Qn;m>3# zwm~78sMKG5)L&h;Dokk2(L1fU!e#y`il@n9)b<@t^kmn`31*qWy(VW4qw;wqyAytJIg*_a5n}73D&ZxsV=T zsT`o5KH#}vF*P6O7gL^sQvB2zwYf(|WZXcl$eppSE2DHo&)xljhbsd|HGTeH{c6#f zt?Q1ZO3VK&3YqHQfV#7=4d(4{4QwQ$X~rp8rBj#;$yu`WFSwixxA zwdR$tl0r@tY+xM6QO~G%xy(kiSC&ZTNut%%+vaY4NwW~`#4P-w1is^B_z}H#f^+mB zm->6I0D+V;;6Gjf(8_-SI0+WUzQHqI+>5t(_5dx#A_Ld`4Vv*{YhIj#jK^u>JTHEY z+9oJjI9R1dMdW2UKEIpa?WbA0!AF(rY#BaLWD6%a*!ik6vBKq#VPOOd*|rLyKkUtG zXKdyOvDlc69|jX=t*4VPCx&mn1L&m!eNSa)u--JDvT?i@-n&PSac}v0ONg}w`pStE5)Uk4r^`iUQc<;s1ExWX z;2b%U4J~xj_#!+=&jSUqwXQ|5bIF1M%>aw5X%Ayv$x%K8LX`9V^++k9YP3u%r1 zE~(=wr$=OB)jhn^bWQ+KU4iflRhI1aOO&{xkwnsnFq)~n3JX46xA7V{Xf zHhj;V>9Mh8u59$pQtg&(V~pr%sv5RoCBn#2+1cb=Tku5Moc%2Z%X;L}XK2ned47FGcGskGlJE9J&r611u$1{I`7=zKl z)4--OM3$;h3R^9jyNoS!o+0G3_af6;IUxM}G&e7t;|L_M3RlL+b#uc6E4%XjuaTj8 zNF#~@s_;^0MNpeS75YMgxJJ(n6R%_WHZb9?UR#4T_UDG}_G5#*A=Ke?Oo%B@yzv*+Wx=5NK1Th?n9&<9D;`j@kJ&}*Lu78|~( zEJqj)hqUanNs#!C8{lVf#^*S4IBwfuxHPw$uiAdv>12qixTZb_zEl(~&f6wmpYYd% zHK;Tzc$G|1vtwtnLIYbN%PK3K8Z@O2!&;JazS{ec=LN}-emkUz-bmd}@5GmZlLHBk zd{Y0?%5No6CBw$$5yss2bv?0+@2#0)$#fU=yx^Mheuh=q&fG(;N8SNo&ah2882Cic zX!<0t??QbaBwd6bl(p2JbgKPq$OZJW zUTow{9cH-&2R7>>7!8n)g|L*zx;WvauHO=bZbwQW&r~Q9=!acXupK>hTsr7CCx*^D znaQm1->~p^Wg|#o%I=N&+aQ(g6u()ZX4K6coV&U%E_K1f5aa}#u$Ud9TJd^knFYTp z+pzmz46uu%A-h1V`zg&+n{y zU_~1D3qIE4_CzQ&*mFL~3$&V7*9sKDMw{H+HLAB@{waEM9mQ3`dr&?#h{+X@{YPUW zL1~Wuq8H0y^wpR@aocl~ByRXsjnmSzFY4ai%*z=98|9ADHTH(6X5&XK%DDJuK;JBr zz8E?CF}a*x+Gc#0AnYg*WY!!mN3yiMyoY$2pHPqSfY##5=Zh7ZP^VLS5%gvo&L2Id zJG!?uKfhSy>hR8(-{vbzEut{U&2G93_ew;r)A3~+*c+0bKpRK8&n7m}FMA=3k1u)G zg3gsz#_G6GaWEjz*L)*{NYkh_LE4wWuwqkPUW2^P?z6d{(NOQ88VeMKnRIY8V0~@1 z7A@iZsq(W7SMQAegjX%^q~9(K71-N+l)&t2)3?manWDB9;TjyI^l)MvsD{&>`{%n4 zp>pb^afUhblk~LQ&DWvxsf;E4<@BQyj#?*a=SA*7P2>(rmlaQf{~f;LoIoGb!#F6K zEm+RpsJ7<#H3u1vyY&*}oKZIE_I}4DS1DTKt4#SR-LuZa_sdGroNy}$hd$_HFOuTQ zA^c!Y0CvH0;<_3ENv|bAM+#DRk)Hhdg_*6eYmBCwXb^i`l^-Lqzfpetu z<=lUp4Eb!^Irjbys)G~9=xM8R; zH}q*x&;f4>M&3RW&c~1$*1UpiQc~U%N{&Q8val)D7=njadfw8KpRb4thLV3p3|kTc z!@ke)o9s0`tyVBaI*zoqZIpFVBxv_guiAVvJ`^a^hMpVhK36S`tn`oB*RTssssHZk!{t??Ux>oriqhfVmp+$v zX8qHNj~jWaE=CqZHm6b6+vGhqY|UD1h%6rsXwIY3_NA!vIq4$l3?I#^N7M;0K2@Lm zWC~NPgD4jshC#%gFxOK$&9C+Pn!>;FC$PkHkoOb^k~FN>W>0e_T05q%nBN>Lm}k6C z407^{!_;-2;Y^Gelx=9=Pk@lEFo-GWJU5t0{G%Dow+v$~F8C0kezUcN^+=QI-etLQ zm(~XvUwUv12WhQNG?JzJ<>jpWI0g!NGTVmRipHJEa2O$I;XFgUnOx5Vk>B-jqH|rD zT#w_N5qum9!b(w8CyJmWu&ZGeQ;@E4weK1~edE=y_q}d0{BqKH*NdMpx%c)zuw@l| zLut!Ri#}B07`OO>dq<5ynW$T|c27NcX%a#N&K6`I4yBw@pN@vik}Z!iz)-ft{D8m- z`sUefix0-UyqRUX)MrBDuQPBy`aA$?E7^8V-T6@zYH<{PZuEt+UgS_|2^rb<6VJNQ zQEynEx8X>IKO6|Pyy$9ggm3C8mVMpaYaC3?%9ZBHG_Vkzn+)#}_*~_Pr3Y z{~oD$nNb}TifpJBlbGU@Q6XaLaHNW~E52(PdrvGEDK%xh{Hen_ll^|E@_)kO#m*z$ ztwjesOEJ}uwZg*xrmgmgX|(^9weNQ%OLJ2R&$Oh~bOIq66?H?y(Vf5IJuQk2q)O6C z_*+NAr$NFnqjy9k0%7}uO%}JSx9LV3QK0>a*#M=>I9xU24lZ0ZbivmHD!*Kas;JAA z8l14`62G|{Q=*L|Yi%$>0UIxuJIALmvPJFseGU?(m~JkCjX!^?*4$^o94f<@Jtt|nZscj`$SD?_1=|DsK#bE;aDhUi%B#mC zjRK56_jNF}0O;h>JSPvW8IP^7x0)HB8&l%J>dN*bPwuV%XUJ;(o&DZkom>f>VlzHi zYTWL*5+%#3W^4EIhH_(|EQC2q_TH?rY-nTGTiiWL^|h%EGkb4r2H5P*A6Umb@5rFp zM^7#_C*5wg%=A*k_}7#45APDaMcjTYTX*v%bgVVLpI`KQHGQL-gpOszdowPVr%|~h zMhhd*6(GFmtQL0UIK;WQcFr+~;c{I9`>>VRObmm>noI7;iTo6>BohZ8YqVv~2&y@# z{Y)iVALJk{t6c~Ea_1;Io|WypiX;_C4)AxKl+mvVf&FWO&dJ(m^kW=ETd81@so?0Z zneA8|&5}&0me?c@gtBC%tgh%5b;n z;sCxs{#sZdsP2(9>}ps{QtGyit{!A=-hFS;DBPl#2TBxm7=2U7Bed+sjOFxneqoc`b`CpvFAH)gpyjHatn=ILwE-aS$y3&WU z6+1=#t`rPVV`=WbDKh8{1RlWPQXPN&7|R4SN;lz(T)#e9DqC&8=@}h@y7L&AO8jZ# zzKWV^CtoHJnRv1p**S>6p+~n2yb3g+LLFEgjDqYOCWLZw!Rm!f-}`!D)CQUg^7ONY zkVlev`8;D5N0qPtCd=k4CFN5sbAE)98qrs&FhrYiBE?+t*C#0qY)a%I99VnL5P&4(9AnTwLxB<|wSO?_VN`*@?p#J39j%v0I^eG6sXT zQv+T_t__V6zHR)2)&_4n{x!F3f27yY+bmhl@M0bbcP+1>16_NfC)JyOk4b(U2s7+U?m7=vY9!NLt^iwE86 zj1HLg%F+PtA016{f2hwoV0`|x!zaLh68rpMQ_QEa5-FM|7iW7*_>Sb;m4{dKWNj{n zP;{vPVCRV+FtA5dCMUUtw`B(}u8_HeN_C8mD*gUj45@LzCfJuA3vE+RdC|d=p0Y0H z1_^9SwC%;v{8eT3ErYEA>zFv$75>pXDky}D16y%ClJ3}j(|MnCDT+Sx*!g9%VkzG; z3cXT0Ls=&D!)oCrn96l;XGpQX@`#~k?7aumWOYlHw%$Qmr%vqJ{L;Yh`0&4cA;w?f zj-yyYw^1t}^fdi%cWb@Nr^t9Z`R`d`Dg7BNaADh(La(|V6aXu5tf zmZR{9VLAAEl4a{9?jOcX{3eH%ke9TQ1#@?eAY6}U5g4oFkKUGs6>+o|B?x==83;Wji;X2=)&_bqQao7^Qm;dOcy>nVpAg zXI5HmWiwH0tUWSJj}SfujU|e4xhIlG8&rK|k4T~P!5rnTap8D5$Lw#d#|&%0#tiGE zFnj;xpF5)1;NS3W_Z77LqnX7-d%Y#WlISENF%8(*S9FdMRdCHGqQ}$sgoC<_WEK`& z=6>3{y8>+TVVsh&`yb|zFXo3I`qM1wn9lUomhB1RZ$wcA9lL}1%e$`iB#sOG`DRnY z8{*#HaXqc54tIMmkjKS3^{%zq{S$H^&W@L_Px4ug?jJV(A6{u#Io`2MXXb+c^dYDl z9rbqAMQF^X*UT#uB=e7AZ1J6dv-$D65yq&}AC>iZ|SL6Q?bsOFPin?#Ti5otq z7cC`DZ!V~*itq8R;ubPV{#SYA^_9TnERGBP9n|*XrDMv>#6y`4i+O$RRGWaZ?ta_i znH@Nex7zTAI4vbtVI~`E*r{Qi8;$qwRZXV+3`EbD`P{YMJ*y9ER7*;5_S9t$*L;bb zeca#t2yxrPvSpc0#{YE%IqmjE=Q@z7SwX44 zVzn!iKKxMc!4j+U*5v!eaQ@keU^(^0fyivk26xsH;>0Lm(x|sp+r@?mX2!!vHYBF{j@hF;0%Vr*??;@$Ht{A3R#1 zHHT8}@ppNj7qJP%^(wj|D%^Wr+)k!K7#<)(7BvAI(Wqvj{akRX0RE0Pj6x;u6v3tV zW%hL1l0}suhFEHta%%c6LjrGQ5NRBToJHvW6ze3%4K7B#lRW4h8b)%|!gfe36^eEb zcEdM47kHK@s!cP>KUv>J;7)ycF_|v#u&?D-H#9Mq>u+0U!>x~)*$Q1F>uamx1<-lz z+pYMmH6cq4B;7|L%g|MepW~YoIc~np$4~497No%7u1d|=^_tkc(^IN^CVm%jdf;xc zhiYZy6N4dXZ0!4i{*Wp717sED4gNZdS0DA8GYGc)KP*#@B`G4=5kzI85W#$4D1M|K z_m2!fhseC`q$p=l+SXQ^gbW$n9M^ker{Ef0_p*R!Psk-h7I}3Z`Cf6mR`u6`-9V6t zyl{DpSh#)E_07sN!_bxmb-XmDipyb(dSTlO7>R(mlO)9$%P(gx>fQ5d4wwASb&fvs zV8(y`X#lzO(^PqSGyK3WRKt@RKwkoFG}rTOPZtlEe%1dhz16p*ya82+YQ-Hj&*q~Q zwwt6Xz0dKA6zN>@9gF6{hu2SLgY{JINNBA%eWNX_|3}Ob4@0U&=-fl+HydvwII`mPzCcN7P}4GCK%TeKg_0N2I?4RO1iL-yEL zio_CWFc%T~I7d*=+fEVdx?HE;;eiFTr0R0x=g_Py$c3iW6RsC6dLw0KR3zN_S735I z8*!PMjzy9aD;KN9BNjy@P`FS)Yl%IV&YTJMP2}+0Cfl~hR^5Kb+qTrcKzOXhtu-z8 z^4B$*V@ehehtXvs^a|y>3jFlD$SZ;U;a%#^O)#_19d-9iJ%os4J1<)(#odWgr;j&) z&3wdf32sW6VBntA(k$&nD7casRM+nM^6;Hd|+BhFxjKN*|T)|x{|Q>k>~ z!n~(TSZ6_=BB&v8^~aMyfvYWR85z|c@+8)1Z%#OqS{dJ!DXNSCEV-nt; zIMk)UQQ;cET)K$`qf~^<#Ani9^ zur;ovecj@#v2AB+d$^|I%L|w0g7x<#cQxusQz%c<1ux$i@!y@;E{`%BLi!tR+8UE- z6b)(2`g2mRCZ`nHayb~ctnefB=Q2ft{qr~K?9~uS6l?{x8)^}Ya$i=YBZv`S#l zC<*_#59;2_UH3St*`~?@#lku{-_=q)W_)EJAR!^4q03F@{F&LD1;*kFeQsB=OfHkm z$c28C&Q=KP;w}At81Wq2+VXjHLEZdi>S|KHK3ZrzbEG9=Frn`|?7Gp%8ZdyWoN03* z+6U-)92?B~c{5*Q+%qA4su)(?pi``Fj3I_Tt~;QuFZ9P)y1XKUyXB`$(5U7+tywci zBd)U;es{;-L-|HWOtVg{qqzsG1uF0s6_4yMYIef%PG7RtV$pxg`n&RS3=8H_pR8{v zL07w6IeDllb8}T-vOm8GmU0qL(e8m{hGy&;?Wpt`GRI?ti8K}5n@!n}wZ^ubSXzSy z+ov|9uwA0x9cAlSZk0ql-LF_=uvRxmH<+$+I^23I#nmjheR(z*tN3<3)}`HWZrkOF zEh{5thiwS8qMgxR+qjZ*ib!W%{x)$*3|z5JP-(BikKD>iYEFq%@6=K^geAYx>Y2u> zdw$u$VVfRffJqxBWD&1i6)@1t%N@2v&(6+dW1shoR-18O9e$6ZS` z>2Yuia+MmoO&58*zPk*4%fY<#P2>WvSluioi_X zDbFVe%Y8ouRg}<{=OLSlFD`7cj*emFr^m>koDCPP8kQ`#Lnb7Imk# z()T2VRT_gK8xQTl`2utmybVV zOQDTm?!Pd5Vh^i_4$pasOfT@dvY4^FVUu&;2=A}q99O04{b-DIupT8rf|j*yU&0m` zi5*1t?0ephdR_SNqPOAuw4h}|;c;zyJc9Zlum{w|$5G^f?KOzMe%4>2^Wz-bhE_0x zF4~BCJaz2XC}lR3VHfzwdKlOv>b`2c8kw2>5F_j#N%YrB;%_^P^-5)Hes(0Q^=<1+ zQPb)rJ&y2gpA^w?8^OH1JWbwh57FGMKO@!7 z%rCw52vG>7{uBa_<`@q;Kj24_rOGwFM#!X9l;i0k(?a+XX`k=r%|AQirz!s&{)k_3 z`@4O&4a40x0gTdbBQ?>2cdMpP&SiakzswmVo zx{A>^i+`icA6UFIc0xtBvxZlYcgWe+^;N1lsIREhOkvvUl=`-tR2PE*-}Dbp5R|E| zBG?NSil~^qP?3OBTKyjaN20eiQ)LqEFWCL@R*6{m6y7)m8{T0fwX%u zj5JkdCrt`aRS1NzUm|(GbJP6vz66N$7V4l*h5_BdzudbTZ7ziemL(e5Uv$SWuU*zx zNKF_5>mI~EgWY+j`jive{JbW^~S3J>LlJ|17123Q$cQoov$>(lX?-W@OhtpUKa9XD-JJ z5s>cGo}bO?_}P&;uAZD?c%&Et8yE1oy)k@i?qoO$@ z9;i?1CZ5D&kQ;(Z5N#ybBn3IeGAE@av{YkUR)dCb0KQI!EbHF!)t9tM8y2t{9D<+ z@Br7)1+nvf?s~CyadQb*J)aI5V_!)9+x5JUvyQa(j%2Lm=y7RZSYIM+FGOD-DY-f2 z!vjgg^38^p{0Td^KR+~y z_C)I(y*bS<3>CnT0XLBYsCQS$7*m{!%^sAdx_+T0%f3d!aR`_+%Ej_mj3Pbw zQbLd=sUC%&QazFxM3*0}!qs@FBJKmqT;;`J`i^IKTXbz#CCg&AcaK zCTGJr%}1$o`22py+{C$Dk{V>q=1fneRmC`BOLM`48R}V`*(F13V3`}<;ViN|$~9Kx zmGsVgn^=_-0#8n-@n^I}yd#?rex5#v)!Ytbg=qO*J`nvYg_wzPq=*3T?{X{N{-~FL zWszOUh0O5`{uejn>4>N`p6SxkKNa3^pP%V{j*$d1Gi8cO3z+7ohGu&PE_Or^etU)a z%(GYp>-=z63V&UaUS*Fkuj8fV->QmePWCHTr`L2(Pz&2$$X17^4eW)ERqk;6Cw7A( zV`$i7pmZI{Yn{$aeMymrSn)WaN1TFhZ^xe{Ef@5!vN$%fIxr0Q*FU( zrS)6Rr&H5tRlW#%S~{3JG+^Myhs1x?0F~F)1W7#GF`T9qOJT03i*fOCG#Idn$N4e` zD59@2-_HdrU2XJ>xX^6EF*3`eOR#o!!pzAP$1l818QdD{h*hr>B!{h`k)}SK4y6#f zsv){=Q@DI}30*x)Vn66CNnhwj3L-8oq{iR=F$7PW_Fyu2QO6F^+p{2H@pZ z3`0FjTw2W{V0~vytd!E_icwr&+J`#!=ICl0Qq;wpAsg?LU9E`p3k?&Bbv6uxT3s(Cmg1$ zg(g+zzCbR9u%ey@(n6FBNPPc>UQ>=?(&r#W$6RE{jd;?4v`2Ta9`~5rX>rV&w4XBD zBe=fjB*oT;k{tI2@7@RLdRIZ@#mg9uf56(~*Kq2;AFW;oupWPzkvHOVZBOzfjvly9 zwb4f~>2rwUW6#s`bTl#9<0~e!YR-N%lv9F=sRZ0lp>BD-+~*-Jk|XbpX_~E+iRs+G zaE~T`9mTZY5!{vpa_Z7eEQVyKz0F|flC1Qw$-%VjcaFa!LA09qf7Bs@Bli3?6*+2;TjBhSnc@8_+vEiBu(~wWY6{!7%HdEEl3_9BPN_VE6-A9zyWmo9>#gjT~-FA z<*{>TM29kM#W~6jI*8fG^9;W7iD}agQYRqk>)#t<8aGbgq5hb|81^}Y&4kMgy&RkS zd}bcRyZfPNxLRT*6s8}Mmq*W{KkhMil)g6Yi63}1ALl7AdPyVoIXCSGRv z^|(B?*)Qh1JejjcZ&G{oVGMfi$6(+IYOH+D1?7wW=KK-4{l&8?=Uu>g^p(@YiWxk* ze4nP{k6_g60A|C_&~|?aZ?flX*8K826Uwyt$1v)-AKm`PsJh}g7nS6QeG^3gd8e=) za1f(G$EmdV5eFkwO1_F8L=;hoa^#|%oH15B? zNQ4M#=8b5mlp7cap&%A7Ct(|*`SBSscC=V=TL|WoxiK={XpzOD#yl;;Ax{}oVt9RMP3SyjcZ1^s-t+*XaNTUwlc`}1#A0{V_&og z$a%fGEe-k~L})&fZTq(~tx+<&`!u58zU-QVBGG$C@aMJiOg?ati+d+gC1M+cy3FCu zuh?EP?lZsdQqnuE;nbB=tm}fagQS0o7;i@TR!F9%zSOT)L+P>i{mM;X~&R&U~W$J$P-1S{*=xU-CCR=!qb-JW0X12SvWtvq*$OP9_vzp0VRX{kbm3Kc5;3rHp8&Jnh5 z*v7H@VSFc3S%JtC-*b7%MAp2prE9lZzb8{g`V$uVHfF^B&r}++jIFCjQu*yHI!(L! zojTtNf>w0GXVNvyx-Vky@uO^??Tf~l@w6Rvlz0F|FzdRtVB!r6y3XIpp4)$%FM1!;g3~tzpe*!a=UPbUGIydOU`nRR& zxo8U;rZgsbZ3jjjNzTz1f0y3!H6%qU<55Dvg(+1f!gDKlNh}*MeBKoN3ac2Z zm8ME%GZGJuz;Db(&b^4qoj+1reE*uqsK!NeKSa`Qv3uVeEPUEiN8g%eEvq8Ay_W;8 ze?9M7{Kc_&HJ{0S+deGawVRcHmM3_5d+K!GO{ivdT6&xD;rJ1yU_?2u4jtr?zBe7b zjNn(tT-}qghXeS#Wp>(f1&KjNS+?Ubh7B51N%qT^s6vGb75_a*iqWwDUv#QmK&5pt zio18-AeWh8Zd7=)mKd{_KfCQgv)x=aZ~cdU4neH#)rcNDLki62kaB4}&AVB}3rl{om>#WF6>T6k2otr@WC7)?Dc>~*5jiPGY z9)>pdW628vSD$8-_;?h5rChr4r+0HKt`coqmqv;fwzXQ(x=97hzcWR|AIgukft~23j_UK9} z6Q=#S0~o@bEUo7JKAmj zkk6Twg=SGU%&kUm6Db}o>k%}f3}v#$Chg^8+69Po=u(Xn101OmAIy-oFS!3Bs+b~? zwHxkn*|a2!`c-0XRSoW*xPkZfFuq#OTufo#`ipeEm`e4g?(7-hN;{2kMlZO@+6WQE zRE})EM2Axe*w=Mq$AF3qEt$f`wHN7mEjdpx!ts3%dFJfKiSgB0P)_9d-Yd9Gf5=;B z7xs;)%mDLv)^B>u{+u8Kkw^E#v351bPyoa%^oT%_&U1SR>BIQ9s>uvu>twupPV40_ zd0DhH%LY~FU@u2%rhH(?%4ghA$Y@Z}9L@KiIH6QWBK>U$M`E<_@i0X*C7iK;-)3u~ z8Do2Ua%4yah7?U=?Yi5!V?zGc2&3|NJQ5FCHAtytT`P^z0Z9)S* zDJY(B;>tEIB`ZKu7O&E|!Cs1l5W++eq}3SGY!W>kJaIHIK%ER8-5pAw1AQ29^A71K zh=>a%4Nx=h$-G8?;9JrK8!ZhaVi0=+`qKNrA1nxp{e3lZ({6C?eIg=Kidnhltao4I zhxWkhH=oP)DQz(kpr*|rcJCTYaO>r)8(IS`z+=)SHrGE*V6YstFR^ImS@imx;NYCP znW>N(RYdXFj^R5_5#PEcAd)6`=dZm>=u=DrRKp=6fCK%W@;n*be>TO3A_0>QhuJwX zQ!Xma<=*~U9C`WVg`&CgzyxsgXycQ`i0CIuvg{p(xv)8S@s?&na`N)~%Sp>HVV#e4POf0w1=` zWbONE%zd(v0X7n#33V(#;?!st`<{$tnzJ$5QUP^6Gt7;(f559Pl404Et%ny;PZyvC zjZ3HD?6a7^&kSTu-LIUHCdG695w;C1i3IR%UJbokZcLcFh4D=Xlel6sJJVXT?dS?x znF>G?8hhwc&ut8|w~waoA4Lk5DoF#c&3l;bYm5L?S^SzK&hvQsDg$h#JSwmc>;L?; zWGenUQFmwJ#pk5z7x^EZqXNe5Hu1cX6tlt_eE;XiOofUcA)aef8_{ISHDVMXNKB|T z=M=|BxD`$ZO4);-WD$d=}GH2=%V(| zLp0+QV4C03sQA8q^>_?L9?fIrb2~;|-^Wz9%$HV^hBhQR`m$ijMfxqP$-@jpGt*+3nvTs)~;w?2)Ux52k& z33Lh_m1RKF`Fog~I*>VwdQf++6ushZ)T~>N`i*^Q)4Vc8lswmIH+FO2eNkGrtAQ30 ztedx_%E;mD-T#VVqwT-H+va;Hg4sHC1@CJt;KAm;*hm1psbvw1bN897e%y)?Exj?> zbev;Pr%}m84dg-iA9{#!^T{;Om-A>*L1S)OXmK)bO`?j|JnqM&py@gc{}pY%`=O>n zg$fn_dq{C?_Xm#3e-h()ao(Rp?=x2ec~Uq}Pp)Fo!Os-!+Kom(kOomqS5Rr%VYc+M z$+SVVsE&RuH^wj6Kwz8k*nRU%Il))25^T_dC3E`Vr2#akhLzNSU8IrpBWsOUWKQrgu!*1LS_D(35=@|8{k8P?eO=thjrCv*^EdZqRTHS|-TSsIDxGREL zQP4X3@n`h4EV)ujG5Ek{2wyIqatd=aca+T z601z6WeEugMl}3uI}N|z1!9Ikoz_*DQBj5fRMJo2@PwBVkl-t|q3M z0-%AJmJ~sdVx+Huff_^tqFkVAyJ~E%uY&~eDQ|+_tke8;ESPbwHr#&s8L@0d<~Jyc zA%KGpGPO5^lYxj7L6Fg)g$E6kWc&Q|6L0KG!gDY$Vj8W%U0%}q9!4$!=uKB-gAFkN~3V>W^m1AQ6V5>VIFz+6X)B+K{k>X5i>q?(22Yj6p8JxNEi09!V+1o<%&UcZINov&aD$kmx zmRa9yW|(~Zh}Y|Q!WC9%fBgRZ=~Z7l-?J*_*%gdDhE+#GQBz^n_BRPVWup}=C*9_Wrw2_us3A#^N+Oo6i2vdLD5f9TuaoUeM?8WloSAS%IgTs zd8|&N0)GBOM#cXw0%{sI)OK$}c`1mBS3HeO2Q;bdP#+5cGQ!VsKJq&6gX8dVFvP*G zAti6V;*|*UsGZEe9_BtdQpJH&=^CB3>S|IIW=!2M#dNla^wn-zqrWdP;|p} zjb`xd>;*oV)uOI_Dp65UnLi2E)T&dQM%nq9q45(7OkjA=f)La?3{TNHz6+@8_ z#_I={IkI5|{;%YDukmNv&WEIACsrQYOg|?`ihRqXYbV(H_ii4fXOCwR*U#TXUbz)M z#d2@GX3hCL3ctpT8w$5$Y5SSf}m%`QE2l;5zns%O_(xsgHnhBeTM$=klA@z$S%_s#HWUk9Dv zJm%6e9ay+!E9>X=r$X3LI(J*o%U|D2szQYd760AH-?L|UD|~!>@bU4Xb;kkBJCly* zh#j0-+6?0#3I33I;@7hH7d8mt=?(70eeXmmMans260?VqU8l0~#9iLUYf|NpMJ)QG zijvLCgxX$8wkU}q#)c9UzhdB$xly~i!Pm1nWjy2J*!hdNDb<;tn%NaIGOa`dJ2J7>5MUz+;0Er`puiAAMTu1+=d!|!qTefG{QDK^z> z=I#_NaGj0$NqsF7^>VFft&~ewQpAt$-nxX`y2*QKMSPkS<@J%nJk0=N1K52ch3f5m zDfS}~T{?xs|`G9#M9uMB8vpQ#%vVk5W|rbca7v)p?t)yJ!x z&JX)Z)QeeC-zZlST^$+f{NOkUYSgQ2g-K2`QrxQ-qnsj!Yr$Xc?hAVv$#bb0zOK3B zk5&=Z&Tqz{T3RH(iQ)l9w5*_=dp&|CEh?Fz_9=>6IlCq$*p@KNwO4D)Fcc)X*c#^A zt94`;3L^5X>yd|j;*5?J4YQ2X@vkGeD;m?pIrn}@j4kjko;#Tm3zSE}gBQ`HSQf=s zNuNi{g4X5K340w)kV3)TXHg^HLzJ*Eoa`+Fjr>ayzOmrN#o_t{Gl_(Ok#!}F= zz{f%0=7UfoL_i+Pp?gV`u3QW^DM-wUvwT=3`V@tv_(UGR3T0cs2Oi3m=U4vuE}?q! zYWTOd#6XcwNN6kznRzwXR3vUk~T;XE|n0b}VRXgR{zEsp1Ean*71R zVXt{T;uX&aoncjlvS^?n`t>Fb#K=LtGL3D`kRa#HoAU%I61o2B21$ULnHP<6QpCn^ z`9e$TZtlbQ%j?IQ*v2?(0jIF)G0fW|x7Q?F)b08RP>R_>{X*Pc<#xw(rI!B2Rf zqCiK_o+=K#n9^oHi^^L5TQ+|D(5p%+mF8Pa1=Q8Q-h?75f+)cPD~r5Os8myr%s{xz zlv5I86Mi6@N8ykdVPah9qB}%{g_H4dEiJ6pe%X{&EOFWIDTz6jWc!sWmp%SttFZ-ja5zA2wdA2vq>6;V|YZ zk7iZ+@*_Z0pb$YKk)l`J9q;b$cy}KS>ET>k+6%vt;~2QYn=7LnzB9TxjiFG82oeeE zMy2ueDUGL3A108>`%^RM)NUq!j%b9};T~9}USapa52SsVkEd*Y-e%PIvj6!g#ykGp z7r!DpjPSHnE{$-)Y()P5%BU3^k3zc^EgKuM{pfMtjk1Ho2f1h2l9@HM3O(k9MKH9d zrnfycy?tq3I*zh_vsiVb3-dj{C~l@gg$flavQcwn{PhP+ukh=Ehk}+RmIhz3K`4Ux zobdgWiMov!ablAhQ~qAVz^0Q)k{DuFr!!;cO{a@Xmghrain;0UHE;=fmRM+i1XFXE?~S}o?c__3@y z5={-ve#0^>sA*uHFPVs;p(fh$B%+g{oo_XEYCL7((S%N=a<3-+Z3tH^t(cf)<5DD~5rvG(`OY`hll`!PS)!|f$&Um8d<{VZOZ~i! zNDQ>FKu&y0e($G9R9q_P>SLMb(H79qR7V4m4~c2WB^p@h=515UP!l6!h)NR4_SQ-z z!WYh8b=o|Ga{vG!07*naROz=yK_uv2C^{~cu@EwUkBv(uL#BhN@=g*#12a7#=bX3# z7bKuyk#1gYQonx$fm}p5S#Itxib$lH~&AS z`oty!VhX1oq*K3TcKy>I@8?^HNinS1`G9%1qWK_K$J#;<7kw$RoZTTBG^%KZWa}qR zCzhmbL^7fFeuLI;c})Q zdd=c>Zy1*$#mw4*9zHINuc-S=o0C-h?;?^;eB4X!2W@5k#Y2RNpk1s9^|U1*zTNn_@{pC(m*pNS`N0uW1TCjayT!b(@i$jKekS%~AUBRJ#;-(v_3X#n&WlLI&i=HT zbQk+c0lba9ENS5ehsIP~fj+CPP&yp(Uzb^`s_qF9)dV7ApITr+- z-`0l;6)IGyQ1Rb{)V?v^_DWH!2xz%A$IIqdloc6{6`avX3nu8}w{(tF;^R^ZQ8Pin z$ixW3Kap2`5lM(o`1bi3cbMtdgRN<;*>pdg&(Xm=xpI&xjm+}sD(cqt7{2B-f#FfS zyM2_uI~j6mQY(6I{P1NUR)P8z7#is#hKCZ7PuAGzSkN~>UuuZ45k!ZEk(%d_MB=lR z=AYDCWYwl{`B@-=fq?`DKH>QAa$kvBRPb>{1GEi0urDd!ztqjCI%p!D%gA|p|5>5p z+cF+b!A-jagU{zbT7zN@CNS35n54%Kd6fZ47k6=ipgPwea>rxhzpM(S=|IP z!vb_1K_8cnv)Om^J<(y$xUg*;9$_2l{iP8CNa|)uBg3D#Px@c(BW!VS$m+NKvBc{6LY7T;sJ5GgJXN`YGU(1#< zJe2S}w=jc>(abMWzNrQ&ZoI`+11*TjC&7gwLOH-UuiGtMFcg0^db-LMNqQ5IR;sO z5j51$BaO&>{YEFG7g(e93xprBqXH<1PnPGshhi#W`HE>O;!}x49n-JW7|_#JM@&j3 zD$m?d5b{2f>!IoB>8K-Bq!ONxx6QP~bP`a9bP7AD-FMyOHry5$}9vvE-%XZsm+L5=FP(io=kGq$oXdb{`^TR@ckmuQpbRF!sGI- z6G>^rDkSJ@spV$v`)*4DrnaS6Jgfolmo??y$cpqgk7M!58~puIRn$^N;gLtJz-OT? zw)1T%J>LPh)y?RBdKXX9L_h~m`?{IgB?KFKcX-b05wCgGe=c>@1wajZyN1{b63iWD zvbWPg_O~8@Th4PPCo%RiYj2$-Oawuqhn~7NHEZqWK&J!js$DyG$3Dq~e%#6Or{{_I{AYn{wnn-=tvcR81(OJz@2xN(RhA-ON*)LZjuRj(7Pp8bl^L_x^W zeOy)=toU=A+4s%>kE&(AzNI(qI(rWU=PFb3AhvD3fTCPg+zm@o#lwP#bH}-poO_BG z<wuBtFxQpV4_3O zegS#P%>I0*F+4qYf@^P+zj??Pa{OCJ#lN!w+AVjG@XcdV*yE>#mfxPt_kP-OdYEd_ zcwJ;6o+XjUb&b)s>_fnB8Q8qYpG>EMwkwk#sFFUbP*Er}Dl_TO4o3M@#;%kDRa=i| z*Un-5vko{~tsZJPD-N`R^eZXlJu9K{+@AxFl_ZNl%Z@{#n0i#DjJhRNs@jrtVk3J#=C&aZ z+Qp8mSue$()myYJu(h+t-rgR2dpk;)el6Ztg1L(;MN-bNX~&x{b`Q!w-sSE`fzpm; zD9mOAwUXs=(fh>VO~>*X8-cVJ+<6#>%&sh@q=}s0b(nCg=Jf7fms+)I<^0rc){pj; zB|O=;k0(F*>K2SEQ`I4ZE62|gt28)Cm;R!*YfDySp{Pn!| zKZm*#)jaeG4mhr~R;F_j3(^vvR4p3Mxnq~fiA$0{=VUy2b!Twv8;VuI>#Xoo`dW?z5BIbGS*{WwhVEnI(RfN%uZEQb(5Qk>6H^{+ z8N$K6)lfu-<_n~@lzzQ<4ObyYh&EiqnJ7)0Iy@QWFTN@W=!*Xu1u_; zLCmK(K7C<|lXLZ63~p|wxv7TbpE(?;O=G9rphBss2~~_TIR7v*_ueYv33#0F(*a-K zLJ&k^6Vr09FFBGkZ}JH)W^m?KsFIUR!Tl@mcpx*O#utH)0@k)B6ig{I|&5JU) zx(U`AnPZ+7k-)p0N&4k{7n478H%y>VrRxv6`JU^75mieR&SesI?Itc0?rQ?<-WGQ;fu~_AtFnsUgsd9g zr3}C8$Wt@*qM?aE^yfGX&CB6x(~EJ{>QY=i^SP61I^g3{2MYn@iO+eSl*0QY2@aMn zR4hM=ab?SpxmjL7$EZFX>`Ea;L44#h-v5frD6@C8_1x&ta1yQbq=@nt9D4fbyKB|I zuCSL*1BMQ(#NLVRX{9xl{G)d2}oiJZ`SpEHrQ(Z1}jXNK_0E=3J$6xfG~|0NXf_b{~O78+j8Og|(TIa05=9J{QL z5;67=v!`96$QXYXcduM1!)<|NJY{XKmfRlvjPpZmzPbSAm*YPMi3JtBn-gOrQ$0&6 zRQv~`VcU|~2U>oaCaf?hLb!GK5bD`4N_i5W?(SjHqQ@Aw*oJQr2`FrFvJ=>`XefW% zj-61cW%8XIEGzp1+j`VKf1m$Pow z40e}jOUd-toLfJW#mAFTn7!a(a2zE{xKb)*ILn9h!E9Uy+$}PAb#wviURuy}-q&_1 zN(<1hWSCbRMc?@inbWEbk}18Yq8Gx+#S>W{=gGVwb@B z0;KZx+F=eQZ0bXsS7u0nJ@73_Hu; z6Bh8Y@*0}hW?6Q0>*Cu`llJrGgWVYZ$?2;wWBz?7yI|6c{vC?Ye7Yaq#nH5NGa~V+ zKMSWHMy>H0db+6UEUQqVLdCD5W>Xe>jYX^(J%jR7nqU!jj(>^>SeIa%^y#Uy%anqaAsR4buaVxKE|Ju>euO zejO621Ti6q`?nuq@90#B6o>jW9yyE()u+>;s~%IkIFWvHHM5VTqc73Q%;qKYWboMf zY#r2-b`~@Fql%1Y+vc!2(h!M6iUg2Yw`WZE#WWq-gzlk3@vCe}!p+r8ns$XEGiFm> zov)V?k~$T*&T5tTaeXZl0U_fq(|y|_PU=Q^wdd@eJr#dhb2jyJ&C8e#c zFl@)T#>Tn2kQl?MnS4DSFF1Lb!M3KhJH?aij>tS!ChC~8lY9bHbe#Wkd zLFVohLFC&0EA&irptY5P2Uh}_{X$0T{w1(eli+NU%B*Ae7^Y!I^P=j+fB3+hTWQ$V zF{h*i5Ysq)Ghr>YzG;Nz3*pv|x!dX2_{!lirshKdSsX5!X+@_GaR(or6o$HJ5%c^t(@rGf*unQamx7r6;4%kipk7+DeRyGpfcb zT5P{Uug_&@RZ5eDpdhCBM^U6zIb5ab9J-%Kje3Sk-zkOZN5Ha(9)@x6nY7y!Syf#U zgWfQ~KbkbMCYnTxvPERXJb1~X`|32(&)~_!*UUZ>gF>N8U~n>t4qE64ns`+-Vd&Q9 ztQ1U`=dPVK|0I+ss)xqu4=g@!#-F9thDUx7f25G_S=G-wuu>!XHL+mR#=H1zO=U!R9a4ke zG2K5Ji)x;9FcB!smSxjodT53|W9)iu5^9=ITuA1^*;m}sG^0l;l_gBY??JCb6KZKn zK=Fzd+nX>yG&i6}&~C-*UUR4`v!hX&(yX|)j@eHdvb3BH6)LacY^78ZQ`3=Y=pYjW zM8zkLU0TB}xg7D~JT{hHOK)>~+BG>&8?PkdGot~2Z$%!a&WLUQs z4EsXL3?5%@LdzT3-^T)m&T9#D&VO7A&+krSeZ==);Qzv}WEtf~9OAfaBx9Bg!*78C z)6(v=SbmJzZ7d4>!2dr*)18S&j-fYZ0xL#$U|yO5Hf~=0b$AAUdVV+Du0W*rgV?bC zBZH@orujAnmQJ;3KmHWw-VUPK=pnRO=)&#x-#FK%K7O^9F?moep1wWD{mI|!Nx-V} zGPb=Q%=npYsFPxhou@Cu_g|&!?56bns|gcb-m%K71uFu!V?JUUbGmIMUfUX{nj_e= za6A=dfapk*HWk^rs3SF>&Ef93p_D090Js_z#_guxr`b&EwuC4hTPk|Z;PBj$l-Gc- zZAlXh+p=PZ1OCH?&@LzgOD9kIZk)yRRu%|=v`l~Yp3-34n1xK~wuD4&YnmK+=q()1u~Knk!$OG@j{fA>B6#Ixxb4EpNSWZaIIYv7wiAK`cwJk_$3r_ zc-ephmS6$B|7#wGFSu#D~V+h8dG(y|O*znV7# zrZLm68d1q$TzN3l`kZF!heGtB?!>VDN0E#e&Cf zL-f%3^!Hkcte7kHyD#K&?+bKnIh*d?ow$2u2-6R&ByHGy=Jnc1ti%{=`^t3MaGWXL z248gy3T6f9SF#$+I&lz#k&{?Es5LXv^eE}!%ijUB_@iv*>LV%Ml`SVT7(IL*^Lp+k z$-sdoqxP{msxQr-XZG_i)mtQ1_^!UpnaZ=6w_yvD_k18GRSm2I`!Pm)nZGTxo9gZ$8I7tE&~md;y71t$MUmd>0VivxP!Yn z8f}SROV6*=dy!D0X$#!Oj%VNAM@)2e`}&7VL2|TR&lzDdqh`*h?}ixEEgY!Uemy5A zwx@WGVMvd9EgPV-V=txJw#j4I{N*thjPP1~g6+nmnZ0ZvexXTdSUOX?`)1bt)t+C< zxU52j3Kc2<5Q=nR>E`G3AHRaGHK&ju*TuQ}G=^GCTW|=-X)&RO9#;AlLTv* zS`6Jeo4>q_3JCm>P`uZAc8C7S#PuU-yD$|U%aW9oXzt>vRjn!Yjn{IlaXT6rDxaUstFyb= z`CN~li+kWyh_U<{Qd0|BJG^G<*7H1#ti_$y#u${brm4{bCe6OY%fa5v00eDomj0o~ zksS}{7_Pvgs0qD$m1C-VX2vz&j-Jfk`HprytlA zs!r!hpSf0~2-9+uBaxT)!!UHMf_a{aDo~UsQ#tuCg9d)Od26Z)8u<38 z#nyfIn7a1{YXm*o_*G=Y^@~ikBQyAu}k?+~q__T{@sP^Vt|8tl=1$kcQ9X?F-r%#CT* zzB-d@>!Y6Xk)xkX=w344h!mn9J=bz<@y%e=*?V}MN+(@i2VcLk6x;hg`=;XE#)E0; z4_UG1BJ(tKaCfz3{e%*1TXK_smfXjAZdE$yf~9LwJhz2$)xH=ljB>BS%F~U_;rE$% z_&W8|Wt1sXl%a#_(D}#}`tQHYM8TSSdFDGHHDO%8@U~^tm;vOab$Ue9vlQ#^oJYO4O*#3E>H2k3XZ^g*2r4`qXP!g*h!OGt+Pu0;#n< z+xw<7+&_pROP-<7(!|!rl7+*Z>13#~E35b&7*Nx`1_pvide{LDgyl^`Bqp6=f6zE; zI~ZbT*O1cJmvB0uHSI$B(95|V?q=2)%VeY^zvaot^BlOdnq42VO8lkXVD2tIp1Sv; zU70F48k(T1md5ALk9qj^Fq>{};o|4Q6o@GZIqB(fght=v+@s|zeQ@tPS^P2)L{U`j zRaWt9q+el}Lw#=af6S%fwuMj}L?YLDQ*5*q`$N{#xDbI|D*m?-1cAc8szl-+Zso6W z3)p-4Ibq2%%p9uGX7mDPb|{M$nW;i6d7P)$l`+Ij8_kLr_1QTq3g71IvT6@VDf#Dl zo^(Eed-VW1-@V50=+Ts|xq#Pl00HA}hxxR@o74jO0!R-&&dd>iu`b{-k%9%~ym~Qh z-WVF{@1%uAXZ*8rXsf%=G_PFxSC@R!@#sGwL6Vv_QY1$Wh=QEA2>OC zG&6Ue%4z$)4|UYdGRtO zcWbg|u{&P>m!Fzq3fFIZBE+gFzB$>AGB~#G1nr_7c|M}l@4vUAoR|a!I(q8=RXV$v z9Lu4bahSUn!!z5_B#&n7_zRr&tjG1{`uwhh{wblMY=0@CZZ&hVGmy%|UQlboE8K^B zvDo4FM6~^AKN%^hd=_MwX#5Ai5LBr6HzEiErRJ6TcZ=~~gDSRHg$fn_T_l`kbc-Hr zj;_J@js6@zw2Gn5?^xZlJO3!xgp|KyL%-47aOlsn<-KvKzmP{4$5UR@jv)cT+??u> zC!$on(qyjPnt`XLHN6f76Zm%nWQFKUj62JSM!w7sEX$ykd)c?LKPB(Y#K&hA_cdFy z`ISF?Z8WJe?H0i&hhSHbCaef%UAGoYykSAt`8zqZYd-A_t}wanKz8M?*`kE})hdQe z3B+ym2KMb*Lf=R=te) zi(~O>K9l>leOS6{H!J@vPw?{g)akyPP!S;U|Fw7LaW>VDAIIP4-aG4^&5T)X&Df1C z#e}Sde)P43gf>))(zhs~LS!iseWem#AxTonmI~iULL$uAvNTy{1~X&E?DwAEAGX1m z8Imhr&&Ol_nEUvg&*$9FojLcM^FE)?M?b#YTJ49gkhR6jnmT)uo{UTMiFCiV&t(j{AOV_d} ze$zJfm=>$W3AxH~c{1=nswY?op1BKYJsIB*>a9+^33&m{`+JlB%{o)4SqT{Q@bDlS`gc^C7DWn)UP?OQ^cM zw@5G5y>7d?P{sZX9v`5HYqe9?(DnW|h=Mtj4$E1!t6qQeZ9N%%>QiZcTOxX7$^ZZr z<4Ht8RJy)fFi<;w&y%X0{-hlHb+Yjq%^MkWc1k*XkdNF9n|y*oRMOX`^D-_s9|e{4 zle=M+JupYE)#uv>X+-rvd0P#+ z`35T_(7Wg-NpiPn^}0;ed1b6#d>~2|NzJPG$TsOWd7f}eB@6ybG;^$KFm91PemYVX zNgdiYly8$;_3|6DH00iX#qM7-D@y&on6FoAoQibY-4&)2(T{7wyKD92+jR@sFhv{I zY?aw;s>b*0r~pZ78YvHtX-Y8DWu6|FYUUVfKI&7A?r`cU;CkbCYhlf|wS8}%RPKmo zzcxkjjo#9hnY~X>sn=RfLQ_<|$0&WUt)pHETc9_m#Hn1rRa*R3!&9}kyIT>d)zs~a zV!urQ0002E&RKNJ6CY|;{8Q@xuSg9~cS!CfRkQsF&706xr)FpjQm2WZYER#OdbsL4 zO39OK0hQG1**W^)(K7$okqnOA*yi%8*Y`N%efZo}Mjrb%Q)x*~*&L zBU^nxTcxsd95Q89cvKlpdb*k#Ud2_2u2nk#@OQXw(=b)foN^&UU=zjga zdxthJo~JFjro!?MDKz|bN7GviSVQY-ww0lEtJcd=Z;aZPIrrb;*?63`CT7X-wq5?x zthP$3S8fp+_3&<>%LEeR@CL zR?OzzYIIbmYUj>yEfJm7qxExoV8eRFI|~Ud4S!XuQBICY!}QRg3_aeyg&NnXu7}1> zI9=d$M|jlNJ*?if*oTvW}U_ zV3cf)U6_negd(}w_kEdN$=C-sWtmKtnK8+}XN0U}Eb|$+PoE#Yf5Z3u^ggfm5AVnG zobx>AywBr(9`A?gd#?T_JSL6}zMF;}#wg4GQA+(L41F}aiE>lEL(}-N>J3QA#l4%l zx_R(W=hm5B2ARBlH*0ypTSq*+0bmOp?~Cm?aF>k?4Kn!WLTxK@S-2O}UBzf=bdb+e zpPrw;;M+%4I&RezxvNWv)a#)3zjnY!KJ<C?Uv zQsKnU`ySyFD^wl$rGeHs!rO=O5ixGBV=-QHXNR8)w~qVH-0Z=Gx8mVwr_U1@Pdyq2I?(2+7;kbZy#o&;bxV4SZ z=fkC9@C5VAttaQ-{JEa0>RX`GUr{iYWQ|<;6j8PKscx!&;uK*FbXp>(T{I;lnaCA- z3iazu0*1`|flEwt)ee%CH|GtZg1zNgw6#BaATb^4)DBi{jqW$Py~RszMYvr zK3>uDDkA*0qG^B<7HJO0yo^5pGOc{@0OM8A09x{u)YOXRh~7d7`Q%9pYz^-Juq_y} zg$7Rf3LmfFQNeHhThPI=gU-NvK4*eX*PEusUSRE}*h&q&F&*uGaFcma;CCUr-9C|5 z65f)*o11niq1zan)kI9-dBtEF(%VuQDb*2Km)Zo{DGx7~de$Czd(zqb;ic>N*kHz_ z+AgCsz(7sQ`f&T|(i3deyK}Da?Gt16e#TcUOW5!D#dJgy6_y)WD=8^{4gvyt`WY%u z-TBF(LDf)hxUFeuc;B`)G4(t1K9V~GGrI;Z`}>VY>!Mu4d(zfyZpyu^liMzyOf^>* zB@xVVGsgHT%Ek?y)prqPtF#xZJQ>T9srt?DKqr0C+&)khSG+r1++;RrDK!zWvDp9k zhLOx}nD-_I5e4t#eTUIocwYv-5#!H(z=}falYYpZ?)LkdQ4#@(?`=u7OJW+kvWJQh za>jGxadw|yhc#c2jGEzXzg*nCauTVt!Jf?ICciNX8(viEyfk&w97-J!IQ_W>S-OF+ zy0hqer0VRVgL{^-9_#u0dpJLLgJ|AjXVO-3%&?ug%E%|e)qxYo#EOH%+C4pD&&s#I zpR>BWVlVe9j}7ajCxT!K@=ko2uQ?D6Vo-kB*WeB!)PT7TykE8d?J;AtG`f4h2s10Q0wb&9Vjb(xdBTE#2+k6`k08mlJWE^#JQtm zu;isweaC4I200jv+|6KB^-zd<=*l!Ns$xk45N}j>7rm39$El$-e>Oa%;5~RXVOQBu zEYFLifKTDAsemet=9kky&+o*d*@*5x*@M+(`;S9CCO-JyLs76u@CdNA53v)P*gHI_ zizUWjE$L_FAL^RQrDq7}>H1pbRX^;3-DRb~mQYT%qWMLDgFF-askpX#Lnrg!R#m!Z zG&)k$++xa}j}~+tIyJ9dv4dRQzR1~#jCJ-FfmFHu6~z4X+H|^of%!7hE#$Hnd*h~k znCo=-k|FFW`s>5%Q zEhCH|wlx9i8R}#S*RC!X8scTqin%PapukhU{V>h$!A-Hjzi_0`e`pRk>D6~lH@22E zVcqKje0&ZsdXBdUy|emZki5RUw4?6A*g>X=Va$YdFx*Ho+NF!a-a($C*sMMpQ2~GJ z?+-xX?Ol`665QCvsdIC1Bqb^}hN z#}KTCEsE~e#~<35QBHCdsc2s46~^hb(e3}>6HfNQcrqZu+lwFf>; zaAn}umvchPn{ZJMiut9{%24YI_TC#KTqsud;Nq#r^}ZAPDZLQ|=bJfy>s^^6jRi0n zuSVSgy623fRpXDUxLQ9*pW}>3l$|tA055URe^9B40|e)id=YcFN^#Rl{P;Yms%1-? zvVA8aD6Ac4b2-stq7RXEzrB{eekI7IHJuZPa3nw6;@7z2dT1}j=u9v;PKj9b0-GeP zET4%ru2R>v^*wkh;Is*A-{zNHi&O?9ob>#?bU~$fr?@q=_{?Fe8U8}ow#Q+BjW^lO zW{!Rf<0kYj{y`0j^WS+N&cL%WIWBBrw&ZN7w6~|H)l;y2#0d6va=7gVh^DT*@;2TG z96{JI9CnkoUXXsthJS>&KrAj(GqmBFsNB3;lcez=AL|48@t)dELFqBdwEk~t(NEIS zG41|@Z@awuap@-ACG{d7OQZGDyF#{Erj8DgOcfMlMHtV;p%CtPMP z!^Yra5bu{Jnb3h&ZHjgDa{HS znsv`J{d!&Q$T?rG=CF=)eo?*$*3$W^MRdGd%&zXZF6B0!SnEy&UUACHNUw!0IBh{b zSOSm(#R*M5U;VAm+U2MkYZ72PiV-1L+bG*Qn9GikXwD-ne3j6E{_ePds#NxG$GJL++7+&2hy^-fc3U!m}+4%a9nKb}! z(gx9ZqjexSHc53#VZ7KrF09T4Is4sS{XM2&nHJVUMJ38KYz zCN3-{9{>x~KdB5rAgw<*+3E7y+1;8v)D3QCljAZk8YV#tu*=jdiBdiEGiM-CZQ}xs zmuTv0>#d1fAbE)99Slhw9S4{uwddi!Ok3Ee9}ovOb#Jh9H^-mkuCYS&PW-C^vQVIAz2 zu7RD-R2{XQ$Z}$Y`Nw^9iF7lHOgk5gF;_H5!X7Y{3{Ze9S!_e6^Efsl2by6G16ymJ zGx8(m)H8s}b6_c5h%N2m5%tY}OyP7?Hj)Xd!PM4R= zd=->3(Os=K$WHfSWIQ*aL^zpliq)_79vMAzO(nt8J43t1) zbK!%{jldi&^_D_1XtJs@P=3c|Va2C81fp2HvAdk5hiU+95C{$XrQ!xp;G2~CQrznm zmA>27C5KL|ebOq+3opbuUp*>*3)btJ6SuW-l9FX>bU#l3+_S{b0$0hh>%Q(K1ueN7 zAimmv?7qqXL!Xh2_5hEe$4#yfmKMf2@3cnatNAprQ^Ct$nu{bBk+yPHh|O@}jmv?^ z!&V04uG=R9S1g5c*u*EgatuOIvvU^9rfWbTfXrqE4i8klo9oRL*QhPe)0;n5(mzeH zpg`3eXrL+V$LEe{lx0a9OeeiQQ*jwk(^hyiF`cQBUbh;9s%^XGXwbRz9!DR`Rh19< zExqppEs8v^+xfvLT?C+uroCU#=SpyYH(wyAr&v z%C2kt7u_E`bpJ|i2A0w+{gUE#Eqdn2rl6%|G@_GmIi?}|=PrR!1>>8nfjBbKOcZ`#GT)9(c(_*eLgCpP&|mh=4=7eg7(Dr$D0;!+ZOGcxfwz z-rg9HnJ0e@BbG>3%M&9 z-bgD7MLQmIkOa0VfXaDWf2tQBkb4#cwU`(ugH<-m$^xC$-!9d^7VXcz)@ilbOAeeT z8GJqtfiLCM-A_x#*0yR_#&Ylk_a>xr3?XL9=S_}hcV?Mogcn!zaICrm!d1CwJ8)MaFSHG)Cl(q)wA>JnsAFfZb|(bJ|vy6-A$vmK3M3I`XaW zv!4Pin|n)!ThV<{)um?^Aa3WFjldQG4bMGuGcxO47gYX3tuSMUS6Y1FPttz+#!qo} zSq|R}phM9JzT)9{I{*PV7obY@w(0-`@G+Z+@8eu{#FbtE0d~AoI`qv@m z?bbBzw8xe=o+h9=Bk10`EoA#t4`)DPq8|#3umd$Y2!^_^m zMKR_hr9%yO)hp8+Az=$t72M5Nu|7+qw{}*=ItOb&!{RxNuxm)Xy`od9N?VU{t8|&Q zAp_jzZ+k6nAcDuJ8AFf5Ke3)v4f0sMN(CQ+wXr)l`@p?=D;Bz>MDg<-$0dm|((UVuh=}3A_vqjwt@?zV z)Xkv#tTC0wg+9@=JaDyM6GRTcyx{cU%d7CA{=b@IMx5%2U-U- zdPN2aKy*p;vPIMb0LOpSs}zUyPn4I3GJBgc{Q;}_sXA#& z{6>(TZ)MK_A&s>{0N~(Ma9C2kodJwn=JO$^a%&JmL285z)D_8o=a%Km%BsIr<7#SZ zEcBT;aeP@FXR0ytvgMIC4g|X64+2JXZpyf;)m$YefYQ{8D%ohqp@8L2j1uqx^BS-I zj_7#}-9bkP4$?E!1Yx#)H=7S6Pi*YbDO0lS9^%ThKA!_ju=Q9hkWUNv!k_0Pv*EQ_ zkurnMIg5d?;g1$tydK(5MKY!kqgCucIi)3N^j{W^<+s1WJ@I{cSB=*zd=vJMPM+U; zJO3#y%s+p*ns?Ar`n$?rL-A8;PZY}ky5{3cm#yMWZ2v1`HowTQci<5Bs}S>)N1$Ky w-@E0f_{-9J+J*nc6;Jv9hw=R%GqSn+bZwSOjy_gg+q0Ibp~YXM8@D6>0~*D*2LJ#7 diff --git a/docs/source/_static/images/tutorial_log4j_find_pipeline.png b/docs/source/_static/images/tutorial_log4j_find_pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d8bc5115bdb9f2918709fd504e10e8cf9b4215 GIT binary patch literal 76748 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ãON$TKhk={UoFHtYe6& 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 literal 0 HcmV?d00001 diff --git a/docs/source/index.rst b/docs/source/index.rst index e1abecc58..94caf4ff0 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -77,7 +77,7 @@ the requirements that are currently supported by Macaron. * - ``mcn_build_as_code_1`` - **Build as code** - If a trusted builder is not present, this requirement determines that the build definition and configuration executed by the build service is verifiably derived from text file definitions stored in a version control system. - Identify and validate the CI service(s) used to build and deploy/publish an artifact. - * - ``mcn_infer_artifact_pipeline_1`` + * - ``mcn_find_artifact_pipeline_1`` - **Infer artifact publish pipeline** - When a provenance is not available, checks whether a CI workflow run has automatically published the artifact. - Identify a workflow run that has triggered the deploy step determined by the ``Build as code`` check. * - ``mcn_provenance_level_three_1`` diff --git a/docs/source/pages/tutorials/detect_malicious_java_dep.rst b/docs/source/pages/tutorials/detect_malicious_java_dep.rst index de2f3ac57..b73a79840 100644 --- a/docs/source/pages/tutorials/detect_malicious_java_dep.rst +++ b/docs/source/pages/tutorials/detect_malicious_java_dep.rst @@ -1,11 +1,11 @@ .. Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. .. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. -.. _detect-malicious-java-dep: +.. _detect-manual-upload-java-dep: ------------------------------------------------------------------------- -Detecting a malicious Java dependency uploaded manually to Maven Central ------------------------------------------------------------------------- +-------------------------------------------------------------- +Detecting Java dependencies manually uploaded to Maven Central +-------------------------------------------------------------- In this tutorial we show how Macaron can determine whether the dependencies of a Java project are built and published via transparent CI workflows or manually uploaded to Maven Central. You can also @@ -24,12 +24,12 @@ dependencies: * - Artifact name - `Package URL (PURL) `_ - * - `guava `_ - - ``pkg:maven/com.google.guava/guava@32.1.2-jre?type=jar`` + * - `log4j-core `_ + - ``pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2?type=jar`` * - `jackson-databind `_ - ``pkg:maven/io.github.behnazh-w.demo/jackson-databind@1.0?type=jar`` -While the ``guava`` dependency follows best practices to publish artifacts automatically with minimal human +While the ``log4j-core`` dependency follows best practices to publish artifacts automatically with minimal human intervention, ``jackson-databind`` is a malicious dependency that pretends to provide data-binding functionalities like `the official jackson-databind `_ library (note that this artifact is created for demonstration purposes and is not actually malicious). @@ -70,7 +70,7 @@ First, we need to run the ``analyze`` command of Macaron to run a number of :ref .. code-block:: shell - ./run_macaron.sh analyze -purl pkg:maven/io.github.behnazh-w.demo/example-maven-app@1.0?type=jar -rp https://github.com/behnazh-w/example-maven-app + ./run_macaron.sh analyze -purl pkg:maven/io.github.behnazh-w.demo/example-maven-app@2.0?type=jar -rp https://github.com/behnazh-w/example-maven-app --deps-depth=1 .. note:: By default, Macaron clones the repositories and creates output files under the ``output`` directory. To understand the structure of this directory please see :ref:`Output Files Guide `. @@ -96,7 +96,7 @@ As you can see, some of the checks are passing and some are failing. In summary, * is not producing any :term:`SLSA` or :term:`Witness` provenances (``mcn_provenance_available_1``) * is using GitHub Actions to build and test using ``mvnw`` (``mcn_build_service_1``) * but it is not deploying any artifacts automatically (``mcn_build_as_code_1``) -* and no CI workflow runs are detected that automatically publish artifacts (``mcn_infer_artifact_pipeline_1``) +* and no CI workflow runs are detected that automatically publish artifacts (``mcn_find_artifact_pipeline_1``) As you scroll down in the HTML report, you will see a section for the dependencies that were automatically identified: @@ -110,25 +110,25 @@ As you scroll down in the HTML report, you will see a section for the dependenci | Macaron has found the two dependencies as expected: * ``io.github.behnazh-w.demo:jackson-databind:1.0`` -* ``com.google.guava:guava:32.1.2-jre`` +* ``org.apache.logging.log4j:log4j-core:3.0.0-beta2`` -When we open the reports for each dependency, we see that ``mcn_infer_artifact_pipeline_1`` is passed for ``com.google.guava:guava:32.1.2-jre`` -and a GitHub Actions workflow run is found for publishing version ``32.1.2-jre``. However, this check is failing for ``io.github.behnazh-w.demo:jackson-databind:1.0``. +When we open the reports for each dependency, we see that ``mcn_find_artifact_pipeline_1`` is passed for ``org.apache.logging.log4j:log4j-core:3.0.0-beta2`` +and a GitHub Actions workflow run is found for publishing version ``3.0.0-beta2``. However, this check is failing for ``io.github.behnazh-w.demo:jackson-databind:1.0``. This means that ``io.github.behnazh-w.demo:jackson-databind:1.0`` could have been built and published manually to Maven Central and could potentially be malicious. -.. _fig_infer_artifact_pipeline_guava: +.. _fig_find_artifact_pipeline_log4j: -.. figure:: ../../_static/images/tutorial_guava_infer_pipeline.png - :alt: mcn_infer_artifact_pipeline_1 for com.google.guava:guava:32.1.2-jre +.. figure:: ../../_static/images/tutorial_log4j_find_pipeline.png + :alt: mcn_find_artifact_pipeline_1 for org.apache.logging.log4j:log4j-core:3.0.0-beta2 :align: center - ``com.google.guava:guava:32.1.2-jre`` + ``org.apache.logging.log4j:log4j-core:3.0.0-beta2`` .. _fig_infer_artifact_pipeline_bh_jackson_databind: .. figure:: ../../_static/images/tutorial_bh_jackson_databind_infer_pipeline.png - :alt: mcn_infer_artifact_pipeline_1 for io.github.behnazh-w.demo:jackson-databind:1.0 + :alt: mcn_find_artifact_pipeline_1 for io.github.behnazh-w.demo:jackson-databind:1.0 :align: center ``io.github.behnazh-w.demo:jackson-databind:1.0`` @@ -154,7 +154,7 @@ The security requirement in this tutorial is to mandate dependencies of our proj transparent artifact publish CI workflows. To write a policy for this requirement, first we need to revisit the checks shown in the HTML report in the previous :ref:`step `. The result of each of the checks can be queried by the check ID in the first column. For the policy in this tutorial, -we are interested in the ``mcn_infer_artifact_pipeline_1`` and ``mcn_provenance_level_three_1`` checks: +we are interested in the ``mcn_find_artifact_pipeline_1`` and ``mcn_provenance_level_three_1`` checks: .. code-block:: prolog @@ -167,7 +167,7 @@ we are interested in the ``mcn_infer_artifact_pipeline_1`` and ``mcn_provenance_ .decl violating_dependencies(parent: number) violating_dependencies(parent) :- transitive_dependency(parent, dependency), - !check_passed(dependency, "mcn_infer_artifact_pipeline_1"), + !check_passed(dependency, "mcn_find_artifact_pipeline_1"), !check_passed(dependency, "mcn_provenance_level_three_1"). apply_policy_to("detect-malicious-upload", component_id) :- @@ -176,8 +176,8 @@ we are interested in the ``mcn_infer_artifact_pipeline_1`` and ``mcn_provenance_ This policy requires that all the dependencies of repository ``github.com/behnazh-w/example-maven-app`` either pass the ``mcn_provenance_level_three_1`` (have non-forgeable -:term:`SLSA` provenances) or ``mcn_infer_artifact_pipeline_1`` check. Note that if an artifact already has a non-forgeable provenance, it means it is produced -by a hosted build platform, such as GitHub Actions CI workflows. So, the ``mcn_infer_artifact_pipeline_1`` needs to pass +:term:`SLSA` provenances) or ``mcn_find_artifact_pipeline_1`` check. Note that if an artifact already has a non-forgeable provenance, it means it is produced +by a hosted build platform, such as GitHub Actions CI workflows. So, the ``mcn_find_artifact_pipeline_1`` needs to pass only if ``mcn_provenance_level_three_1`` fails. Let's take a closer look at this policy to understand what each line means. @@ -219,12 +219,12 @@ This rule populates the ``Policy`` relation if ``component_id`` exists in the da .decl violating_dependencies(parent: number) violating_dependencies(parent) :- transitive_dependency(parent, dependency), - !check_passed(dependency, "mcn_infer_artifact_pipeline_1"), + !check_passed(dependency, "mcn_find_artifact_pipeline_1"), !check_passed(dependency, "mcn_provenance_level_three_1"). This is the rule that the user needs to design to detect dependencies that violate a security requirement. Here we declare a relation called ``violating_dependencies`` and populate it if the dependencies in the -``transitive_dependency`` relation do not pass any of the ``mcn_infer_artifact_pipeline_1`` and +``transitive_dependency`` relation do not pass any of the ``mcn_find_artifact_pipeline_1`` and ``mcn_provenance_level_three_1`` checks. .. code-block:: prolog @@ -253,7 +253,7 @@ printed to the console will look like the following: failed_policies ['detect-malicious-upload'] component_violates_policy - ['1', 'pkg:github.com/behnazh-w/example-maven-app@34c06e8ae3811885c57f8bd42db61f37ac57eb6c', 'detect-malicious-upload'] + ['1', 'pkg:maven/io.github.behnazh-w.demo/example-maven-app@2.0?type=jar', 'detect-malicious-upload'] As you can see, the policy has failed because the ``io.github.behnazh-w.demo:jackson-databind:1.0`` dependency is manually uploaded to Maven Central and does not meet the security requirement. diff --git a/docs/source/pages/tutorials/exclude_include_checks.rst b/docs/source/pages/tutorials/exclude_include_checks.rst index c0c3d2faa..3cb766483 100644 --- a/docs/source/pages/tutorials/exclude_include_checks.rst +++ b/docs/source/pages/tutorials/exclude_include_checks.rst @@ -24,7 +24,7 @@ This tutorial will show how you can configure Macaron to: Prerequisites ------------- -* You are expected to have gone through :ref:`this tutorial `. +* You are expected to have gone through :ref:`this tutorial `. * This tutorial requires a high-level understanding of checks in Macaron and how they depend on each other. Please see this :ref:`page ` for more information. ------------------ diff --git a/src/macaron/config/defaults.ini b/src/macaron/config/defaults.ini index 8d7b2b1cd..ae0b72cb8 100644 --- a/src/macaron/config/defaults.ini +++ b/src/macaron/config/defaults.ini @@ -146,7 +146,12 @@ wrapper_files = mvnw [builder.maven.ci.build] -github_actions = actions/setup-java +github_actions = + actions/setup-java + # Parent project used in Maven-based projects of the Apache Logging Services. + apache/logging-parent/.github/workflows/build-reusable.yaml + # This action can be used to deploy artifacts to a JFrog artifactory server. + spring-io/artifactory-deploy-action travis_ci = jdk circle_ci = gitlab_ci = @@ -159,6 +164,8 @@ jenkins = [builder.maven.ci.deploy] github_actions = + # Parent project used in Maven-based projects of the Apache Logging Services. + apache/logging-parent/.github/workflows/deploy-release-reusable.yaml travis_ci = gpg:sign-and-deploy-file deploy:deploy @@ -237,6 +244,8 @@ jenkins = [builder.gradle.ci.deploy] github_actions = + # This action can be used to deploy artifacts to a JFrog artifactory server. + spring-io/artifactory-deploy-action travis_ci = artifactoryPublish ./gradlew publish @@ -495,7 +504,7 @@ artifact_extensions = # Package registries. [package_registry] # The allowed time range (in seconds) from a deploy workflow run start time to publish time. -publish_time_range = 3600 +publish_time_range = 7200 # [package_registry.jfrog.maven] # In this example, the Maven repo can be accessed at `https://internal.registry.org/repo-name`. @@ -505,9 +514,12 @@ publish_time_range = 3600 [package_registry.maven_central] # Maven Central host name. -hostname = search.maven.org +search_netloc = search.maven.org +search_scheme = https # The search REST API. See https://central.sonatype.org/search/rest-api-guide/ search_endpoint = solrsearch/select +registry_url_netloc = repo1.maven.org/maven2 +registry_url_scheme = https request_timeout = 20 [package_registry.npm] diff --git a/src/macaron/json_tools.py b/src/macaron/json_tools.py index 4b4aef98c..3cd7a7d37 100644 --- a/src/macaron/json_tools.py +++ b/src/macaron/json_tools.py @@ -31,28 +31,27 @@ def json_extract(entry: dict | list, keys: Sequence[str | int], type_: type[T]) T | None: The found value as the type of the type parameter. """ - target: JsonType = entry for key in keys: - if isinstance(target, dict) and isinstance(key, str): - if key not in target: - logger.debug("JSON key '%s' not found in dict target.", key) + if isinstance(entry, dict) and isinstance(key, str): + if key not in entry: + logger.debug("JSON key '%s' not found in dict entry.", key) return None - elif isinstance(target, list) and isinstance(key, int): - if key < 0 or key >= len(target): - logger.debug("JSON list index '%s' is outside of list bounds %s.", key, len(target)) + elif isinstance(entry, list) and isinstance(key, int): + if key < 0 or key >= len(entry): + logger.debug("JSON list index '%s' is outside of list bounds %s.", key, len(entry)) return None else: - logger.debug("Cannot index '%s' (type: %s) in target (type: %s).", key, type(key), type(target)) + logger.debug("Cannot index '%s' (type: %s) in entry (type: %s).", key, type(key), type(entry)) return None # If statement required for mypy to not complain. The else case can never happen because of the above if block. - if isinstance(target, dict) and isinstance(key, str): - target = target[key] - elif isinstance(target, list) and isinstance(key, int): - target = target[key] + if isinstance(entry, dict) and isinstance(key, str): + entry = entry[key] + elif isinstance(entry, list) and isinstance(key, int): + entry = entry[key] - if isinstance(target, type_): - return target + if isinstance(entry, type_): + return entry - logger.debug("Found value of incorrect type: %s instead of %s.", type(target), type(type_)) + logger.debug("Found value of incorrect type: %s instead of %s.", type(entry), type(type_)) return None diff --git a/src/macaron/repo_finder/provenance_extractor.py b/src/macaron/repo_finder/provenance_extractor.py index 42a8819d0..7b446c00e 100644 --- a/src/macaron/repo_finder/provenance_extractor.py +++ b/src/macaron/repo_finder/provenance_extractor.py @@ -4,6 +4,7 @@ """This module contains methods for extracting repository and commit metadata from provenance files.""" import logging import urllib.parse +from abc import ABC, abstractmethod from packageurl import PackageURL from pydriller import Git @@ -17,6 +18,8 @@ extract_commit_from_version, ) from macaron.slsa_analyzer.provenance.intoto import InTotoPayload, InTotoV1Payload, InTotoV01Payload +from macaron.slsa_analyzer.provenance.intoto.v01 import InTotoV01Statement +from macaron.slsa_analyzer.provenance.intoto.v1 import InTotoV1Statement logger: logging.Logger = logging.getLogger(__name__) @@ -355,3 +358,340 @@ def check_if_repository_purl_and_url_match(url: str, repo_purl: PackageURL) -> b purl_path = f"{repo_purl.namespace}/{purl_path}" # Note that the urllib method includes the "/" before path while the PURL method does not. return f"{parsed_url.hostname}{parsed_url.path}".lower() == f"{expanded_purl_type or repo_purl.type}/{purl_path}" + + +class ProvenanceBuildDefinition(ABC): + """Abstract base class for representing provenance build definitions. + + This class serves as a blueprint for various types of build definitions + in provenance data. It outlines the methods and properties that derived + classes must implement to handle specific build definition types. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type: str + + @abstractmethod + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + This method is intended to be implemented by subclasses to extract + specific invocation details from a provenance statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + + Raises + ------ + NotImplementedError + If the method is called directly without being overridden in a subclass. + """ + + +class SLSAGithubGenericBuildDefinitionV01(ProvenanceBuildDefinition): + """Class representing the SLSA GitHub Generic Build Definition (v0.1). + + This class implements the abstract methods defined in `ProvenanceBuildDefinition` + to extract build invocation details specific to the GitHub provenance generator's generic build type. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = "https://github.com/slsa-framework/slsa-github-generator/generic@v1" + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + if statement["predicate"] is None: + return None, None + gha_workflow = json_extract(statement["predicate"], ["invocation", "configSource", "entryPoint"], str) + gh_run_id = json_extract(statement["predicate"], ["invocation", "environment", "github_run_id"], str) + repo_uri = json_extract(statement["predicate"], ["invocation", "configSource", "uri"], str) + repo = None + if repo_uri: + repo = _clean_spdx(repo_uri) + if repo is None: + return gha_workflow, repo + invocation_url = f"{repo}/" f"actions/runs/{gh_run_id}" + return gha_workflow, invocation_url + + +class SLSAGithubActionsBuildDefinitionV1(ProvenanceBuildDefinition): + """Class representing the SLSA GitHub Actions Build Definition (v1). + + This class implements the abstract methods from the `ProvenanceBuildDefinition` + to extract build invocation details specific to the GitHub Actions build type. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = "https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1" + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + if statement["predicate"] is None: + return None, None + + gha_workflow = json_extract( + statement["predicate"], ["buildDefinition", "externalParameters", "workflow", "path"], str + ) + invocation_url = json_extract(statement["predicate"], ["runDetails", "metadata", "invocationId"], str) + return gha_workflow, invocation_url + + +class SLSANPMCLIBuildDefinitionV2(ProvenanceBuildDefinition): + """Class representing the SLSA NPM CLI Build Definition (v12). + + This class implements the abstract methods from the `ProvenanceBuildDefinition` + to extract build invocation details specific to the GitHub Actions build type. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = "https://github.com/npm/cli/gha/v2" + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + if statement["predicate"] is None: + return None, None + gha_workflow = json_extract(statement["predicate"], ["invocation", "configSource", "entryPoint"], str) + gh_run_id = json_extract(statement["predicate"], ["invocation", "environment", "GITHUB_RUN_ID"], str) + repo_uri = json_extract(statement["predicate"], ["invocation", "configSource", "uri"], str) + repo = None + if repo_uri: + repo = _clean_spdx(repo_uri) + if repo is None: + return gha_workflow, repo + invocation_url = f"{repo}/" f"actions/runs/{gh_run_id}" + return gha_workflow, invocation_url + + +class SLSAGCBBuildDefinitionV1(ProvenanceBuildDefinition): + """Class representing the SLSA Google Cloud Build (GCB) Build Definition (v1). + + This class implements the abstract methods from `ProvenanceBuildDefinition` + to extract build invocation details specific to the Google Cloud Build (GCB). + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = "https://slsa-framework.github.io/gcb-buildtypes/triggered-build/v1" + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + # TODO implement this method. + return None, None + + +class SLSAOCIBuildDefinitionV1(ProvenanceBuildDefinition): + """Class representing the SLSA Oracle Cloud Infrastructure (OCI) Build Definition (v1). + + This class implements the abstract methods from `ProvenanceBuildDefinition` + to extract build invocation details specific to OCI builds. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = ( + "https://github.com/oracle/macaron/tree/main/src/macaron/resources/provenance-buildtypes/oci/v1" + ) + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + # TODO implement this method. + return None, None + + +class WitnessGitLabBuildDefinitionV01(ProvenanceBuildDefinition): + """Class representing the Witness GitLab Build Definition (v0.1). + + This class implements the abstract methods from `ProvenanceBuildDefinition` + to extract build invocation details specific to GitLab. + """ + + #: Determines the expected ``buildType`` field in the provenance predicate. + expected_build_type = "https://witness.testifysec.com/attestation-collection/v0.1" + + #: Determines the expected ``attestations.type`` field in the Witness provenance predicate. + expected_attestation_type = "https://witness.dev/attestations/gitlab/v0.1" + + def get_build_invocation(self, statement: InTotoV01Statement | InTotoV1Statement) -> tuple[str | None, str | None]: + """Retrieve the build invocation information from the given statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build invocation + details. This statement contains the metadata about the build process + and its associated artifacts. + + Returns + ------- + tuple[str | None, str | None] + A tuple containing two elements: + - The first element is the build invocation entry point (e.g., workflow name), or None if not found. + - The second element is the invocation URL or identifier (e.g., job URL), or None if not found. + """ + if statement["predicate"] is None: + return None, None + + attestation_type = json_extract(statement["predicate"], ["attestations", "type"], str) + if self.expected_attestation_type != attestation_type: + return None, None + gl_workflow = json_extract(statement["predicate"], ["attestations", "attestation", "ciconfigpath"], str) + gl_job_url = json_extract(statement["predicate"], ["attestations", "attestation", "joburl"], str) + return gl_workflow, gl_job_url + + +class ProvenancePredicate: + """Class providing utility methods for handling provenance predicates. + + This class contains static methods for extracting information from predicates in + provenance statements related to various build definitions. It serves as a helper + for identifying build types and finding the appropriate build definitions based on the extracted data. + """ + + @staticmethod + def get_build_type(statement: InTotoV1Statement | InTotoV01Statement) -> str | None: + """Extract the build type from the provided provenance statement. + + Parameters + ---------- + statement : InTotoV1Statement | InTotoV01Statement + The provenance statement from which to extract the build type. + + Returns + ------- + str | None + The build type if found; otherwise, None. + """ + if statement["predicate"] is None: + return None + + # Different build provenances might store the buildType field in different sections. + if build_type := json_extract(statement["predicate"], ["buildType"], str): + return build_type + + return json_extract(statement["predicate"], ["buildDefinition", "buildType"], str) + + @staticmethod + def find_build_def(statement: InTotoV01Statement | InTotoV1Statement) -> ProvenanceBuildDefinition: + """Find the appropriate build definition class based on the extracted build type. + + This method checks the provided provenance statement for its build type + and returns the corresponding `ProvenanceBuildDefinition` subclass. + + Parameters + ---------- + statement : InTotoV01Statement | InTotoV1Statement + The provenance statement containing the build type information. + + Returns + ------- + ProvenanceBuildDefinition + An instance of the appropriate build definition class that matches the + extracted build type. + + Raises + ------ + ProvenanceError + Raised when the build definition cannot be found in the provenance statement. + """ + build_type = ProvenancePredicate.get_build_type(statement) + if build_type is None: + raise ProvenanceError("Unable to find buildType in the provenance statement.") + + build_defs: list[ProvenanceBuildDefinition] = [ + SLSAGithubGenericBuildDefinitionV01(), + SLSAGithubActionsBuildDefinitionV1(), + SLSANPMCLIBuildDefinitionV2(), + SLSAGCBBuildDefinitionV1(), + SLSAOCIBuildDefinitionV1(), + WitnessGitLabBuildDefinitionV01(), + ] + + for build_def in build_defs: + if build_def.expected_build_type == build_type: + return build_def + + raise ProvenanceError("Unable to find build definition in the provenance statement.") diff --git a/src/macaron/repo_finder/repo_finder_deps_dev.py b/src/macaron/repo_finder/repo_finder_deps_dev.py index 468bf472e..4696caa27 100644 --- a/src/macaron/repo_finder/repo_finder_deps_dev.py +++ b/src/macaron/repo_finder/repo_finder_deps_dev.py @@ -125,7 +125,7 @@ def _create_urls(self, purl: PackageURL) -> list[str]: The list of created URLs. """ # See https://docs.deps.dev/api/v3alpha/ - base_url = f"https://api.deps.dev/v3alpha/purl/{encode(str(purl)).replace('/', '%2F')}" + base_url = f"https://api.deps.dev/v3alpha/purl/{encode(str(purl), safe='')}" if not base_url: return [] diff --git a/src/macaron/slsa_analyzer/analyze_context.py b/src/macaron/slsa_analyzer/analyze_context.py index 1f00df010..f6c8fd22a 100644 --- a/src/macaron/slsa_analyzer/analyze_context.py +++ b/src/macaron/slsa_analyzer/analyze_context.py @@ -313,7 +313,7 @@ def __str__(self) -> str: return output -def store_inferred_provenance( +def store_inferred_build_info_results( ctx: AnalyzeContext, ci_info: CIInfo, ci_service: BaseCIService, @@ -321,8 +321,9 @@ def store_inferred_provenance( job_id: str | None = None, step_id: str | None = None, step_name: str | None = None, + callee_node_type: str | None = None, ) -> None: - """Store the data related to the build provenance when the project does not generate provenances. + """Store the data related to the build. Parameters ---------- @@ -340,15 +341,13 @@ def store_inferred_provenance( The CI step ID. step_name: str | None The CI step name. + callee_node_type: str | None + The callee node type in the call graph. """ # TODO: This data is potentially duplicated in the check result tables. Instead of storing the data # in the context object, retrieve it from the result tables and remove this function. - if ( - ctx.dynamic_data["is_inferred_prov"] - and ci_info["provenances"] - and isinstance(ci_info["provenances"][0].payload, InTotoV01Payload) - ): - predicate: Any = ci_info["provenances"][0].payload.statement["predicate"] + if isinstance(ci_info["build_info_results"], InTotoV01Payload): + predicate: Any = ci_info["build_info_results"].statement["predicate"] predicate["buildType"] = f"Custom {ci_service.name}" predicate["builder"]["id"] = trigger_link predicate["invocation"]["configSource"]["uri"] = ( @@ -359,3 +358,4 @@ def store_inferred_provenance( predicate["buildConfig"]["jobID"] = job_id or "" predicate["buildConfig"]["stepID"] = step_id or "" predicate["buildConfig"]["stepName"] = step_name or "" + predicate["buildConfig"]["calleeType"] = callee_node_type diff --git a/src/macaron/slsa_analyzer/analyzer.py b/src/macaron/slsa_analyzer/analyzer.py index 6f809894a..8190f87fd 100644 --- a/src/macaron/slsa_analyzer/analyzer.py +++ b/src/macaron/slsa_analyzer/analyzer.py @@ -927,6 +927,7 @@ def _determine_ci_services(self, analyze_ctx: AnalyzeContext, git_service: BaseG asset=VirtualReleaseAsset(name="No_ASSET", url="NO_URL", size_in_bytes=0), ) ], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) ) diff --git a/src/macaron/slsa_analyzer/build_tool/base_build_tool.py b/src/macaron/slsa_analyzer/build_tool/base_build_tool.py index 13a25cde3..db0fff3cb 100644 --- a/src/macaron/slsa_analyzer/build_tool/base_build_tool.py +++ b/src/macaron/slsa_analyzer/build_tool/base_build_tool.py @@ -307,7 +307,54 @@ def match_cmd_args(self, cmd: list[str], tools: list[str], args: list[str]) -> b return False - def infer_confidence_deploy_command(self, cmd: BuildToolCommand) -> Confidence: + def infer_confidence_deploy_workflow(self, ci_path: str, provenance_workflow: str | None = None) -> Confidence: + """ + Infer the confidence level for the deploy CI workflow. + + Parameters + ---------- + ci_path: str + The path to the CI workflow. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. + + Returns + ------- + Confidence + The confidence level for the deploy command. + """ + # Apply heuristics and assign weights and scores for the discovered evidence. + evidence_weight_map = EvidenceWeightMap( + [ + Evidence(name="ci_workflow_deploy", found=False, weight=2), + ] + ) + + # Check if the CI workflow path for the build command is captured in a provenance file. + if provenance_workflow and ci_path.endswith(provenance_workflow): + # We add this evidence only if a provenance is found to make sure we pick the right triggering + # workflow in the call graph. Otherwise, lack of provenance would have always lowered the + # confidence score, making the rest of the heuristics less effective. + evidence_weight_map.add( + Evidence(name="workflow_in_provenance", found=True, weight=5), + ) + + # Check workflow names. + deploy_keywords = ["release", "deploy", "publish"] + test_keywords = ["test", "snapshot"] + for deploy_kw in deploy_keywords: + if deploy_kw in os.path.basename(ci_path.lower()): + is_test = (test_kw for test_kw in test_keywords if test_kw in os.path.basename(ci_path.lower())) + if any(is_test): + continue + evidence_weight_map.update_result(name="ci_workflow_release", found=True) + break + + return Confidence.normalize(evidence_weight_map=evidence_weight_map) + + def infer_confidence_deploy_command( + self, cmd: BuildToolCommand, provenance_workflow: str | None = None + ) -> Confidence: """ Infer the confidence level for the deploy command. @@ -315,6 +362,8 @@ def infer_confidence_deploy_command(self, cmd: BuildToolCommand) -> Confidence: ---------- cmd: BuildToolCommand The build tool command object. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -332,6 +381,15 @@ def infer_confidence_deploy_command(self, cmd: BuildToolCommand) -> Confidence: ] ) + # Check if the CI workflow path for the build command is captured in a provenance file. + if provenance_workflow and cmd["ci_path"].endswith(provenance_workflow): + # We add this evidence only if a provenance is found to make sure we pick the right triggering + # workflow in the call graph. Otherwise, lack of provenance would have always lowered the + # confidence score, making the rest of the heuristics less effective. + evidence_weight_map.add( + Evidence(name="workflow_in_provenance", found=True, weight=5), + ) + # Check if secrets are present in the caller job. if cmd["reachable_secrets"]: evidence_weight_map.update_result(name="reachable_secrets", found=True) @@ -350,7 +408,7 @@ def infer_confidence_deploy_command(self, cmd: BuildToolCommand) -> Confidence: return Confidence.normalize(evidence_weight_map=evidence_weight_map) def is_deploy_command( - self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None + self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None, provenance_workflow: str | None = None ) -> tuple[bool, Confidence]: """ Determine if the command is a deploy command. @@ -364,6 +422,8 @@ def is_deploy_command( The build tool command object. excluded_configs: list[str] | None Build tool commands that are called from these configuration files are excluded. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -383,7 +443,7 @@ def is_deploy_command( if excluded_configs and os.path.basename(cmd["ci_path"]) in excluded_configs: return False, Confidence.HIGH - return True, self.infer_confidence_deploy_command(cmd=cmd) + return True, self.infer_confidence_deploy_command(cmd=cmd, provenance_workflow=provenance_workflow) def is_package_command( self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None diff --git a/src/macaron/slsa_analyzer/build_tool/npm.py b/src/macaron/slsa_analyzer/build_tool/npm.py index 27c7e2de3..5f575b899 100644 --- a/src/macaron/slsa_analyzer/build_tool/npm.py +++ b/src/macaron/slsa_analyzer/build_tool/npm.py @@ -90,7 +90,7 @@ def get_dep_analyzer(self) -> DependencyAnalyzer: return NoneDependencyAnalyzer() def is_deploy_command( - self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None + self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None, provenance_workflow: str | None = None ) -> tuple[bool, Confidence]: """ Determine if the command is a deploy command. @@ -104,6 +104,8 @@ def is_deploy_command( The build tool command object. excluded_configs: list[str] | None Build tool commands that are called from these configuration files are excluded. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -134,7 +136,7 @@ def is_deploy_command( if excluded_configs and os.path.basename(cmd["ci_path"]) in excluded_configs: return False, Confidence.HIGH - return True, self.infer_confidence_deploy_command(cmd) + return True, self.infer_confidence_deploy_command(cmd, provenance_workflow) def is_package_command( self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None diff --git a/src/macaron/slsa_analyzer/build_tool/pip.py b/src/macaron/slsa_analyzer/build_tool/pip.py index da3f980cd..5abf0c0ba 100644 --- a/src/macaron/slsa_analyzer/build_tool/pip.py +++ b/src/macaron/slsa_analyzer/build_tool/pip.py @@ -98,7 +98,7 @@ def get_dep_analyzer(self) -> DependencyAnalyzer: ) def is_deploy_command( - self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None + self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None, provenance_workflow: str | None = None ) -> tuple[bool, Confidence]: """ Determine if the command is a deploy command. @@ -112,6 +112,8 @@ def is_deploy_command( The build tool command object. excluded_configs: list[str] | None Build tool commands that are called from these configuration files are excluded. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -141,7 +143,7 @@ def is_deploy_command( if excluded_configs and os.path.basename(cmd["ci_path"]) in excluded_configs: return False, Confidence.HIGH - return True, self.infer_confidence_deploy_command(cmd) + return True, self.infer_confidence_deploy_command(cmd, provenance_workflow) def is_package_command( self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None diff --git a/src/macaron/slsa_analyzer/build_tool/poetry.py b/src/macaron/slsa_analyzer/build_tool/poetry.py index bd538a5ea..eeb54216b 100644 --- a/src/macaron/slsa_analyzer/build_tool/poetry.py +++ b/src/macaron/slsa_analyzer/build_tool/poetry.py @@ -136,7 +136,7 @@ def get_dep_analyzer(self) -> DependencyAnalyzer: ) def is_deploy_command( - self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None + self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None, provenance_workflow: str | None = None ) -> tuple[bool, Confidence]: """ Determine if the command is a deploy command. @@ -150,6 +150,8 @@ def is_deploy_command( The build tool command object. excluded_configs: list[str] | None Build tool commands that are called from these configuration files are excluded. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -179,7 +181,7 @@ def is_deploy_command( if excluded_configs and os.path.basename(cmd["ci_path"]) in excluded_configs: return False, Confidence.HIGH - return True, self.infer_confidence_deploy_command(cmd) + return True, self.infer_confidence_deploy_command(cmd, provenance_workflow) def is_package_command( self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None diff --git a/src/macaron/slsa_analyzer/build_tool/yarn.py b/src/macaron/slsa_analyzer/build_tool/yarn.py index 2856dc4ee..90c424035 100644 --- a/src/macaron/slsa_analyzer/build_tool/yarn.py +++ b/src/macaron/slsa_analyzer/build_tool/yarn.py @@ -88,7 +88,7 @@ def get_dep_analyzer(self) -> DependencyAnalyzer: return NoneDependencyAnalyzer() def is_deploy_command( - self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None + self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None, provenance_workflow: str | None = None ) -> tuple[bool, Confidence]: """ Determine if the command is a deploy command. @@ -102,6 +102,8 @@ def is_deploy_command( The build tool command object. excluded_configs: list[str] | None Build tool commands that are called from these configuration files are excluded. + provenance_workflow: str | None + The relative path to the root CI file that is captured in a provenance or None if provenance is not found. Returns ------- @@ -132,7 +134,7 @@ def is_deploy_command( if excluded_configs and os.path.basename(cmd["ci_path"]) in excluded_configs: return False, Confidence.HIGH - return True, self.infer_confidence_deploy_command(cmd) + return True, self.infer_confidence_deploy_command(cmd, provenance_workflow) def is_package_command( self, cmd: BuildToolCommand, excluded_configs: list[str] | None = None diff --git a/src/macaron/slsa_analyzer/checks/build_as_code_check.py b/src/macaron/slsa_analyzer/checks/build_as_code_check.py index 0a0f95c48..df00ef2b3 100644 --- a/src/macaron/slsa_analyzer/checks/build_as_code_check.py +++ b/src/macaron/slsa_analyzer/checks/build_as_code_check.py @@ -12,10 +12,11 @@ from sqlalchemy.sql.sqltypes import String from macaron.database.table_definitions import CheckFacts -from macaron.errors import CallGraphError +from macaron.errors import CallGraphError, ProvenanceError from macaron.parsers.bashparser import BashNode -from macaron.parsers.github_workflow_model import ActionStep, Identified, ReusableWorkflowCallJob -from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_provenance +from macaron.parsers.github_workflow_model import ActionStep +from macaron.repo_finder.provenance_extractor import ProvenancePredicate +from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_build_info_results from macaron.slsa_analyzer.checks.base_check import BaseCheck from macaron.slsa_analyzer.checks.check_result import CheckResultData, CheckResultType, Confidence, JustificationType from macaron.slsa_analyzer.ci_service.base_ci_service import BaseCIService, NoneCIService @@ -78,9 +79,9 @@ class BuildAsCodeFacts(CheckFacts): class BuildAsCodeCheck(BaseCheck): - """This class checks the build as code requirement. + """This check analyzes the CI configurations to determine if the software component is published automatically. - See https://slsa.dev/spec/v0.1/requirements#build-as-code. + As a requirement of this check, the software component should be published using a hosted build service. """ def __init__(self) -> None: @@ -121,6 +122,17 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: if not build_tools: return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) + # If a provenance is found, obtain the workflow that has triggered the artifact release. + prov_workflow = None + prov_payload = ctx.dynamic_data["provenance"] + if not ctx.dynamic_data["is_inferred_prov"] and prov_payload: + try: + build_def = ProvenancePredicate.find_build_def(prov_payload.statement) + except ProvenanceError as error: + logger.error(error) + return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) + prov_workflow, _ = build_def.get_build_invocation(prov_payload.statement) + ci_services = ctx.dynamic_data["ci_services"] # Check if "build as code" holds for each build tool. @@ -150,27 +162,30 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: logger.debug("Workflow %s is not relevant. Skipping...", callee.name) continue if workflow_name in trusted_deploy_actions: - job_id = "" - step_id = "" - step_name = "" + job_id = None + step_id = None + step_name = None caller_path = "" job = callee.caller - if isinstance(job, GitHubJobNode): - job_id = job.parsed_obj.id - caller_path = job.source_path + # We always expect the caller of the node that calls a third-party + # or Reusable GitHub Action to be a GitHubJobNode. + if not isinstance(job, GitHubJobNode): + continue + + job_id = job.parsed_obj.id + caller_path = job.source_path + + # Only third-party Actions can be called from a step. + # Reusable workflows have to be directly called from the job. + # See https://docs.github.com/en/actions/sharing-automations/ \ + # reusing-workflows#calling-a-reusable-workflow if callee.node_type == GitHubWorkflowType.EXTERNAL: callee_step_obj = cast(ActionStep, callee.parsed_obj) if "id" in callee_step_obj: step_id = callee_step_obj["id"] if "name" in callee_step_obj: step_name = callee_step_obj["name"] - else: - callee_reusable = cast(Identified[ReusableWorkflowCallJob], callee.parsed_obj) - step_id = callee_reusable.id - callee_reusable_job = callee_reusable.obj - if "name" in callee_reusable_job: - step_name = callee_reusable_job["name"] trigger_link = ci_service.api_client.get_file_link( ctx.component.repository.full_name, @@ -183,15 +198,27 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: else "" ), ) - store_inferred_provenance( - ctx=ctx, - ci_info=ci_info, - ci_service=ci_service, - trigger_link=trigger_link, - job_id=job_id, - step_id=step_id, - step_name=step_name, + + trusted_workflow_confidence = tool.infer_confidence_deploy_workflow( + ci_path=caller_path, provenance_workflow=prov_workflow ) + # Store or update the inferred build information if the confidence + # for the current check fact is bigger than the maximum score. + if ( + not result_tables + or trusted_workflow_confidence + > max(result_tables, key=lambda item: item.confidence).confidence + ): + store_inferred_build_info_results( + ctx=ctx, + ci_info=ci_info, + ci_service=ci_service, + trigger_link=trigger_link, + job_id=job_id, + step_id=step_id, + step_name=step_name, + callee_node_type=callee.node_type.value, + ) result_tables.append( BuildAsCodeFacts( build_tool_name=tool.name, @@ -199,7 +226,7 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: build_trigger=trigger_link, language=tool.language.value, deploy_command=workflow_name, - confidence=Confidence.HIGH, + confidence=trusted_workflow_confidence, ) ) overall_res = CheckResultType.PASSED @@ -207,9 +234,12 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: for build_command in ci_service.get_build_tool_commands( callgraph=ci_info["callgraph"], build_tool=tool ): + # Yes or no with a confidence score. result, confidence = tool.is_deploy_command( - build_command, ci_service.get_third_party_configurations() + build_command, + ci_service.get_third_party_configurations(), + provenance_workflow=prov_workflow, ) if result: trigger_link = ci_service.api_client.get_file_link( @@ -219,13 +249,13 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: os.path.basename(build_command["ci_path"]) ), ) - # Store or update the inferred provenance if the confidence + # Store or update the inferred build information if the confidence # for the current check fact is bigger than the maximum score. if ( not result_tables or confidence > max(result_tables, key=lambda item: item.confidence).confidence ): - store_inferred_provenance( + store_inferred_build_info_results( ctx=ctx, ci_info=ci_info, ci_service=ci_service, @@ -280,7 +310,7 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: if not config_name: break - store_inferred_provenance( + store_inferred_build_info_results( ctx=ctx, ci_info=ci_info, ci_service=ci_service, trigger_link=config_name ) result_tables.append( diff --git a/src/macaron/slsa_analyzer/checks/build_service_check.py b/src/macaron/slsa_analyzer/checks/build_service_check.py index c5f43c484..abbef2f35 100644 --- a/src/macaron/slsa_analyzer/checks/build_service_check.py +++ b/src/macaron/slsa_analyzer/checks/build_service_check.py @@ -12,7 +12,7 @@ from macaron.database.table_definitions import CheckFacts from macaron.errors import CallGraphError -from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_provenance +from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_build_info_results from macaron.slsa_analyzer.checks.base_check import BaseCheck from macaron.slsa_analyzer.checks.check_result import CheckResultData, CheckResultType, Confidence, JustificationType from macaron.slsa_analyzer.ci_service.base_ci_service import BaseCIService, NoneCIService @@ -140,7 +140,7 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: not result_tables or confidence > max(result_tables, key=lambda item: item.confidence).confidence ): - store_inferred_provenance( + store_inferred_build_info_results( ctx=ctx, ci_info=ci_info, ci_service=ci_service, trigger_link=trigger_link ) result_tables.append( @@ -181,7 +181,7 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: if not config_name: break - store_inferred_provenance( + store_inferred_build_info_results( ctx=ctx, ci_info=ci_info, ci_service=ci_service, trigger_link=config_name ) result_tables.append( diff --git a/src/macaron/slsa_analyzer/checks/check_result.py b/src/macaron/slsa_analyzer/checks/check_result.py index 5e7193099..f9d5c1ad0 100644 --- a/src/macaron/slsa_analyzer/checks/check_result.py +++ b/src/macaron/slsa_analyzer/checks/check_result.py @@ -201,7 +201,7 @@ def justification_report(self) -> list[tuple[Confidence, list]]: # Look for columns that are have "justification" metadata. for col in result.__table__.columns: column_value = getattr(result, col.name) - if col.info.get("justification") and column_value: + if col.info.get("justification") and column_value is not None: if col.info.get("justification") == JustificationType.HREF: dict_elements[col.name] = column_value elif col.info.get("justification") == JustificationType.TEXT: diff --git a/src/macaron/slsa_analyzer/checks/infer_artifact_pipeline_check.py b/src/macaron/slsa_analyzer/checks/infer_artifact_pipeline_check.py index 82afc9720..594c5c467 100644 --- a/src/macaron/slsa_analyzer/checks/infer_artifact_pipeline_check.py +++ b/src/macaron/slsa_analyzer/checks/infer_artifact_pipeline_check.py @@ -4,58 +4,78 @@ """This module contains the InferArtifactPipelineCheck class to check if an artifact is published from a pipeline automatically.""" import logging +from datetime import datetime -from sqlalchemy import ForeignKey +from sqlalchemy import Boolean, ForeignKey from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import String from macaron.config.defaults import defaults from macaron.database.table_definitions import CheckFacts -from macaron.errors import InvalidHTTPResponseError +from macaron.errors import InvalidHTTPResponseError, ProvenanceError +from macaron.json_tools import json_extract +from macaron.repo_finder.provenance_extractor import ProvenancePredicate from macaron.slsa_analyzer.analyze_context import AnalyzeContext -from macaron.slsa_analyzer.build_tool.gradle import Gradle -from macaron.slsa_analyzer.build_tool.maven import Maven from macaron.slsa_analyzer.checks.base_check import BaseCheck from macaron.slsa_analyzer.checks.check_result import CheckResultData, CheckResultType, Confidence, JustificationType from macaron.slsa_analyzer.ci_service.base_ci_service import NoneCIService -from macaron.slsa_analyzer.package_registry.maven_central_registry import MavenCentralRegistry -from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.registry import registry from macaron.slsa_analyzer.slsa_req import ReqName -from macaron.slsa_analyzer.specs.package_registry_spec import PackageRegistryInfo logger: logging.Logger = logging.getLogger(__name__) -class InferArtifactPipelineFacts(CheckFacts): +class ArtifactPipelineFacts(CheckFacts): """The ORM mapping for justifications of the infer_artifact_pipeline check.""" - __tablename__ = "_infer_artifact_pipeline_check" + __tablename__ = "_artifact_pipeline_check" #: The primary key. id: Mapped[int] = mapped_column(ForeignKey("_check_facts.id"), primary_key=True) # noqa: A003 + #: The URL of the workflow file that triggered deploy. + deploy_workflow: Mapped[str] = mapped_column(String, nullable=True, info={"justification": JustificationType.HREF}) + #: The workflow job that triggered deploy. - deploy_job: Mapped[str] = mapped_column(String, nullable=False, info={"justification": JustificationType.TEXT}) + deploy_job: Mapped[str] = mapped_column(String, nullable=True, info={"justification": JustificationType.TEXT}) #: The workflow step that triggered deploy. - deploy_step: Mapped[str] = mapped_column(String, nullable=False, info={"justification": JustificationType.TEXT}) + deploy_step: Mapped[str | None] = mapped_column( + String, nullable=True, info={"justification": JustificationType.TEXT} + ) #: The workflow run URL. - run_url: Mapped[str] = mapped_column(String, nullable=False, info={"justification": JustificationType.HREF}) + run_url: Mapped[str | None] = mapped_column(String, nullable=True, info={"justification": JustificationType.HREF}) + + #: The triggering workflow is found from a provenance. + from_provenance: Mapped[bool] = mapped_column( + Boolean, nullable=False, info={"justification": JustificationType.TEXT} + ) + + #: The CI pipeline data is deleted. + run_deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, info={"justification": JustificationType.TEXT}) + + #: The artifact has been published before the code was committed to the source-code repository. + published_before_commit: Mapped[bool] = mapped_column( + Boolean, nullable=False, info={"justification": JustificationType.TEXT} + ) __mapper_args__ = { "polymorphic_identity": "_infer_artifact_pipeline_check", } -class InferArtifactPipelineCheck(BaseCheck): - """This check detects a potential pipeline from which an artifact is published. +class ArtifactPipelineCheck(BaseCheck): + """This check detects a pipeline from which an artifact is published. + + This check depends on the deploy command identified by the ``mcn_build_as_code_1 check``. + If a deploy command is detected, this check will attempt to locate a successful CI + pipeline that triggered the step containing the deploy command. - When a verifiable provenance is found for an artifact, the result of this check can be discarded. - Otherwise, we check whether a CI workflow run has automatically published the artifact. + When a verifiable provenance is found for an artifact, we use it to obtain the pipeline trigger. + Otherwise, we use heuristics to find the triggering pipeline. - We use several heuristics in this check: + We use several heuristics in this check for inference: * The workflow run should have started before the artifact is published. * The workflow step that calls a deploy command should have run successfully. @@ -68,16 +88,19 @@ class InferArtifactPipelineCheck(BaseCheck): def __init__(self) -> None: """Initialize the InferArtifactPipeline instance.""" - check_id = "mcn_infer_artifact_pipeline_1" - description = "Detects potential pipelines from which an artifact is published." + check_id = "mcn_find_artifact_pipeline_1" + description = """ + Detects pipelines from which an artifact is published. + + When a verifiable provenance is found for an artifact, we use it to obtain the pipeline trigger. + """ depends_on: list[tuple[str, CheckResultType]] = [("mcn_build_as_code_1", CheckResultType.PASSED)] - eval_reqs = [ReqName.BUILD_AS_CODE] + eval_reqs: list[ReqName] = [] super().__init__( check_id=check_id, description=description, depends_on=depends_on, eval_reqs=eval_reqs, - result_on_skip=CheckResultType.FAILED, ) def run_check(self, ctx: AnalyzeContext) -> CheckResultData: @@ -93,35 +116,55 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: CheckResultData The result type of the check. """ - # This check requires the build_as_code check to pass and a repository to be available. + # This check requires a repository to be available. if not ctx.component.repository: return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) # Look for the artifact in the corresponding registry and find the publish timestamp. artifact_published_date = None - package_registry_info_entries = ctx.dynamic_data["package_registries"] - for package_registry_info_entry in package_registry_info_entries: - match package_registry_info_entry: - # TODO: add package registries for other ecosystems. - case PackageRegistryInfo( - build_tool=Gradle() | Maven(), - package_registry=MavenCentralRegistry() as mvn_central_registry, - ): - group_id = ctx.component.namespace - artifact_id = ctx.component.name - version = ctx.component.version - try: - artifact_published_date = mvn_central_registry.find_publish_timestamp( - group_id, artifact_id, version - ) - except InvalidHTTPResponseError as error: - logger.debug(error) + for registry_info in ctx.dynamic_data["package_registries"]: + if registry_info.build_tool.purl_type == ctx.component.type: + try: + artifact_published_date = registry_info.package_registry.find_publish_timestamp(ctx.component.purl) + break + except InvalidHTTPResponseError as error: + logger.debug(error) + except NotImplementedError: + continue + + # This check requires the timestamps of published artifact and its source-code commit to proceed. + # If the timestamps are not found, we return with a fail result. + try: + commit_date = datetime.strptime(ctx.component.repository.commit_date, "%Y-%m-%dT%H:%M:%S%z") + except ValueError as error: + logger.debug("Failed to parse date string '%s': %s", ctx.component.repository.commit_date, error) + return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) - # This check requires the artifact publish artifact to proceed. If the timestamp is not - # found, we return with a fail result. if not artifact_published_date: + logger.debug("Unable to find a publish date for the artifact.") return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) + # If an artifact is published before the corresponding code is committed, there cannot be + # a CI pipeline that triggered the publishing. + if published_before_commit := artifact_published_date < commit_date: + logger.debug("Publish date %s is earlier than commit date %s.", artifact_published_date, commit_date) + + # Found an acceptable publish timestamp to proceed. + logger.debug("Publish date %s is later than commit date %s.", artifact_published_date, commit_date) + + # If a provenance is found, obtain the workflow and the pipeline that has triggered the artifact release. + prov_workflow = None + prov_trigger_run = None + prov_payload = ctx.dynamic_data["provenance"] + if not ctx.dynamic_data["is_inferred_prov"] and prov_payload: + # Obtain the build-related fields from the provenance. + try: + build_def = ProvenancePredicate.find_build_def(prov_payload.statement) + except ProvenanceError as error: + logger.error(error) + return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) + prov_workflow, prov_trigger_run = build_def.get_build_invocation(prov_payload.statement) + # Obtain the metadata inferred by the build_as_code check, which is stored in the `provenances` # attribute of the corresponding CI service. ci_services = ctx.dynamic_data["ci_services"] @@ -131,66 +174,147 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: if isinstance(ci_service, NoneCIService): continue - if ctx.dynamic_data["is_inferred_prov"] and ci_info["provenances"]: - for inferred_prov in ci_info["provenances"]: - # Skip processing the inferred provenance if it does not conform with the in-toto v0.1 specification. - if not isinstance(inferred_prov.payload, InTotoV01Payload): - continue - - # This check requires the job and step calling the deploy command. - # Validate the content of inferred_prov. - predicate = inferred_prov.payload.statement["predicate"] - if ( - not predicate - or not isinstance(predicate["invocation"], dict) - or "configSource" not in predicate["invocation"] - or not isinstance(predicate["invocation"]["configSource"], dict) - or "entryPoint" not in predicate["invocation"]["configSource"] - or not isinstance(predicate["invocation"]["configSource"]["entryPoint"], str) - ): - continue - if ( - not isinstance(predicate["buildConfig"], dict) - or "jobID" not in predicate["buildConfig"] - or not isinstance(predicate["buildConfig"]["jobID"], str) - or "stepID" not in predicate["buildConfig"] - or not isinstance(predicate["buildConfig"]["stepID"], str) - or "stepName" not in predicate["buildConfig"] - or not isinstance(predicate["buildConfig"]["stepName"], str) - ): - continue - try: - publish_time_range = defaults.getint("package_registries", "publish_time_range", fallback=3600) - except ValueError as error: - logger.error( - "Configuration error: publish_time_range in section of package_registries is not a valid integer %s.", - error, + # Different CI services have different retention policies for the workflow runs. + # Make sure the artifact is not older than the retention date. + ci_run_deleted = ci_service.workflow_run_deleted(artifact_published_date) + + # If the artifact is published before the source code is committed, the check should fail. + if published_before_commit: + return CheckResultData( + result_tables=[ + ArtifactPipelineFacts( + from_provenance=bool(prov_workflow), + run_deleted=ci_run_deleted, + published_before_commit=published_before_commit, + confidence=Confidence.HIGH, ) - return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) - - # Find the potential workflow runs. - if html_urls := ci_service.workflow_run_in_date_time_range( - repo_full_name=ctx.component.repository.full_name, - workflow=predicate["invocation"]["configSource"]["entryPoint"], - date_time=artifact_published_date, - step_name=predicate["buildConfig"]["stepName"], - step_id=predicate["buildConfig"]["stepID"], - time_range=publish_time_range, - ): - result_tables: list[CheckFacts] = [] - for html_url in html_urls: - result_tables.append( - InferArtifactPipelineFacts( - deploy_job=predicate["buildConfig"]["jobID"], - deploy_step=predicate["buildConfig"]["stepID"] - or predicate["buildConfig"]["stepName"], - run_url=html_url, - confidence=Confidence.MEDIUM, - ) - ) - return CheckResultData(result_tables=result_tables, result_type=CheckResultType.PASSED) - - return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) - - -registry.register(InferArtifactPipelineCheck()) + ], + result_type=CheckResultType.FAILED, + ) + # Obtain the job and step calling the deploy command. + # This data must have been found already by the build-as-code check. + build_predicate = ci_info["build_info_results"].statement["predicate"] + if build_predicate is None: + continue + build_entry_point = json_extract(build_predicate, ["invocation", "configSource", "entryPoint"], str) + + # If provenance exists check that the entry point extracted from the build-as-code check matches. + if build_entry_point is None or (prov_workflow and not build_entry_point.endswith(prov_workflow)): + continue + + if not (job_id := json_extract(build_predicate, ["buildConfig", "jobID"], str)): + continue + + step_id = json_extract(build_predicate, ["buildConfig", "stepID"], str) + step_name = json_extract(build_predicate, ["buildConfig", "stepName"], str) + callee_node_type = json_extract(build_predicate, ["buildConfig", "calleeType"], str) + + try: + publish_time_range = defaults.getint("package_registry", "publish_time_range", fallback=7200) + except ValueError as error: + logger.error( + "Configuration error: publish_time_range in section of package_registries is not a valid integer %s.", + error, + ) + return CheckResultData(result_tables=[], result_type=CheckResultType.FAILED) + + # Find the workflow runs that have potentially triggered the artifact publishing. + html_urls = ci_service.workflow_run_in_date_time_range( + repo_full_name=ctx.component.repository.full_name, + workflow=build_entry_point, + publish_date_time=artifact_published_date, + commit_date_time=commit_date, + job_id=job_id, + step_name=step_name, + step_id=step_id, + time_range=publish_time_range, + callee_node_type=callee_node_type, + ) + + # If provenance exists, we expect the timestamp of the reported triggered run + # to be within an acceptable range, have succeeded, and called the deploy command. + if prov_trigger_run: + result_type = CheckResultType.FAILED + # If the triggering run in the provenance does not satisfy any of the requirements above, + # set the confidence as medium because the build-as-code results might be imprecise. + confidence = Confidence.MEDIUM + if prov_trigger_run in html_urls: + # The workflow's deploy step has been successful. In this case, the check can pass with a + # high confidence. + confidence = Confidence.HIGH + result_type = CheckResultType.PASSED + elif ci_run_deleted: + # The workflow run data has been deleted and we cannot analyze any further. + confidence = Confidence.LOW + result_type = CheckResultType.UNKNOWN + + return CheckResultData( + result_tables=[ + ArtifactPipelineFacts( + deploy_workflow=build_entry_point, + deploy_job=job_id, + deploy_step=step_id or step_name, + run_url=prov_trigger_run, + from_provenance=True, + run_deleted=ci_run_deleted, + published_before_commit=published_before_commit, + confidence=confidence, + ) + ], + result_type=result_type, + ) + + # Logic for artifacts that do not have a provenance. + result_tables: list[CheckFacts] = [] + for html_url in html_urls: + result_tables.append( + ArtifactPipelineFacts( + deploy_workflow=build_entry_point, + deploy_job=job_id, + deploy_step=step_id or step_name, + run_url=html_url, + from_provenance=False, + run_deleted=ci_run_deleted, + published_before_commit=published_before_commit, + confidence=Confidence.MEDIUM, + ) + ) + if html_urls: + return CheckResultData(result_tables=result_tables, result_type=CheckResultType.PASSED) + if ci_run_deleted: + # We set the confidence as low because the analysis could not be performed due to missing + # CI run data. + return CheckResultData( + result_tables=[ + ArtifactPipelineFacts( + deploy_workflow=build_entry_point, + deploy_job=job_id, + deploy_step=step_id or step_name, + run_url=None, + from_provenance=False, + run_deleted=ci_run_deleted, + published_before_commit=published_before_commit, + confidence=Confidence.LOW, + ) + ], + result_type=CheckResultType.UNKNOWN, + ) + + if ci_run_deleted or published_before_commit: + # If the CI run data is deleted or the artifact is older than the source-code commit, + # The check should have failed earlier and we should not reach here. + logger.debug("Unexpected error has happened.") + return CheckResultData( + result_tables=[], + result_type=CheckResultType.FAILED, + ) + + # We should reach here when the analysis has failed to detect any successful deploy step in a + # CI run. In this case the check fails with a medium confidence. + return CheckResultData( + result_tables=[], + result_type=CheckResultType.FAILED, + ) + + +registry.register(ArtifactPipelineCheck()) diff --git a/src/macaron/slsa_analyzer/checks/trusted_builder_l3_check.py b/src/macaron/slsa_analyzer/checks/trusted_builder_l3_check.py index ebd632e50..e9f629447 100644 --- a/src/macaron/slsa_analyzer/checks/trusted_builder_l3_check.py +++ b/src/macaron/slsa_analyzer/checks/trusted_builder_l3_check.py @@ -13,7 +13,7 @@ from macaron.config.defaults import defaults from macaron.database.table_definitions import CheckFacts -from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_provenance +from macaron.slsa_analyzer.analyze_context import AnalyzeContext, store_inferred_build_info_results from macaron.slsa_analyzer.checks.base_check import BaseCheck from macaron.slsa_analyzer.checks.check_result import CheckResultData, CheckResultType, Confidence, JustificationType from macaron.slsa_analyzer.ci_service.github_actions.analyzer import ( @@ -133,7 +133,7 @@ def run_check(self, ctx: AnalyzeContext) -> CheckResultData: ci_service.api_client.get_relative_path_of_workflow(os.path.basename(caller_path)), ) - store_inferred_provenance( + store_inferred_build_info_results( ctx=ctx, ci_info=ci_info, ci_service=ci_service, trigger_link=caller_link ) diff --git a/src/macaron/slsa_analyzer/ci_service/base_ci_service.py b/src/macaron/slsa_analyzer/ci_service/base_ci_service.py index 6089d9aff..4a2b69e19 100644 --- a/src/macaron/slsa_analyzer/ci_service/base_ci_service.py +++ b/src/macaron/slsa_analyzer/ci_service/base_ci_service.py @@ -187,10 +187,13 @@ def workflow_run_in_date_time_range( self, repo_full_name: str, workflow: str, - date_time: datetime, + publish_date_time: datetime, + commit_date_time: datetime, + job_id: str, step_name: str | None, step_id: str | None, time_range: int = 0, + callee_node_type: str | None = None, ) -> set[str]: """Check if the repository has a workflow run started before the date_time timestamp within the time_range. @@ -205,8 +208,12 @@ def workflow_run_in_date_time_range( The target repo's full name. workflow : str The workflow URL. - date_time: datetime - The datetime object to query. + publish_date_time: datetime + The artifact publishing datetime object. + commit_date_time: datetime + The artifact's source-code commit datetime object. + job_id:str + The job that triggers the run. step_name: str The step in the GitHub Action workflow that needs to be checked. time_range: int @@ -220,6 +227,22 @@ def workflow_run_in_date_time_range( """ return set() + def workflow_run_deleted(self, timestamp: datetime) -> bool: + """ + Check if the CI run data is deleted based on a retention policy. + + Parameters + ---------- + timestamp: datetime + The timestamp of the CI run. + + Returns + ------- + bool + True if the CI run data is deleted. + """ + return False + def get_build_tool_commands(self, callgraph: CallGraph, build_tool: BaseBuildTool) -> Iterable[BuildToolCommand]: """ Traverse the callgraph and find all the reachable build tool commands. diff --git a/src/macaron/slsa_analyzer/ci_service/github_actions/analyzer.py b/src/macaron/slsa_analyzer/ci_service/github_actions/analyzer.py index 2009d97ff..2f0e49888 100644 --- a/src/macaron/slsa_analyzer/ci_service/github_actions/analyzer.py +++ b/src/macaron/slsa_analyzer/ci_service/github_actions/analyzer.py @@ -45,7 +45,7 @@ class ThirdPartyAction: action_version: str | None -class GitHubWorkflowType(Enum): +class GitHubWorkflowType(str, Enum): """This class represents different GitHub Actions workflow types.""" INTERNAL = "internal" # Workflows declared in the repo. diff --git a/src/macaron/slsa_analyzer/ci_service/github_actions/github_actions_ci.py b/src/macaron/slsa_analyzer/ci_service/github_actions/github_actions_ci.py index dec8221dc..d3f820ade 100644 --- a/src/macaron/slsa_analyzer/ci_service/github_actions/github_actions_ci.py +++ b/src/macaron/slsa_analyzer/ci_service/github_actions/github_actions_ci.py @@ -20,6 +20,7 @@ from macaron.slsa_analyzer.ci_service.github_actions.analyzer import ( GitHubJobNode, GitHubWorkflowNode, + GitHubWorkflowType, build_call_graph_from_path, find_language_setup_action, get_ci_events, @@ -243,14 +244,68 @@ def has_latest_run_passed( return "" + def check_publish_start_commit_timestamps( + self, started_at: datetime, publish_date_time: datetime, commit_date_time: datetime, time_range: int + ) -> bool: + """ + Check if the timestamps of CI run, artifact publishing, and commit date are within the acceptable time range and valid. + + This function checks that the CI run has happened before the artifact publishing timestamp. + + This function also verifies whether the commit date is within an acceptable time range + from the publish start time. The acceptable range is defined as half of the provided + time range parameter. + + Parameters + ---------- + started_at : datetime + The timestamp indicating when the GitHub Actions workflow started. + publish_date_time : datetime + The timestamp indicating when the artifact is published. + commit_date_time : datetime + The timestamp of the source code commit. + time_range : int + The total acceptable time range in seconds. + + Returns + ------- + bool + True if the commit date is within the acceptable range from the publish start time, + False otherwise. Returns False in case of any errors during timestamp comparisons. + """ + # Make sure the source-code commit date is also within acceptable range. + acceptable_range = time_range / 2 + try: + if started_at < publish_date_time: + if timedelta.total_seconds(abs(started_at - commit_date_time)) > acceptable_range: + logger.debug( + ( + "The difference between GitHub Actions starting time %s and source commit time %s" + " is not within %s seconds." + ), + started_at, + commit_date_time, + acceptable_range, + ) + return False + return True + + except (ValueError, OverflowError, TypeError) as error: + logger.debug(error) + + return False + def workflow_run_in_date_time_range( self, repo_full_name: str, workflow: str, - date_time: datetime, + publish_date_time: datetime, + commit_date_time: datetime, + job_id: str, step_name: str | None, step_id: str | None, time_range: int = 0, + callee_node_type: str | None = None, ) -> set[str]: """Check if the repository has a workflow run started before the date_time timestamp within the time_range. @@ -273,7 +328,6 @@ def workflow_run_in_date_time_range( The ID of the step in the GitHub Action workflow that needs to be checked. time_range: int The date-time range in seconds. The default value is 0. - For example a 30 seconds range for 2022-11-05T20:30 is 2022-11-05T20:15..2022-11-05T20:45. Returns ------- @@ -281,15 +335,16 @@ def workflow_run_in_date_time_range( The set of URLs found for the workflow within the time range. """ logger.debug( - "Getting the latest workflow run of %s at %s within time range %s", + "Getting the latest workflow run of %s at publishing time %s and source commit date %s within time range %s.", workflow, - str(date_time), + str(publish_date_time), + str(commit_date_time), str(time_range), ) html_urls: set[str] = set() try: - datetime_from = date_time - timedelta(seconds=time_range) + datetime_from = publish_date_time - timedelta(seconds=time_range) except (OverflowError, OSError, TypeError) as error: logger.debug(error) return html_urls @@ -298,7 +353,7 @@ def workflow_run_in_date_time_range( logger.debug("Search for the workflow runs within the range.") try: run_data = self.api_client.get_workflow_run_for_date_time_range( - repo_full_name, f"{datetime_from.isoformat()}..{date_time.isoformat()}" + repo_full_name, f"{datetime_from.isoformat()}..{publish_date_time.isoformat()}" ) except ValueError as error: logger.debug(error) @@ -321,33 +376,48 @@ def workflow_run_in_date_time_range( continue # Find the matching step and check its `conclusion` and `started_at` attributes. + html_url = None for job in run_jobs["jobs"]: + # If the deploy step is a Reusable Workflow, there won't be any steps in the caller job. + if callee_node_type == GitHubWorkflowType.REUSABLE.value: + if not job["name"].startswith(job_id) or job["conclusion"] != "success": + continue + started_at = datetime.fromisoformat(job["started_at"]) + if self.check_publish_start_commit_timestamps( + started_at=started_at, + publish_date_time=publish_date_time, + commit_date_time=commit_date_time, + time_range=time_range, + ): + run_id = item["id"] + html_url = item["html_url"] + break + for step in job["steps"]: - if (step["name"] not in [step_name, step_id]) or step["conclusion"] != "success": + if step["name"] not in [step_name, step_id] or step["conclusion"] != "success": continue - try: - if datetime.fromisoformat(step["started_at"]) < date_time: - run_id: str = item["id"] - html_url: str = item["html_url"] - logger.info( - "The workflow run status of %s (id = %s, url = %s, step = %s) is %s.", - workflow, - run_id, - html_url, - step["name"], - step["conclusion"], - ) - html_urls.add(html_url) - else: - logger.debug( - "The workflow start run %s happened after %s with status %s.", - datetime.fromisoformat(step["started_at"]), - date_time, - step["conclusion"], - ) - # Handle errors for calls to `fromisoformat()` and the time comparison. - except (ValueError, OverflowError, OSError, TypeError) as error: - logger.debug(error) + started_at = datetime.fromisoformat(step["started_at"]) + if self.check_publish_start_commit_timestamps( + started_at=started_at, + publish_date_time=publish_date_time, + commit_date_time=commit_date_time, + time_range=time_range, + ): + run_id = item["id"] + html_url = item["html_url"] + logger.info( + "The workflow run status of %s (id = %s, url = %s, step = %s) is %s.", + workflow, + run_id, + html_url, + step["name"], + step["conclusion"], + ) + break + + if html_url: + html_urls.add(html_url) + except KeyError as key_error: logger.debug( "Unable to read data of %s from the GitHub API result. Error: %s", @@ -357,6 +427,35 @@ def workflow_run_in_date_time_range( return html_urls + def workflow_run_deleted(self, timestamp: datetime) -> bool: + """ + Check if the CI run data is deleted based on a retention policy. + + Parameters + ---------- + timestamp: datetime + The timestamp of the CI run. + + Returns + ------- + bool + True if the CI run data is deleted. + """ + # Setting the timezone to UTC because the date format + # we are using for GitHub Actions is in ISO format, which contains the offset + # from the UTC timezone. For example: 2022-04-10T14:10:01+07:00 + # GitHub retains GitHub Actions pipeline data for 400 days. So, we cannot analyze the + # pipelines if artifacts are older than 400 days. + # https://docs.github.com/en/rest/guides/using-the-rest-api-to-interact-with-checks? + # apiVersion=2022-11-28#retention-of-checks-data + # TODO: change this check if this issue is resolved: + # https://github.com/orgs/community/discussions/138249 + if datetime.now(timezone.utc) - timedelta(days=400) > timestamp: + logger.debug("Artifact published at %s is older than 400 days.", timestamp) + return True + + return False + def search_for_workflow_run( self, workflow_id: str, diff --git a/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py b/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py index 62ae09c06..65987d1e2 100644 --- a/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py +++ b/src/macaron/slsa_analyzer/package_registry/jfrog_maven_registry.py @@ -7,6 +7,7 @@ import json import logging +from datetime import datetime from typing import NamedTuple from urllib.parse import SplitResult, urlunsplit @@ -851,3 +852,35 @@ def download_asset(self, url: str, dest: str) -> bool: return False return True + + def find_publish_timestamp(self, purl: str, registry_url: str | None = None) -> datetime: + """Make a search request to Maven Central to find the publishing timestamp of an artifact. + + The reason for directly fetching timestamps from Maven Central is that deps.dev occasionally + misses timestamps for Maven artifacts, making it unreliable for this purpose. + + To see the search API syntax see: https://central.sonatype.org/search/rest-api-guide/ + + Parameters + ---------- + purl: str + The Package URL (purl) of the package whose publication timestamp is to be retrieved. + This should conform to the PURL specification. + registry_url: str | None + The registry URL that can be set for testing. + + Returns + ------- + datetime + A timezone-aware datetime object representing the publication timestamp + of the specified package. + + Raises + ------ + InvalidHTTPResponseError + If the URL construction fails, the HTTP response is invalid, or if the response + cannot be parsed correctly, or if the expected timestamp is missing or invalid. + NotImplementedError + If not implemented for a registry. + """ + raise NotImplementedError("Fetching timestamps for artifacts on JFrog is not currently supported.") diff --git a/src/macaron/slsa_analyzer/package_registry/maven_central_registry.py b/src/macaron/slsa_analyzer/package_registry/maven_central_registry.py index 67a2b100b..92a52efd3 100644 --- a/src/macaron/slsa_analyzer/package_registry/maven_central_registry.py +++ b/src/macaron/slsa_analyzer/package_registry/maven_central_registry.py @@ -4,10 +4,11 @@ """The module provides abstractions for the Maven Central package registry.""" import logging +import urllib.parse from datetime import datetime, timezone -from urllib.parse import SplitResult, urlunsplit import requests +from packageurl import PackageURL from macaron.config.defaults import defaults from macaron.errors import ConfigurationError, InvalidHTTPResponseError @@ -75,8 +76,11 @@ class MavenCentralRegistry(PackageRegistry): def __init__( self, - hostname: str | None = None, + search_netloc: str | None = None, + search_scheme: str | None = None, search_endpoint: str | None = None, + registry_url_netloc: str | None = None, + registry_url_scheme: str | None = None, request_timeout: int | None = None, ) -> None: """ @@ -84,15 +88,25 @@ def __init__( Parameters ---------- - hostname : str - The hostname of the Maven Central service. + search_netloc: str | None = None, + The netloc of Maven Central search URL. + search_scheme: str | None = None, + The scheme of Maven Central URL. search_endpoint : str | None The search REST API to find artifacts. + registry_url_netloc: str | None + The netloc of the Maven Central registry url. + registry_url_scheme: str | None + The scheme of the Maven Central registry url. request_timeout : int | None The timeout (in seconds) for requests made to the package registry. """ - self.hostname = hostname or "" + self.search_netloc = search_netloc or "" + self.search_scheme = search_scheme or "" self.search_endpoint = search_endpoint or "" + self.registry_url_netloc = registry_url_netloc or "" + self.registry_url_scheme = registry_url_scheme or "" + self.registry_url = "" # Created from the registry_url_scheme and registry_url_netloc. self.request_timeout = request_timeout or 10 super().__init__("Maven Central Registry") @@ -109,18 +123,34 @@ def load_defaults(self) -> None: return section = defaults[section_name] - self.hostname = section.get("hostname") - if not self.hostname: + self.search_netloc = section.get("search_netloc") + if not self.search_netloc: raise ConfigurationError( - f'The "hostname" key is missing in section [{section_name}] of the .ini configuration file.' + f'The "search_netloc" key is missing in section [{section_name}] of the .ini configuration file.' ) + self.search_scheme = section.get("search_scheme", "https") self.search_endpoint = section.get("search_endpoint") if not self.search_endpoint: raise ConfigurationError( f'The "search_endpoint" key is missing in section [{section_name}] of the .ini configuration file.' ) + self.registry_url_netloc = section.get("registry_url_netloc") + if not self.registry_url_netloc: + raise ConfigurationError( + f'The "registry_url_netloc" key is missing in section [{section_name}] of the .ini configuration file.' + ) + self.registry_url_scheme = section.get("registry_url_scheme", "https") + self.registry_url = urllib.parse.ParseResult( + scheme=self.registry_url_scheme, + netloc=self.registry_url_netloc, + path="", + params="", + query="", + fragment="", + ).geturl() + try: self.request_timeout = section.getint("request_timeout", fallback=10) except ValueError as error: @@ -152,41 +182,49 @@ def is_detected(self, build_tool: BaseBuildTool) -> bool: compatible_build_tool_classes = [Maven, Gradle] return any(isinstance(build_tool, build_tool_class) for build_tool_class in compatible_build_tool_classes) - def find_publish_timestamp(self, group_id: str, artifact_id: str, version: str | None = None) -> datetime: + def find_publish_timestamp(self, purl: str, registry_url: str | None = None) -> datetime: """Make a search request to Maven Central to find the publishing timestamp of an artifact. - If version is not provided, the timestamp of the latest version will be returned. + The reason for directly fetching timestamps from Maven Central is that deps.dev occasionally + misses timestamps for Maven artifacts, making it unreliable for this purpose. To see the search API syntax see: https://central.sonatype.org/search/rest-api-guide/ Parameters ---------- - group_id : str - The group id of the artifact. - artifact_id: str - The artifact id of the artifact. - version: str | None - The version of the artifact. + purl: str + The Package URL (purl) of the package whose publication timestamp is to be retrieved. + This should conform to the PURL specification. + registry_url: str | None + The registry URL that can be set for testing. Returns ------- datetime - The artifact publish timestamp as a timezone-aware datetime object. + A timezone-aware datetime object representing the publication timestamp + of the specified package. Raises ------ InvalidHTTPResponseError - If the HTTP response is invalid or unexpected. + If the URL construction fails, the HTTP response is invalid, or if the response + cannot be parsed correctly, or if the expected timestamp is missing or invalid. """ - query_params = [f"q=g:{group_id}", f"a:{artifact_id}"] - if version: - query_params.append(f"v:{version}") + try: + purl_object = PackageURL.from_string(purl) + except ValueError as error: + logger.debug("Could not parse PURL: %s", error) + + if not purl_object.version: + raise InvalidHTTPResponseError("The PackageURL of the software component misses version.") + + query_params = [f"q=g:{purl_object.namespace}", f"a:{purl_object.name}", f"v:{purl_object.version}"] try: - url = urlunsplit( - SplitResult( - scheme="https", - netloc=self.hostname, + url = urllib.parse.urlunsplit( + urllib.parse.SplitResult( + scheme=self.search_scheme, + netloc=self.search_netloc, path=f"/{self.search_endpoint}", query="&".join(["+AND+".join(query_params), "core=gav", "rows=1", "wt=json"]), fragment="", @@ -196,7 +234,7 @@ def find_publish_timestamp(self, group_id: str, artifact_id: str, version: str | raise InvalidHTTPResponseError("Failed to construct the search URL for Maven Central.") from error response = send_get_http_raw(url, headers=None, timeout=self.request_timeout) - if response and response.status_code == 200: + if response: try: res_obj = response.json() except requests.exceptions.JSONDecodeError as error: @@ -221,7 +259,7 @@ def find_publish_timestamp(self, group_id: str, artifact_id: str, version: str | # The timestamp published in Maven Central is in milliseconds and needs to be divided by 1000. # Unfortunately, this is not documented in the API docs. try: - return datetime.fromtimestamp(timestamp / 1000, tz=timezone.utc) + return datetime.fromtimestamp(round(timestamp / 1000), tz=timezone.utc) except (OverflowError, OSError) as error: raise InvalidHTTPResponseError(f"The timestamp returned by {url} is invalid") from error diff --git a/src/macaron/slsa_analyzer/package_registry/package_registry.py b/src/macaron/slsa_analyzer/package_registry/package_registry.py index e7e68f8c5..55ae778b7 100644 --- a/src/macaron/slsa_analyzer/package_registry/package_registry.py +++ b/src/macaron/slsa_analyzer/package_registry/package_registry.py @@ -1,12 +1,21 @@ -# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023 - 2024, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. """This module defines package registries.""" +import json import logging +import urllib.parse from abc import ABC, abstractmethod +from datetime import datetime +from urllib.parse import quote as encode +import requests + +from macaron.errors import InvalidHTTPResponseError +from macaron.json_tools import json_extract from macaron.slsa_analyzer.build_tool.base_build_tool import BaseBuildTool +from macaron.util import send_get_http_raw logger: logging.Logger = logging.getLogger(__name__) @@ -40,3 +49,77 @@ def is_detected(self, build_tool: BaseBuildTool) -> bool: ``True`` if the repo under analysis can be published to this package registry, based on the given build tool. """ + + def find_publish_timestamp(self, purl: str, registry_url: str | None = None) -> datetime: + """Retrieve the publication timestamp for a package specified by its purl from the deps.dev repository by default. + + This method constructs a request URL based on the provided purl, sends an HTTP GET + request to fetch metadata about the package, and extracts the publication timestamp + from the response. + + Note: The method expects the response to include a ``version`` field with a ``publishedAt`` + subfield containing an ISO 8601 formatted timestamp. + + Parameters + ---------- + purl: str + The Package URL (purl) of the package whose publication timestamp is to be retrieved. + This should conform to the PURL specification. + registry_url: str | None + The registry URL that can be set for testing. + + Returns + ------- + datetime + A timezone-aware datetime object representing the publication timestamp + of the specified package. + + Raises + ------ + InvalidHTTPResponseError + If the URL construction fails, the HTTP response is invalid, or if the response + cannot be parsed correctly, or if the expected timestamp is missing or invalid. + NotImplementedError + If not implemented for a registry. + """ + # TODO: To reduce redundant calls to deps.dev, store relevant parts of the response + # in the AnalyzeContext object retrieved by the Repo Finder. This step should be + # implemented at the beginning of the analyze command to ensure that the data + # is available for subsequent processing. + + base_url_parsed = urllib.parse.urlparse(registry_url or "https://api.deps.dev") + path_params = "/".join(["v3alpha", "purl", encode(purl, safe="")]) + try: + url = urllib.parse.urlunsplit( + urllib.parse.SplitResult( + scheme=base_url_parsed.scheme, + netloc=base_url_parsed.netloc, + path=path_params, + query="", + fragment="", + ) + ) + except ValueError as error: + raise InvalidHTTPResponseError("Failed to construct the API URL.") from error + + response = send_get_http_raw(url) + if response and response.text: + try: + metadata: dict = json.loads(response.text) + except requests.exceptions.JSONDecodeError as error: + raise InvalidHTTPResponseError(f"Failed to process response from deps.dev for {url}.") from error + if not metadata: + raise InvalidHTTPResponseError(f"Empty response returned by {url} .") + + timestamp = json_extract(metadata, ["version", "publishedAt"], str) + if not timestamp: + raise InvalidHTTPResponseError(f"The timestamp is missing in the response returned by {url}.") + + logger.debug("Found timestamp: %s.", timestamp) + + try: + return datetime.fromisoformat(timestamp) + except ValueError as error: + raise InvalidHTTPResponseError(f"The timestamp returned by {url} is invalid") from error + + raise InvalidHTTPResponseError(f"Invalid response from deps.dev for {url}.") diff --git a/src/macaron/slsa_analyzer/provenance/slsa/__init__.py b/src/macaron/slsa_analyzer/provenance/slsa/__init__.py index b3418946f..cf9a9cfb7 100644 --- a/src/macaron/slsa_analyzer/provenance/slsa/__init__.py +++ b/src/macaron/slsa_analyzer/provenance/slsa/__init__.py @@ -2,6 +2,7 @@ # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. """This module implements SLSA provenance abstractions.""" + from typing import NamedTuple from macaron.slsa_analyzer.asset import AssetLocator diff --git a/src/macaron/slsa_analyzer/specs/ci_spec.py b/src/macaron/slsa_analyzer/specs/ci_spec.py index 7f4bef2a3..0f00e5bdb 100644 --- a/src/macaron/slsa_analyzer/specs/ci_spec.py +++ b/src/macaron/slsa_analyzer/specs/ci_spec.py @@ -9,6 +9,7 @@ from macaron.code_analyzer.call_graph import CallGraph from macaron.slsa_analyzer.asset import AssetLocator from macaron.slsa_analyzer.ci_service.base_ci_service import BaseCIService +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.provenance.provenance import DownloadedProvenanceData @@ -36,3 +37,6 @@ class CIInfo(TypedDict): provenances: Sequence[DownloadedProvenanceData] """The provenances data.""" + + build_info_results: InTotoV01Payload + """The build information results computed for a build step. We use the in-toto 0.1 as the spec.""" diff --git a/tests/integration/cases/apache_maven_local_path_with_branch_name_digest_deps_cyclonedx_maven/maven.dl b/tests/integration/cases/apache_maven_local_path_with_branch_name_digest_deps_cyclonedx_maven/maven.dl index afd7a54de..2c750872a 100644 --- a/tests/integration/cases/apache_maven_local_path_with_branch_name_digest_deps_cyclonedx_maven/maven.dl +++ b/tests/integration/cases/apache_maven_local_path_with_branch_name_digest_deps_cyclonedx_maven/maven.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/guava.dl b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/guava.dl index 5f5927982..fdf03032b 100644 --- a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/guava.dl +++ b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/guava.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/maven.dl b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/maven.dl index ef16459c9..708676471 100644 --- a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/maven.dl +++ b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/maven.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/mockito.dl b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/mockito.dl index f754eb3e5..92e0e16c8 100644 --- a/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/mockito.dl +++ b/tests/integration/cases/apache_maven_local_paths_without_dep_resolution/mockito.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_local_repo/policy.dl b/tests/integration/cases/apache_maven_local_repo/policy.dl index ef16459c9..708676471 100644 --- a/tests/integration/cases/apache_maven_local_repo/policy.dl +++ b/tests/integration/cases/apache_maven_local_repo/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_purl_repo_path/policy.dl b/tests/integration/cases/apache_maven_purl_repo_path/policy.dl index ecc9383f6..92d3b8d7b 100644 --- a/tests/integration/cases/apache_maven_purl_repo_path/policy.dl +++ b/tests/integration/cases/apache_maven_purl_repo_path/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_repo_path_branch_digest_with_deps_cyclonedx_maven/maven.dl b/tests/integration/cases/apache_maven_repo_path_branch_digest_with_deps_cyclonedx_maven/maven.dl index afd7a54de..2c750872a 100644 --- a/tests/integration/cases/apache_maven_repo_path_branch_digest_with_deps_cyclonedx_maven/maven.dl +++ b/tests/integration/cases/apache_maven_repo_path_branch_digest_with_deps_cyclonedx_maven/maven.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_using_default_template_file_as_input_template/maven.dl b/tests/integration/cases/apache_maven_using_default_template_file_as_input_template/maven.dl index ef16459c9..708676471 100644 --- a/tests/integration/cases/apache_maven_using_default_template_file_as_input_template/maven.dl +++ b/tests/integration/cases/apache_maven_using_default_template_file_as_input_template/maven.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_yaml_input_skip_deps/guava.dl b/tests/integration/cases/apache_maven_yaml_input_skip_deps/guava.dl index 5f5927982..fdf03032b 100644 --- a/tests/integration/cases/apache_maven_yaml_input_skip_deps/guava.dl +++ b/tests/integration/cases/apache_maven_yaml_input_skip_deps/guava.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_yaml_input_skip_deps/maven.dl b/tests/integration/cases/apache_maven_yaml_input_skip_deps/maven.dl index ef16459c9..708676471 100644 --- a/tests/integration/cases/apache_maven_yaml_input_skip_deps/maven.dl +++ b/tests/integration/cases/apache_maven_yaml_input_skip_deps/maven.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/apache_maven_yaml_input_skip_deps/mockito.dl b/tests/integration/cases/apache_maven_yaml_input_skip_deps/mockito.dl index f754eb3e5..92e0e16c8 100644 --- a/tests/integration/cases/apache_maven_yaml_input_skip_deps/mockito.dl +++ b/tests/integration/cases/apache_maven_yaml_input_skip_deps/mockito.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/behnazh-w_example-maven-app-tutorial/policy.dl b/tests/integration/cases/behnazh-w_example-maven-app-tutorial/policy.dl new file mode 100644 index 000000000..e5dba0031 --- /dev/null +++ b/tests/integration/cases/behnazh-w_example-maven-app-tutorial/policy.dl @@ -0,0 +1,17 @@ +/* Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. */ +/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */ + + #include "prelude.dl" + + Policy("detect-malicious-upload", component_id, "") :- + is_component(component_id, _), + !violating_dependencies(component_id). + + .decl violating_dependencies(parent: number) + violating_dependencies(parent) :- + transitive_dependency(parent, dependency), + !check_passed(dependency, "mcn_find_artifact_pipeline_1"), + !check_passed(dependency, "mcn_provenance_level_three_1"). + + apply_policy_to("detect-malicious-upload", component_id) :- + is_repo(_, "github.com/behnazh-w/example-maven-app", component_id). diff --git a/tests/integration/cases/behnazh-w_example-maven-app-tutorial/test.yaml b/tests/integration/cases/behnazh-w_example-maven-app-tutorial/test.yaml new file mode 100644 index 000000000..9e760d683 --- /dev/null +++ b/tests/integration/cases/behnazh-w_example-maven-app-tutorial/test.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +description: | + Test the example-maven-app detect-manual-upload-java-dep tutorial scenario. + +tags: +- macaron-python-package +- tutorial +steps: +- name: Run macaron analyze on the remote repository and resolve dependencies. + kind: analyze + options: + command_args: + - --package-url + - pkg:maven/io.github.behnazh-w.demo/example-maven-app@2.0?type=jar + - -rp + - https://github.com/behnazh-w/example-maven-app + - --deps-depth=1 +- name: Run macaron verify-policy and expect to fail some deps do not pass the policy. + kind: verify + options: + policy: policy.dl + expect_fail: true diff --git a/tests/integration/cases/facebook_yoga_yarn_classic/policy.dl b/tests/integration/cases/facebook_yoga_yarn_classic/policy.dl index 0d652339e..75706c7e6 100644 --- a/tests/integration/cases/facebook_yoga_yarn_classic/policy.dl +++ b/tests/integration/cases/facebook_yoga_yarn_classic/policy.dl @@ -11,7 +11,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_tool_1"), build_tool_check(yarn_id, "yarn", "javascript"), check_facts(yarn_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/gitlab_tinyMediaManager/policy.dl b/tests/integration/cases/gitlab_tinyMediaManager/policy.dl index 1a1bd419c..2e6676a22 100644 --- a/tests/integration/cases/gitlab_tinyMediaManager/policy.dl +++ b/tests/integration/cases/gitlab_tinyMediaManager/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), check_failed(component_id, "mcn_build_service_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/gitlab_tinyMediaManager_purl/policy.dl b/tests/integration/cases/gitlab_tinyMediaManager_purl/policy.dl index 11e3f4b73..c2bb7761c 100644 --- a/tests/integration/cases/gitlab_tinyMediaManager_purl/policy.dl +++ b/tests/integration/cases/gitlab_tinyMediaManager_purl/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), check_failed(component_id, "mcn_build_service_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/google_guava/policy.dl b/tests/integration/cases/google_guava/policy.dl index dddcdea35..e872e43db 100644 --- a/tests/integration/cases/google_guava/policy.dl +++ b/tests/integration/cases/google_guava/policy.dl @@ -7,10 +7,6 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_as_code_1"), check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), - // TODO: The GitHub API is no longer returning the required information about the workflow run - // steps for this version of Guava. So, we need to disable this check for now and adjust - // the logic in the mcn_infer_artifact_pipeline_1 check. - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), check_passed(component_id, "mcn_version_control_system_1"), check_passed(component_id, "mcn_build_tool_1"), build_tool_check(maven_id, "maven", "java"), @@ -22,7 +18,19 @@ Policy("test_policy", component_id, "") :- check_failed(component_id, "mcn_provenance_level_three_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), - is_repo_url(component_id, "https://github.com/google/guava"). + is_repo_url(component_id, "https://github.com/google/guava"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), + artifact_pipeline_check( + apc_check_id, + _, + _, + _, + _, + 0, // From provenance. + 1, // Run deleted. + 0 // Published before the code was committed. + ), + check_facts(apc_check_id, _, component_id,_,_). apply_policy_to("test_policy", component_id) :- is_component(component_id, "pkg:maven/com.google.guava/guava@32.1.2-jre?type=jar"). diff --git a/tests/integration/cases/jackson_databind_with_purl_and_no_deps/jackson-databind.dl b/tests/integration/cases/jackson_databind_with_purl_and_no_deps/jackson-databind.dl index d045d955b..c722e0298 100644 --- a/tests/integration/cases/jackson_databind_with_purl_and_no_deps/jackson-databind.dl +++ b/tests/integration/cases/jackson_databind_with_purl_and_no_deps/jackson-databind.dl @@ -11,7 +11,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_tool_1"), build_tool_check(maven_id, "maven", "java"), check_facts(maven_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/jenkinsci_plotplugin/policy.dl b/tests/integration/cases/jenkinsci_plotplugin/policy.dl index a3d674888..355ee5e08 100644 --- a/tests/integration/cases/jenkinsci_plotplugin/policy.dl +++ b/tests/integration/cases/jenkinsci_plotplugin/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/log4j_release_pipeline/policy.dl b/tests/integration/cases/log4j_release_pipeline/policy.dl new file mode 100644 index 000000000..3044be45a --- /dev/null +++ b/tests/integration/cases/log4j_release_pipeline/policy.dl @@ -0,0 +1,23 @@ +/* Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. */ +/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */ + +#include "prelude.dl" + +Policy("test_policy", component_id, "") :- + check_passed(component_id, "mcn_build_as_code_1"), + check_passed(component_id, "mcn_build_script_1"), + check_passed(component_id, "mcn_build_service_1"), + check_passed_with_confidence(component_id, "mcn_find_artifact_pipeline_1", confidence), + confidence = 0.7, // Medium confidence because the pipeline was not found from a provenance. + check_passed(component_id, "mcn_version_control_system_1"), + check_failed(component_id, "mcn_provenance_available_1"), + check_failed(component_id, "mcn_provenance_derived_commit_1"), + check_failed(component_id, "mcn_provenance_derived_repo_1"), + check_failed(component_id, "mcn_provenance_expectation_1"), + check_failed(component_id, "mcn_provenance_level_three_1"), + check_failed(component_id, "mcn_provenance_witness_level_one_1"), + check_failed(component_id, "mcn_trusted_builder_level_three_1"), + is_repo_url(component_id, "https://github.com/apache/logging-log4j2"). + +apply_policy_to("test_policy", component_id) :- + is_component(component_id, "pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2"). diff --git a/tests/integration/cases/log4j_release_pipeline/test.yaml b/tests/integration/cases/log4j_release_pipeline/test.yaml new file mode 100644 index 000000000..54600056c --- /dev/null +++ b/tests/integration/cases/log4j_release_pipeline/test.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +description: | + Analyzing with PURL and repository path without dependency resolution. + +tags: +- macaron-python-package +- tutorial + +steps: +- name: Run macaron analyze + kind: analyze + options: + command_args: + - -purl + - pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2 +- name: Run macaron verify-policy to verify passed/failed checks + kind: verify + options: + policy: policy.dl diff --git a/tests/integration/cases/log4j_release_pipeline_deleted_run/policy.dl b/tests/integration/cases/log4j_release_pipeline_deleted_run/policy.dl new file mode 100644 index 000000000..2a2a68caf --- /dev/null +++ b/tests/integration/cases/log4j_release_pipeline_deleted_run/policy.dl @@ -0,0 +1,38 @@ +/* Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. */ +/* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. */ + +#include "prelude.dl" + +Policy("test_policy", component_id, "") :- + check_passed(component_id, "mcn_build_as_code_1"), + check_passed(component_id, "mcn_build_script_1"), + check_passed(component_id, "mcn_build_service_1"), + check_passed(component_id, "mcn_version_control_system_1"), + check_failed(component_id, "mcn_provenance_available_1"), + check_failed(component_id, "mcn_provenance_derived_commit_1"), + check_failed(component_id, "mcn_provenance_derived_repo_1"), + check_failed(component_id, "mcn_provenance_expectation_1"), + check_failed(component_id, "mcn_provenance_level_three_1"), + check_failed(component_id, "mcn_provenance_witness_level_one_1"), + check_failed(component_id, "mcn_trusted_builder_level_three_1"), + is_repo_url(component_id, "https://github.com/apache/logging-log4j2"), + // The GitHub API has a retention policy of removing CI run data after 400 days. + // Note that mcn_find_artifact_pipeline_1 fails because it returns UNKNOWN, in this case with low confidence. + // That's why we cannot rely on the check fail here only and need to also check the data gathered by + // the artifact_pipeline_check. + check_failed_with_confidence(component_id, "mcn_find_artifact_pipeline_1", confidence), + confidence = 0.4, + artifact_pipeline_check( + apc_check_id, + "https://github.com/apache/logging-log4j2/blob/5a5d3aefdc75045bb66f55a16c40a9a07a463738/.github/workflows/build.yml", + "deploy", + "Maven \"deploy\"", + _, + 0, // From provenance. + 1, // Run deleted. + 0 // Published before the code was committed. + ), + check_facts(apc_check_id, confidence, component_id,_,_). + +apply_policy_to("test_policy", component_id) :- + is_component(component_id, "pkg:maven/org.apache.logging.log4j/log4j-core@2.19.0"). diff --git a/tests/integration/cases/log4j_release_pipeline_deleted_run/test.yaml b/tests/integration/cases/log4j_release_pipeline_deleted_run/test.yaml new file mode 100644 index 000000000..2b33a0a24 --- /dev/null +++ b/tests/integration/cases/log4j_release_pipeline_deleted_run/test.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +description: | + Analyzing with PURL and repository path without dependency resolution. + +tags: +- macaron-python-package + +steps: +- name: Run macaron analyze + kind: analyze + options: + command_args: + - -purl + - pkg:maven/org.apache.logging.log4j/log4j-core@2.19.0 +- name: Run macaron verify-policy to verify passed/failed checks + kind: verify + options: + policy: policy.dl diff --git a/tests/integration/cases/micronaut-projects_micronaut-core/config.ini b/tests/integration/cases/micronaut-projects_micronaut-core/config.ini index e42c7cdd4..5f5a55c82 100644 --- a/tests/integration/cases/micronaut-projects_micronaut-core/config.ini +++ b/tests/integration/cases/micronaut-projects_micronaut-core/config.ini @@ -7,7 +7,4 @@ exclude = # temporarily because provenances have failed to publish due to an issue in `generator_generic_slsa3.yml@v1.9.0`: # https://github.com/slsa-framework/slsa-github-generator/issues/3350 mcn_provenance_available_1 - # Exclude `mcn_infer_artifact_pipeline_1`, due to a non-deterministic behavior in deploy command detection, - # which will be fixed in PR #673. - mcn_infer_artifact_pipeline_1 include = * diff --git a/tests/integration/cases/micronaut-projects_micronaut-test/micronaut-test.dl b/tests/integration/cases/micronaut-projects_micronaut-test/micronaut-test.dl index 35e35f7ee..2e6da73d8 100644 --- a/tests/integration/cases/micronaut-projects_micronaut-test/micronaut-test.dl +++ b/tests/integration/cases/micronaut-projects_micronaut-test/micronaut-test.dl @@ -14,7 +14,7 @@ Policy("test_policy", component_id, "") :- build_tool_check(gradle_id, "gradle", "java"), check_facts(gradle_id, _, component_id,_,_), check_passed(component_id, "mcn_provenance_level_three_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_passed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), diff --git a/tests/integration/cases/onu-ui_onu-ui_pnpm/policy.dl b/tests/integration/cases/onu-ui_onu-ui_pnpm/policy.dl index 37005b017..56b09f46a 100644 --- a/tests/integration/cases/onu-ui_onu-ui_pnpm/policy.dl +++ b/tests/integration/cases/onu-ui_onu-ui_pnpm/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/purl_of_nonexistent_artifact/policy.dl b/tests/integration/cases/purl_of_nonexistent_artifact/policy.dl index a7a8fc53b..e0ae8d6c7 100644 --- a/tests/integration/cases/purl_of_nonexistent_artifact/policy.dl +++ b/tests/integration/cases/purl_of_nonexistent_artifact/policy.dl @@ -7,7 +7,7 @@ Policy("test_policy", component_id, "") :- check_failed(component_id, "mcn_build_as_code_1"), check_failed(component_id, "mcn_build_script_1"), check_failed(component_id, "mcn_build_service_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/semver/policy.dl b/tests/integration/cases/semver/policy.dl index 9412c57f6..717062b48 100644 --- a/tests/integration/cases/semver/policy.dl +++ b/tests/integration/cases/semver/policy.dl @@ -14,7 +14,11 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_verified_1"), provenance_verified_check(_, build_level, _), build_level = 2, - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + // The build_as_code check is reporting the integration_release.yaml workflow + // which is not the same as the workflow in the provenance. Therefore, the + // mcn_find_artifact_pipeline_1 check fails, which is a false negative. + // TODO: improve the build_as_code check analysis. + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_level_three_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), diff --git a/tests/integration/cases/sigstore_mock/policy.dl b/tests/integration/cases/sigstore_mock/policy.dl index c16d43f7c..b35d2bb4d 100644 --- a/tests/integration/cases/sigstore_mock/policy.dl +++ b/tests/integration/cases/sigstore_mock/policy.dl @@ -12,11 +12,28 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_derived_commit_1"), check_passed(component_id, "mcn_provenance_derived_repo_1"), check_passed(component_id, "mcn_provenance_verified_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_level_three_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), - is_repo_url(component_id, "https://github.com/sigstore/sigstore-js"). + is_repo_url(component_id, "https://github.com/sigstore/sigstore-js"), + // The GitHub API has a retention policy of removing CI run data after 400 days. + // Note that mcn_find_artifact_pipeline_1 fails because it returns UNKNOWN, in this case with low confidence. + // That's why we cannot rely on the check fail here only and need to also check the data gathered by + // the artifact_pipeline_check. + check_failed_with_confidence(component_id, "mcn_find_artifact_pipeline_1", confidence), + confidence = 0.4, + artifact_pipeline_check( + apc_check_id, + "https://github.com/sigstore/sigstore-js/blob/ebdcfdfbdfeb9c9aeee6df53674ef230613629f5/.github/workflows/release.yml", + "release", + "Create Release Pull Request", + _, + 1, // From provenance. + 1, // Run deleted. + 0 // Published before the code was committed. + ), + check_facts(apc_check_id, confidence, component_id,_,_). apply_policy_to("test_policy", component_id) :- is_component(component_id, "pkg:npm/%40sigstore/mock@0.1.0"). diff --git a/tests/integration/cases/sigstore_sget/policy.dl b/tests/integration/cases/sigstore_sget/policy.dl index e7bfb3344..df5c2a294 100644 --- a/tests/integration/cases/sigstore_sget/policy.dl +++ b/tests/integration/cases/sigstore_sget/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/slsa-framework_slsa-verifier/policy.dl b/tests/integration/cases/slsa-framework_slsa-verifier/policy.dl index d9ab6910c..51a2ecb7a 100644 --- a/tests/integration/cases/slsa-framework_slsa-verifier/policy.dl +++ b/tests/integration/cases/slsa-framework_slsa-verifier/policy.dl @@ -16,7 +16,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_derived_commit_1"), check_passed(component_id, "mcn_provenance_derived_repo_1"), check_passed(component_id, "mcn_provenance_expectation_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), is_repo_url(component_id, "https://github.com/slsa-framework/slsa-verifier"). diff --git a/tests/integration/cases/slsa-framework_slsa-verifier_explicit_provenance_provided/policy.dl b/tests/integration/cases/slsa-framework_slsa-verifier_explicit_provenance_provided/policy.dl index 253100908..f9579225c 100644 --- a/tests/integration/cases/slsa-framework_slsa-verifier_explicit_provenance_provided/policy.dl +++ b/tests/integration/cases/slsa-framework_slsa-verifier_explicit_provenance_provided/policy.dl @@ -13,7 +13,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_expectation_1"), check_passed(component_id, "mcn_trusted_builder_level_three_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), is_repo_url(component_id, "https://github.com/slsa-framework/slsa-verifier"). diff --git a/tests/integration/cases/snakeyaml_unsupported_git_service/policy.dl b/tests/integration/cases/snakeyaml_unsupported_git_service/policy.dl index 3940f2b8a..dd3b5d280 100644 --- a/tests/integration/cases/snakeyaml_unsupported_git_service/policy.dl +++ b/tests/integration/cases/snakeyaml_unsupported_git_service/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_version_control_system_1"), check_failed(component_id, "mcn_build_as_code_1"), check_failed(component_id, "mcn_build_service_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/timyarkov_docker_test/policy.dl b/tests/integration/cases/timyarkov_docker_test/policy.dl index 1d8efaec1..599dcc138 100644 --- a/tests/integration/cases/timyarkov_docker_test/policy.dl +++ b/tests/integration/cases/timyarkov_docker_test/policy.dl @@ -11,7 +11,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_tool_1"), build_tool_check(docker_id, "docker", "docker"), check_facts(docker_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/timyarkov_multibuild_test_maven/policy.dl b/tests/integration/cases/timyarkov_multibuild_test_maven/policy.dl index d70078002..90c4f2339 100644 --- a/tests/integration/cases/timyarkov_multibuild_test_maven/policy.dl +++ b/tests/integration/cases/timyarkov_multibuild_test_maven/policy.dl @@ -13,7 +13,7 @@ Policy("test_policy", component_id, "") :- check_facts(gradle_id, _, component_id,_,_), build_tool_check(maven_id, "maven", "java"), check_facts(maven_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/uiv-lib_uiv/policy.dl b/tests/integration/cases/uiv-lib_uiv/policy.dl index 3823d052d..ae20ef440 100644 --- a/tests/integration/cases/uiv-lib_uiv/policy.dl +++ b/tests/integration/cases/uiv-lib_uiv/policy.dl @@ -11,7 +11,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_tool_1"), build_tool_check(npm_id, "npm", "javascript"), check_facts(npm_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/integration/cases/urllib3_expectation_dir/policy.dl b/tests/integration/cases/urllib3_expectation_dir/policy.dl index dfa3d0d4a..2ba5f9dbe 100644 --- a/tests/integration/cases/urllib3_expectation_dir/policy.dl +++ b/tests/integration/cases/urllib3_expectation_dir/policy.dl @@ -16,10 +16,27 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_tool_1"), build_tool_check(pip_id, "pip", "python"), check_facts(pip_id, _, component_id,_,_), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), - is_repo_url(component_id, "https://github.com/urllib3/urllib3"). + is_repo_url(component_id, "https://github.com/urllib3/urllib3"), + // The GitHub API has a retention policy of removing CI run data after 400 days. + // Note that mcn_find_artifact_pipeline_1 fails because it returns UNKNOWN, in this case with low confidence. + // That's why we cannot rely on the check fail here only and need to also check the data gathered by + // the artifact_pipeline_check. + check_failed_with_confidence(component_id, "mcn_find_artifact_pipeline_1", confidence), + confidence = 0.4, + artifact_pipeline_check( + apc_check_id, + "https://github.com/urllib3/urllib3/blob/612cead3f9704716f4ab2a1334a16e0f05fce942/.github/workflows/publish.yml", + "publish", + "Publish dists to PyPI", + _, + 1, // From provenance. + 1, // Run deleted. + 0 // Published before the code was committed. + ), + check_facts(apc_check_id, confidence, component_id,_,_). apply_policy_to("test_policy", component_id) :- is_component(component_id, "pkg:pypi/urllib3@2.0.0a1"). diff --git a/tests/integration/cases/urllib3_expectation_file/policy.dl b/tests/integration/cases/urllib3_expectation_file/policy.dl index 79bfae7ee..3fea375f2 100644 --- a/tests/integration/cases/urllib3_expectation_file/policy.dl +++ b/tests/integration/cases/urllib3_expectation_file/policy.dl @@ -13,7 +13,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_derived_repo_1"), check_passed(component_id, "mcn_provenance_expectation_1"), check_passed(component_id, "mcn_provenance_level_three_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), is_repo_url(component_id, "https://github.com/urllib3/urllib3"). diff --git a/tests/integration/cases/urllib3_invalid_expectation/policy.dl b/tests/integration/cases/urllib3_invalid_expectation/policy.dl index e8a017826..48dd5adc2 100644 --- a/tests/integration/cases/urllib3_invalid_expectation/policy.dl +++ b/tests/integration/cases/urllib3_invalid_expectation/policy.dl @@ -12,7 +12,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_provenance_derived_commit_1"), check_passed(component_id, "mcn_provenance_derived_repo_1"), check_passed(component_id, "mcn_provenance_level_three_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_witness_level_one_1"), check_failed(component_id, "mcn_trusted_builder_level_three_1"), check_failed(component_id, "mcn_provenance_expectation_1"), diff --git a/tests/integration/cases/wojtekmaj_reactpdf_yarn_modern/policy.dl b/tests/integration/cases/wojtekmaj_reactpdf_yarn_modern/policy.dl index f24ebd492..0ac7956cb 100644 --- a/tests/integration/cases/wojtekmaj_reactpdf_yarn_modern/policy.dl +++ b/tests/integration/cases/wojtekmaj_reactpdf_yarn_modern/policy.dl @@ -8,7 +8,7 @@ Policy("test_policy", component_id, "") :- check_passed(component_id, "mcn_build_script_1"), check_passed(component_id, "mcn_build_service_1"), check_passed(component_id, "mcn_version_control_system_1"), - check_failed(component_id, "mcn_infer_artifact_pipeline_1"), + check_failed(component_id, "mcn_find_artifact_pipeline_1"), check_failed(component_id, "mcn_provenance_available_1"), check_failed(component_id, "mcn_provenance_derived_commit_1"), check_failed(component_id, "mcn_provenance_derived_repo_1"), diff --git a/tests/repo_finder/test_provenance_finder.py b/tests/repo_finder/test_provenance_finder.py index 3426fed0d..20f2c0ad9 100644 --- a/tests/repo_finder/test_provenance_finder.py +++ b/tests/repo_finder/test_provenance_finder.py @@ -19,7 +19,9 @@ from macaron.slsa_analyzer.git_service.api_client import GhAPIClient from macaron.slsa_analyzer.package_registry import JFrogMavenRegistry, NPMRegistry from macaron.slsa_analyzer.package_registry.jfrog_maven_registry import JFrogMavenAsset, JFrogMavenAssetMetadata +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext @@ -159,6 +161,7 @@ def test_provenance_on_unsupported_ci(macaron_path: Path, service: BaseCIService provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) # Set up the context object with provenances. @@ -182,6 +185,7 @@ def test_provenance_on_supported_ci(macaron_path: Path, test_dir: Path) -> None: provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) # Set up the context object with provenances. diff --git a/tests/slsa_analyzer/checks/test_build_as_code_check.py b/tests/slsa_analyzer/checks/test_build_as_code_check.py index 2cd4dd0eb..99aba2af1 100644 --- a/tests/slsa_analyzer/checks/test_build_as_code_check.py +++ b/tests/slsa_analyzer/checks/test_build_as_code_check.py @@ -24,7 +24,9 @@ ) from macaron.slsa_analyzer.ci_service.github_actions.github_actions_ci import GitHubActions from macaron.slsa_analyzer.ci_service.jenkins import Jenkins +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext, build_github_actions_call_graph_for_commands @@ -56,6 +58,7 @@ def test_build_as_code_check_no_callgraph( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) use_build_tool = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") use_build_tool.dynamic_data["build_spec"]["tools"] = [build_tools[build_tool_name]] @@ -106,6 +109,7 @@ def test_deploy_commands( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) ci_info["service"] = github_actions_service deploy_ctx.dynamic_data["ci_services"] = [ci_info] @@ -143,6 +147,7 @@ def test_gha_workflow_deployment( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) workflows_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "resources", "github", "workflow_files") @@ -188,6 +193,7 @@ def test_travis_ci_deploy( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) gradle_deploy = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") gradle_deploy.component.repository.fs_path = str(repo_path.absolute()) @@ -208,6 +214,7 @@ def test_multibuild_facts_saved( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) multi_build = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") diff --git a/tests/slsa_analyzer/checks/test_build_service_check.py b/tests/slsa_analyzer/checks/test_build_service_check.py index 74ee6e933..0f5d9aeb0 100644 --- a/tests/slsa_analyzer/checks/test_build_service_check.py +++ b/tests/slsa_analyzer/checks/test_build_service_check.py @@ -14,7 +14,9 @@ from macaron.slsa_analyzer.checks.check_result import CheckResultType from macaron.slsa_analyzer.ci_service.base_ci_service import BaseCIService from macaron.slsa_analyzer.ci_service.github_actions.github_actions_ci import GitHubActions +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext, build_github_actions_call_graph_for_commands @@ -46,6 +48,7 @@ def test_build_service_check_no_callgraph( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) use_build_tool = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") use_build_tool.dynamic_data["build_spec"]["tools"] = [build_tools[build_tool_name]] @@ -96,6 +99,7 @@ def test_packaging_commands( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) ci_info["service"] = github_actions_service package_ctx.dynamic_data["ci_services"] = [ci_info] @@ -114,6 +118,7 @@ def test_multibuild_facts_saved( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) multi_build = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") diff --git a/tests/slsa_analyzer/checks/test_infer_artifact_pipeline.py b/tests/slsa_analyzer/checks/test_infer_artifact_pipeline.py index f38874f1a..65f8a6042 100644 --- a/tests/slsa_analyzer/checks/test_infer_artifact_pipeline.py +++ b/tests/slsa_analyzer/checks/test_infer_artifact_pipeline.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023 - 2024, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. """This module contains tests for the Infer Artifact Pipeline check.""" @@ -9,20 +9,25 @@ from macaron.database.table_definitions import Repository from macaron.slsa_analyzer.checks.check_result import CheckResultType -from macaron.slsa_analyzer.checks.infer_artifact_pipeline_check import InferArtifactPipelineCheck +from macaron.slsa_analyzer.checks.infer_artifact_pipeline_check import ArtifactPipelineCheck from tests.conftest import MockAnalyzeContext +RESOURCE_PATH = Path(__file__).parent.joinpath("resources") + @pytest.mark.parametrize( ("repository", "expected"), [ (None, CheckResultType.FAILED), - (Repository(complete_name="github.com/package-url/purl-spec"), CheckResultType.FAILED), + ( + Repository(complete_name="github.com/package-url/purl-spec", commit_date="2024-01-01T01:01:01+00:00"), + CheckResultType.FAILED, + ), ], ) -def test_infer_artifact_pipeline(macaron_path: Path, repository: Repository, expected: str) -> None: +def test_artifact_pipeline_errors(macaron_path: Path, repository: Repository, expected: str) -> None: """Test that the check handles repositories correctly.""" - check = InferArtifactPipelineCheck() + check = ArtifactPipelineCheck() # Set up the context object with provenances. ctx = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") diff --git a/tests/slsa_analyzer/checks/test_provenance_l3_check.py b/tests/slsa_analyzer/checks/test_provenance_l3_check.py index 6f6220051..0715d33c1 100644 --- a/tests/slsa_analyzer/checks/test_provenance_l3_check.py +++ b/tests/slsa_analyzer/checks/test_provenance_l3_check.py @@ -13,7 +13,9 @@ from macaron.slsa_analyzer.ci_service.jenkins import Jenkins from macaron.slsa_analyzer.ci_service.travis import Travis from macaron.slsa_analyzer.git_service.api_client import GhAPIClient, GitHubReleaseAsset +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext from ...macaron_testcase import MacaronTestCase @@ -72,6 +74,7 @@ def test_provenance_l3_check(self) -> None: provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) # Repo has provenances but no downloaded files. diff --git a/tests/slsa_analyzer/checks/test_provenance_l3_content_check.py b/tests/slsa_analyzer/checks/test_provenance_l3_content_check.py index c04eaf3fe..5decbd16e 100644 --- a/tests/slsa_analyzer/checks/test_provenance_l3_content_check.py +++ b/tests/slsa_analyzer/checks/test_provenance_l3_content_check.py @@ -16,9 +16,11 @@ from macaron.slsa_analyzer.ci_service.travis import Travis from macaron.slsa_analyzer.git_service.api_client import GhAPIClient from macaron.slsa_analyzer.provenance.expectations.cue import CUEExpectation +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.provenance.loader import load_provenance_payload from macaron.slsa_analyzer.provenance.slsa import SLSAProvenanceData from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext from ...macaron_testcase import MacaronTestCase @@ -84,6 +86,7 @@ def test_expectation_check(self) -> None: provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) ctx.dynamic_data["ci_services"] = [ci_info] diff --git a/tests/slsa_analyzer/checks/test_trusted_builder_l3_check.py b/tests/slsa_analyzer/checks/test_trusted_builder_l3_check.py index 88f2ec841..936a98957 100644 --- a/tests/slsa_analyzer/checks/test_trusted_builder_l3_check.py +++ b/tests/slsa_analyzer/checks/test_trusted_builder_l3_check.py @@ -18,7 +18,9 @@ build_call_graph_from_node, ) from macaron.slsa_analyzer.ci_service.github_actions.github_actions_ci import GitHubActions +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext @@ -49,6 +51,7 @@ def test_trusted_builder_l3_check( provenance_assets=[], release={}, provenances=[], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) ctx = MockAnalyzeContext(macaron_path=macaron_path, output_dir="") diff --git a/tests/slsa_analyzer/ci_service/test_github_actions.py b/tests/slsa_analyzer/ci_service/test_github_actions.py index 59f5a021e..1995c3705 100644 --- a/tests/slsa_analyzer/ci_service/test_github_actions.py +++ b/tests/slsa_analyzer/ci_service/test_github_actions.py @@ -4,6 +4,7 @@ """This module tests GitHub Actions CI service.""" import os +from datetime import datetime, timedelta from pathlib import Path import pytest @@ -110,3 +111,63 @@ def test_gh_get_workflows(github_actions: GitHubActions, mock_repo: Path) -> Non def test_gh_get_workflows_fail_on_jenkins(github_actions: GitHubActions) -> None: """Assert GitHubActions workflow detection not working on Jenkins CI configuration files.""" assert not github_actions.get_workflows(str(jenkins_build)) + + +@pytest.mark.parametrize( + ("started_at", "publish_date_time", "commit_date_time", "time_range", "expected"), + [ + pytest.param( + datetime.now(), + datetime.now() - timedelta(hours=1), + datetime.now() + timedelta(minutes=10), + 3600, + False, + id="Publish time before CI start time.", + ), + pytest.param( + datetime.now(), + datetime.now() + timedelta(hours=1), + datetime.now() + timedelta(minutes=10), + 3600, + True, + id="Publish time 1h after CI run and source commit happened after CI trigger within acceptable range.", + ), + pytest.param( + datetime.now() - timedelta(hours=1), + datetime.now(), + datetime.now() + timedelta(minutes=10), + 3600, + False, + id="Source commit occurred after the CI run and outside the acceptable time range.", + ), + ], +) +def test_check_publish_start_commit_timestamps( + github_actions: GitHubActions, + started_at: datetime, + publish_date_time: datetime, + commit_date_time: datetime, + time_range: int, + expected: bool, +) -> None: + """Check that a CI run that has happened before the artifact publishing timestamp can be correctly identified.""" + assert ( + github_actions.check_publish_start_commit_timestamps( + started_at, publish_date_time, commit_date_time, time_range + ) + == expected + ) + + +@pytest.mark.parametrize( + ("timestamp", "expected"), + [ + ("2023-02-17T18:50:09+00:00", True), + ("2000-02-17T18:50:09+00:00", True), + ("3000-02-17T18:50:09+00:00", False), + ], +) +def test_workflow_run_deleted(github_actions: GitHubActions, timestamp: str, expected: bool) -> None: + """Test that deleted workflows can be detected.""" + timestamp_obj = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S%z") + assert github_actions.workflow_run_deleted(timestamp=timestamp_obj) == expected diff --git a/tests/slsa_analyzer/package_registry/resources/maven_central_files/empty_log4j-core@3.0.0-beta2-select.json b/tests/slsa_analyzer/package_registry/resources/maven_central_files/empty_log4j-core@3.0.0-beta2-select.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/maven_central_files/empty_log4j-core@3.0.0-beta2-select.json @@ -0,0 +1 @@ +{} diff --git a/tests/slsa_analyzer/package_registry/resources/maven_central_files/invalid_log4j-core@3.0.0-beta2-select.json b/tests/slsa_analyzer/package_registry/resources/maven_central_files/invalid_log4j-core@3.0.0-beta2-select.json new file mode 100644 index 000000000..6fbd853a4 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/maven_central_files/invalid_log4j-core@3.0.0-beta2-select.json @@ -0,0 +1 @@ +{"responseHeader":{"status":0,"QTime":4,"params":{"q":"g:org.apache.logging.log4j AND a:log4j-core AND v:3.0.0-beta2","core":"gav","indent":"off","fl":"id,g,a,v,p,ec,timestamp,tags","start":"","sort":"score desc,timestamp desc,g asc,a asc,v desc","rows":"1","wt":"json","version":"2.2"}},"response":{"numFound":1,"start":0,"docs":[]}} diff --git a/tests/slsa_analyzer/package_registry/resources/maven_central_files/jackson-annotations@2.16.1-select.json b/tests/slsa_analyzer/package_registry/resources/maven_central_files/jackson-annotations@2.16.1-select.json new file mode 100644 index 000000000..0acb881f0 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/maven_central_files/jackson-annotations@2.16.1-select.json @@ -0,0 +1 @@ +{"responseHeader":{"status":0,"QTime":2,"params":{"q":"g:com.fasterxml.jackson.core AND a:jackson-annotations AND v:2.16.1","core":"gav","indent":"off","fl":"id,g,a,v,p,ec,timestamp,tags","start":"","sort":"score desc,timestamp desc,g asc,a asc,v desc","rows":"1","wt":"json","version":"2.2"}},"response":{"numFound":1,"start":0,"docs":[{"id":"com.fasterxml.jackson.core:jackson-annotations:2.16.1","g":"com.fasterxml.jackson.core","a":"jackson-annotations","v":"2.16.1","p":"jar","timestamp":1703390559843,"ec":["-sources.jar",".module",".pom","-javadoc.jar",".jar"],"tags":["core","types","jackson","package","data","annotations","binding","used","value"]}]}} diff --git a/tests/slsa_analyzer/package_registry/resources/maven_central_files/log4j-core@3.0.0-beta2-select.json b/tests/slsa_analyzer/package_registry/resources/maven_central_files/log4j-core@3.0.0-beta2-select.json new file mode 100644 index 000000000..5623a1276 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/maven_central_files/log4j-core@3.0.0-beta2-select.json @@ -0,0 +1 @@ +{"responseHeader":{"status":0,"QTime":4,"params":{"q":"g:org.apache.logging.log4j AND a:log4j-core AND v:3.0.0-beta2","core":"gav","indent":"off","fl":"id,g,a,v,p,ec,timestamp,tags","start":"","sort":"score desc,timestamp desc,g asc,a asc,v desc","rows":"1","wt":"json","version":"2.2"}},"response":{"numFound":1,"start":0,"docs":[{"id":"org.apache.logging.log4j:log4j-core:3.0.0-beta2","g":"org.apache.logging.log4j","a":"log4j-core","v":"3.0.0-beta2","p":"jar","timestamp":1708195809000,"ec":["-sources.jar","-cyclonedx.xml",".pom",".jar"],"tags":["apache","implementation","log4j"]}]}} diff --git a/tests/slsa_analyzer/package_registry/resources/npm_registry_files/_sigstore.mock@0.7.5.json b/tests/slsa_analyzer/package_registry/resources/npm_registry_files/_sigstore.mock@0.7.5.json new file mode 100644 index 000000000..6ceaee958 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/npm_registry_files/_sigstore.mock@0.7.5.json @@ -0,0 +1 @@ +{"version":{"versionKey":{"system":"NPM","name":"@sigstore/mock","version":"0.7.5"},"purl":"pkg:npm/%40sigstore/mock@0.7.5","publishedAt":"2024-06-11T23:49:17Z","isDefault":true,"isDeprecated":false,"licenses":["Apache-2.0"],"licenseDetails":[{"license":"Apache-2.0","spdx":"Apache-2.0"}],"advisoryKeys":[],"links":[{"label":"HOMEPAGE","url":"https://github.com/sigstore/sigstore-js/tree/main/packages/mock#readme"},{"label":"ISSUE_TRACKER","url":"https://github.com/sigstore/sigstore-js/issues"},{"label":"ATTESTATION","url":"https://registry.npmjs.org/-/npm/v1/attestations/@sigstore%2fmock@0.7.5"},{"label":"ORIGIN","url":"https://registry.npmjs.org/@sigstore%2Fmock/0.7.5"},{"label":"SOURCE_REPO","url":"git+https://github.com/sigstore/sigstore-js.git"}],"slsaProvenances":[{"sourceRepository":"https://github.com/sigstore/sigstore-js","commit":"426540e2142edc2aa438e5390b64bdeb3c8f507d","url":"https://registry.npmjs.org/-/npm/v1/attestations/@sigstore%2fmock@0.7.5","verified":true}],"registries":["https://registry.npmjs.org/"],"relatedProjects":[{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"UNVERIFIED_METADATA","relationType":"ISSUE_TRACKER"},{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"UNVERIFIED_METADATA","relationType":"SOURCE_REPO"},{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"SLSA_ATTESTATION","relationType":"SOURCE_REPO"}],"upstreamIdentifiers":[{"packageName":"@sigstore/mock","versionString":"0.7.5","source":"NPM_NPMJS_ORG"}]}} diff --git a/tests/slsa_analyzer/package_registry/resources/npm_registry_files/empty_sigstore.mock@0.7.5.json b/tests/slsa_analyzer/package_registry/resources/npm_registry_files/empty_sigstore.mock@0.7.5.json new file mode 100644 index 000000000..e69de29bb diff --git a/tests/slsa_analyzer/package_registry/resources/npm_registry_files/invalid_sigstore.mock@0.7.5.json b/tests/slsa_analyzer/package_registry/resources/npm_registry_files/invalid_sigstore.mock@0.7.5.json new file mode 100644 index 000000000..9e53589f5 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/resources/npm_registry_files/invalid_sigstore.mock@0.7.5.json @@ -0,0 +1 @@ +{"version":{"versionKey":{"system":"NPM","name":"@sigstore/mock","version":"0.7.5"},"purl":"pkg:npm/%40sigstore/mock@0.7.5","isDefault":true,"isDeprecated":false,"licenses":["Apache-2.0"],"licenseDetails":[{"license":"Apache-2.0","spdx":"Apache-2.0"}],"advisoryKeys":[],"links":[{"label":"HOMEPAGE","url":"https://github.com/sigstore/sigstore-js/tree/main/packages/mock#readme"},{"label":"ISSUE_TRACKER","url":"https://github.com/sigstore/sigstore-js/issues"},{"label":"ATTESTATION","url":"https://registry.npmjs.org/-/npm/v1/attestations/@sigstore%2fmock@0.7.5"},{"label":"ORIGIN","url":"https://registry.npmjs.org/@sigstore%2Fmock/0.7.5"},{"label":"SOURCE_REPO","url":"git+https://github.com/sigstore/sigstore-js.git"}],"slsaProvenances":[{"sourceRepository":"https://github.com/sigstore/sigstore-js","commit":"426540e2142edc2aa438e5390b64bdeb3c8f507d","url":"https://registry.npmjs.org/-/npm/v1/attestations/@sigstore%2fmock@0.7.5","verified":true}],"registries":["https://registry.npmjs.org/"],"relatedProjects":[{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"UNVERIFIED_METADATA","relationType":"ISSUE_TRACKER"},{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"UNVERIFIED_METADATA","relationType":"SOURCE_REPO"},{"projectKey":{"id":"github.com/sigstore/sigstore-js"},"relationProvenance":"SLSA_ATTESTATION","relationType":"SOURCE_REPO"}],"upstreamIdentifiers":[{"packageName":"@sigstore/mock","versionString":"0.7.5","source":"NPM_NPMJS_ORG"}]}} diff --git a/tests/slsa_analyzer/package_registry/test_maven_central_registry.py b/tests/slsa_analyzer/package_registry/test_maven_central_registry.py new file mode 100644 index 000000000..8a0287b36 --- /dev/null +++ b/tests/slsa_analyzer/package_registry/test_maven_central_registry.py @@ -0,0 +1,249 @@ +# Copyright (c) 2023 - 2024, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +"""Tests for the Maven Central registry.""" + +import json +import os +import urllib.parse +from datetime import datetime +from pathlib import Path + +import pytest +from pytest_httpserver import HTTPServer + +from macaron.config.defaults import load_defaults +from macaron.errors import ConfigurationError, InvalidHTTPResponseError +from macaron.slsa_analyzer.build_tool.base_build_tool import BaseBuildTool +from macaron.slsa_analyzer.package_registry.maven_central_registry import MavenCentralRegistry + + +@pytest.fixture(name="resources_path") +def resources() -> Path: + """Create the resources path.""" + return Path(__file__).parent.joinpath("resources") + + +@pytest.fixture(name="maven_central") +def maven_central_instance() -> MavenCentralRegistry: + """Create a ``MavenCentralRegistry`` object for the following tests.""" + return MavenCentralRegistry( + search_netloc="search.maven.org", + search_scheme="https", + search_endpoint="solrsearch/select", + registry_url_netloc="repo1.maven.org/maven2", + registry_url_scheme="https", + ) + + +def test_load_defaults(tmp_path: Path) -> None: + """Test the ``load_defaults`` method.""" + user_config_path = os.path.join(tmp_path, "config.ini") + user_config_input = """ + [package_registry.maven_central] + search_netloc = search.maven.test + search_scheme = http + search_endpoint = test + registry_url_netloc = test.repo1.maven.org/maven2 + registry_url_scheme = http + request_timeout = 5 + """ + with open(user_config_path, "w", encoding="utf-8") as user_config_file: + user_config_file.write(user_config_input) + + # We don't have to worry about modifying the ``defaults`` object causing test + # pollution here, since we reload the ``defaults`` object before every test with the + # ``setup_test`` fixture. + load_defaults(user_config_path) + + maven_central = MavenCentralRegistry() + maven_central.load_defaults() + assert maven_central.search_netloc == "search.maven.test" + assert maven_central.search_scheme == "http" + assert maven_central.search_endpoint == "test" + assert maven_central.registry_url_netloc == "test.repo1.maven.org/maven2" + assert maven_central.registry_url_scheme == "http" + + +def test_load_defaults_without_maven_central_config() -> None: + """Test the ``load_defaults`` method in trivial case when no config is given.""" + maven_central = MavenCentralRegistry() + maven_central.load_defaults() + + +@pytest.mark.parametrize( + ("user_config_input"), + [ + pytest.param( + """ + [package_registry.maven_central] + search_netloc = + """, + id="Missing search netloc", + ), + pytest.param( + """ + [package_registry.maven_central] + search_endpoint = + """, + id="Missing search endpoint", + ), + pytest.param( + """ + [package_registry.maven_central] + request_timeout = foo + """, + id="Invalid value for request_timeout", + ), + ], +) +def test_load_defaults_with_invalid_config(tmp_path: Path, user_config_input: str) -> None: + """Test the ``load_defaults`` method in case the config is invalid.""" + user_config_path = os.path.join(tmp_path, "config.ini") + with open(user_config_path, "w", encoding="utf-8") as user_config_file: + user_config_file.write(user_config_input) + + # We don't have to worry about modifying the ``defaults`` object causing test + # pollution here, since we reload the ``defaults`` object before every test with the + # ``setup_test`` fixture. + load_defaults(user_config_path) + + maven_central = MavenCentralRegistry() + with pytest.raises(ConfigurationError): + maven_central.load_defaults() + + +@pytest.mark.parametrize( + ("build_tool_name", "expected_result"), + [ + ("maven", True), + ("gradle", True), + ("pip", False), + ("poetry", False), + ], +) +def test_is_detected( + maven_central: MavenCentralRegistry, + build_tools: dict[str, BaseBuildTool], + build_tool_name: str, + expected_result: bool, +) -> None: + """Test the ``is_detected`` method.""" + assert maven_central.is_detected(build_tools[build_tool_name]) == expected_result + + +@pytest.mark.parametrize( + ("purl", "mc_json_path", "query_string", "expected_timestamp"), + [ + ( + "pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2", + "log4j-core@3.0.0-beta2-select.json", + "q=g:org.apache.logging.log4j+AND+a:log4j-core+AND+v:3.0.0-beta2&core=gav&rows=1&wt=json", + "2024-02-17T18:50:09+00:00", + ), + ( + "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.16.1", + "jackson-annotations@2.16.1-select.json", + "q=g:com.fasterxml.jackson.core+AND+a:jackson-annotations+AND+v:2.16.1&core=gav&rows=1&wt=json", + "2023-12-24T04:02:40+00:00", + ), + ], +) +def test_find_publish_timestamp( + resources_path: Path, + httpserver: HTTPServer, + tmp_path: Path, + purl: str, + mc_json_path: str, + query_string: str, + expected_timestamp: str, +) -> None: + """Test that the function finds the timestamp correctly.""" + base_url_parsed = urllib.parse.urlparse(httpserver.url_for("")) + + maven_central = MavenCentralRegistry() + + # Set up responses of solrsearch endpoints using the httpserver plugin. + user_config_input = f""" + [package_registry.maven_central] + request_timeout = 20 + search_netloc = {base_url_parsed.netloc} + search_scheme = {base_url_parsed.scheme} + """ + user_config_path = os.path.join(tmp_path, "config.ini") + with open(user_config_path, "w", encoding="utf-8") as user_config_file: + user_config_file.write(user_config_input) + # We don't have to worry about modifying the ``defaults`` object causing test + # pollution here, since we reload the ``defaults`` object before every test with the + # ``setup_test`` fixture. + load_defaults(user_config_path) + maven_central.load_defaults() + + with open(os.path.join(resources_path, "maven_central_files", mc_json_path), encoding="utf8") as page: + mc_json_response = json.load(page) + + httpserver.expect_request( + "/solrsearch/select", + query_string=query_string, + ).respond_with_json(mc_json_response) + + publish_time_obj = maven_central.find_publish_timestamp(purl=purl) + expected_time_obj = datetime.strptime(expected_timestamp, "%Y-%m-%dT%H:%M:%S%z") + assert publish_time_obj == expected_time_obj + + +@pytest.mark.parametrize( + ("purl", "mc_json_path", "expected_msg"), + [ + ( + "pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2", + "empty_log4j-core@3.0.0-beta2-select.json", + "Empty response returned by (.)*", + ), + ( + "pkg:maven/org.apache.logging.log4j/log4j-core@3.0.0-beta2", + "invalid_log4j-core@3.0.0-beta2-select.json", + "The response returned by (.)* misses `response.docs` attribute or it is empty", + ), + ], +) +def test_find_publish_timestamp_errors( + resources_path: Path, + httpserver: HTTPServer, + tmp_path: Path, + purl: str, + mc_json_path: str, + expected_msg: str, +) -> None: + """Test that the function handles errors correctly.""" + base_url_parsed = urllib.parse.urlparse(httpserver.url_for("")) + + maven_central = MavenCentralRegistry() + + # Set up responses of solrsearch endpoints using the httpserver plugin. + user_config_input = f""" + [package_registry.maven_central] + request_timeout = 20 + search_netloc = {base_url_parsed.netloc} + search_scheme = {base_url_parsed.scheme} + """ + user_config_path = os.path.join(tmp_path, "config.ini") + with open(user_config_path, "w", encoding="utf-8") as user_config_file: + user_config_file.write(user_config_input) + # We don't have to worry about modifying the ``defaults`` object causing test + # pollution here, since we reload the ``defaults`` object before every test with the + # ``setup_test`` fixture. + load_defaults(user_config_path) + maven_central.load_defaults() + + with open(os.path.join(resources_path, "maven_central_files", mc_json_path), encoding="utf8") as page: + mc_json_response = json.load(page) + + httpserver.expect_request( + "/solrsearch/select", + query_string="q=g:org.apache.logging.log4j+AND+a:log4j-core+AND+v:3.0.0-beta2&core=gav&rows=1&wt=json", + ).respond_with_json(mc_json_response) + + pat = f"^{expected_msg}" + with pytest.raises(InvalidHTTPResponseError, match=pat): + maven_central.find_publish_timestamp(purl=purl) diff --git a/tests/slsa_analyzer/package_registry/test_npm_registry.py b/tests/slsa_analyzer/package_registry/test_npm_registry.py index b35d423cf..ef4ed893e 100644 --- a/tests/slsa_analyzer/package_registry/test_npm_registry.py +++ b/tests/slsa_analyzer/package_registry/test_npm_registry.py @@ -4,17 +4,25 @@ """Tests for the npm registry.""" import os +from datetime import datetime from pathlib import Path import pytest +from pytest_httpserver import HTTPServer from macaron.config.defaults import load_defaults -from macaron.errors import ConfigurationError +from macaron.errors import ConfigurationError, InvalidHTTPResponseError from macaron.slsa_analyzer.build_tool.base_build_tool import BaseBuildTool from macaron.slsa_analyzer.build_tool.npm import NPM from macaron.slsa_analyzer.package_registry.npm_registry import NPMAttestationAsset, NPMRegistry +@pytest.fixture(name="resources_path") +def resources() -> Path: + """Create the resources path.""" + return Path(__file__).parent.joinpath("resources") + + @pytest.fixture(name="npm_registry") def create_npm_registry() -> NPMRegistry: """Create an npm registry instance.""" @@ -123,3 +131,72 @@ def test_npm_attestation_asset_url( ) assert asset.name == artifact_id assert asset.url == f"https://{npm_registry.hostname}/{npm_registry.attestation_endpoint}/{expected}" + + +@pytest.mark.parametrize( + ("purl", "npm_json_path", "expected_timestamp"), + [ + ( + "pkg:npm/@sigstore/mock@0.7.5", + "_sigstore.mock@0.7.5.json", + "2024-06-11T23:49:17Z", + ), + ], +) +def test_find_publish_timestamp( + resources_path: Path, + httpserver: HTTPServer, + purl: str, + npm_json_path: str, + expected_timestamp: str, +) -> None: + """Test that the function finds the timestamp correctly.""" + registry = NPMRegistry() + + with open(os.path.join(resources_path, "npm_registry_files", npm_json_path), encoding="utf8") as page: + response = page.read() + + httpserver.expect_request( + "/".join(["/v3alpha", "purl", purl]), + ).respond_with_data(response) + + publish_time_obj = registry.find_publish_timestamp(purl=purl, registry_url=httpserver.url_for("")) + expected_time_obj = datetime.strptime(expected_timestamp, "%Y-%m-%dT%H:%M:%S%z") + assert publish_time_obj == expected_time_obj + + +@pytest.mark.parametrize( + ("purl", "npm_json_path", "expected_msg"), + [ + ( + "pkg:npm/@sigstore/mock@0.7.5", + "empty_sigstore.mock@0.7.5.json", + "Invalid response from deps.dev for (.)*", + ), + ( + "pkg:npm/@sigstore/mock@0.7.5", + "invalid_sigstore.mock@0.7.5.json", + "The timestamp is missing in the response returned by", + ), + ], +) +def test_find_publish_timestamp_errors( + resources_path: Path, + httpserver: HTTPServer, + purl: str, + npm_json_path: str, + expected_msg: str, +) -> None: + """Test that the function handles errors correctly.""" + registry = NPMRegistry() + + with open(os.path.join(resources_path, "npm_registry_files", npm_json_path), encoding="utf8") as page: + response = page.read() + + httpserver.expect_request( + "/".join(["/v3alpha", "purl", purl]), + ).respond_with_data(response) + + pat = f"^{expected_msg}" + with pytest.raises(InvalidHTTPResponseError, match=pat): + registry.find_publish_timestamp(purl=purl, registry_url=httpserver.url_for("")) diff --git a/tests/slsa_analyzer/test_analyze_context.py b/tests/slsa_analyzer/test_analyze_context.py index 7328b862e..c9bb23c4e 100644 --- a/tests/slsa_analyzer/test_analyze_context.py +++ b/tests/slsa_analyzer/test_analyze_context.py @@ -10,10 +10,11 @@ from macaron.json_tools import JsonType from macaron.slsa_analyzer.asset import VirtualReleaseAsset from macaron.slsa_analyzer.ci_service.github_actions.github_actions_ci import GitHubActions -from macaron.slsa_analyzer.provenance.intoto import validate_intoto_payload +from macaron.slsa_analyzer.provenance.intoto import InTotoV01Payload, validate_intoto_payload from macaron.slsa_analyzer.provenance.slsa import SLSAProvenanceData from macaron.slsa_analyzer.slsa_req import ReqName, SLSAReqStatus from macaron.slsa_analyzer.specs.ci_spec import CIInfo +from macaron.slsa_analyzer.specs.inferred_provenance import Provenance from tests.conftest import MockAnalyzeContext @@ -100,6 +101,7 @@ def test_provenances(self) -> None: payload=expected_payload, asset=VirtualReleaseAsset(name="No_ASSET", url="NO_URL", size_in_bytes=0) ), ], + build_info_results=InTotoV01Payload(statement=Provenance().payload), ) self.analyze_ctx.dynamic_data["ci_services"].append(gh_actions_ci_info)