From aa5da84deea6b2f620d335b797177dcc18dde3b8 Mon Sep 17 00:00:00 2001 From: parithosh Date: Thu, 15 Feb 2024 13:52:32 +0100 Subject: [PATCH] update readme --- README.md | 39 ++++++++++++++++++++++++++++++--------- architecture-diag.png | Bin 0 -> 28644 bytes 2 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 architecture-diag.png diff --git a/README.md b/README.md index 6d11d0d..2c89b0e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,32 @@ # Attacknet +Blockchain networks in the wild are subject to a lot of real life variances that have historically been difficult to capture +in local or controlled tests. Chaos testing is a disciplined approach to testing a system by proactively simulating and +identifying failures. Attacknet is a tool that allows you to simulate these real life variances in a controlled environment. +Examples would include adding network latency between nodes, killing nodes at random, filesystem errors being returned. + +The overall architecture of Attacknet relies on Kubernetes to run the workloads, [Kurtosis](https://github.com/kurtosis-tech/kurtosis) to orchestrate a blockchain network and +[Chaos Mesh](https://chaos-mesh.org/) to inject faults into it. Attacknet can then be configured to run healthchecks and +reports back the state of the network at the end of a test. + +![architecture-diag.png](architecture-diag.png) + +### TLDR; Capabilities +Attacknet can be used in the following ways: +- Manually creating test suites/network configs +- Manually running single tests against a network +- Using the planner feature to define a matrix of faults and targets to auto generate test files +- Running the test suites +- (WIP) Exploratory testing + +The faults supported by Attacknet include: +- Time based: Clock skew +- Network based: Split networks, Packet loss, corruption, latency, bandwidth throttling +- Container based: Restarting containers, killing containers +- Filesystem based: I/O latency, I/O errors +- Stress based: CPU stress, Memory stress +- (WIP) Kernel based: Kernel faults + ## Getting started Ahead of public release, please add _any_ issues discovered with Attacknet to this Github tracker: https://github.com/crytic/attacknet/issues/59 @@ -21,19 +48,13 @@ Adding issues there will help guide the development of the tool and avoid time w 2. `helm repo add chaos-mesh https://charts.chaos-mesh.org` 3. `helm install chaos-mesh chaos-mesh/chaos-mesh -n=chaos-mesh --version 2.6.1 --set chaosDaemon.runtime=containerd --set chaosDaemon.socketPath=/run/containerd/containerd.sock --set dashboard.securityMode=false --set bpfki.create=true` 4. To access chaos dashboard, use `kubectl --namespace chaos-mesh port-forward svc/chaos-dashboard 2333` -4. Install kurtosis locally. -5. Run `kurtosis cluster set cloud` +4. Install [kurtosis locally](https://docs.kurtosis.com/install) +5. Run `kurtosis cluster set cloud`, more information [here](https://docs.kurtosis.com/k8s) 6. If running in digitalocean, edit the kurtosis-config.yml file from `kurtosis config path` and add the following setting under kubernetes-cluster-name: `storage-class: "do-block-storage"` 7. In a separate terminal, run `kurtosis engine start` 8. In a separate terminal, run `kurtosis gateway`. This process needs to stay alive during all attacknet testing and cannot be started via SDK. -## Run modes - -There are three workflows in attacknet: -1. Manually creating test suites/network configs -2. Automatically creating test suites/network configs using the planner -3. Running the test suite - +## Usage guides ## Manually creating/configuring test suites Attacknet is configured using "test suites". These are yaml files found under `./test-suites` that define everything diff --git a/architecture-diag.png b/architecture-diag.png new file mode 100644 index 0000000000000000000000000000000000000000..ca98d75d749e420928d311bff4a605cf3d1c7167 GIT binary patch literal 28644 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≧E!)@j_h_T>m45qS6}6FVEF(>3jo zG)`0|cze)oM7cQ!l%7n^@H3*9WCqt*=zGyA;NkKc0BN4a!?;6G2RF3|g@?aqKVn?D zqSzHqhrJ<9so1Vu`p|p@$8-ef$g5k8p=PzZvwH}8z?oc2Pk*m3Aj%?oTWTZ1Cr6wP zP#k(MT=g{~#l}XO<7Bzw_MtpklV8$(Mtn;&2-N=aO+4DirmTl#e|%pB@Pf!}tFH@2 zt!ymi`8S{BZ)%t-PoTPeDReGdnJ<#KHwU>JuFv9Lh3kmHdaKsG*G;v7@!&Ol?Cy`2 zF=eo*O1b+Q7@HZ_%pgvJf=KTO#@GHJSFf_Qsp}(*D&Ikc-CH#&0K}7M#=}_ZT!iKve$KNG z&bPHcL9hoIr$BY%g__`JP8}_=x}z^3MncgpW#(8Bn(_EG)jv^>p>=vt_wdNYpXqUk zem9Y#bY6BqRGw=DVQ;vQkp)M~@M={YY{gC4CP#}lwt7YwxNT3TI|8%*BMT!|aU~loEDrfGa51wMEuAXVWpAHeJO#B)G&f%PN zX@=WX7H2L|vZ)E0NjADp$+npEly!3IW7^OveRvd-yPj9J3f+Io)#BNMQ<9()fyNB>xGbyQOQb0HiyF;nqA5GtXC@SODoboy6{UBVodS%- z6MyUz$p5+%L*ve0)Al7H;Aqmp4GQxvOCwE5TW^$iB`|emlpqy+f3eq1*ktylm597h zimL~ek($GX=@urH+qVKFtHZ3Aw3I;1hk**kBq-IfX6rcNQq08%#3P%n3$%Bi-9vLh z^Z*QFO@pj4zjkNzrj`gu6x&!y0o>uCZb$eSvi>m)8P)ZRnBceq1XNf>G$`ZBygJNmeTD^ zJrlZFe!Xs9pNVe8Z_+kXvl3LWt$hmq5Z!#gr15L6F))bb~IwKMMPbtI$_X*@=Qt6W~3RZyZ{yzWP+#FJtJ- zj%KYQx5iBW%FMI+?z3kZjE_|%3B(tWT=K)sFptRZBEU6nfK#njHP1P#NJ7U&?T09z z(mz0ywnaH;zum0;0LjK}q9z@^YFl>*#e6WHZQ?GG->rbR((o2@@r`=wx(n%lnvW}H_BhG>FQ!B;sQyJ;K7TTk)Lki5q zD9Q42YYzolvYIv{e99`TD3b{Q3S6EMt8}sqlan+D(viP-@A|WApWA#s)SdtcJEh@> zf%0MCCKmjUMCfVD!0`@O4?cfa}pZU zx7ty-l-e3WzfwN9rP=(u9-j(AjFP(b3=|;5Xu5Y~yuV z>TM^p(bZ!zx1TK5JO&u&^b3MzIH-3vY}5e=$>brNHOsI|!pD_|=A~yT>bb$^xpp3x zuQ=9E02JOo1pN6k%a32VF=S5^uZ)&up(utN42xAo*Q)y>o_#oe7)3N7iXzFdUkU0u z-Ot_O>B{hgXS<+@$OAyEG8Y4B(TL*aD$v{J(D#RTgLa?ykKY&fveq2KUO~Zb-S4Au zd15dc>ms|2gKRw7uG(WHoBhK4uIskb{LWzTnAxWJ(f>*UnRp>jQrCWpD?+)5!GOW z&^j+aS$0sASJKG`yU(AAQeW)WqH3qW5TQI=aEF18sJ!F3pb0c&tJey~o~fi9ID4=0ne_hSxfAwM0Cy z2vxj2i!qKAeEYFI+WXFQlHQ}Qv7bJ|AKiai-TK7HDw?ds8Qv7xSd_MPaZS*W9@e4*XbY_?7CuD7h%CmIA_5STJb* zD%Z>xeV}rWWuxMwzwBtw6RDL5AJX#=F|vV9dTto$DeTjasua=*wt4so>^imWEb-oS zg7&|VN@TVs+R}4Y&gr?J&u$Of86St8Gh<^j(E&v8{>F534gP8bbuZt>E0Jb^aIXTZ z)vS93Pd&ZV(sYw5!@9duDD6s{3xqCd4cwm`*e*0{PE8P0jy$^HlN>hqZ7-96h2ECq z)2Ac~kx@8+3LYh|@q-3I7rYSj^9O>y-~c9%`O8dkZuddiJxkxV!HCxr z=5LgEGU2bY!Sy_O#cWMy*!B@gf5~dl5Vg-mXDLOg>)ZXiA%`lG@m%3Q%Xq0r|Bpx zRqgM?ACV8m)nPlJvW{ZL`pSDgFq> zeX`zecJOnAkJF>1s)9(AiIPqBSVqGGiMJR;*t_)RcfZlTmO3VnihPmcNtD)qZ@S7= z(zjqzK4PdLv>&rJ%Chz-O55RF=TpmqzT{e0IssA`mZ#&yMARJ~k*Fn0VtVq&s7Dl5 zZ$O#Qe)=F|@9ubbPA%2DPIM~s2ampg%C@i_Bu4VT8!J7Ox0$<%Wh-E=b!cRFfc=vM zBnc13KjG)hbACQhFO76)DcIXnOh~Ge${;Z>MkH9ct9y&x!?_McPT1I`k=dL{t2!oE z_?)&U>g*pTiwe%aJxMOOqhb=p8^(fGW`Ae*`C6Vev%dOb3JYjoC=y^+NvbuETJB30 z0!^`j>+^@+*E-SHK)={q`EcPcpZKHLPsX^Q$*=BK)t1tEgr~ghNToR@j*l=Sp`c^wKz}yJ`nGLXfYh#L(pI7 za}^%Wf~F+{go&+qEw?|BBAemID$fj`X1SU9fVTbtUXv?SP71zQrn@Gw8vcZ;i{x%z zA<=@lT%S6}OgfzC2~vHhhV74w^PRFyT~kk9Rmlii(miwTSjJ6O*^L&^_leI*5l62! zhxIA!Yh)TB5y22n1TBkp^0#4RsSTXvsJ&WVo&H3U4bRDtCp26rI`l_|nALBii(;)|z>Aju_ zzB1%Z_uRX1`=)*8&+yzrLq?2UZ<+5gr9{YWYlxz=%R+o1QWGVVl;GMnzl+ae^Tt9% zq^%_`lEk9hHTLLhb@5#p1YK8vFvPXd{`R0Z}8rWAq99`3O+J&cLgYR zAlkxXn2A1Fd7M~|g%ib50aezaeuT;w!x$Nx6aQJOaRoJ15+~p(gdkK66P^az5r>{= zwKT?AklyX0d#D3Y1kzDV`3!>3CAjLtyJB#W5&GyDE$53y9Uuc?B`u{di>@f0F!ZE4^)a@pP4$v0B5ey0dKsv$ z?R=!Wd|td(8=fQVlp&JR<2d$Am}CuJr{6_%Mmf&BZFVa)GK%Zgr%j3!*sBSvjcV8C ztloupR>UdtH>I;)RUf)gx#ZnXKB#>}g_*30g?66fqxM*s9QmB!`63r+akHqH;@5@6 zr_uE!J|q8l`t0aq+}cCWs!=PCo;MZ4Z4g8rq>gCL@zIbZYA1e%AHtH=ej>Qc`APXq zX()zJ5JO^}T^f}c#V@@Pe{dFoR9ALfoRTjVfBkC3G`D!?h6Uv^5grB^A%;skN!t=($p#nhOrMbzkckutBO;OZI63eEfK2>f_-jX_YrJ|+uyYthtuAC(%@FL zH~gMe_cfZ*5-Hk*{6T=0^r4HyQWOEB>7w&dRc{x9hC>^Dqj!Q}j!_(H~Q9F>$OE0v7NW02X{NMfJshLQ--N@NyX{JU|pjhpCHyq5ae{GQte! zU;uri!V6!6VdT{6cEQUhxZw#{Js~n!O3_uc5(e658Ea@8RTSS7=cV=fC%Sd~7bQVQ zHGaCv;AB^Np{VPTp?5QcXSJDDA9?d@i~5ZC*;+Ij{XLl{{??9Re0)7a4BW5Kd}W#v zX6&GEp8K?5#@~2@E0__qE2JjLxtlW;!Z0x-HscxjZB6!vQ}>tp2aF`aw^Crm_K5D2 z^Ay~o^&s2(WxOR_fTv2XPs#V+4h{`0F;iJF%XwqH)(}-0l?%pv|0)IT8tM0%jVo&S z&h&!UzTh>nD)Xq(AC*{F2RLAci;rN!4b1PJ>@Z=GbvUeS$|dil6Y$Dy!?i7L?!Nde zbC$1axa&P>!N@Vn7EaR3yE~RyU@BEJWm6w?17M1 zX0d1tg5jm~LJ^S!k^>j}-1}-+TB)RkrV?qg=_wf7Bt`Ls5UqXNBZ=JCRoQ05>H|2e(;b`cGy>ip z?!)!+a9XoFd+(E-9sR$LYwRLsPYEyRI?Xm>M&zMWXXc>~* zxo8@ZytF7@MTA;i8sNV~6ae9coz3!MHmo>MK0@O;Xhx~pM1zMvX(`~L&2{d!O;s*j zz9G5U;F=03b@gf;y)FSQ!^P>x4&!SCrTf6U=i~dAqP~#J*bmr>`ilC3COxI=T*|TQ z5P*1AH4c?en9-J0Aa4)CLy(sOdBxh!pe-@)r8iim;GII0Tr!BJ`L|)hJJ1wHI{7Bg zv~2!Kn~jf!u+e4(ucd7U#tha`b(U_$v50R-B*B8cS$W`Tk^DrJS2%+`m07!QGtnJZ zwL6pHg_jZpby|+Ygc9Ut)=(9L@RT`}Jg?#*AEBC)8{tvL2SwFMi8?FY>RU#K6Wiia zhz4azsVCZM|o{FJ++4N>|$2e-jJ)3Pu~LAZQhdg0Z}T z9X_j+cVC8$qA2i;T%{YX%Box4nFPUXMylaFsc`qGyq()dtyOA+$A+k8GwpNkXCTFf=2UGa7)OlC#^??Z$qL8R`U z5EGrqLN?yUz(S1$e$M!p3W6XW$BoGnMuekGKs0mXDobK<+!(^|x!poyg`BL<_g+Ko zH0A+8%#EI*36RWj*RS_fd@NDMeVW;W^=Q=X%Dh9w7*TEX5w;UOX?%_Dig;z_zVsac z4^%!FLv;FJt(mVcEt^ViN6%sB1(P9gzey(0_PExSMu3-t^;H>(#@do-BXj+>QX}(K zObl(x8N}OO##lD-$xkU-g_1n6xHQI%BU0{V5JZH?n>t21#I+NX#`Cdzn|6eryO!#n zIs_X=+K{DKym<42=$+Na8$>AgddC9>$&309kA4umZhU-1#)-G_3ZA=Q3}wc;j=CW? zg{&3^OQO3r9s_4x$AP04^^;+Dc$?m3htgviUQv=9=vKHOFF6FL;wPqlMoq?dxILKj zex@Z58LpZ(@13W4AE=q=B+Lvoxk$i)n8NFvnY*5IDv>cj*)|-*s8G{Yw8R(DwyZy~ z8Y|{4q!Xm_`+JO@2xKyZIf8H#hj?xr0Il_P=>lD-io1wwkzC*oEac%fnSzz@7)1)z6!5({l2ir~5Qp0sxk-%s{M zCvbn65u+pJfU?=oY01D;|hIA8LB%wt?u|aXAK|PwCrePHJap=A+gHT8He3leuamw7` z*Zm3#dNRv%T}IZREw#b&%MVb*6q9`$*B{Y{eqglOlTx>2g4VDkYRwvSFRLgJC|kWX0a z!95Lf)#A$qNF1-4Qkz<4rk}YuARGGo{o)t8%@wxM%{dB#Tu>;{G%veoVjeeCDNR|$v#HgI~qwEO0>cUfy=@k*%o@cn3cOqv?+ROl1PoLC}WT{RJ0(zRx$1gRz7A~}R{Zq5I>_GeIVde&D#nsn0% z6CN&xyGf(R^*ujsiioZT@tR>dO6LMu5TUCEMAHAo4CoCQCxDl&M8GV+M@$p$DkgIu ze(i2yA4}4wk=Si(r0caB!6jGDQ>}d|tC5A2Y#~sX+Glf}P-iiT8I|IiPGwy~#jTb* zp2DvfBkt0Ke$>}vobb9!9q@$;T}|0ZUOBQSGJ=uw39YWb|NVW5kVWKf5O=BQc*{!? zp<1mdjJ{{b;jOJz7ez}<(h{*Q3q0lUP4}f@DB-QlXs_Mob+fB;*Nc@-^!b<*EhhpD z{}V>i;p2@yiE|~>(uYGbN;50yXRT{RL9Rq~@mJUqU`jsrTkfp0vF*D~cBLiPJ3qYC zM$`<_K+Qlxtkedy&o=BzuUEZGPgkH1A!TLHph;JIZy_)EE}af^c8h9*(oGsW5jMd- zNk%H-twyv%MLB-%ATN=w+E^?v!?VD2<@msaXM&T?RLr4pLp)672t^CkuVN9c+l?P? zh=$?CFM-~~`!)}*@A1oUDZIDh>*91t(Zm`(fjlVx)PqnHk;p+txs;G^Gk0ZRJ~oIrWfbNn?<-*WR z&ojDa+xzZ4R$6{4o65Y64{+z4)MG0Ih~&0^E|KT`MrMr95eTQ-QWBE-rw(a zU7z=-=@fHsq^aTBOO;cDXgFmPd)Gv%x3rb{OUf^zjDIPgFe~ZcV7WW6K73fE+Bk|e`pRjcW6D5 zg)TbXpMPlWXrmg>i*xlhVX%|<9kl&8%uMhLx(c$;xEuZ1S4%<0DD`+x7fJrHMG8${ z#75dik)}VQaO#stC$EH@GN5BZ{UqzUOUnH55m)*{`*jTM{Ek;hY;T2e<`Ea^tDMer z3)yHHUhDY7D@RSU~5S|IoJ!*-xVkaBc=QIeyRYsaW~?rlYGsRtf8 z#31);_6mCE47om>b>Z3ZsI(M6sQZzsdhU{7m3<-wPrZo=wEVkI@8sQj6iK(|RX4X-nHcTn!nG5Hb)TPL?R zonyejA7xLPmi;7wbzlAPwmwBGHNYMx)4yd%j4NyjZc-i33*K03oV)4VosV86!JX+CjX*J!@)=~S3&Ec?gJrMm!phjm zRmVsYp%B~tI@OWmZ!v|(5A63*CN7l!b}z>FxlYH_F1<agte1& z(`#5H zD;-73x26~PZ-zRo+MxX0oIiy=^|>x)z^D~TRxPprE!)kx_0Ht!$b^>ICak$Ge2rk`f||W#nwJRH*w!1x9lKX3tYN1@AG)O0BbSI;@=3F< zxSE0_*e?ay?z4Wr2Z^OsK_)bZ65|H9-R472pvMs;?s-Oc z9_pyvecL;16_m0goArQoZXUjFdu7;XH$CELgAUwpJ9+Quy+0LyKz+;(`Y#tL&wDD= zEm__8eW4(XLB=MlY++GE{gVF=_Wj=;&`HVgpJI=QO;OPMj7wm|X1aZ@mked&geT>9 zo4l~-ljklTx_ent&xAzm^pP@s+(8vxPJ&LtxXlsXF-K2rVK_nhgE4x`zYcR9Gq20W z&FR5D{=N*bW?5U`6M(Cf1y7r4{DEj8JecmFnT#VAtem3!Ki)mpaeXms>(DuCL+<9B zFVZ*t;?Jy6mG;Oi{)ECJeFb}cK($~@l`IX-xSu=KB{fAed0O5VMFhe$GckR);2js< z*I8L4Jr(A*q@L$LBg$T>YJA}(twd2+=UE$TF7>clAwL^FPqLd`kSn8=+|e1x9Aqu( zN9BIl4jcw0hOq^e;W)txx%)qc{Er7N6vI~OWMDYMhjKp|Q@Ob5lMhqx{OdUWKOR?yJr*!84x{$)d0JhuAKEqk?j+gxfxTB)-H}N1 zuT+9%ns-e#m=w@nx}0RhHKQrZC)a>pn*gDcI=GKqa`io<*bBxpLCKg4(+FD|-1sCv z#Cu&l!C}5$-=-9Q{v!QmU4q=8omgB(QJI8*xU^ zI{7usTD5HsQo^EbHbw(80KZKDXRHM(>dPZgqq(+lm}D-h;p`E9+7(7=_AS9GwB z>O()kXf>fq(~QVpVnGUZ04i_2JiFVxN1-r)Ag+ywfXgtTB=+j;g;Ps^Bql~a;8J2b zOnR+=5T}=2D%gAVT`Q3N{ri3E+Lzq4VrE<#K?F6{Z?`pJu3Kq>O5@i8-Cn`e^VY_Y zc&OL#%uJFjWvlf|se7tKi)qcS2i$4xeIp)MK3h!&p)?zdH9 zh4Sts;u>@HP}RW+kkjj^)V27IgqIU>4GqwVy?iHO)oo5a;m;@*y*lg_|0MX<)YXX| zmFwC(s??+rpA4B^BvWX99$`Hu8v+glUw(z$e*!?e8@bzNESg`$xJM3q9xsFg6)fEgQI1?^+LhuoQDhnd@-?&LFrA+?*xcMnC}bFLsAnZm^N6{N7koA&0M zR-gJWiQk%HA>(?yG!LO}?W@W^UA=YEZB(tN5i4WvIwjq!wVL61>#TGz&8&(F%Du}V z8-GA72Mde?<8QmiP*LjE z3*{RxF|Sk`6L=I(@6Bn!`HeP*9Gz@u`ewQ2vT5uZ?g!bU>Xfoxsd_)s#mvD4L6y`X(OwtBBcn8BG4H_rBk){!`1E++BQiR-w~xW#FIeuHtr+8VsC zsSMqa5{Q^I6%sO(l37UWL)uXR&3eSb$%=F17dND-uOhN@xF2B{<0_w@3>vXPgzY-> zFv_riHX|Nw7+n+qFbYy7MW=bTcUuB>qrHiNx}+7f?K)8M12vYmiD6%$Rk%jJlDM(X z+H2Pk{V#bw6WY|ZX*YY0I2pq{t}YvFXOS%%f*|aBEY@@U5N>^9VaVpD!hIEH9L6yg zWU@~p9;*eU5FSB+@o+QKmq(@g3qc@vTc?TCyFbg@%U0+ONl0|a{wg0aHNl{SOzt&K z-3uF%mjWjpkDH3nRphDNY5NBU9Y&7xpP0wGYOHhZQ=n>rsdf9g|9w#nu?r{e{}n2n{d*mEBL;rS=~!Djn2(g@AAy~_+)u1sHS4b1Cntdi zRX+a50t%lBaX$(O_2JdW>YA@qbivN!|L_kYpn~F$@{Lerx3L}Id=E|~ zT8N{`Klz+cmNiw$6Foj1(;Xw_k3Ae=p<+Y?X+ns?B1q)FxBXbBS=U2mV_lDFl)l)Z zP6gz8o`mdfaOj#HOuy`+k*G)W**1S@z%yM#!07M`0Nu7)L!Ue*+;R0KAKPCe;OFS%xfR(aCdd=&Y!RjW&!d z!7dp#`}nIztyVOg&u}FFkr=RCOHWNASQ=BRiOAe$`6SwEfl;B3=~ZslsK3EtxSYd> z_ns}xiZV;C82$TO7*q}TE!x4}7wlgUHzxSDSuz|;Sh?oBFeWGIsh<3^H#=R5)A{6* z9gi_R=u|;vHaId;rn39nqLCYnX9)MPft-Jx8iP8U1cyL7xkd`J8JOaN@`}|cR}YE9 z-jKVIUPSpGW3nGOI}$__VXODossER6