From a83d3e1f1ee32a12856ad0316d9556ca7c28370d Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Mon, 19 Jul 2021 10:14:16 +0200 Subject: [PATCH 01/28] . --- gloo-edge/gloo-edge/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 69f5c093d6..ab011eb2be 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -47,8 +47,8 @@ Run the commands below to deploy Gloo Edge Enterprise: ```bash kubectl config use-context gloo-edge -glooctl upgrade --release=v1.7.2 -glooctl install gateway enterprise --version 1.7.2 --license-key $LICENSE_KEY +glooctl upgrade --release=v1.8.0 +glooctl install gateway enterprise --version 1.8.0 --license-key $LICENSE_KEY ``` Gloo Edge can also be deployed using a Helm chart. From a1505f36ab076fc09b65fddc588766f58c29673b Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Mon, 19 Jul 2021 15:56:47 +0200 Subject: [PATCH 02/28] Put first routing features --- gloo-edge/gloo-edge/README.md | 264 ++++++++++++++++++++++++- gloo-edge/gloo-edge/images/httpbin.png | Bin 0 -> 96042 bytes 2 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 gloo-edge/gloo-edge/images/httpbin.png diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index ab011eb2be..1da30b6cb2 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -69,11 +69,11 @@ done ## Lab 1: Traffic Management -### Routing to a Kubernetes Service +### Deploy Demo Services -In this step we will expose a demo service to the outside world using Gloo Edge. +In this step we will expose two demo services to the outside world using Gloo Edge. -First let's deploy a demo application called bookinfo: +First let's deploy a demo application called bookinfo in `bookinfo` namespace: ```bash kubectl create ns bookinfo @@ -113,7 +113,96 @@ It should return the discovered upstream with an `Accepted` status: +---------------------------+------------+----------+----------------------------+ ``` -Now that the Upstream CRD has been created, we need to create a Gloo Edge Virtual Service that routes traffic to it: +Now, let's deploy the second application, called httpbin in `team1` namespace: + +```bash +kubectl create ns team1 + + +kubectl apply -f - < /dev/null +do + echo waiting for upstream team1-httpbin-8000 to be discovered + sleep 3 +done +``` + +It should return the discovered upstream with an `Accepted` status: + +``` ++--------------------+------------+----------+------------------------+ +| UPSTREAM | TYPE | STATUS | DETAILS | ++--------------------+------------+----------+------------------------+ +| team1-httpbin-8000 | Kubernetes | Accepted | svc name: httpbin | +| | | | svc namespace: team1 | +| | | | port: 8000 | +| | | | | ++--------------------+------------+----------+------------------------+ +``` + + +### Routing to a Kubernetes Service + +Now that your two Upstream CR have been created, you need to create the resources to route the traffic to them. + +First, you create a Virtual Service. For bookinfo under `/` and for httpbin under `/secured`. + +Please, notice that the oder matters. ```bash kubectl apply -f - <&PyZB1`sNvageU7-OPEWvh^7EXls_gc(GUJ=<7@ z8B2C!#yS`?&eQ9CKIgp8=gs$g|A6z0o7>!YJ|A;kkL!BeANTwHy58$(sWF{qKTShJ z!}R#keO($FIsy&NasE>$flso%a~o)AcxWEqSJ8)9E|1fDUohBjS*8E{ktU7A$C>fr zrGDlI9?cKlCq898I`{G0MiI{g*+;A=RCE%F*S}pCq@@+4RVP?vyg7erQo--VkgG3f zMAG=TU-wRG!!owUYfhrvzsG;Jo51%SM&42=z4nrZ_7u-yKhB2HPPar14wu^4l(udU z8qhY8w|#!xH9K)undaDk{+Li|B# zhSHwc=DPRB=^=#MM`G*H_Z`IW?i=v5fyPsW^w|e4{~6N1!VGpieRcxMtOg;}TogWc z)U%%7QhrIe!ZV3-(5kq1*!TPAeZ0qL_kLevAlv|bqdO{i<=c$FK%7yBaCd;NjvqO` z5I*3A*!M(iIrN?3;WGftiU$wySM0GwMP_&D+WSYvMKpg&gB$rk#IBP=za0Ino5Y+G z+nE}1edt2W)T7A;cLu_AQvC5lXa680AlE1G$AXG2Q5)?-#g0Eh=-4If!}+r>;H6)a zdb4cQjvVpfOGGpc9E0;UBT|&ctk@H|ml*IWavP^oW&5=>ZpOP=2!F5&;#%jXKY}?LH5Cm#yH;9sBS#>1ppb z;iK}V@i-eq=NL8Vu9rcbFaB1tm5$EG(F&(RLIdtXCgr-z69{+0S=^1omg>Q0^4`JU znTgQN#Y{_7fErmI=bv3{-;=_Lr!*5DLAYIFyk8#~dmOFD#R;YTKm%dZ3YivF!oY%$ zu-TS>I9ZJIEVlLZjpQR!ME+Fp_fy27LbL3tUm8E#i9$w2UlpL#a1X23Br(2><3|oQ zy}((-v7jo~kqVpEZetEAke2#Yu2(4QJxXGW(L}|Efy?1X#Y?<%;v2^VVsy)>*m5xZ zibR2RoT!ynM_h6Epx$ta^{bOi>^Z=+-LJE1B0Kh%-Z*l^n=ic6dWoxW(qrO~Hs@8p zP0FBLkYyqr@^HgZV5Ed+hA&{915|xFTU{(-OYAefc$sORx9rQR&~vLHF(a1PiyKIj5|5MJQ=D zknc(S*V!(!p9{Ik3ebmmOm#o7c;#i8CsAroB#+#vi1x>{kMAYR`3bt9UE8Dis|}=E zU76S=|7P*HDwaXouxeS$wXuL%2*NeL-ezJDxem{_kKt3HZ?Mp5)Xu)$52(1lT(deFJ# z`a}h&Zw#3i86|#2?#LYb=ONS|uR>$w{XOwml-cGY%2qU4uh>#yrVC+&3fPRS)I&)4 zrR;7kTr8vl)!kB| zgSeiMXCM|^HMrA}8ur%0`u)i}J30EfedxK?sMJ62S^1xjza=W7A1@re=rDBG8Ht!m z7obiVDpd6IAmNT1SC1@F6V|7{GZMLdUx1&SB5=j-J?ykh8}WCsEaw zu$DJRjzcA_2j>JZ_xMbQXQ$)?gDLb;&V+hZS&y}(B1=YHM@Pr-ld*TK@9}D1%5gQ3 z$azK`Ymehs3*WVIIP}e2S<2=ow_lT3*4sT@PayRtI!73Hck5DpmVYkDa9VG3~Og`23n@3s%!_?5wh?eGUtE7=Z@t+Diwe2Z-Kb#Od7` zJ#2s=$;##@wxcW{N}d}RERfq#&A&8K6$^Ja0-Kjaa;neFw-36o%RUe3f6*QXeaK{) zcW&BxMd^jHSrsJ@1z$1xLA#^Bn~)u=WL0#Tq(NUQ`pkZ;XUBHuIOB?&!!z2wAyc%& z$)IH`-GIX&F+`cRlygGKcM>*zDcO6H5XKyL!z=5IsSJ4Pc2oeUFF z3-7$xn`sfQHNW>J%(<^DT8~>pF(Gebq3>r7*f$auypvk=VO{s`%0oBx`3h%4(3bWG zu0xmm!Aq|IbExz+Y_==(eFrgUfz3tIrzJ4EpYW&XO`_EGoXsq9Q%r}++OOJB*$h4= zXC1}4G|OYmk%y$kS-s%lgXBv0=haG*FU&W3wG5r>KD>bcjyv&xZn%aB8xOA3-QabmtAFIf~nrD)3 zDlRci7-Q%i!nvV~>!{w2Mkr_hiz4ybK|%GqP90j5693Ru&m=JKp?#*8}+GtLI)6qs;fkB5DK5ja3jlC=3G zVpX%~&EE4xpolH+%g}h8-^}#1&0sUPyz>W?#g6zdyC(9-I=|REDzpi^n>Q5W(p>E@H&Ny`IR~QkS^p{1+t)E4S@=XCs%60rio40K)5G!DCoqcWjd>k$C z_65(hQEA~Np;lHCsi{{Bc^l>e33uQvNxx)$W<#WsE=9Nq!LdnbhsU39_6lh(Iqxho zX_c>QVsv@Ka(p+{cW24MyVO>zB(2sH`xNZT*|_Y-xI>qy{GH(V6TlMf{r~3%WEG`yp2d%S^EuxR>TP;+t~NdbwsNQBL+&_r{dS{ z+6!&ix=T43>w(1CJsb=6R!w-MkB&`<%Eo%302q9|@ z=6TAl>iLP1L!7-i zv`mFWhSx$NIg)28KpoHU#kApk7{%i4{s~qFZkt zYE@h4%R*xtn4MSW_TP~Bz7q!O6Z*0>Zs?i8=fF^l$cO}zSiR=LVW6pzk?tGoL~9ta z{zckeqNIC{lvz;k=Zl8h96=J-wwLf`dFU_$^OKoblr7FW$)LX5$%n)>h{$)Hz^?U{++{$|x-nHhh{`qDpwK^zW(PZOI zM`^66nJx;7Ec)9PT_ayrN33^BuXP^E%C+w_&Dq55&Ff6#ylp!d8}u!TE8VBiuFcg- z&Ogb~Ns)5IarZp)(xm3OqS3_A>%Tr+s-RteuQ%&V?zRx=NgLLCGm!2gXV;N9Vq>Mv zp7=6wC$G3-v13z&z=2Rj)eahDqu1NxuO(yLHF)oI*LOPW{+Ote~A| zm)Upoi>boA@csLy8zXUo`aIR{W8X79GgA$-!WSx>@qU83w^BDL8zW(ZnKq0<14@wX z@64Qc)28{g7JdrM;m%1B(gW{~96JQ~Pn&6#)~@2Rtt(&DM7Dl~t+Icmy+0p) zs`blVy^|4KJ4I3&3VX96NO-3IaZb4)bwtn@yEQIrS-U|od4}*ji!_AW`}!%JUk}*!j?*vlX4qU%YQLdm#6tJYySGVFn&nKV4~{%{EUNC#P;+ODUuBJF zRqPYfx)rmCD@x5yp!JuwT_60ndb&91708h<0zOWy((n%ET4*ZNR(Os6>U_6v6SZEG z^*C8qlLM{)cEhP)gxY`~&5m_x_>}Moj9uLJ949&J%=zall{@0GN-WMJ?VDSK(5RH6 zYXo0k$gAhL;2WmfBXL?bw{&k6FAnCh$M&Zk&a6a*E9=u9>_=*w?UnGtghWuT0}lVM za<8Xf_enUO6Xf*85WeFRLn7Tof+mZy%ZoKJys1xo1Y4&?kWuX~J7NXW&Z!2-;m`LI z6$R%UnB7N3E$`fIvGb;m`sskZ@oX1qp_mk~j}D$K`M9G|w>=USfGoOpqoq#%i$I$M zeCxzgosdy+E`DKd#y&fW_+mB%~ zzVDd&i z)K|)yoesl_jfg?3I-Lg#+@I7wJDg(RVmPJ^%n2KIsF?IEr87>$-dab318boy=jq5D zD{L`V`{&xVYr7unzT(k(=zsK(7ryXJW!qjqQ({p`RZ#KZNCgLGHeb?wfO7$=KRcxOo7s zC$6`7E*)!mHP(5rvbeGUJlNr&df0Z(qj>86rHR&jBDQKf7vDrrkE^mb=9cyBT(Ep0 zr8+LT>)4%*{#HE+GAi$GuCDQz&T<}v4?0Maq=Ehulnq!VKeXzNR?X~`)??r9-F<2GY_9XL3LKD@%^$jUYF$h;J*Vfb1 zgC#{F;Jq)eaeu$sTD^2hZooLI6TO8JV9=`z;)rvfJ=T$5Ea^G#huOjnWaDndjU&!K zSm@7O{XK&IeLK+{X?zaoMGUiKBm95I2pXKGqod2!YOd016?38WcEpTLdX<-W7W=8m zR8okqeh8XoC}&*A3heH?xWsMz5*$K)xM}&-Tr0!q?a9NIN)+ONgF-S8G}}I|Bqulb zY;s6D4a5s*4UJhq!Dk3vu6`0r3VYHX?dHN(Gv>`>uTgv(m2T(WkQnDQV@#H%m+dbJ zyA3Zh#f4>QCEOVcz%*944Of>|p-PCHp0?8Kr`=vp(CJjE;JOs&<^ z(?bN!l#QTi3n!~537UN%9A$oE2T@#&?$~q*`0E@{mQ2Zc%x5KbEm&P%_e|^n6ra8|P zv%~848?Ako_agh}>|1IQ7C3{}TZoE#u6~$!IIhwNyjg1{s<3SMKOqw329OE~y-I$w z#&Jrg{5FR)-?Qm0{;K-*5CT>oM1sb4*b{6vxaA)zQIO+K;i;Vz9RSCLuSNL}tuzc2 z&hcbZuIHsU_+Y?`a*h65un0E6T0HhmRl&xO6HoK#>2LsolUqp!bbppW#8V7pY2TWa;7>DJvwgXHwn9+ zR#R6?oa|r%z8xV?G8~`LqM0~Twi4*w4E38EM7hWf78-QT;NG(GYv&ta$UY0r?z~}a zgYi!(%iJ|y(n}Wut6n%~!2QNzHFt6CJEu<(s|mR3{abF78BjJ=F^T-)Y41fCoSE#H)fX_PEqlg`nNMFl{>&ZWgBVxsD4W!aM`0k}>3 z#P`uBx$Jsne0%7Mrxrf0LrqkVgHp5+E}$~)4AlW9U~{V29F-LiF?yFtH1OHV%C*PI zqk{wKVe8aMIpn1a8AEan`TY*v4|aN5UyHrk(C-a-ijCqtEbY%KPy9GN{7->L{8H{} z$}g%?Q$T{|D%=NYcgXynvI>4P<{#LE3Q7qqCDndxf@~r&R?#g?J_}U=T_+lPN;M+IdaQPfcYQlqG@-Q|+nI@Q??-@W%k;CE!a%#Ms;?*);BWuiNVUk)S zslTVZr(LQ3b-Ok3oK~5-cN3Jys%jVsT^x*7w^KyQe>-k>SrqO7a1IT$52YaZKoeP0 z$$jvv^>k7<=-W$5Xlj*7aKLt6Tlf{->(UV~0~?kT{x2*zGr@lo;OsDiI6Jx3=`JMQ|(J>62?756LVvMHWaGvfsrk z+5SA?Hn!nap=wt?O;6Y~dY>I8v*EEmD?C^*G&%#x)@IM#+wmM}fC9mm&xz!ik-p;1oz!K%(=XFY?!qHt7U9TAIe zjM){VT$KwlwSt$o&1hPOP-8pn|bMK@634R>EF(e5r}qK5^ZoMq|%#jQFQTa z8-{GH^p~;cv2|vcX8>RbC<+t^UEjg&MzAaRCU$s9vOH2((CbW`sV6jEa~rGpWhbXc z!VT=R)cx|Fr4%Vq^{cDtAS7+?$PNh{3Fc3;ecmZ2zyYJ&l#A5c!VfO-I{HHAo( z5wX!hnh5RLpq$$Y`v@m@#q}>lYI#q?fFv9EN&E!%#I`kP{q0W-EYxKVT&JMm6Y4u# z3&4Dnw$BvO$q=Wr0QQ%WF_v1a`hbpaj}vxMIMbeR!>nSHz$RF+05dW5x)hudQ z)Sr>-l`hYRVP1ELspd}X5mG@b`+Od>smRE;<(+iggK=}wAkmUovN3aej_+!r3^ z@I8ne>S zm_7Nvrzk-~G`av8I43BYSqoQ#c;`7FP=e^-F6v*W#>xF zcAO|Hk}f~H;8Mt8#@I3{ZDi-wNs`D$X3ylKop#!NM3xq+-A8nomWI5IA4xBZiSEIk zW)Vuv%3DNpRWY;TnWkAm8}I9J6@yNfY8gT}q;qoFtaAQtX;D_lUF@=b{whO1D0OlJ z>mbhinT7b5EiV90I4N>}VXy6gm7sW)Q(BDXQq0BIiT@IR2*lWvf7&~ z>rT3R0KN*?7X&`j3##sV0|>`&6lVb8u3y#wNG{I10p@49-?C{jC-bBLBPETBBF`U3eAf#MlrZJ4OXs`P{s!(e4b>E1yY~7S$KfF%fe+=wA>gFufVw05SO}MdI>iX(= zVdITA&67(5MOj=HqYq?mvSNpFFzva(3({khQkQD?SeCBd6*>HYGN;dCmG1eSn55kB zE`9Eiv(6S&RI{$+HQ#$XQqE)SZ1vJ*^O^unLPSEIFveFl!uDU}n#b+Pk41;WA)YEa zKo~ZYWF`Y}M%7$&C7`t!K98?&PJS4F{lV$M{B@+~EacvMR{GxselK>~4e-M?8i?xU z7yb{069W?`d~{F^&2IQ-Sh;Fk}jogZrtyrtpu1t>#jeC zce^yl2y8q^64k|)``SN4HuWqgTPt<&8?R7>@3=2cHpxjx|9E4G+VQ)VO(47yu_vIb-+2;kzji z9;Bhsh7DW1ZyzmUQTx1Yt}R)WH$`NMV)Ua!ZF^+SD$k>Nl*KjX$B!So&dq#4ha}u& zV_6^g02qJ0w2&RH;o;{2Ux7_4N2_q|27b2jNBZavhTE_XV8WeyD=ag}e~t*Bi#xbg z1eq%7Q&j8i%$g}AY5NnBsTHd`6jHRbGG3Rbm!J6IqVVNR#pmU#L=s;v94E3RVpOoJ z{vhmvPEnG!do)E6*x1G|2e`SfYf?PwCwwMj#V-TXNLa8z`y_yBQ{c=j$qzLA1Bhx zOG>82j-TSjl2%r00gq5YX#zb<7h<3~#7n!G3?;2RSQxv`NC1IHt^w?_2+s4nukfRe zFU1A``K3^`A&De?R~2=VvDvyen7e}%cW6JGc@E$<--jLA6Q7d51f-YNB*kKLSwf#x z@vTQ$eRe^{ zm8sKpUpzAf9sEkoduxm?_O_*drDef&)-q93+ZDP@5i*jc>@AtSj5J z^$p7UPQ?Vm&I|JJDC0*ZV;dS8DwnG84FY$ZbltFJ7H})1ZEV>Bx+dZ?-N|h*?U{Kex(%zM@n>(k zX4=10j9S)v8UWg5H5GFLZ3QcTY+(s@Q#c_LG*vO%ZS@T(TxtRR_b*`^%=aG%$z#{& zf(~|d0u#J-u|GP2)IhCQo9niCr+WqAu0Wq_5?w2(m-pJ|sst;pld2u_yJwfwqG=X$ z+e9}`f}r^a70@-L1^jZEI^BaAEY#!J+1{Q97!+XLlL9tlTMQw%a?%|XXo@rQQOc97 zjqdHoofrm{q2i@Cc^9vv zsFNH3Y)uG1oCtvY1uDxv6G1b1n*#)1_>*R1TDmI)fazC#S&!{3CIG~ohAV3tVP&Zv{lLiU~&e%UoTJK$W^_Q*^ZO^h3nF0-pynVkh@7a(G3&7 z+FuwzDQchXOx{lbQl=f1_aQK*T3ym%*;x_qll56hW%0_1RPs5glYJ8b)?+6 zrQi*qU^M{JrcJ}+CnelL=&F1<$B93s?6M`<6d{Re%f8zs@8jPs&QjDkUjE9L@zT;Y>~-O*TWl6r1Tuo>#Dlwfmck$Y)oErL~*LL>nJc zm=w#C-OUBp*vV42$!7A;W5>2Y;!RuSP?Dl1qEcB@AEs63yPr9$xj3S+7w-!gJ$sYr zG}2KeB0&A$_xr+n=yKy}2ev(tCMfF{biSDd&`(y;da~X^bQxA7!*VTB`C<+B6>Q$_ zH~q!S`I<;!Iiw2QVlBj^#?2}n9UE@(nOAppM$M}y5bM>3e9^bP^zyQ`_n)#$RYX-5 z3nM{x(8#L_Y1&F=nSRg)C!e{;ko}?hSG#k47h{FI8csy=n{AIQPaa=Q1_=KhMtI%r zU#x&-gCTlOrt3ZkAUtxD;uiI*-@X86BWv!n(8Qev_vi0D#CO3s1{{h2Ji*tGO2CdF}gVM*Aq1tVMja?C9|+paU}to4+Km zmvIqWz3@j*Tgl>QQ26Zx@f-kYY{9jYq_yEId^sZvw7!5jo_rVDUHhd<>P+WU^X$4VFQNF&Szj|i zE6`8*{CM`*pAr?YoIHeh+3NfxOuxeMP#D-aeN7oc_~CQrbZy#eMTRl75Xjo=ck)?Y z?Uc@35bJ3x6nn-6fzKvCO0p3QSzWZ>+oE~B65H@j+(n}atMMh{IGhsS`1dgqV8LD^ zk@TKD``S+e(5uOhpbrN{zF&>XpGJr=bMB-C_z)ZmJ)RXI1kx)U+tfD+m|p?J5;t-&0Oo=!LV;T6 zChL1B;W_c?B4oJiLk+7K2p+Z}7c+thgvZd=@EBlE%x!tMKGRBcs~5K3YlNH>ED z5kdP@YG|Qs&{T|pcpI|jDaw>C)RdBvG?&)gTF|FqFXypV5#YNt(dK@H4K%p*{zNGw zfjfF>Z8-I*|IpBi z0d+d6=9fe~jvv(+(9o6&0_{b9lK0!Ax{H^}od?~Z`y-bBk6`lv?zh0R@5<5d z`G14*?{oJ*2mAjG%Atb-x!p_#Wb*c*A+=n+%LyC&UU%i5VI_U$ z>{KY*Z#+PL%ns{Xsgp9z?>Gop*IQH@&ya0VwNv>!`D%-f*9>QxMmj%sr}t7 zGZ^aIc|%Qm{uP5n1*zxwme^mwu*ax8C`oOhj-fTd2zfXGOTj6Vu&M=T zYwXHTq8qw81J}1g7^dlw{hB>rpbz=H$IIM8XN8Tkq8uWISVxk$W#hLfWM6|f4jLxq zdDVomOn_HL$A6;em)(C_y#FHtfIV0Gvkd?~wuaLsj_Y`=#2hQ&=S}XUZ296QP3vv# zUrP|(0AuVrznR2J#7v?O&JkZrsPJ64%^RgwPQ=Zx0fm7+$BNLco-CXB(tj8>(gH*JY41UX|jI?&TEBVhR0YtOG`@O(TK-t|iUE(vmwIYbL0^r9N zSSeao3oyhCX6kXo9jjTu0WF`kcHqih<}RKz?v8tSCwN1GH$^x95)&uVoHN^Un%Q}z zAjPuCs=p0wLFN-3Dx;r*N*|^^qfzB@UPE@#qRh23X3Zwm%3yR#Rv|8 zYLCYUaVzBmZrXd-LG z73HY(Gbbv*!n>`$f3?2B?=(|pBBJ4ORR*HZiCs=VaH7@A-vyX*j|BAf zk{bC9d!vF+_3|GYxKvd##B2U`x%YcYn+?4dyR@+chHm`&ddEc8PJ@ktj)GvnG^#ypq$+ZOnyM+2lRe2pp@B%7fXV_0+vfBB5^ffH@7LEG{6ox z#5NEBVGY8dpsBSRS98QOKe%*MC9`k4gA9s{MVh#a^NB&5iA?MObtnv|Dn3QP995!C z9s6rbD=izB{lhkGsbgpa%enDlocmaTb-JSdO47*S_RMJQ#j6E?Y0jXk;0m7f18CjQ ze?D>N0Y?l3t!gvsF%>3OFbawi@va0WnPa4Sz~*q>+@`--#uYPG4{I$%*+6VajiLI1|uT9bNNX{*vF}elGUA1;8}TjDk0Jvitu6 zX9c<{iY*!ZazLQXB__^Mk%q{xWi~q8=yLL`ycugo*f@!N!b7nM#%ZytN0r&uvKPwK*?3P zCKT#Etip|^HLDeZG@JHQA|BLML=*IZSu9ZnJCVtLKnCR} z=M$-^VR4dyFGQhAg`@SEi-Ur>5BdYp4wDXW1d;mleLuTWz*iWz+1J|L^^sbCp-qY#o-dj=Mab+PZ`AVEgprl2uBw)$U0etd>SEAKMRMFH|t;XP6!}sjVdkzc< zxegypB!(kYt3g)fSjQ4KKIQr#%G*}JuGD&mg-(&;nrYu{d9(akK|+mNQ-E1b?C&Nr zpeUH}2DnPpcP&HKPyS@=G5WL1gxHw;d)IVx$5rSZGmsomuP6I7a7r1)FZ7MO8w3QrMtfqnZTGQJ0F4bF;1%?ZS5biHGA(F_TXe# zl%hp#`)NH*6jX10+yDY!vM+%dA{TJ4Nq~K=ihc?3sS|_uXH%>5aT8)_+RPu-U`#Vq zFMWR}vCE*)nJ)W|q7^o2D{^YdyGg?o~U%W z`u)M6(ma$4t6@(9DM105D&v!47%1IOg>4hD$r!-jZhQ@X-zI84WygO>3nfQ{yX!ra?fHqRm%XAV<@g1Uv1wmp72a**&Zs> zTdd6%`X;aI)nz^LFs4H#NqPa|@M{tQcE=#=YU{^i3d=!!%dR6?2!qcz_U;u-eljYe zsA?W5NEHKT5Q+GEYa% zKZINWPApJ^Ra+N-w)H1Uxm8GUj1NdyRa2pH<^7uE7Gc?3@7(8$BZaRh8=8+}Y=a*c z60tD_{*^Fo7mHWscT-D7hn@dmoUv-Y;Uz`(Th+Ngo=-ay^R@wyVZx|#Zb z|89BwwrN?DX$9KV+GRCVK?@kem|>^Uyf8t-TZJph7*iI0c4_?l20FM7%Ck&y#&U^C z5t>Ebx-kB9(DJwPU;kUe1Rj5obzeVa?Cy1ZhXDkOxb-@+x+?(0dk=7YO}=>31h6!)a=n`J$D z{OGquLcmT(y|In340O{}rvPw=8dm4Nrvk1kZ~UmwW`JKto}pmANb;!68&cIB^ng;a zep*3Dh`S>$SoJ_cX&O2Mnj;>#N_(}}X?_`=ZoRaN4l4byh%PF+`Iy#Ly*Hi*8)H=3 z^@xC;ky4=OU(5HcGm#uHH2n1%3zS%O`+an=WL481fMz}c-;0rOL-ygp!Ip(qH^YRK zo9~ZTz~;Eo1z^@^N`U5{)n)!HcJ+$Fq6OVH+019R**ziz( zH#@1NK~#FBvd4DUU`VAEeErqK$dub=jqc6^gc0b03}*mzK=Xi?M;5kQuzBg;ebN$8 z)Jp&&k=i=2p$(iLeH)SJ7&|V;cnkqL?Yg@z__{Km#i+jXnmXG|=O+W<#DVgaR=`5{d#JT%vE%kT zx1uz4Ba0DuB(~1E1KF57707R(#taiSL?tAJ(^_ zRs#dCds1(k7BS(djuE(UlxxEI02E9EaE+E@jf!Lkj(-1S5rN1jfdMnwD*70G5+q&Nf`< zYep$dBmu^x8{T1#%hrU8>t739qEyf!o%Rwz7lmS;qGUyl87Yav zW%W-WxHA9a*=3+vE+@d+pU;8``90gvypQe->7UhPSa0l>ej5aZyvrFW3>^a|+5;m4=%t4)*w7g2akRl%Ore9m}$zT+Q~UIx!0 zO#}rOYd5{-;%q)qo5hDrSmnGNf77t_uUm2g56N;~LFf;tyt&yO@LAMCK?4Cxjh#p( z=t_tJvbwS^a3&8>7%D`imlpTNIGY2DpkOdLqWv(bXhXIy7%FwezTeve&ehYqjC<9>E=R2PhpR`%raLbcee zeHWFXSn&s**&>}3zv&j?B`R@~0$#OV=ivdQrP83TbSU$3=>Oi+{?~8B?bAQWM8zVJ z!u*k451)co6yUU{Ob208Qd09x)>BqA?wtOiUwt-Z0sz{yI3t<1(~|Ec*?tJ#?2^ihjjc#NR_9jm>&3%8PTO&~kKaZf?B zTF8a1Zvuy|%~Ozann@JMinHZN_WZ2qfmdn9ZZ6|+FB9NrL7KcIViCp6HisV0IWWAu ziv#3>)wMFOz9T7k>}^2*=`spE`ZBJc8o(ey{73FO9X^PF2nq&F!KB&z=HWwyz5|tX zDia|3k;vsF$-@T(@P&c^-59z)Xni>DJK%d)bpdI^($ZIp{V;TK@L3}Q7&X++;vMOu zVhx5In6^bl<@h81SN{Arsbr!H7&UC5&t;CIVpT?70F;`zxa8=ENBD})0=M7*_f*u& zh98QA4r1l8Jdj~JI=UYp*5drbZ~y;K6Vh@90q|~Os=*z5`+$?jzlyc+pUIfI&jXw` z2ChAM`tAPvg8iQVOt`3O8ep-&VCgVlzLEz2b-pxM1>MNGgY@Az#yZ8Xl@w2-S;_#80ni5im@$HjiY9zA;J$Mm81pRkQ-0UFovt%bu^9oe8o;86qxOl!4H#+rn^qW|57`LZH@cG?wy?eOfr*&+C z<4jsSsrN}Sjr_j58FAa!UJ#1BNxrl@+c>?D*HJ5XF+s-}U<83QtFhEj54qKd)X%m^ zHX%6cb#{+=&V{Ym*Xl9X2V_BHDd_J8zjePS3^#Evp`SwNlON@*%fVvtJ929p?EX+c z&huC`b_pZ^<2hh!K7G`RDssem`HS0xP|XDZ-rDYzxIO`pt(!L1?jh zi|Xy**Q8V!H4{KkUqAl}bMDLu`hXV$d_1DXN%tPqjp?tPthTX*`lm)24rvvIxPf!; z;}Bwt9aZbO1j>e6ow9<&#M>0ti&uqUeeWG;hqU?i=iLNMB6Z^A#%ew(4{6`jpI}W} z)4YoMBVK0n`t2j5sO?)GyE;4B??%OfC_JUUJ*RXEV~t{KCoFojcCS^5&p9<&c@3#kCLv?a_7w6S?NGGN0lJzJRUkcgW8{ToQwY%u#+u> z_UAU9Di)?h=S;=$D6BSdR$C(Js4r25=@c<_T!ti|!e@9Tx+JOTKs^QXM*rj|o~`o36c zQ|2~=z^Cus!&81+!MmACnz{nJLSnN$UQ{>;SdGr5i`vK`ar4<=3~%wgz#3Xe0X%_ab4Dlc@hgNhQ%b{H`9#E%1(3aqo`{O0}Vr1-;eSU zAqLJwrk$H>%TF|Kxi(Fz@gl80f?_*fQdL4p)gruqqQ;{I{fl&B+2{948pmZ6>IAJ# z$D_X(Jx;sezmnIkrh;Zmc}uElkUIBfPwa|=KF~7Fs&=q0Bm{wCvL0=4p9j1eJIv4N z|6_p&1h7N_~%_(2RW44@pr_;TOzYEz_ltZv4m zqNl3Rd<_7d&CMdCZ|;cdOQqHz{2L|*m6LbcdJ^%_xn0VdGA|C5M(ZZeV%<#JB7+36 zIyM^!l+k_X>OuPThUQz93OqR9uPZ3F(%fA7kX)=IN#2J&f9b2K?mEuM7d|F^^L^); z?b`i1CB~g)dv4gcY>l{*pW2SuNi!AdFN^xT^4UDyS+6sqUANtFFHfi&jg{Wivu(XI zN&Wm;Aok`og=Xg`=)L#+`h7u#jklX0+oFZrfdeI$pDN$alCD*s{~zqVcT`hr_b$3E z*if;8f`APX5ZFo+5U@}b1e6kxP(-AcNG~C4Xqk2rY>Mg3>|@fdmqf zUP7n|5R%-*SI_5$-#!1_anCs8`$I>f$;!LlHQO_vIp;gxby`XTKu78g_{&}lV*ys6 z!#ayZeV_#Y!3x&ndRO5lzf)OyW0T2!?x_UPxGKvV6l<~Al~TgzN)^41|;f$lEj zqn-2SQ;I<6YnDN>?v^bt{C*A}N1%XdEf}$r+R6)I^JT%S4@T59)={3Juq&OC)p(Uo zEj5-Wq4KQcL1;0Pcb;vp1rikWl%tBP_Anr}w?8;Knn*kJ9njEXB$-=KpJr4}(wG%q zrFq7lO>t{VG`m2EM3Iw|xb6FIA3b8EUOi|^Oj%=w70;aT_d-~*lK0%?*yZsbuIF6T zcp*14|Hk;UhGUqVw((L$-sjsNnSG@4S?bd&EnKSEm&C)lwNWIvqHnIbB$RhL-2H?_ z?5ZW?;FYBwLq}w2cy`6^i=>(a>lN^Jnb{Wy=xJ%%&f!dS8pkz4}mZ94K zzbvonAyT0zycl1;|K_J>TGqw2i{j9;=r(jmdGnr|{sd{elKIGC(DwtTYW3xP`eN_H zNmkzGdHfuqX&^1~Bzu`^RV*%4-#YS6 z)r=5>_d+(`pOGvbeWIEU7CJ0#5UDOb*JcRxlt_}MdwGW@V)M3uRFgGIw-x}dE}A0U zx$@Rz1W(g@${N#fwJCkLr!wtxReH;lvdMYfi1gu!#ZGe-JzM-Q;lC~fcUFgS4Y{`Qw zmkkvb-nK-Sw(;-1qQb2j=4E7l&EnogSOW!#tP%_m5egt{cz?OwJNpT zS>@h1cbLk~smi%MGBZ9dJVxvI4q02IY;TOpl%Q1>z8>LLH)gCtfk|J(7KS2!vAH(u zHdp0T_3k`RN`Y$zT-}0sK8lrulE^J-n!1%fnjZn?{XEb@6bP2zEG4kji@2%#utz%?878fOppdo*Ri6&dRzIpV2IN~@+Gxv zl82?8Qz@5TT}|u#;fzKV4<{W>OIs!zi>UKiMJYPoje7_@FM3lKO2)JJK-8=z$pC{M zL|=7(8@Tk9lz^+}e4vxOU!b8@f0US2IYfHu;ch=f=T)xdcOJpHN3zm~jU6MSEcUOS zhkZYg1(U8R|JZp*P%qXnO z%4cfDgc}96JF47#o|?OB$EQD@e|Y*h(x2#V2k0+~wBJMj?w!5b(?;6Yr`rsCtA<#i zq@pO*s4j(_@87e+#KZ?vuq4|lG;_Am8MRV)#nFq-KU?6T7d0U5x4f6ezmu=nvlYCEey1tg`Nqt4g7Z1gBIa5)#&jJ?BjJEj)fT?F0#E+t29%a;c?d_Cl? zsA?Jm(cWXG21_flQu!C+W8O`OL}3%28{`FSS%%0{_|r|Wety|dSD)ETe|uD>-RRj# z>_S(+Qj`(FB1eOS!a=6R0toWr`aRzWK8szxFJ^R_NwJcZiRT>fU`l49Xv82E)?7PE zn0zM?`sr$(XsA5Q_Bb73;Uyn1{q^ZUUCc+waOFvCvFbvtQ?*m_N9Jn-JT@*@b|<_t z(ZDcRQ+B(Y?ZKf2r)L8_Sih#;Po4A|gORMBx5u5lO!FAdXDhkU)_)F-VvEO0gLDd@ zUmobOc1z4SCa;jkm><|MUnltw9^%{7aTO|kFxwgkxR)S2m6N*AI(!yhu%wX@j)VWO zmF{(J&_qQfSCUKD9x^=qweo;rt2l0?u|pbPc!QcGw8QyhHSsG(=y-tN0KOkqE;8l( zA!ntb9yAqo4;Rd`y-8%Lstp&1`VZi*BN7`XSR~j|a!=^N94(q*?+2rB2Z9luaB>iK zgC{-rm&8G>-O1B+?9Z;n^Oq?Q44Qq{MuvgB(wb$_jh*KLeH8u@&iV!h{>vRh)*`mE zqCv6bK@OM^nmOfF)0O%_!sF-9pVr4uRL6>vANFh1h;>_Nt#WBP6R5a4 z++(5K__&C`O`Y88uU@dX35OAs&a&xJ-jP}v_?CZ56h0mCbkU6{m+XL;)vEX%+3?Z> zLM#_LhkvA<&ELIKBY6xZ@WC$@+$IkM&2M68N_^SPiO>Ls5m;V zi_Sxdyy*fgD0uB+Xjs^jmMXb+1Zf|h@ZCR)-FiQ;z-(R`9z*}$r~!!#Rp;4&eb8yX&heYmU)!Cq)P`~ zN^SVfR)4z1%oUL&1$mGC7p4|lw%n5@#CCim_?q1tm5J(VUvOnD;jnkqTgqv{_N9Ep zomA5wC+H&E1s_0{)h&We6lb;Ywk&nDju;G32d9%+JP zV@S=7P8C9@^{yl{Y~OAd)58Cm%aXrI`5|&VIyfY&Fzg*XH&)I75$Hh44k9<#!n|f- z=cZSRuv)7F=DD)5=iPh8zKwnv%?Q|?-jJ3`Cdd!M9MWCFevRO+2Jve@41&nCqAEs} zIm-(uZk(#JVZd$I$}D%pg4QF88IWh6yY6EWr^ya|ap9Zz#n49?#-6Z2Y~aVp~n=jhl2dmd$juw?aCV`kC$*Ca{mdu*`o0M2-;^K^Fzy6{nl8MAFBneX~O^j2hl_p$} z5?=NWy5wZEDAOe4!9deEd8{GFyjqxxRw1`=q>SWGyqy4@XB&J_d~~KX#NY23TUVDC zwE$nRsS)I;^uf=}_m7=`Pt^K??{O)J-GxUw`#-){QWo=cxnNis#n)`7@sod&o_r*g zd7h*aA3uP(lvF)Woq7egRCTjWiz|hF!Lu&(5J?;_DL;u!H)u~ncya;Q*~XV6 zdcQJ-k5~u6dB=1gyjIRSCLH4}ZMXg5hd@Bl7 zn*JGxp?2~wb~xsh{Km*t4K4&>;7`4;4OJb*6?;!vJZzLO*quk@!dW1n`X)@-@NDf} zR0E8zT+^vx8~kqm@v+wNWbC!Rl+mZbvJ=kq_PLzC7pp&hCegxNa&4e*6xbgwEU6*1 zt5e3Hw~AL^1+{9Nt0OWob5L5^G4%OHftf0(J5`MLGaniECbw;8u+S@+I_B zY*iblM!!4gR!EphAF&ng-XA(85{sFqHsO0U`9Wj-@E4T?Ob7?X8d_=yqUCc3NRdBn z!2#(N_519eDXP?9;4DCx0*n!Z-05rn;oKTHOR1K9>w94sj6RDi9_zxv>}8s_#b$cY zUZsD|z|G=5hLM**Y0fi`XwBj%4|DoTak#sO+|+8rEz>$EWF!nmvvMuW!R&m(5pjSz zDvtST2hrlf^D1`ylD&%8!dbHW7)Y!Em!aFr^C)(w%s>#M^ves2-ooB3Z-9zIyx&i$F?RZ8Ak;=% z*nVhBRa3WilCTGc9&l-^^Sr1Ck?I8K)w6DP$1qdB1Nc;ZWab zIV!cnOClI~=rqVV6mboAzjN{~BTVOG+$ESuk5wzXXD@>nqVfekS?r?*7LfB*DnlxV z(UVvrXKDhehYb=E%#rfq%+_1??|phUN_3+T`nxQoonmEP!h5pxX+{Pa_*xybM)R>lsb|oaS0_f|LxZG$I z`{XgPpwHA90s@30K0kb}N{bNka|;@Q-VK2{`d;t=bG;vH0wE&!gzXH-in529Ehg9o zR^89VZ@%?iBm)FxD~1Q(*%M|;M%#J08@*AEB+L^nk3k$y9X3Y97J zXN;jFHy-@^x>TuIix=wPUt#hKwn5lAT+7v$nnYy~_suk}339>Ljj$+L>P|jDw z7)@%;mzBPDxkKk{zFYaQR>M`M!P-oQZbq6`!(?P#X}^L!ZR_t4b|B+3l%I&h$gg4M zDEJ%Yk7?`^L0JiIv90`!ZOu=DJr&0mjQUbmHNUT&_|-~&JMjG7EUvQ4{!3VhRT4sv zmJ|iA`7VFn4CFMB{EUp{-?PW;o;kAR^`bCGN=7D70%~H?v$Lg@J~aiwp@2UW?3Ey9 z-cEQz8Sa_?-8b^x28K4`PQi2)&_WpV%e_gMk$1d>B55Y@meK2kQO>E|YlHsqFE&Za6)e>LdHx5ONGg+)~HkwBl$X;#jxxJ--nILmyEduKz;&+ajX z#&oHb_aiRaEx1ju_>En7A(ISb3NSR`wF$)nUBP+F?4q3Ql`-z> z)+7a{C1Z#eXTaxn9~aSd@L%eZx$!W08zaQK_$8^nDp;WZPG30QEicHi01T&f67HHd z-VCCdNwxjTiJrW|_er@%fH2_}g3{vpMQGYBXW53V7-HsmYvC!MGGb5k4(|X^7XE!o zW=yq3F1-zI=oNoh#V~^GXsg_6+lg>FT11}5w;Hs2r;nWPVMV4!hjpW)KI<~HMODt$ z(2h7oX#U!i(jEdZiAZNQraY9yiFIfC%2#Xdy^@(OS3Tb11Z)0KJj;cMo=_3U`y7>+ zS$Xsuw43~gQl`qsi`%Wv7cnW9S^HkLAbB{U$jD{~B_7bXxw9_djB)``E%K2Mc6<=l z{#5Z7?(&b%=VY%2;cpomH>llYw1w@cNV`2Ys( zYQk>I@0i8KDi;6qOM9OE+97zg9$+Z-rn`5j6#e}9z}#$E`N8lynR}qOZ2QllA$VNL zV3ONvdwj%b`EBq_}Fe}R9txvA+PPqIF?N$-zqXMh_!d;cSrkNM)oi|wrB_L}yizXq~a27k=r z&<|aOeo?M}zl{(CZU}QArui?N;lF5H7g>Pq?upB?`St4m{)*N4t3kBum*svHv436T z>Id}pT@0|n+kj2E`vWc?fg9x?tl0bS)&24+qUX@b8i?#Y@}{FVu6~FF z$9L3i;P*0Qxr>Onwt)zvvq^el%zR|B=bWw7?u%Rzlyrfa{VjC4hlTHn@B-wcF|5Xp>L~x#$Mn)P>nv~-rfYxdA*)_WH1wW#Fj`lm%(`(VDZd!% zyb96uUe)KwV@zUWrhW)a%8rX`y1w5}Q8jm71c!UsXzX{g4Y#~o$nS*gA?l&;(puwz zPVw~QXhi+SllOr!gZubS1Cd`X{qq5hcYk8?1o#JGbtaO=_wvdzj}0i5VAYFr3#=No zYWg`VPc^!fd{}<0F+#WuQOUPwvg(v4u^Rl~N%RhN6b*Hr6d-!|;nd7jh*y#tD`lg4 zpLLs8_V%jwQP<1(}2-zD_m`3)E?I7RTSt$U>4Jb5U=15P+A+1dlssOXw^5|M1`7XvT5H<8D6)n zY%KGjv8>2dG@+EsV~?Qatc{<;nG`vlu@fm-6_)9JuL<-1ma%5{cBjrax%oH8kl=dd z-W>E$UAn&Y_p^a8>(}KjhfxLs1W<5RO0#So#nsT>F_qBTBYH@Y9>2Bqo=I-pOEYxAlF%DJP%Jf zkZ}f@o$F~;!v;DZ4*LximCw}hpkdKCTTu2#mB0gWah>78N*Jn60x z0JSQgn%49+!a9NE;gBTik^B~}`X|^ESe_`A zuv*iO)h@bP$up8l!j#?ALgu&k?R0j%&pN_;>BCJSV^J|`l zk!|mb^(g_*NpG;7)(5yFc8*nHF5sod|0PPD+aojrY85W z<{fXQD;oC7*G00ZHCFF4UrJA8Nkr=3dQD826E%M@5+Y_hlNJHE!9@yr52xtUZ6PtT zZupJ_@sbbt!m$S1_A6X_-2Pt8@7RY$iN94!m?tTJG>s;6TD^Z*Z{i3(sBQ%&^-%th z4Z=;e_6wuOuz#}39VnHTqyj9*-M?Uv+X*s-oiAch?XxzfN?taGOg+tSfrviY?QQyb zm8;w)p&qyI=~+oIU1tlQulxC@@XMtw11dSWgUq*Uce8mlZ-;F6_GXuckD86QNP;HT zw%j8-mS*l?KZppt-wKt{h)+F)VC$i1uSvGsd+iZJ*dp52asHjFwk~UMaGpXo$`8S7 zWF&u_8Y?6|rs*p!l(l*3K+Vy9E!&#Q8sFZUq3jf-hL;vt2gZ0XYI$!@*vhg2ahgon zc1dY1!ci@NtxBQ4<0~aSmk`jyWx!k?B5lrU!eosLs}< z*C48Ne^d8IjUGl``yqkC%}#|%I(+~*vF*O-T5OoK_sD&ZuPl}3ChJsx{s~VwMidl3 z0Lq~O?jm5us+3uU+#efj9{qXkg)#qPw=AE8%q4T=|}CAu8q7b9fUH%=s(<6O4 zTu}G6Rkm%iMCBoca_{Mq8h!tpEO=6}gX6UDliNz2l zKWmGvjpXlA`DVfJ{@$9zOA!lhjsZsLxK8Ze%b%R{XM)a<;0l*84(#lSZ&cSAJ{^Za z7&`MKOV*cg<41Gy(G|E_m2r|0RX#&1U8Zfbt$lpxIZ$x#Mx{tY8N2o}WPit;#M79! z$TfzoA*0)%nN^*aA{w85m$8-&mGK@DC0w}Boe(>36U0Cd+<^)P$SWLkk1Rqa;#Zsq{k0V;wZ)WML-x}n^yg%xgg~PGLxpe;!$*&Zz5_C*M zEjv4`D$M#`VR)N0axv3#Y4Yv3atyjoM&x1gidUEBHIf)zhT#x_Bc|ZJZi1I)KnoNB zz-Z2f({|GbbkPApSpjbNf+CviO6hHjD|p?+6KQni!hILC%t*ct5~1XruM@Zqkr`-v z_eEc^zo3-AjzGPQ7Pv7PWz=sxy!ye~4+?R*U;+C=u7&0C9)fI0SW zkC9q+b*v1#XER97g9Tkf5#NZTq0cl|^SaRx1R8rt&d`NW zc8H3x#fd)M0K@x1cEF|~mh7xeGM@lq`X@E7Nh;4rjCj7A z;rRy%_fW!Bf4~xTqF+}FS@6lWtPybd!pVpT+DyAMbE#X-Ise^8Ubn^|ADAB}53jp?Oqs z%)x)6)P1paexJn(`1nUw_<7=RyjoS9Hr1ZCt0+#l{4Of6*QvPN;*Urc=rA4@QXuof zLC@#N1kgXPzlpPoZzcf+vOrh?+mCtOe*5&+sH}ow;pONXb)xrsI zB*Z>6xy&+LHS;t3o?)1J4wJh*ASODmq>2px>^hx0Rarb9u49`8z4-YhyJ7o^#>PtV z)a2ypTDIhvkW0hb<2zMPVc>H8D@9jY{$#)9(>TY@j=(f&jW^VmMX2kRk$OZ!{h6x& z2FU;M3V^XdRER@As;wL#E6vvhUsx3V1?m3t?Q>-Sd+$p1mXTO!O4JeVJ)<*mYs&q* z-uR>Af*UXMU?`~Cm8`G2hfK%S?s0oCh=oZejgHB0ob6pnTRkQ2~0 zlzg(813d72d&F~o#;c}$^mwd^XP>g|K*TV5r#nvS+d%!m zOMM0YGaV^0#_Y_i3PML*n8#C(ikyjlS9V)(=@zj9tDxf2P@}n$r42Yo*EU(V6tIOz z;+1NvtfR!Lp$ev~7p9mW6>5(JjarOzJCGvz1nWDwl4E02eJ@f)rViot{)y{<+579# z2Y^|*OTHvGE-FjzCW9z@H@pzpE)@RO^?vM;ui&_WJ&oCd)I@W$YH!HE7nbZF&uZDu zf`V={LOLN2t(&*aR*``eOyth!a~mgePEKwIU@zW-DU6gV=+3;j6xC6F3Dy>O9d2fZ z@N_GX(=3P%n4IRXGEOToc>>Lugv-AwyMQuz|GikvCF;mJ2H@QZ#nf1zI_CPf zo_BmmlS*0&zKfM%B#wY4Y4RwdxVuck0U0{R=4G4eWdmmPZ|s3}Xc^BUv?s*wF$19G z{t54@(ed&Sx3CDn8EF%VM6&PHS;OhXtk=Vqq}V+1F;{A$#LQZK#jzzu+NT#gmq9)F znzEb5ZSw5^<`CJ-NMA0yYAk>Ljz2o#hEL1q)94rHa?#3~R~W!Qncj&W0~ z&rYIIugpRB==v%)!4F0Jn_e#nAdAP^(<;XV1t-~Xpv9h&36i~b#Gm)`;{6SUv{w7% zgIXxU*y|Ju9-->UyB&UKy0vavCo*KME>yG#78ep|;Dc`QHON==ye=tJPmx|K(RUpy zd?DPfp_9I5ogW)6-SH3HXt8H>IVurh=$2xnak7s176S!=^4eypVPUmrnr$wJ_0LSK z`uj)Pa`JE9Sk0^y+A25>HVomP-^sj5bn2T+n!lUYgc!cQ;1FPF>U|G>;i~4toFkl! z@V6pOPZ%TLCs!H8=5eDulY9(Lwg=mYAvt;e9H@+Nw4DS8^C(Gs1~^WIG8g>@Ki<=S z9(|YK^#Tx*kJ(`<3|p5)nv~AMTfvDO^P^!;K08;fKOvsey-GEw`pV)$sr>d*{#S|t zjJ^99$)h#GK6#wV;Nd5stV@HvHl{=+^=kyV3w{AMr9Z8MXm_BJ^yH6k06J3sYK`z3 zP~lU1+hP{wCB5J`Ada0{om-$#v07 z4>;&v{2JmmFT^XlP3^pC6!WJ4AeQe328AHn%DOIZYwm`ykE90Pd}|8?Em1T=*U}A2 zzB6$4FndhsD3Ezs0Ll|QN0tBtIQe#vzJ|aN(u(!n`4Nho;TY~L_o)W#REcPL-&8V9 zaO!7W37S^^ea8844$AC7=<6BbO8b4msMs6GLXPHp!~G28fXLX$c+}AmB_LvMeleZU zD~uj)G`1aFo$GypBd$g0*?3w8@#>mAF1D5U^8~rZ-1D@^iFB?B`M#Z76f1fq zXpj@Rt z0i*h#65;9k`bx$Jg198O5>?C+fmf zjD2!~5G6q8Z2S~L6vP|}uRI!Ze_*r#R5iBpm2cI-GYcGnFZs|3Q}|Kvq~!4)27RQl zh@Cj`+%}JU=}G{PVn-mV(}b!uNt%=V4BuCXH4fSx0FoBzJkaFUg$C=b410M=4{FRb zJin_4zN3W3^Bt8wnrIH3@mI{OQ7!3Is`h+8Z2Qde{YlClOtJg6I(GIlu#c}zVYJbr zAwtTY)RlT^z(}rx6Xglj>1v%guD^Ej?`vaEilPV)?v`Gn0NjNbBc47HJP+FA$Y|3KpasNBd}`~mb!foB}WS%Kyj$|zbu zW=10m1p4JjlW6fSl~!>oO|2$1z|tai02pm`RP0#7&Sxy(S$zWAwR%f9TzF2!IXnid zhPB6h0boN|!|P`=aoKb1Lev6e3x?yIFcyDsESMrDX!y)DCX}ISY2#-9eH%oPA& zITgsNlcLS=ZRf7l8q8>L$jmB1X`x~#%DCZSdDSXh5MVkE$ZHBpt`=jk) z9_MQyEm=&BXU109bhWb;t&UiS+To)!$-4!qDp?wc8;}wAXY{!IzE>|57Zhn2N#W}9 zfWDN5P@n<=cbHrq?M8oBU3N2`+8WQ=_v-DHsKEuoZjFt}mxw#N*X`C4a07iviiC@~ zeHP*_M5K)hWOmq<9BNp=Y>bp}r@FbSgt^rs^gWmllH~`mi^$e^NmTc!=g?B@lTvFb z5z1|%etkE3o~loN9qdHMX3 zXz;3+PVlQ*wyNEc$|;C?d8$Z!=a7u`eLO`Fm#7+`7~lz1 z23-`FuVJJdA5%7@))>~vrDDmR*6d-a)FUDpf*MgDSBtv-T4wP#X?YsEj;Y65EG1;% zL!ve%KmCA2^uDR&(XfY(#xp?2cPd2(v;bHZ z9~*Fh<-}3S{hnHO6^JCyLEJ7^)4)F*;ESW2ASr)es%7&|P}<=5;yUHeumVtDiu+gr z(QXPz59vcG4@quI6#J!RM1DTnrcs;ZL@%l=ycqmM{sOWm*cdgB8G(mXPPJNNIX1=N zuQ}z$odBMkgJ_B@yO4;wHb5;zef52tR%kWuR3ceC^>L@P4YyyIQ$kk3Ox!9i+}@VI zrq9EiPwJ#r8Y6u?`!5$DL;UXX44*$MMABVZkZ+CZw9$oR$B{xj$c{Eir|@UK)%@R( zsFM;S#1iwKzPw^NMdVbG;T?-%^D5d-FI&oqJNzA#?61V*zyf2Cv*o|x4Xp|e4NcBi z_yR>z93+pLUEW$*&aCVKg?ha1jB{f)H}uMBv>^o{)48bVhC=t4S4dk7L_|^1xz!aF zKudyp+Gs}DDl#zSyx@$y5ul%(-@b4k@F1v{5yBO&yb{~!}@YeLwTxz+WGMj!^;h zdHQDj8!!HluYf4AhninDHE{*`T7fA!xj`TuWAo=Ztd zx09GGZmlzWlR3~$*Ye5NBU*OTWRy3IR%U`7f_Yj_dl#P1#qN~!mKwPzwyV_ zZ|jcKNdL({fA_Bo+Aaw=(iCxv|G|;|-?k+H@FcXhntFH?T)NaLQolNvV`mNmWzVR4 ziu;%eZ=7CPPd}eLww|Ze;&{9f3t8L^3AJI5~fs0_%xZMyOC z+@|ynkYBwnci`Y4ELbNJn4ATCgET%IuPb#%!$!4Il?+J-=5O5trt;4_zu2*HrgZ%Z zXVKx%SGSR2Bs(g(g@^wFOUC$w%~EWW7b`15O1Tbr4Y zQQFT3LuI@$=y;TPct>28-PGr8%%0;pG3J!=KC7}}84U$!q2_!19gYCmB13m?$6K&p z*O^$YJPW&UW7W!FpwmStRcTI}-h;7to*n1(OIG>cZ%^w0BndS6wTM?G*mn#&GU|xZ zSaqwPJ%eVYRZlLd&`3lc7gbJv;4A9)!}jH?SEOa{#+5pDN5(T(?&Gg=-!ONyG&Bq| zjMemZidUf2{M}H;jqx9v<&-e`GdDL6S)dCn&dWfmk1_(*#h)aVG9@V(G z;+2(^?e^_?{D4y9-s72o?0o<_ABP^VIHxD)r1V=GhAjuA1~skd8yb4c3o)tg7NW{O zu6}K7jC7H9-JIYtSx>?Xr2HwMW&7b3&mS9eT=}Nd_ghKaVUGddMm*YpA?E*#MGIqP z7^MZhF-m<@Grz#EmN%AJ%s{)+kKh+uOV8rg7I!ao8vbm`Xs5l$Mk0*oW!Q0Mt3>hQP#Fo2t|J!9tI= zmq!swKrh}Npd!JR+lm<&YZ{)$FvRlDqaH0yVg{U=&qcCwj4pqH4-_xZH7{PgsBfh2 zBmdil8c5eU16nBi3F1q5$I4-);oKX+r#Ds21G%Txb<^A*-4Ly1j9+6`i&zJM-tHIa zC3x-vgKP_L2^e-6EKvOr14xfngl{(KFg5+do5uY;FyKFGET}$X6z|cAA-}~p+knOCv=jZ3v%`-BsMik^u-Opfj zD8BEw-1E+#y*mhcA}Bmom%ril#sc-`4Digbd`p7laLy72koF6*){Bu%O--kr-yXY# z-3k;+PgWbqM{9B|{Ta9nO76Sg(syp6MYT33r|Y2d6}))_#BVOk;xIXieYmfd3w|En zY-r&=CZ>My2d4ecP3oracddhaTv?f!g)J;Y6I^t2+s+fYbCNN40|G{~Gj1DO8J?7s zG>$b)%O=@|>s2$#Uln3kFG)y96tCil^{$(oW~cn@YHt(^4u?xiOLsnhGh_}3qGYzF z_9Ohov=qZ}F~J|{zcbAw&Yg7`HI0>0QZfg$D*2AU#GXyUllCj?NsNX0dBwGg`2KHW zxMj12?U&V0Z{H!R)EPbWK1bZb$>|)xz_v&~*~myd*ctC^pj{AEKi zJutWRt_T&+nbBLF9U`E4xM~EA3$1)1Co4>fr=&F}LTH(H@*y_Tg2^pB@35pW87pd&C{5`K;0`>z1hNKUN1q_%ARq-f$*uZ&3z){uQ z(7~0QDS{R+2e8^eUE47Yw|5P(3)tVEKO0K43-_<|3oYX?(`$-FO&twO?`#&kh|l5uygt zT-66SH1`2Q4&fcLF}tNZV&`-g5XPxkr@i^W4rUDmPOVO%NJtDdzu2L%#|1Lkou@`G z>+)-s#f+!;wzfu!2)#>fpN%8JK44kl6u-0A-9Zj|a=ZSCpQ@M2WGVQwv(Z0aiE z3v}FE00Id}%{}VVnPI-=o~%23tfxR9$@Z?l^pX5sWOlu{+8xDmu&NxzdRjtz>WlUD zZ<{p6(213%QGedHzO3TYp(9i|1KziGN3@_u0Dg88n&fl#NuXV%X%P0~89KT4sh*oS zP>$m7bX;gd&F+vofF8tRf<1mTu|Iu!APSrQK67i=h2(`Vdg&ASQ(Od=IgOY?F_FTo zn3R+&qR?7x7Kt>bImlb7{c1P)sku;Skkhbo{~#4|!g=QLf7pY6nH&+llWukF=(=Vb z<+s3Oy@t5aO^$6Yx(K9VRi0g9x%dOR1Ckuwv5EK`1Q46bX=RL?2JpF_(k#b~9eD3D zU;{;HDeC2q0n;S&q4Vs9o3Lxm6Zl-Xh=$7k^|6uvFDi|P?x+aA2`uzR?aecrtnbA- z%^Y6a+huP1Hy@HYJ>6pXG||grZv?Q5sq1d!?Ah@bdGQHIOxOLB zt@Fgejc@v7yY{+&diC<; zPP^|vYXSPw9UL5XGtLB(k8gai*WFVGn1k5XxX4ApACzZkrk##XBwJl?nBVdaB)N<1 zgl39=fejN>&ukbrofO`F`g9FzYbYBpL@u4w6c)2vvFHW6Kz5G!d~%>3m)LNB-^c;Q zK(I{XBSV|^Z9NwQq<8$iyY9=4cLGSyp92Kb{?c8)!yDUn0B(l>l9=IKczlz|uK*qK z4j3dG^fOCg+R5lMz^?=|sWHjl`hF*U? z`gr;RP_B2kk8Dz#0o>t#H{_Q%@V^`K|ILOx;Ii|)e8RgItD(3AjLc~ucmV!gTx3c8zI=C_CoU$t$j#M(~)C01;?Yr{0 z458=ZmYvK~nsT;MQr|_e0{sX6^NIfJex5hYhLPh-;mOHkPT|e6Rj#uiwuoHWy?&w? zHDv4tk6?U4;ri~~-XY7y$6G_(su&fiI4(2loL%Ws57?#Me&-ZhJgftO!kdoyyShq| zA1t(%4U~gjU$s^%=g~i3+-du}SIZ;E%p8)-(2%i^%a<_&6&KbY9Htq=b|Bdg|29Q& zH8Xr1#gh$8jJZ5|Gc|a%;;rK0ZY7m|ACxV0$cEIwqf z8Zy!}#`EU1#?TCE^~9>X9QCu;XsP@J?w0AAR{B!?HvQZB?HzT-UT+r$qr@_UQMiF& z_x+O?OkvepD3&wRST(vz5y5)R9_09wr7~1@{cyKCc6szO4M+!nB|`}VZYg0a=9uxi zSRs!`3|~UhhmU&VJuc~!YW8%p^?Ig*huR^arVV5rbfQh8!~&Cie0>K905-30(b?Eh z95}TebBa+ZzP%70*01#_&tvvYfqadY{qUVswZR}B8pu5f|33ayjk4!l4UZFxSDYDM z;Lv-PIsxZ#oojA?Y@-Vwlz24YPnuX6OD8E1u4Kq!`b+LPu$M@7N}jK1g+T%AVpz<;Y}Lk$L?!tS_NRYc!e1a(H%PhUe>l`*i?0%pJxaFy^Ks z?5e%N=8v zPo1KsnvxERhyVxQsJpe2PaG9WtT2s>k6TYcS5#C8vZ^bE$iBWSL`)TAoBwosVP&GP z=3iW;_VcSoMln0~9y`hZ(=MFjzckU6bL$MaCaAc&ZEJY7oVt4TEs}SfF_0euhI>>8 zcq#{Z71l77u>j*UGiFom*SXlpaGUL0=l=Ygj!!i&T6_0ZPKLMRM66A#J=(Sf(sD%u zdmF;3$&m2e^@)=_R+o|HwMKE3Oez#8DHSDS5OcNmGrsX0ky1@otxVMdRnJBpO+dJh zV6hd;Gwk%GW>on3bGqvsSRa4H=R3ZA^KjtI6Ze6jW-OPRdMPX+V5T^O%?_Y=WGyb5 z5p9FD#%H-RRYzqk)G4Xe5R@#Yx1jB!)w@+rtkx8U#%*sRx)ag9dY~hes5vlwcq>p{A7!z1RWDLY)fTjdtqTF zPtrepp4F6>w@b7MF1^r=WK?i^5M=u8 zxajR~UdcS})X!2hkXY;oW_gLoSRlO-l`1_4j{&p2c+0-;tNiK14NF}F{KW7JAy=lU zK$XzR0LzoywG@k`-X|E(0=XV&Iynq&?4ch-!w}l`wH2%Oj(v;y-sMy&WR4jaW>3Du z+7(020|n0IhUIOl3uiI!OR-m~*to_4r#3yY4m>dxu&$}^ME;fj`iC_<0NQG}Z+7?0 z4Fx1%UxlfO2?>+WPYtaZf4RnCc9Ip-6pYIILCHZ{~bM#qYI_R zh9)K^aq6BEoe=*vJ`3g5-2kfxsb09&`kt-(gw(&1jv!WBuyiR%SncD;|A)Kx3~I9L z+JU=5kgBs z3jspNdvZPZJ@d_@zQ4X-?>K{_j{DqY?Y-At$FYuOGgYI-Eij=zB#v6_K-mWOmw7R( z9KeicrW)- z@^#IoroD-(;{pE$kdXjFYpALD))=VpWZi#3M8rj%yVJY%eQj(ioxQsnh;3(@SVJ{H zs$5&E%6L=Ok_7~3nWE&IE%OeDN0OGl+rw5DsG3^Z{fEN^^U;*G`zVt^QvfRQoL^_@&-6JaS4cj|aCMa~Y1`nw~S7eEeW3da3*jb7EP4CTf1AD+74Ns-R zQ~@<6asb0XFlbbD%Y`V6?ZxqDRs^{Jp#5xtJi8cZ4dYk=&{hVD=&N<$#;c=ciG$Z(D)!uk~6E6Gc0C*&9gbq=Kam>nc4|+<7qxiIKG`?jD^Y4a zSG>=kJ?rfE*zft<9WP$Kj(z*-%wyX}w%hjY+ovi1<&4;5$M-LHs?~4aIV?Jz7)1$G zNS$3C5uGHDVFwaV)f`QimUHfYgl5hB zBtI;1qchkHLILYy#HS093gj%7D*+xU>@toZJJD z>PBl^ddVrOb=hdg%nOS$9xqALhk#C=s@lq@%v|$~j|}Z?5Q+uV*LQoNoVcL<#g{nW z6|=0|2jj2I%l!i|OBt~FD^p{K&2h`h6xFPhz!$_u%`wweoKuGoD}|p7y=a3IoU3lk z$vVvt@*RA)QDA|_KI7!1@vb^zs1qjFu#f%5OthA#j&@)?kRKnEQGz-myLum_FAu!Z zc6WQhrqeSnMV^{sscn8dUR!c#xMo3_9$>mMU#EGbFWb7FC(o_{pBYegsiIJYy&)b* zB}My8PK(UWj|!_?wj%x9dF0b3PgZ}!%aU3vH+WK*>TH`Ivk_3_ zB4Yz{g4V7Uy2iA%OIx7ciSKn7zv8}ejO1sc%U@2cP?L3eaqirCACg?cOod(I?5~(8 zBOP}=y$_{kOkc)u(nV_db!~C@#$AKVj;v9bg8v50(k?6BxCgK#>GZ~{>)&2f(hq&9x{OO{OzAaN%$c*%vz?WhXHxhQr zc;uR}{y~C!G&SU|>yI5Clft1X6H$VNJ`Qg{^#> z0*0)$8|KL`Nd2_HRTOtV#d-Z#k2Ea9UWzb(nu(dXhh%g&q9gh1%r6u3I@BptI}Md- z3)9{mHRWYYCv9Qst-%9uh-XOEz$+CGcxJtUY(Ea&eWrhN%?XML_P_YzYW%^{(aol6 z4oMYo9$hFIMbfX)^+9gNWju6#tFGz+UUpD#PblnWdYjAUDjY;&S^FbAGJ}hRQoQZ3 z;0>IYCq)7~zlkF7X1kMy14lPQ?H;FP$9+91WB)!W4bI?1W3Q-;D{b?onOJ(oSo_oW zQfhaBFtV>$5&ZD1&jzVLcB#_Fw1;~p+u*iPCl;jI6>&6knp9b&Bmmjp5GnL^vh7p` zHXA5qirL0WRfbL_#wTDHzCdkblpv(-Dh@q7O_s|lsOHYZnyou9&HaMG6e;daj_`?( zg=CD%g~8GZVf2quG(9wKPiZ)xbxRX%*+AEOjN{QL-}5~fjkUt9vuQ+>H}Brk#g^-D zD+|mXeHz2B`MFZev3`s`t}1t!gm7-`pG}f3RO|?P}`6ndE;Di?kIa1HjXUK_RAwWU<66p$| zXB4+REyebS0S%Zb3zh5s-*nwOIWWT+%ExQ+%7Ha?Ckc#(8%v)+nxG?OVl{54dxgcv zjaMoSb0zwzp7?HF7HsLe0O!4e8=6S{(5A$C;Rr#zi=47Tgsz(I{XC3}dPdUL*6#Y~AU@*iFYa`8wTWu!EC4EW6MXKd&HHL* z^A$_kZ*Ea#u9)N49%w<4u%>Iy2C+E07|7_+#Fd$+=rarxibPLsv`WDmM8~ia-ZJC= zYUN%SPpv$Nll_VrH2#Fw&YeEe5ZBgZs!T%6Z?*-1mTMwnNW|^dY;f&8ep{k#A&{fh zo^%wJ5$x%O#Y|kJTVn{!<1RhxVib>pSe>QJ$Ua)8Z*VwEmh5kFK3p)Ua}@dVJk!L6tEoVqg7gd;ZTEk^dMdCSjv*xBYnL4F1`C~%n4t{C@Qv5dl zz8D36oJU#sMbshWz#KQm%RE`i;xdsgz)nH$c_ME|2?o?14*y=-Op~BKyp2+bvc?Cl z|BBHyEU~Ts2ww;v-N(zGCu^21S0cfeX1K8RxXD(lQ8uokmYq!J$3-hKB(~kEP?*F~lX6tOnnC*x>}|S=>u~G$7!LN2=;FJEgU@$mSr)stHMH(@W6kZRqI^XvEA#k50%o8TICeaSEZC}}(9REW zWnuAX=3H`-{#i3XhRK2_!8$0l{W`7AJIl4ZBE)qC!_y~jyqW*Gj0zq?i^IVDs{-W4 z`UbWmleoA070WnvVj(TvD(5&Th((XkE3#0U$`!vV{n2H@Gyh>U|1vZM`5s4NN-hbK zp=tA>JJ&P4kQlmgsOmUzm#;N^B;O{*9oMc9GqTd6>#xQxU|r)NWu_Y%nkOy$bG_1D zu}*@?)Mco9gaT3E3{-J~XOt;n}sXpaH-wVaOA{tU1$db*Rwes`! zWB&9412baX>BJt+w+7AR_bGjS1-d93pSR$c(~-grX?O>dLmOZiZvBvyVL8x^rOlGF z9cwOt_&SF%+Ybm;u-NM#N{)4i7q#~;4^Y<#=p&MVFtQJa7NH@GYvif6ZUNLx7${fL zBz+Hr&)b+^ZFyn4((F5~;~O^5g*D9|_Ljx{4f!`Y=N))Yc!D8SOKEv$xz!sv?mgm# z)8`n~Z#c?%rHYDxo=ArkOC>juIh*T~*V6kXnB-b(%1{k>I+{}Ynb;37MSa%#Qb30C zjd@mT3mG5G$m77seCZ=2p1h2sSJxbtrQ3PHUKswln>|cHcOPDJzxht&9;>Hkp^*#~D^Q}y5HioFu%KB4CWg0-ixsuf%7aIO42Xu-w2h>WV zW*x)!O&FHlld~!CguBn=*RWStL(e)i_*%`1`%v8!oCE*^$wec0UNWQdlN=PUe-#1QI)k|ffXyf zruN*303Xm%#Y!{hoRJzR_WQeFRJQvtU-lTD*+stonbj^rmrN{oh*})~8OB;+dx4|d zl{PEVnSf8;LLM$*N;D^ki(}C`YP36d6Qm~i?gfv2IP9+dqTIoEab3B3R|AnhQU4`oc^4s5ehq};j3SY^GgjDWr<@t83(7MS9( zUVTK_y4Y=dVO&_QWsYs(7-zO@a(1?!g1IU#9~wA%yVhq^{aqfl3PyG3-|dH;-i=;$ zZa_IN8LP;6m*;Qd}Y41;dyZ=R1}`X`ZD(wWL{AZ z#>a2%Jv3z?L8Q&Q3cLbUE#}e+4HG!*cBoJv1D@}fRl+XoGfJ3xC10>XlOq0!UuF;J z&%!^2vrba36tnA+3X-gbPUp>%3Jrv9U_lIW>HJ7@#_88@3~X<`XpVj3Tjo^|AcyWD zhod?Rk^HI9k+}XQU4Mui+l{YyK*ID!sk@}j>p57e@Aj^8*+s8)L^Y7hd#tJ6g#3wq zdWDyf7Q(8B`LXo##HFQ{xvp~|p_1J$kSl|sZ_3@Mg(R_~R>N(mj=_8ibY;$<{_Vt) zC49s&6+!xW&BV7p&uX)a%jdGZ6tldNY|^b_e;;ZMRX%g>oF(A&hs``Lo42$5X;^4! z78WiXbSBoKrAZPEqp@GCu6b?z9KKW~g+i!|mhL%oa(0M8tg_LJ6A(W2TkH{lEXM%I zQg{+Dbj*VMPS{+w2#FMD$1Uo5EvDqMLRwG6TbO~wAso8AQ{*{TgZ8NzGC?J%5mj$%<3BAY z$@X=?vobkh6`lGxzv)PnG@kqM;dXaqGDn^lcB==K3olGLUW4YWXC z8maGd|DG$9C%Tc^1Acj3csr^)C3KrKE;=%@$BMHX4Ae3HT-c}MKhxBhXTs8P8OaXz z*f_}Fr05opU;FeRr#qwEcA}$n&#~LPSv@iu3ZfsqJRkjWP7bZ=ZcR$%_I)Og8>6g- zOMQ~goj-3>=4ccrp5!&XKd%YzMRkvpw$VXGWv4ncC2TBrI=+LDOSOSFtZ`dnpCM9n z;1Qyn-E&3>IEY?`aQh%6#uBMi>qtHyHw@H_~(@hwfH%2uA$9_!w z=`tzYSDZ?@2;M<6pW^+4Wo_G0eF;FaUC-Zx{}svB!~r<<8(~|izoAU(X9fX`In=Fg zO8SqV0FHL`H$Zlg^up~{p1;E3yOMy<6i1%m{5fwQK)5b10C391;MbMvf1YK4e)IS! zfZU@Fr&s;yI{EkSE?NUI`Z``2{=X(m9dZReQ!Q`1{5Ksi^)Gcm!DFCE?BtHWPTC7? z0Kpl&_ippAWt!*5jp})dHA* zPlvAmwV3m^9e06jG8=Ey>EA04|Mw{y60|oqdtOyeuJ5crd{XOW%76diH^}sb&KZEL z#~fnIPD!1)9jsA!#F9cVc&Cfta(&}*6O+(c zoL8yYR%O1gY*@f|Tw=3xoLj%~vqAV>}VtlG6&t>C`=M?gHJ z7APLCy6qkXF|WFiS=d_9!7#lWr(YM_v_?we{KdvXZc71P)sH4wL}$@F0mj}ohk)1aKTqc68^8fmQ`XA*0Ay%rQ&~|jS-}P+ zXa9Vt?Rvh|>i(?;{~vCZXD{RE(U@zn&G1~kjE{x5FLzN?%hI1t9HeuZj@sCXzC74V z3XHv)mobd@D}u0_kBiUzrJphV4 zu$ae#>6Kh7k6SN3D!4xSncdahFG*ke(UpEY@Xq9@;&e|(?6ozyxWpSnZu|oimqbeg#@)DpA-cc-z@`3VI;tmj-=8~CdOYw~rpHtb~JdktfZK&EWDhIG!zrl*D}s;UWT=RI)0A5vpL^#@Aup7ITyI;H!Y42#fOXG zqEE}-8xu)>zow+Ge~g$Ot`Fy0Wl-QYXS=#SqaK(OEcb>A8!Rg?k^E!^EYH)1#)(q- zFz8)UFf{(&ULZ^Bhp~y%n$-*eruj)pjtH}p!rma=ez9@z*3BCB9z?Jnz;{TWd?%PG z7AIy;4BL3c;<{3D>b}_*5R1E1E?j;$AKb-Kn-2Lf-karRfyB>z-6);FP$u1!uX*%W zLv07>_;ot953@SgGg2iU8)-}_r14_sRYgS~93_7$A}U)kmcT3!h>M9v?0=*YW;V_|-Id#7-2%6<(GAgKu;E(Mp zv^#huww2q4Qg|ptMZG5Rvg~i4u=IZOJrFT1}rp2ZxANM2q5av}K z=dNF@Qtin)%6H_PQT8XOzpy|aC&4OSr*8%6WhTz5;)-6ls=w#e0fWUCJV10;?@su^ zJ+hTY@RK;r!xjaqY9S$7UPC19Fp2q zC;WXX*00LtL!aG4^ZRmF8h7^wVh$v(udqwiv9^_^N(-MZVHR;^*G6+n-oA-6 zD3~$wv8N@{)1rCCe02mOa=g?!`Lzgs5OY(}6sdxuR>R>-KyjQEczxrh+>KIS z^>7wx&wf2DfOiTog6EoV2~zSutTX4nVKjQ51tX-_+Bw#P6&4S^L=9MuB~7c&^nF%Z zn96LQUaD^)F=9DU_$v;m_(IDJ5|mZhZHV@BP8T~aUI7j0%`2KMKN{6P$J)$#S$79X zSPnv7U%QUK;)4<}fu8>rFJE9dODSo0ccpClrzsnIPwTr|7Ga9Rl&qk4qgbDXX> zUx2_$5u$&iaG>!<4j#&Dk5OA^PTdbk!)-R!{1)Xq-2fZ~+pnyKE8%q4$M#%Yrp*@K z_~zvlM<43pp_Z6fj)52k@(}&z$xxqp1LGpSZY^oe3GrX2$l@38J`mr`3rW2mSgz0A z=*hBNACI>37gn%+sm~|z48hi<|0;#td?i*j#?fXS=#L^nQToXA>ITk8(1>d)WRtfuUTDek^ClMt@!+;c`{vS;Ba4_OM|ko^H8(V`Vyl}YP9@0#&lQo=y4C^%&`d89H4d*U3)%y-h286I79_u(R9I^mhi@>|Z~cvn*Tmh@GlRHj@bGPgHw31w&^H6lvR1?3o5AUAlxX6A8-2G7~25DG%Yt4HE2m+%% z#En)`<5w`h=41io(ekkmO5=5QFt#u$o6sC583P_lo?BTu7)xq}iYLi#Y^oBL;-m#q zCNTR}8p6UB{d{J>Xil_LE^5lt$pqsVcn9HxoSUhxmdWN^LqA)kY>0#Ef2kr-xiKPZ zgw*G`d+$|?(5InO2Yney7XhZNbjqKLKzV<#mM^1^enr>9! z$-_KxU80Bcgctnu51vBRmZzY3e9X80BpF&A;BxDQtu+2xOCn3u0xd>=C9nZv$X>5M zc;ZWMeFO|Kd4f#cGQKlvV;pHP_t{uMSec)<^QWqPAyB&~ zHMlEm+S(sdMku0tAc%|%kv$dfyNB)4ZGgKee5K0DDP`GaD$&B9;x{krZp@&i5Gzi$ z_2a_-5iBGa;vu;90ga>-H6J>AD88+!rDVgWLlnp88Z-C7OnUlV#_m?;X7$)~Zg624 z1CzL{uILe34WNT?!AJP|9Xla>2j1vCDqxJWvG=^yb($4ihb=52?iFut1UMwY7@nwkK8DbQq^!Ptmq75u@9bpRB&n!<#cg>-fggg zxEi`taq9{c$(kn%nFh28seZ$=a2=AJgn}L)Oxi>S{X8S2>&1hP%6SqP%c27zeyC5& za}hcE!lqO*dOn!gZWXxjX8Y%$IaUYxyFaU^Xt|M+G*S!1^#DxBk=G>3ZTLGr{G{cBo*HvoLt zqmA^nh;N&M^2}&xj0$@t&xgS-JHV*o1|Wq3eR05ja7cDOr{wdx?_!CzgTwQ=vDSBJ zHE-TWQTax-c$LQkpA7sVu;M-c7*O$y=F2`$eR41;=V<|5MolS*L34W^p+rhM%W?O* z_+$r=r^_=eZ%lUe0+FPr0bHfJwLCz03T`88X_6kCa(-lI0smHrRr?eM0GgYKtO$tLGRn!c4}=siNqOWFpmBSj@Vja-eV^I!k)iAh{*-xZhcLU zD|b&hg7INPs)tL)W7iw1ORp4~wL#UICo2|}6NHnW(1_BJ9#La3DK?*dHUK+W_y=-m zJB{$37x7AqW8PUSHBRjL@th8}CdD352jRoSohWf+qGVAK7Ri&WR(1v8whz%BKXr4k zJ9nNdK4yn7Yhw#o2qurY0`(|++JjaIEnADr@~a*$ALEQf^I<&2mPBsQKvreS2*A05 zl55P1@XRr)A{|mzM7#OjfhuHqWoTyBqRl@k0OIgUiq@?_vN&w)`*a=0Yw6EuJBGOS z^Q_76B`lu+e~|*2eW#3nLl+V$P*_yOK1=+}a*lrDGZ-EPHIkIR(a4l>YmvgifxX3S z74MOA8o6RJtI}Bu1)9O4eBf^05F^}Dv+O!_iI220f4}Vn^JNr3+%i!Wb@PYt=FCMN zDLQaUQAaMKaw^lybYtlJ%Q6?qiR@4{U;SfZ!PEYgxbk_|NW~25T5H_Wh`83y?*x^Pe?@ zW1d!~`Uihq_r+JE)pPuULF0v(2_cp)1XU0@_WZCN=~k)r&}s2Ko}>a6mUiie;{8a0 zex}t6H{rx5GS+!XWO~$|k$0PDk#`SGcqzW+o}#FErv_CA9|_RMMr~-1WGOg;=I9!r z7+*zS+si<^5_6*b)V?MaR%s4cdKT8)sx4pXIG}`@*8A+3?sS|C*>r+Nv8z@lq2`<8 zMKhGV^sicR{VxZom5ZW$WMWMYix+;=2W(^lWSo<}W}OGHk9eB0r9T3QFQo1a&vh?2 zg{gECM{g^LbIP$Sc>zi`*<4IY6g0BY18~_cbLgX`$%tBJ$BGq(Hg-5s*7sA=$yAgX zynqf(N$hjj&Z+IteuP)j$kwIGPotJKXhiDQJrLpe)r*R14xx3SnGcPA&6(}nySJ%y5>IAAezh7~uzvn!|-L9k+-mCYbVKzmYW{ zGwtK{#K1zmhwp3aU~1wOZ3cWZl0E3?0~yAU`aIF`zSZWSM_B;lW=8<1TcBU%RuyLr z9c)vjcl6c4=4-@}TYW}=djYUZzGlZYCzw$CO)AC%nZq=O@zse{$4I2xfV)Yc{m3{A zt3Cvl&m-=z2lI8C<6+{;-KgmN~y zo9<%b-hgFw2RmJK&5zaAVFwT?3ijn#KXV&j0^^V~<!?4X3Y_`f?_y;J#tCJ~UX_4;CF2Xx4VBPnRYChG(-wJ9&(L)Z+Epa7+6@ zvr$zgK)dNf_)g+gf{MdW$zSRxm~DnyucKX~ILcWiBn&J|DA*kbW&a%3>gXep+*=n^ z+r)4k^vzF;{X6hVRFXG@w#rs+@crL*cIKJ?7S8kCUl@pn$Saz$V`5+?u5oGSZ{0Gy zB=PVGw|xgC=2P}dxKnRdhA2N@rv8&B!z+ya>*bWV10VzY`>%a7Kj$D;*e=eFs|?MD zhWakKx%ci=g!A;fUMf}l_W(OW=9a;-hAC_BK~ln1StjvWB)>EF&Wk);3XArM&Mq{F z2GbpR)ke@*DW%!i(1G~mpDvKR&o2Mv0(`Y_J^^yYJD&AKqatrplEz^jzb!FNK3se zU^Ps!>UK-$*>n^>d6TFz94jp6;a<%QW0T+5-K-W!!&QBjrYVoK5kj>>p=04(Me z$uCL1HhBR;hxsz!Ip|A_P%51eV)5b$;G8c(H+TKevHn8Je*zPH9cfT`wd-@BBc$Zc z%W%;f8>552`di((A%hZlFQNjLQ6^wPB-10Vc4hS7d14aS*Yeo4jvV3FZ;Zk`r-cW9 zp}BLvD-vJ)pAgE*qcFfB$f@rS!@XqnP~q7o)^Lm4Y)WRCj*?WPs)f1$KYvkfocLr# z3dq%uVc_XmnroEv$?g7}pgrK40x=V#iMJD_BmFz-@a%&Xr$!Zd5O3Z*7{=ITiPQ8e zZ-q(J+QOraTtiJ>i|A--Heba_*BLy^hVyvl?&Ll4+Yto-t6SPcl>*1t_<)d_jszSy zQihZ%vZh!Tt)rA4)WwRGJ+`I9p*NGMCO^hWE1P`yoBchy%5y|{B%4!4e&p?4e(v14 zs|9H%B}@cAzJLGh8MF6{E6}vsQ-CXp`ZAf%Qq@Zb%4Jla6yb+8UavjNUmO-9Zgkn^ zt5*MM&t3_g3cCRzqst}@jE~ntI-S=4pp~@i8;Dr?u@?epJ0{0A2pg8=uIRR-wK{Q^1{u70Kj z2BjfXEV{b70GRO6)2CBsuY<=B=PsN*dlos*3w;_j6~-zlDG}>I6_{EwJ1e~S{*3;p zpLxV1fm6HU6s4IUwFQNR+K<72WElxuG-2W1UED^gVXmQvPx#VbaqweV0M2*>x?A@7OxZh+652|DHv>iF!iCEYOqaW=^UrHA-g;93RGFP>mmwNTf73GkbsNAK zMM3;x0W*dd_Y3BBW@;Zld2-s3bd*f3E&GBs^@pf!;kyqX8qOrjy-ifH$f3ZcFJ3sd zJU{n)g4lmn;?VvbA3p3;oW4+x24}s$q-|NiE-t>pKXR1J-?J_AzfWNljEL`Q`1`f?(z4j;qHC;@?{0wAHEx_4J?ghJ}Vf=ItzmHu2iRS|N4PSkm+NH zT3T8fU6&!kQrYPj0l?t+PE|!kGe91wRE^fizVU2&`p;rMK&$FEd2nA;B_tlM92F9x zZ|+~&rUnRyl~==TZNK(2KB$r(-2?l+6qU*Na=U%=uf3=~bLg;`T+YXQty!T*_kr+%cW=FU>e%vXeF?l1sH7q$qN-{gV;pA?BX(9Puf6&%`2S+W3E#g~-7a_3 z$aPl?M11}F)pBpjW2^7-z#}oq2Qmf&gn5NFGT#a*s(n7m3LjvcGx-}=W_6eA?#*$V zm(KSi1jVc{{YF!8bL)<6pY3d5ctD3wVlOZtnSOMeWw0uxO(}!8XCa4F|fKWKK$NV;OX{n)V4q8FYCT8zDXjcaS!G+u zPk>k@tqP@l<^V-aHYMJjWUZYRPYU7Ih2aX{>#F+xS(z!s7O1`_y?gmx)-n*~3i&!= z^Zf4fB}ilHpDpRx6tJ^-@d25#N67q~Gr$#%mvQ<_hibMubfYCm7)ZILcn34?`!f`d z3;g+(QQrpeC-;2cYViNzR!!f}tDcq7gS36l%I(XY`KTqe%uWuec;cyFdaL%>$mTupL{!iM^apw{l@|O+0)6J(>}pX}VSk5OLHAvLn=hJi zViU7B5St7yK)%AEl2J)bDG(s~^}YUZySLnVJV>zW!d&@J_Hi*IOnIUl*!+l8IQUO1 ze>v@6->5j`1UWoRQyR5T&;P087awJVRQ2J#%4i4x6ugfy6OgHNj zOJC=-LwaKkVQUiuO4GlN0xVudv{kf_!fd9L%0cXW@J#GUOd3q!?%lhJ;nY-^wH&y= zGg1)pBSA*_c$B)W{>M!1&pGaBZ_(tPp2vRQ%wJyq`{;YV+twd`*KYci-ND^U5!}~( z2~~|1RVLyBg((Y%*PTtABi%&fqWfk3a78=T5ue6C@^*XB5}b%OBnD2HIS zPLbqVdrh|XmjmFG+NNnr;IQa$iCwrdcc!mu zI&N>wwZ+d*2pqD_eA*I?oSw&S1?9rI9NxYH3k|$Gt#CX_xdGfr$92CK2HUm1FBqCZZFUn~y~XxqreQEQ*9Xe=RdBUAFK$;L8~4#^*r??P(oq z{ouu4&g;wsIXXq&TETC2E{eV81VTE@ssYiDIaP%Y3&?EFXIaPTh>oh>cu5PNR*%N1 z%p|4tW(hN!A{U>^$u?-CS+YliGiG{HCy>^cLr;}SlBX5+>=ijpZBHP5;w&^G0_VEY z=)q|889oK0w&Cqr+|a5&`1=w2 z{Vd>+s@08}rAQsBWs68_8Wk+2nOBPHr6;^2MxPl3x9N*|`Y&euK=W$F?~Vswg{it+G%`BZE3{ zE?!SpRn<~DN_c$7&+@igV_3!vV+RC!sO!sE6*;ZL63;Rq(ny*tUykIJ{uFgAWV@mAQ|0$~k=N_==#3bC7~ z(D$B)H9MiMTMbwe^@(UkCmF!}T1zy*wG;s#Cj?Z^qdP*(0QGL`irMiKAieUN1686m zgap4iwk1`*uQJTJObOl32$XzINON;?@?5Cre_GE{dpb9`pu~OQ<8K4$g}NBg;v#)O0PXB z-pz05Pwph>pr1|^Hv+Q$Z6p~4%<*+sK6gy*pIe~ zFzR6P|SK_JmF+7IWF>~iVo^}ei)kXj(I1nk;bYh?z?3ImhZvYg(s0Hh+yAO zr{t8HIi#BPqAKfOj;Elq-)KwQIl|s$6(Id3@~jQO?MX;-H%vkeRBF3rvc7ER1=ER; zsiG?RsX_v0dGIK2o=cw?ovqiQS|rpdwQFKj_SgyD;a4+vcCZu^NET5%o#6`!eUltgEU zCyiUZE;!JM^y0PhURcA>*TJxXBTRvMrs zS_I9$q{M#uB|dFGPOco63>-~k!(`dCwAM`y8|lYTjf6eH>8NoG(etJJWZfjyCZ2_p zN%#Y$>jQFufxj-dC8@Q*++fJhoR#-=!+9~8E=@l(=mj9K1=`(+kqVm-l+BVUlRG(y zm!p`-i=f$!g+7fdg45(@Kio%lj#l|#{u_Y%|D0vVOo7aa?=N}O)X%(PMJFeGU5~3R zcLA5CS|7`mb-6ebZ*cC|VZN_S>__Gxe;Q#vcx?EDU&8nR?Th zZSf{~g@&mZMS6^f^2$g&B;!K&C zzrBe;I(3kNwuw&T0NbDy%CK&l>R!iyM?w#S>caO!A2x0%w~%!<*~2~<200{A3HFr_ zR#q36bCUIQ>LGW?^ov#1O_(2VAnilA(7=Mo=~RA9tMHLlQscHx)xOxwK z_I>E);RKC1n(BR{@Y&g29zZ(bWSauh zv#bOm%y!Mh+7s1?-cFQYcNDtM0DXmQKKyuON2i8xa1AV&yhgQGdIgK`Yh{1XOK8$Y~4`(u&CRp>O{``X* z-`T<|VJto+3&{Y8F`C8s#GmSsVP1$u;q#h;>*Ep}iRg-o>upKwsJt7l~Q zK2%x&V=5+Et*0y<;fZAO!^;e7!_`uxaKbX4uZwmQ!dOZ2?w$?_`2oE45;%0Jo?@g~ z1K_*^+ZpNH(?FMe^Gx3t(|gBHs4B7Uz{pbdjU8>K;s_e|vq! zVIL#L;M+HD^T;eQvb&CPF!)fuEW_=rfjED6nF(5g-xWF3dH$8!_=~!1eZAaAgyg(6 zT3nLH&B;`JVI~IYgb+x3r6D&@a+9A-JIO~wo?187sxo2FF}V{HJQ&%fqvWg$Srtkv z$k|>`SsJ)EJ53E>@r4zyu*v~F0aZm&#YT>sJf<(7(Ze#{%JOKtj}FtrC$hXKfy6!t z`lIwp@l)UpX1-c)0+bv2aemfiBckZ(1g{!qTa{T^=5V<)kh=5HQt@2gtUK?Ge0L11 zvkuURzUpAw9QZeZtBYOhUO|$e1P}|`?3LA z+B=gaa^4$=54Gd^k~e30T$g^}Rau8(OBlnP}#)E`b%?gP zLt&XkI*C6W{fH8t7W=Q=xM7(#_9WLV9dk;-{a4Zx6}xo-_by#fUV(%bK2QU5a%Psh zs@3uCRI2+Wlwd~`n3xK$R?IcbDP5rt6{O;M+jHBsmcm$e_i}?dfdnhr-Sx8r7Ab7D zWg8RpLoF~FqGwqL_W_8)adEwo~cu)x)1YnQ8}4$eHYG09zk&Lv|!cm`$pp z%+`&grao#(dvb$k+X50*z=dqA%0Jo01-ZcQmVomb3ZT?rl=aQ%RE4}JwOpZ6f9l#) zt?o7Vxm_$>i+NUd`YDY5HTfm-@C%k|r$A9v4xpV?!O&HlxI-ghDJD7%Gn0Uo`%?r? zq1s-5(8Z{$0_7>7?D1a)I^Mk7OI-lgL+x`LlOm5s)IzD*Dw%iy^{i0xF_`yEzIRNV zV6I*|20CT$;6>o9V7+<8!0fEbRPHRC2F|xEsT9m?Uz7Y2 zK|jjQ5xGj+{z;{{M5au^(h~!BwXk?Pz$dz5?mO7tPEAHrwbfy5!< zZ99*>9>bSh5NQxU>li%~%d7YKzVi~` zfF#whBidqcMh*m)JcBwpU|sgiuSQ(DVt72f)Xc{9UH}k!xQahJs;lNXOu4oC`o}+h zpL_@WmI2KIkAkRxoNWDlAa2oy{;*eKj^uZjvYCSNh=JAtM~D-0HMi}T?rYs2rQT6- zfh8x|@*veL$EqxuJ+>s7e9P8J?Ic(ll17!>pVadZVi6>N!LVHpJqeJhc2MhLbXq-^ z%FDV~3}Vq$hn7{oKBn)Ln3r`gy;~jC;p8cZ~N7 z`^$D^t-0o!^O?`Df#``OnHJC5n=F)rPcy%mEr8{zuLHAMr4Ll{UB%N8h4FOfqCf&> zb|i4MF46Z#)Kl?eUheU6a6KRj;S)dlD}$+3Btf_tZX|0?GfSbpRG6Tw^{;PuuZ zgM<{W?~~Z*jl9G~x&YJ0mpq+FLP*;3)&7OL{9AV9Gu?s8wU!1X5$eRI$E9-2Q z9PN)@F;i-4YQPK`l?K`(uVGj~K&1dmI77fd>2XMI`!1i>->u=3iqDi0uk4z_?hm@J zD1fGN`GUel09s!N^q&BlR%x2Tg$uV3WUa2=bK_mv_ktl#QS9rt{1n^m|Jhpp+vdFG zfb=M%qUnOak7nj(e3{Xz$jeJWzuSZrtZb3A{pypyK!ksYh=}_1DRUK?8ZHyr7Rzm^ zrXjSxc>TaX&jNoB_st>ZJ1^8UvoFrJV-MfY3;g#0_Ild?0kC%#&i?~o|IY!i`N=(U zKjl_D+7Qc?

V)}atJbVAVn3QqIsP|0ML4@PO`!Mcv##-;+ zzpuI?%OnqXo8w&pJ|*>U!oz!(k8*Zi&JGm2WQMxNbzN}JZ%=|bfTuzeUrW&?{lEqX z2fOoo272u$d_D;by}%Ly*g7+3@FsjYTrF>Dj~L@aE4#17Pj9*%?LEH5kb}4OW~T3g zVne@gXD@bX9j%r4+_J|d_8kbi*a{`MYrb}vsD|diw0$k^=KEcL+f<2JP!JGM!JRP# zJemKUet!K&dT>~nK&3c(aaE=gS-veU8b(Me>x>+kanMP?+`pUIeAz%*=A-VXno&wcIW{>4`s1@w~y#C7?w*OC%?CZlYiBABfKPa2AyU)V2fE|Kc9D2d~@dRwx z*v98#H7!|Y;`ko-?hEcc$To(;2iytbnkn2zDfIM5w|BqgBl~uS=8xaN1$lS={Qu>u zF9KgsL8_JiY^cxu6902%0eu_Fq`m|3mb6mt&54GzY!g(WNjy|#e^?|9eedT_z{1vj zU}s0>EZT$iG`5rVscouUUP9kMmcvDv3slTthH&ueM5j`VWJR#CP6 zCgFZPCZZvP=`ar$Pbsgg)|-$Ik5+$_@-lN{&kxf-xK?$&7F5Y{4CnN6j{6uyl%YJu zqc=5k;F|_)=I&@=1N5i7<*k((asS6(P9;29D)9IG@g;z}hA>?e&Q^b5Gq?ZxBr;7x z8=soq#F^toNR||8W#S4zO{+m z#`nooIg%m-W4|iy=tX9--GFgB?Pi#xQw(OL^6YF+TL@nzQg`-p)X5Vqop`CEw5vnN zbL8cFs_{u`mhY>arTJ?!Te`d%nI?w@&SZ=Xw5n2{NKf4WiLY5NDW7YybUT`$ueBV*3 zFNjMjFCw-5kkFpWtUa;h)mwd>Ql~&I{QdVcQL!Jg^Qs=CMrd6(w{D2`qR$X3BFwp# zvty+lQ@iI)#&hz%mUToU#r07AQm|1;|FMv4-6E{4r~N2({CK5p{+v&hN|VE;+qigt zg>9ZcbvnHPVm2pN3yxtk?WNIS3Z+?zTpRh6<$>DNfS_ak%c~o)3Vt667#Cdsrt_+- zGpSTxT$>$b0XLuLxuc1gjq;?^y?;_UwyQ7VZmjy@^Z5Rd)=*PxU+J*{GbHS5tJ&r* z1D(3#YxI;e`C1K)A6jbno#>1$^}pTqR(SNPzmrLFg3wX_qUQ2r?^pVoPhj)i&19Ze z4c6v)zO0}5k>8&EyRJ#J5o&TRreMQ}Iyp1;$KZWjL0ItRjI(JD_30Lj7GlEFz6T5h z*LI^zZB+w@Nos30uGsa?2eZsm@72@DPqrP%3q7X21=t)&YR0?P3sFtw7_sdecJ_x zUu9X(iVV^pI*;^DXB*$!}%0khDXP|zYz4|($zn20GE&r4>pITb$0CJ*JrY{O3479h8%It z)=e+YF0{TQZgukp>H#BqrYkR}S*Emu-8Nx{(CpBPSYSM&16{MpY7d98am2)AJet#W zW=bT~stAK|9z>Vq^au&r=ZSdyt}olqodPEO48q8jwD|j(-%Ez(l{YsVD8-h8Dl)T# z=AJ4K&Ye}s+?TX9*Wo$CuDLo)Lt^)>m#Ng*eKErs(zg zWwWM_Isk|2zH(GrYN}oBn9S;8vi4vLn`uCp|H@2uX67~`u4c9|fzHz^3acoeZ*rfD zWHYEzDi5GybbOj~H~gsyERmqo=^=hiJuO+id`Zf1cALJzJA)S`bQbxrkygV3$OZ}C zDw4)Oc^z5b5ljwkJNL~Hg{LGxXE2Y9QolLQypUO;V-zc_ke$T^{)63S9Rf}5Y)ClD z9VnRH=Abl9lZ{D|3$Ms+t7g|KMi}!C=Qx2TjvUIDII3S}gnT6i?zH7obZ7;uDjo_| zDcP1$@L~C5M6LHSWb@UGOl}5RUT*9U%vS9;n-+rajg>K+Uzmq(HLZmektGEN_=3VM zQosfdxQcgWH$^!RlAentYZSCLOxZs1;`4vq?fgqGE)akjqsSwiTYP$VvJ` z{?J`c#y8z|2=*ChWSv6%FiwVsQ?h#@&~>9>b^Yh|$LZov!q{vl&3U!KoVe1hcjwAp z1-Jfa2gi@{*50(!2DB?_A6+ci}y6Kv|%%*d0rDhlKreMTo= z%X9_>;ihPW*89m+!75;KFG4VpeWbc&GLdIoNt>C7GR}%v8gH;>@5#y{(xF%c-(N85`=sVd4$v%qRff%-I5;tb5UBtw0t+Bj+ox(ck=c-7u=P7s1 zY{uo6i{WQ}ml2SbW}Ps}l!LWj29#M@WY!t;o=pV9YrFJ&u;_0J^hW*2487(h0M#3GI~IP#sNCJ!n&o`6EY*|EiPBr8Ur+!YI2bx0>H}1p9Oh8#?DQ7) zyicF(WXxFsu~z{4&N9tCy%FBk6i+pQTU}Y`{)#P~@7fT{b)u3|SdMqR6D0p^6U_<7 zuh;PVeQfeWd{y;#ZaiB;2}m$8^-pAM!O~RZ6}4(C0yOG)NUb>eg`cX(*|Jei?BPq| z$9YpETdp^uSQcAiR{^i#@MEgwBw41cA8-Ue_K-x399t57xjp9EOg2Yd#qz0DR%Zac>3`oFhc(chAmFNX%bG;&BDeI#tRK^*jd0__eg z+z6t2I3P20g6uj=6<6;qt-)R_=U`kp59#%BG5>LxwD>ws6RwX$Uq{yf#WZ!TJSfX> zt=7f{;_GywumlAu73P;}l1cFgL?CRrI)Z9U=GbJNVU#>FsIvCBd>=lEqMDYuhP3&I z#G@HdRNkQqHX@;MAtMpm8&zJA-w|j{8|=i?mOsS(h5Ebzrx0;fL2jZ`GWo!h}PBK#fm>0vGis7N*OsV_a@jf*!1CI4jhXg^kaAT@MSIQ684bo=?w%V~ zgHvx?R;lh1sBq-0Az)GDKl+|e2m5}JMHmw`LYk4p#4dNWV$Co3$kDEsk-wqtsq3V? zF3jdRje4MLOi_N@kayBFze?a#J&h=FOrcGU)O&eq1)1yz zrua?|nd6sDZgw+MkUWd|98wC+W;M3RfbjzlX?<{4QF*@G7GfKTm}!^lanv4#k-=0qnNHROSwBeq+hO2OnD;74?tnd1_o9DG|-}dEPb6LssN}fm6L`>hiu!RA!dDNq3X#V7;o%WY;K`0s0m7c zq|CW& zguV&tm+^ENMN8xvMiyRYwL<{y>~+@W5@ok&`qC@tsUl0diYD@!x}#y9!JxlaG4NnD z$iDwIio94&>!WD>Ts$>~l9`we;kT#|>&}7@qT2lYzwx2x-UE#I;m}JhV`|i3$8BEj z_g3%CIA>3q_0Npy$DQ>>j-LdjphaH^oHkDN4_JS$pa8w}fkfBI6#t!*??3jfcN*G3 zKt&>c@qwEY98~vdZjchs7HMbodz~%NQhV1Jy=?RBx3yhPiIg<&f%T{ll9Ed&D1u#f z=wrjWCUL*#eI>vR9Bfp=tbl{Z*gRr3VI47OD-(&z5sTtHq~VKv)riCj$NR|+gE=KbJ8|Boh6OsTYZO9s1SuMFom2(P z?+ViDw4akadZTB;TRZ}m!2Widxl8o5Lhmq)4D2Zu80%-k+={-?2DuC2u~)*m%gUdo``dQLG@tMqR!9a+LmTgCk;?4Qhu%}k69>1BqJ~dZIL~d zUuc(oeDQc%eKieP1&N)E-S0QZ@_ljpFxM`gmkT?rxgqmwp!&f)L_svV)gHZgG1Y&i zq_arrV4Ag!-AsC}>|D2hr^8(R@D032P}SXmkFLHXNo*Jz6;MnN)Q<_))Hb+p_sKAA zuC0auXAWj^M8RpVlf)~27c#PdZYcP?VIwMTuD~4p>+hk-)ciX0Ru&R{&IUmUOelTe zOyN9?H6iCU{V{ICLwFQJ9bmkJI7$2XDz3Cm4l*z+v*;X%wJ1+K&e%9nTalqOY2g`0 zF3ZRhk1uJz0eJXNqzDK3D>3YyqvnaJ*7(alUelZjPjaCP?>>G^w7nNI0KjISTQov0 zWf&~pUs*`gGs%b*hG6VgzlOz*t|Vxz^hj>gf$asl_EoPD&ZTOoYXEAldAdp4&GDpD zUu9Ql8t#HFXz>`;5$k{UJ}UGXAhd`cce>@3fGsgCPZ$_p=f%^fHy@1-MP>Y)wY+z0 z7>DD2($6k9yBXFq@dp&D|7GR}w5V+v2+$*2on=_uLu$RJ`VG6X4ceL$jQQPWWN!4Y zHrSN5e4?3zjY8}>AakXk3$M$pPN#>6%aKs453QXl^9MJ*0n2-4Qwvq%FwTKteTIX5 zfK9;G7Kq)PzVO}#4#`EopcjuF)*AiLS2cC3p^*5p&$Ms#7Y5}PhPn8&kM%16#yp<( zRc);odwepURQct~z5NRa3D18DRRizuII$ffKiLWPDCuM8K?fvjy+NlU)@tpC(s^OL zI76C~LFn7=59`}k-KiGY=S8GxZt?hI|r;oP+?m^(eaZG(F7-d zM=OCaozRqQ5x91xixVP;HYkP4)5)5;1S=ndSWL$c07Ia1=E0G8??z@|*8`SW&yd9a zgTFaSr}PItc9f1F&3tsFyH?~BxmvnLljlREDiM}|H*bVThkvz6B|Iu{?l&8yCCDrj zt7*V&NRva(EJSguk?MzulbynHn#_;J82MVXGS*HFl}JRa4p(ar7HC~ZWj(S2{y`1u zzz_oZ>5=O#-^tPzQ72b;a~3-FEzCu7)V9T!fP4S2Y33UQ=bQ81WtO@3+MPQpGl3z^ zZY)+#+i8ko9iQHh4vu_d-GbaDOT{&9(`6LPd7aG;VjSB!PP~e_3`~<8KBwU$a^d~3z zNr7@or&kH?C|v_@rPI4ojjc#xyke%gMi#MSv_7TIh1XAv)D^**BF*0%W*?Z7K#`J5 zk5YdV9PEiNH2!kNJR$vD!}gN1)oN=6b!N`yh4?lsXs7AIyymP6$@8=J5Wq{AjMwu9 zkOFHPs{3Ea9~CwePyub2AfEofHH-}VoWfgS12t&@Q89TEQ(K1EXQgIHQ4`M7@0aoHHXlwQbuwp5mz37bF4fDwHzF}(wdb0i=PxX9S($#K zUBS~VspJPyqDG~yAvbA`ExXu0JO;i0!(Y~U!xk9tOucQ=nGI2AweJEc_H}Exppb^I zqR-j^P2^Q|s-pB=+pCKFEw>qnCYq|JCtWr;gfKb-pER%?Q1TPOKSDwl%JDXm&rv7K zf(FMMCb=v7tJ6WUk>PlDlxYlW?9y?H+w~{U0%yMPuD9(9@7{!iM(+M6u93Z9eR9Hy zfy^Aj@e#Pp33sX1j7FX~*WSdQz>@u*<*JX3mSX)7ca*rsLIf%me|+XT`Ad8GVACyB-_j$znhxUppm(5~K5Rvy0;s@H3kPp>+# z_EA+$Ew=un$iZC%LQlV30Hu=R3m}0AUZ`3>{FSsoBqe^U6TH;q5Em^3YjyCZL0wAs zkRpBnDt=%MqyeP-&!6Pi&_*bGY76=Pc34L4{Kzx#C-nNk-BCHN9q;4kw#H)skYS7Y zZvrxiYT7eGw1caS%Dxrpb*zr?#ru3Y@&6Tj;@kgXPvCj*=IS3xnQpp1&tn!%&dJt~ z!G7&=^WT-PvG0It?ynXj4w!0sbsX4orIH^WszO@XNRnHG4Pu6f+TzlCjMkUaI}PUo zKnU+E+7s6NMl!J3+y9%by@BeyR48$cr11H&o=egV8}U3dSN z^}sLQ1u#mt`I~oPZ*LEH7o}rS{-y5vJ1}c^LlSBCYk}hV@cDchNi*u)gY-7tI$(!; z<3{`fW8aOCN=F;;K~W+iBBX?^pK~ZjMT-`y?f$G_`d(Z5?c+t~j^MEeCtl~K{Cod^ z7Jz61{{X$Dw zKi=si{9$g0sus?7wg%@8R~Bu(y2(W zWZt^&wC5bS`S~JP;iJde#{2i={RHZPg7DI-P_11KhJU|;$j8rs^Mb974Ypv3A@=iN z-QK1KTlkxI@4lverOEX=tNk5cAjrp8L!~_A<=WiSl_DRppLuRx+s-bNMxYgK|KA=0 z^73XoA0vJ~oJ#wWmSMZclmH*$zvUMwf?b$QdC0QxToz1>fsFKY2ZIr5+!<;dTzw!l z@@?_K|1!Yfz_TB%Po&;tWl4|6PJQ~6{T~txK72^VpDCSrBg&h3d$q$$YvYjcIS%&U zFlWtnht_vKYn^8}cA-sK?@${$HH9bJEhtRXO!IFN#$o@hnt!tr0A>j-u4c)#){ZkH z!J#K#@lEc1$;Jc7Ig_MusPr`2LG+&~27q(!+3?bs!_O3IGr&9XU!)kEjDFe#w&NZr zoMFcE*BM-20=%)K@jou%S+(! z(bB(O6~s_kiGl(G*>x{_j#8MP*Ol(^=58K6o4){ePtXc}^X5XO;;$G3MdxJ<7_pKy zn^Yb&`cRjjdXUOg{L+c8`OKogY?9|5v__!wXL$5PRwTJxMX@HPE@9ArMYl7z5 z=O1~}Hs8C;5qxJ6{TEeLuu}2(1Xv>XC+P3KCf8lts1p#KX;FigB|HM%9dZ=Doz-2th$F931O;GzlxARsALP7>ij4!5rnZQ3G*op`K)Wi6AWR zV=c;PI{%WCn7*X;JinZg!%}Ttu-CG4d3i^wqHq2;_fj#Gw!&Y0d`#!{N_D2bAR-oe{Mlv zTUr&ays~cQyK%+TAjiOPG$PFC?%lg5Q@Rk_DFz5s7kRJ%5GF23*?R}p8?A3s5}mnt zk)J_(q-P=&;_3Mu3uN@@wYhtjo(yO?xd*)AVir60&l2I99+++iAC4WoP>Glws|r3E zGN5W@UClaJ{^(;^Xcn3cFd5<{9(PaF^oX_Fg2%myQ};B8idef|n~tlnE-H6aHfq$T zO%BdpeY`67UH13Gz}f&7kP6=-vxOqp0)-8-b#mz|lS9 z3VnK!Kkm`!NY`9sEqU^cwyb%bw1e-rASzhvV&Vvcj?=ndDNZKyt26mX@eROH(z%Z{yGJ zX#)07I=YXs9PN0SnlMuo5NmUFJ}vmPM1Pe}cp?q{Z43D zhT)c441nf*+TVLDg{)IhG3u!w{VeE8=>j80(4u<MPw7yauv-N*>MJQ(}u*U6h&T6mflx2a#3%SUv4r^Uv>EPkH6R zOJ#XrVOOq5b}datuc&koh1pJ{(kd8j2N5k%N=lJ2iI#}+k1_AFWYdK0w}fQMk$GDa z*Qq{tA7m<3SD$3HO{^1g@Wl_!vs~RMk@0Lfh?&my(57fxB|^kaXViF zfc)vB98#Uelkw>dXs4u4?QH-&#;C||$F2!vlzAA-O_Xg`Ef<%q+%WTM`W_^G`4aHc z&WT_ZTYmu3Hn9uIMSwUV5+$VHpHRbG;r!7zK~~C39gp6jEYRW+Tc7M@3+(v-1{uD& z8A9=z9D;ZenQU3hwrdeG_KoWL#UtVPfdY_=t`-8kc55trdxQEhRKJ@nif$NS@-Wei znaPvlkn_(L_a&8EMbr9-A1@hI#k)*(ssY+br!%cqlirxtqF@ z7l;a68w1zU($XATVX)Qpca!(C+?7}H%M)BQeu0ZwKGcd%>RKWQUY_vZ2s(=P)NL_O zSmM?O$JmNZ#au&Yv7Sl{t3%C8O$W~rH|+dcVzzO`OF43n1!G9bo%42uIH43@E7KvL z=O(w&8FAHZPD7MF?L%GoQCpyz7nc1XD^QN%Xq7%a))8yR7+{I-hywGS-8M1z&8Q9b z%B@MvHFfR^^9&AE>re=M^fBoiNFMMMiW0Ffj5dW=p((A|U!b+<)d>Z&t5!2yRJyNM zyGQ>SwmgiDXlr2_qHMI6-bY>Ip}~F_PKlqE+eJh09oQjRXygZ7ce)uwomJ==m{&Kr zaKl70Zq++_@khPS%7R-DR+cJ`+SCbowC#ykluj;Gk)EGn3~o+FcjavMIT+7g1z@fX z7EUO-6(IvpF?a)kad{;RJIvja!6Ne*_Kz(;owOqWAmX4ui4wScPtwA@C>gglgu884 z=G3I*NvL&5gm5ydZ_7@U9U_xhy{lxl`KYcUNh3^@$#|cahXzS4bU2}#8(T6tNG2Hy zq~7<8{J71CW~TA_&A3R(Z`|qQ+{cIH&gm@nBuV7v2KO}Mhc27>cLfDW3ty^Kq&G%% zRe3ln-?=ljk!00bxH?Ye@_j7AMPiE@E4G9jmUf>X+9wMM@h*6r>3Xg+>q&H z^=AF=_2(i#y?ZdkV0BlmyOXmV+GF1^;mko>I&1vJS+d`GaVX5$fBL%-(*0{yi6T(> zY0EDK(gtjdNj^Pi&>t&TVWarC)s+-+hn4kV@`bxC%^1fYRz6v}qgKV1bOGh4V0TNp zZ3w=-Vp*}hqeWqgN5eQP9?*-j;5GhYWu$zU6y`yFef<*eCjSKD)))*e<>QM4=Ycp` zmd+CiXoK0=ybm}DHxFd9ETvkK$}U(jp%NPI1!K(jjQg)Vv-L8o$N_=EqW4k$U9eKB zU?rXrneB511-*t{J^wEgeCTrfoAVi zM|f3dL7fa}k?Z*n_Z7%4&*=~LGZP6MpyO{kUs2rM>@2ssew%NgCW7HZ1OjqLhq(s* z1lt~-`D0ue^#&s45}3n(Bw$MoeD8c>9%05#&Y8@cnqe_rKQp9t$A!;H*?r+7@BcK2 zkt?O#Hyz+f=pEa}O9n9t^LOb!J$b#;@s;p3&tOhnVC1cfnnYLX+kVW;b02O)YiLy< zRc28gF8Z&PRys+PnVhoR?^-#kkzJ|j#zj*V+tRuPZ=jy8bP+G_lF@-u^SH`I$0p*^ zbDG4bY8u`sw+;3@QKvyVnj*>E4?NDii(xL-nt-ceZgF{I=c{|Rd17wbhL7Yn`<#rm z_+vSBraLEXp5UFW9e#`K6Mh2M({zY2AFa4D^&B|$yM4=49h`G=H1rvaSZBH9{uvcD==bY>n5ItZWsk z6+U&-&G6e-oxa_cE!91Ux#>Z6TQ0>wVLKFs;beYt(o6Z{3)M7R^MG&i$MbEdcT&!9 zWK*372V0Pc%}`=YkxmPKtLzwuV4St0%gWjB-@dKaPs~vgixwDIPP7}#p-SnkH_-!x zvx6=Uc`xf8ufEx(qw!nBPNVRx;dziibp3J}Vm?oM#e0Af>*Ih>e(}n9rS76F zZv!497g_)_z<+JOj8%VZP=uktcbi^C`rJVmx3*}Nw^aIEU)UdO!6FwrP?IMdI>-*B z%a27wA2roe;=NV$+4}o6#^>gBUQ&xDLa9+}1q&+`u5eHZ5mD0-#7=@Mj)E3}I(Dq7 zNh!)X${)-#J~Hsx(yV0G7e(=5n&;)_9_M*nxk|o6YFwk>&9b8tIitZFk?eY73k~gMu&b@&jTV#=4a3aTo(7=)))O$@gwR~ zVY|4IDULFd4;YOVq|o3nq4D~f-pgLDqQ8lRb^xxx4K~XX+VqNKEOwtPwCM1)(OL~J zS4CgRiFpr14Xy6giM1waOe>CFB17XTY>bhzun5>R>!uc(iyEoaK_5o+l+i2T5$T%n z4%~a43>VS){&P9O=Ne{{1P=j+fWBqHbsm>qsgklOCqL%t{%cxs*B~jiCk83kevuDa zjD5GiEzmmGQ%7L|M~@!$hpy4ca!xF|E|po&wVal=k%zw^Hm7&ddFg!qMQS?#>@0D+ z(kc|*UtkD{c(mHlT%vY4Dy#L!5lzKu8-rlsl+}B3o|D1G=*!Jkb;aF6<1@nie45T5 z!F09!MpiFOhN6`~!d%psvg4LBL@C65A`^8%H!gIy^Yol5ZH zZl3SZsq&OIK{^b#ozeJkxUkV_*6DCKDc)JBajs$H;Vp?HMHMe**48Y%?m zpM6VR%xgG6pBsj)VQ$UIxwr98f)ci{{yO*{sWMuuMAf=)Wrt0>*L=V$R`mRK3S)SO zTq+|3YzM?5Q5F)GwRe%0x_HT59ITIU34>DpHow^yzXL**ym;?76HXg#U3Bk|9}L%$ zKIwC@nLahSOuCYh)2vx1SdMxrBJ%BHR9qPM!+ASQ1V5tEzO9@!x|;Fm&RY?rRmgxs ziRF8O^aB8g_pWRV=S@vOD%M%$niO6DzxJ+FOkZD3qVLZjilOv()}`X0`-e#zF9^=< zvnjwxkKK=j>2f@t@?OqUW!Xk7lT>1b$-5IK(?MXJFE(B`wE5<^W?b>nI4yXNy0-DG zIQa#zo_4{1cC#9*%(JL$?RPfhyAsDCSAes*qaYt&FD-Fv2u>j7$)VlKw19aUnlB!qa22Lo2sBK;5KUO$TC2r!B13X_=E+$aef5| zR1j&`E@#Z~ZmAw~z*&yW)6tskM*D=!nq;NYc$-bm_bZVPotP~TdbmxfG|1DA%Sots zv^usx3n*Hr1LnK@O9hOVPmiMC7H5BvAW{Ct`t&P{gxRT{mlamca9AR%*n@bh2^e{S zk@zeeYqGt@8syh^?SXL`7@W0J0(iH=S4UZk332y_JpQE^O1OE9VnHJXmXsSi3DC{F#5=4@VmD{{AjS#2 zn7r;3M3cVF{j!(b9fpEYIjGicCWiDV+8CY zA<+ECv{Lr~ARwfqr~}KXmNsO=wzp&)%J{qkzkaUqpfj_TbHxtZQdN0LYnNZ(~I=4Ytd zfHlKb1_Jc}HTg2kyG|OzEGDZCc2*R?v9DZ@sKpOg&U-LdPqvti(FW8;-}+kyx>{Ng zY!==zcDN3Z#_qs}j-gsNv@k2vb82V$Zl9jb2@My05l44s&Ixi2>F##}gk&>>|3JGN zp1FHM>X0EHqr@m<798CM>bx68^2&SV?G{+?tdZpbh3eL|<++Hi^g*dAXgwU+Q#P)E zWark{0pj3#hJ*M*!0&+5}+V87lpY7w~tU~J{5LF#lA;-9VMLOIg^(EDYviN{>@J{ zZ8hEU{7VKQVtHLh31>OZkxLhC7Hn-E3tOwk6BM!?Hg2aYX1TH8TS{PrldIEi7-j+m zmXAoJ`GH0DTfsY0EECG-1UUt8?`doIH14*q2)Rx_rz$Mc$y=5|rJM~E}i;G8H>^!J#B>354 z#8%>OQDSFO#_@Tbt#vA!)qa#-U>+k3DP2*xfTfn>#@~I2PyTd8;uv$2zxub>dA4)x z1uc*RYcZil4}5zS(hT(U^`hRr%RF|DrCHu_*zb{2GC;W_1fy2vg(QB;A76BspgGPs zPcrqN2+yH}8Ki48(|(i|eYi4w+On$T#G21Z=#TfOkeOGksq)>7wI<5)R_#yDoKK(h zu5TKBf;RI+re&l}PUSUiYHJM45>r3#g2z3(ywfsHIdfzfX8FhErx=?wuO+9LnEJ-c zL(A3ibLX8QpB5OPJJhlA({-c1f2@lMd;=WAt6}JrvNCxzk1zaIPFFFhz&S(M5UumD z$vNju;)f42tOr(Y9!;t~^s0}bre`{Bv@4%%Vfo#)fM+6{WH`o7WShOG{^cuk_CbpS zV&Uq$K%2h;=Jy?U%LmyCHw~wLaSs|F<*2(bXK2B#?pH~EST@NoZB2M|7!O!=^hf=+ zd_d1wUcmNG6!FxhUw!A_LHAzq2uLgdbPuWRd1drTY*g~kJOI*ffAX`<$FPo2zf~}q z+B2AYN3ez*0yl09Y$x>o{?GQ;&GQd`+236Py>rBl=L3EIP1m4Skx9Sxqa&(-7cRFu zGQI!-1PIsc5yCq_A8^9)@y>z&LifZI?gD#AmZxnXhMI8;kU`;Ad)Yx8-a$=100G{Q!jd1DC%EE zV-+P7{*in7uTfDeeHuj7pYaA=qn&Vzvm6{8k!)PR8|njlqPD)++T_1$4Q zfE@0aKD>OHb5BFFM5yOZ-M9N*CFGjwYSSm$zKBn?;?SqA{GOM8U=)cI7JbY$(SLrF z0IdR-`EudZ!U2Eg+4=CO`lD+@#NI%xQ_Wsha#*O`E$=MJH54cfkq%^;_@xhN9|@c3-((u9^)D_*I*oe?;w${DFIm+^Ks$ z+`yW0?se}sb#~B)@%*;E+&1<-`v4YKiw~;Nj(d_!j;Mj3`OGD~XXeED|49J~mvo0= zfI`D5LZN)P@nr9z`LfNtlUu-BiGMzre&+?1wHu1Ka^*_E_R0S;w}8f$|AokS@$w}W zk5izN4cf>f=WN8iC=9XEF8n-=$aacLVpy=L6k+rBAD-N60X!Lf)8xYyR&T?Ba};4&*?yp? zcCXM^7)Ok=nWI~!DThb@Xtmw**`8l~x7gejjGMX5Muf~m0qgBI$fv(k3(lN5 zV_?~K4(M+GH>m}HI?rFtb4d)0 zHS-?#asKJA-S{tH_h9w}zc#pU%6Y--LMmMSz}66_^zJOUFQ-L!%AOkFT7+CAuQry6 z&pZfH6)7H%PbN3P_h3eRxxfaPhGS#2#MZn8MncZP&lz6{OsxA)5(`o$cl|e9Z+`8W zz_kig9{(?s2dd9MetZcK#egkBcK+0{@pD%RH`{`NF`I>_+}iF`m1nmB-4QX>M7_=@ zxl_7;`h~Pt8q$}qKwYlr`%zip_hH!k=`G@WP`e0A?{VRMJ5-Msw>~>*6@(uch83Lg zII#QMy7n53$l=pPnXevAz;wsANZ|`agh=Tgm#x{k-}Snizs3*1*?>D_UmMSIAEl;j z2AjVAoz(Z}#%&XSY_$@IGT_jAYdhS!>w7p476$OM!oH{0Sax=2mD4Cvy_>o3zjljs}nYJTa3vzEeNO-1S=R38N;qWSxKPoxzP_m}3%}P3PV|iXo>`X?Iy0YHL`NhhCIyAy-3TvVzRY|S zyz+wctY)V7<&I?*txy*HCUc}mSG2Fs&(T%0a19kiY*hmYQ zCEqS1|BO#{r|heh9jc~f9t)mZuur@)-B2q+kCq6Y+kAeO1KrtjNW^3Cl?x$XL{KEx zL^92laVw@^_AD{eEV1r~MwtFgE;CEk7NCEy+*r-7VhqdRq!#TBvhEk_3?f6gWxNt? zn&~>DD#yFsPRwo=H7F2nEH8NijkXYKOS$ScTc@CSC30!$cD7N) zOTCVE&+Ul3vOb#jKo22rp-S(&JK1z2RQ*7mX~CF=VeJelBFYab8GYNMC!<)fdUI6i-XD?J@|T zUQAG`{xfQ&kFWlLltt2om}AU}#Zo;X9K@DH%mXWdrmoTFu5C=V$dL+&%G;Q%5>Ajf zdBVt{KQ3g2hIH&)m@=8^D^F{7Bz8Ju$Rtq?S@&#?&YUbL&1ZEU+EXK5t|!9B!}+;g zqOCAyXxo{P1;Q=8@Ok=0v1;4mb_!Un6QDmA8dRkYP$TEs4I`3x2R^QJdSF7cD{I~w z9o}6^=|xRiz-n;zI!OV>gS`y35?uOsg-MJfr@UpDi8&l?o^YiHrm);q$2_2TLE;`? zT~m8BiJt!B#}O|VXpCG7?jSbXW>wff;M;ErJzI~B{dgVMa8vyhU3uD%eOu2Z{ruZzi6rt2xBzk>F?KedO{p^AiMXhOWF#v;NDC@v^i z+B=u3QTst+PC~7=#Spo{coeAmL#@NRjw|=4Z(*Ae-wudF(fAgrUFOg zXr4M*db+WHSv{+=z?ycbDCWwRWXtI@cg{b1Dn;QC2?&dm?0QnxNyOL z^SjVY?}VP2-%sPhFTkxAEDeofKpGu5 zcqm5`DO7$%sfL%F5dk~;jjoRL8aIE3cnmjCqJOH*_m*kI;qG$ExO((hHWAVJhsAMN^BhU7>$eO<3|hkm z-8NUl@m5@hpPub#hfOO5if!(}N_RC>!wds&|gSJQS%3%u2_V{$h23`gd+=KR3z z@LS=PxwOOH9Wfb+nIPhPaFDI$<%+?etkhNb%nfDbAjc=$oXacCt~8np1zkx_i2~HA zH>V@6GB#+BziyKpr895gOtK#&IVIr_&;5P2`w!>T-->?WmgeVQQKxfA26ughg1XCf zj)m&@S4*e0ln3A?De6kT+mjaCnG{?Lc1f7-+H8y`{jH~GYLaeXjJ6C$@hENlA-FwV>xO5)6;Su zo-M@QeCR~Mq=3Uuxs*X$R$^R4sK=TOi|yLQi^9@k<}G1~SsrmRZY&2YL5Nel?lER& z1Ji&&Amz{F;qi>1h`zS9NF1&|xjNrxxRx&@Dyj){aT+~|f7B&QUHg%2EPlyFyIO(B zgY+_x>L%=Vvl9dNkG2Oh4xtZVUtC&m^ORM(>u zb9*;%=Zb9mwqH?^gL#c!Ap^6nSq zWXJG`Ed~oal)I0o$71*gNAEpDAz9E)bpa99EGQbcD4DIpOr*A$pz;{+DpD0x_38>g z_VFzjmxTbYWu78ULxO99ZVud8n_qPiM=w1MMR@TeB7Zy2MBm;e?6mOlkL#yI+#Mh)cLHePj0rwJHYh#w%l_95WRv_ z$86N{jm3zW#Y@IE)vXS&R2X(2A>!*kl@gH4}#ZLh7Y9PVmS6 zN{F|0GH8rtIw9_Sep#wpeD#8bv1r2NqQlKc2RAOnImRPk&wCRcx=zM^KZr@rN<#;h z-+-N8e9hDhQ1ge%SG;PHV>~W6ttNu}!9G16&pr=)FBj+sIICry6|BTP=C~^NSYikV z-Z{<7s(-X^g2t^hf|!4}hfBEkZo4-u&qg8tBn$>%OqgMOd1`{f#RtLS9`>@B!Yfg7 z`8D{XYSwCi&`Sxp)q*Q_rp~7sz+56NM0YaE$v(J3UZ0hO`T5b}j~^Ynl86W=EJ+h0 z!b0exwz*6;1BD9LI9)i>n|21sI^!T%^Qe6BXT@Row2DLP^?T#jZ7O!%nE2%yXja)> zEw-HN%&|L#&kgc*vo<|zkQ}fgcw*pM`*vp%(v(5Zbp6$iDwjB^a~~bZNyQ8*!~m|V`TsaoL6(Wk#|A; zjgO~E{KZyRwBvlbyZ0~3snbWjy5W)dF#AmQ7eh^_6mXv{<4@6lEpKQs&!%O`0MH?g zoi1J6sDKR?X5J-s+b`>T<;g|3ZYwX>(Jk2g`qyM3t5iZl{$M_KykUF|okZm8r!v4S z?$luXpkDwV?2O!S%$+D;gXiq@JyGddo_?Y0;&5)3D_|aPyma`(9{JIIf|z3EOVD>$ z*;0m);7y)2K%ofq9Y0zr_WLzmz-Jl)7WbE3vk4{%acHU%)c8S(P6uUsMT~$j!%duu zu2gi8hU!tJksp5Ku83S-F;jB6n1n<_*KbF_3fBL9D0AE$5cIH0SBFRUj=qjS8A$=2 z4IxTZB=$2qk`7>_7gg0~;rYeUowpUJg7?~k=>bWT4R^%256>aQXU@RAzgFcfr>s|O zzBE`k9u2Tx4;S^YCh%C?1B1ZO_b{(KNyVc_Am$d=Ba7T5I}Oi);89PaYprBcbmOJ`J!ZuQB}M9MrJ)XNCDwDoHe4w76AYFC`jj>*1M= z;rjXl?f*2xHMQtvNn`+@{??0qvg1XIZos5oHCShVejG@+hG^W@g51k2Zp-;y zJXgF0$f^)3Jbp(d$eEF`+Qf}$5dXbGZZkV1P{uN0fdZhk!9fw5gXOA2fH=PVI7-f` z*Ag^M>Se$_EG_bDTJ_4(r5^?G6I{{6$M;CpSy%ih51Wa$(@>6!BxAW#(BsWR{52q5 z1p0j?u~6@rN9W0HfE*LscOl8-g56CkXG`wh;q1+Cl&^|EG-@ zZj}uQ%+ZEIb+!MAvaZ#`%__%LV)+VFp_H#1i)peVQR7bV78MZ;&HoTEpu0Lzp5svi zP5YWHp)`hNFJr05N{#g}6lwVqAiGwI)x@gsL8s2j1xzKIZ?_Sv;Um_4_2GNvIz>48 zvp};?ZgB)n`l^s;w7I=O21uPk34K!I)@z5--a<2v-8g&aS%5n$--oySh?|Gau*DmyHPQ`TSy4aA;$zIw|5@=CQA0{AH7+Vhnf3CkPa;&5v(2w(Ldywu2l z?IZX-en1S==|=(*qqH}L{V&s}#}F%rN?#VdDoN#%t0QZin;B5GX^C!&p*5P(U$BJg ze)@c7vOSy($}SU@A86|r<&P7J#C9i?DOf$f_>R7?*OcobU3;|Er%mbf7m=sB(ko>p z?_A`1muDhxnLg~i#(#rU|CDH5xVeRO%@$c*N_CdPtXJ<{1Pq8E;hTT2F%5RM zJs$rl%4FnsMPUhSucExHikRT$hyMG-eUo%|F5=~nq7u*#9%Ow3Z080=tx~qiWzn-| zSBQ^0o13?7B`Dl3z}y2vs}vv;X^$Us0A-CLqrT4WDPr;BOYC0>N#ja(7t(1R3tq^` zFNgh8qWSaC`TUO)e2v^xEQ(SRE%os^jmL!xCZJC*mH6tr7=X~I|1_Q51(AL3q3vbe z1=@lQ3CISGN8Of+;btwS5S9zzIQ`iH z6D%*DW5HJV!6))Sh?M%9_N-r2E1x>|llp_aSrP%@r48Ox{;~aErK%@Q@lylPTZIZ;k{lQjTWDh; z(XApk5zC6_Pmvz2wnvJYh`!0Z(q5kvOH4$Hn1GcfB&;0UX9}uT*A9xEm(-J^#y|7+&9;LF61 z(c!6Veoa+Becu6+-f3*cYVx~x3-zR#8Ha>JugDwush0-8X8jEa{^K#6zrZBnL|`+m z{#Z+01&|(rCI|hf6z}8>7TsS`VhiZ)GD_8Z8^Rxt6gt-W`-Q+ufDLY15IrFxx{$(g z&S*~)C;+cC14!0d>&iV=fYp*JK!DS|b0@)9611JS&^ws+aeIbJMVa*LH~?l6>M%9a z`1>nYgn9dn^ZJJdDp?p9AayE}WIOKK{bE@AH|L_aYS?I$e0W;7pK|S$C%wuygMwmMV9u)(Dz4 z0ePQt=OH!L)>2rqC6QoBBvl^mkAWuguQFUlOLdoaKr<<5MAc5v8$O{t_u()9h6rA) zU9Z;B=b^px>o5Gg+GO@*GRW(_6`tqVA38yQ?$(KCL@n=;s}Fv8r+@ssXg4L}TGZC^ zCjPh<0pI(eLl3n4RbR9Ey&vvSLvD^CFq&UAJYX5oVFOLRXRimYZ!C>p#+fPv_ z6mx*{n;TCiRnn;bMf-YmYez=R%MEmNY@ZY-Sg!KOqOq8SZu9J{tZB1m+2I;>I;wav zLSi>8iud@&wHB)x8J*F50(Nw4qEM}QJ8W5un(=k&rO}Ox3}j-xcTyw zT&A{JQ4}yRDb0&+?Ww)7XLWe$*q0oFrcb#Z#LcVZ>+mEERC~UtZ)qJr4x#V1L2v42 zWJMhq)>x-f+OaU%Fd!&N1wb6Encvz-3165=MRCQh~=htW$F#7QV(W2%sOm|!p*9{mh*W$VuzkB!x z?~G|h^Qqo3=3VZmrL*C$D;)KkMU@v?*v^&F(PSJ}J|*75dDhoY*@zNM4&4?-L_XCz zH&gEJN8eP8`b;x*|8(kiSIgX7xU|cnYZr0g?rL;WE)Qf}Qx!y# zT*X&Osq$3sWnV&ViOR8oV5nysXPxs_M!t|wsX!kkrisTRpExQqI7lRy_5@$kKX}Nk z03Hv|b#dv>HKt-(tjU*V_uvmtMy}d^=rFBd^nK!gH+{uxbzU#W^y`^9r|ivMXw5`K zSf6MCv&~bn1aa3JWnw&t95ak(8$AlHGdt_Ayb026g9TaM&Jh0 zLMf%!?su=;T=z3o;3KphpPEO7T z1Mt^doTx?1VcKs#fFOjMCF9zc0L!7bzlNRwQ5;gX_Vb}F z2Jdy6_~cVB*Yz=F6hv>8)acFLPF7}5D|5@$J$gNf;nW=5nAu@%ZS{|>rW%`6v7@GB zFRGovYNu;$H80LKs9bM3r63a6GZREe@kf2Fbd=o#_x3-&3fZCT?Ci94HKNyuxS9dO zjCjwI8|j1)&THzH)vunKNF>)~Lus$LujBPJNYm;v%|Y^1d_pO#Y`jsx8G8C8$!Ai| z^Xkqr=_GWAw{dGeI79Cf{43JW?@O71w)ROulcx4p+6HNk9|msTnY`{Upc{X=6<5(1 zl@w#)J2ls(lw+PHn6f|G1~radQt-5E`>Ye0Ku!=#h_J#IojS#60>Vdq*0VsasZX_~ zt(T+d76%GrSc~*8%gME^l$G!v7tE;?4W!UyBMjqO!WkL*OynD-N*~V%!2jp3l)VZSPGDuJ^=Jq?Wlk_W@Oy^jH@idBww#L%l-?2w%DiMz1G`IM({i z!D)=2TYC*<>rw@CAcV1WPBKx-!~9E0bBIRE48v0zNRTaAT|*hV!?>f*mvgU*JB4;+ zdKtwKIb34pdF@jBT%?S;FLT38)X9ytRWNbgt(S?ByGO|;E2iwdsr7NIA5Q0qBZS^p zW?Ke*wEsT$8HN7~Q+~H4~n1IX;2WgYJ=IQ|U}A9E5#6V?smJpDV}cq2G#vUD7uw z8{A%{EvxnfbH~DxMO#=AQw;ZuO|;%~2q!k$2t}?}duMHK`pLremTpbb{4FQ=b5YQy zWL#x{$q;1F9Qmk(7#A9s`l2tcO#XL!9S4%S^2&0oq)gsKWtKERH)^*C{j-#qCg=-oma&I&icAP zS9^X&*dZAhj5qpmAo&6|5>I3hv*vRF(sg-n7V4}*le3M@$Gwgz;C1-Oh6Hfot75jB z6Y_5vZDX#SuGSF$ob}dQ5*f~_sI%w)Iu5!?hT~n=7EoQgUq;Z^^YJI2Gv&} zkTFS3&8Bul!T9Njp{}aa96U*F%O{p;qwfP<6`nI%bJ3H-w{cBlTAP3XLZoAEX1~or zGU4bOH!qaQ!1YJo=8IajXF1W%G}(h_zugdBx2k_}Kqn+JajE9a8*efxv< z7}4o|UrT#Tpq-1$g{3+12+`M&qeCic+ODQUs+-c#!!z!Y*3Z0W@o{&$Q&1EJ#S7e% z81EG+P;s5ljAqQ|8>l1!`Ha6Oj6c#%HCA@phsC39eO2p+{qXtAu&GYV{1@J$5T}5S zozi()yQ2`H&7(h>s!s(Z2q7minV7-?m9)K6rktV0JLg}1$}=-g6t;^OQk@K%Vp08L zDqb;il=GzQy|XbB=cEKXyE-p7jcOcfsgJzAa(jm_COVoia^SFv$OrU}SNg77xHi*L zebBDJFg9%F9LlZ`c=Qb=+4)QL!;m-M=B6UE@8I9ex_ORQW)2QxJ1QD6&ttrr^g>J| z3OBkY*ASN+*y8ueaK5bi@?!BHnG3KgemmrE^UfTTb(YGJTVvr>jGgP^&g{1kj`QCX zx&3ZcDvfr-a{aG6gFiD6H7^d}ZIHMItJbaKHO;sXlDN-*umv3q>XE~>A&=JuXzIi>5kNAsXEm5W%%JWf@E~XXJS>p4oi1muz-&O1n4x%3K{b)Ub<|7d zQ{GNxZ1!_!Zdp+xmdJRgR^A1FV)lqjc@@f%te~~_K6oIUBl$qmj4wPs{+xgG`B3<1 z*~`hGM~#1=Lh`+5?#qinpa{C<1DX!Gj=85T-}VVLuJ|Yo>IL<>yLlca4d__6@#dAG z5@~BZ{Ay#zi46{R-SL2pDf{vxBLZpCQ{VJ#DUEuRQ+nWIhG?#}{6y-Nnub8XUh`F-@3q&M_#A0V%D-*LLm=k<3)225s^QLPfX(rC!Exf^MYye}r}_6U<7ukFu`@FfqW7}5_2iDW zWQ*b>;6M)a`zVQZB02sdxxMQFe^xf76vf%sG9yN%D#xW6Wlz%5_?1;uxW<+qvJ=G6 z!5dRF?#q__C06lT8w4)mnKkUZlzqP`KjC2JIp6m&goI|rcqZH}wlB_SHfZpUa{{v_ z9XG<91f+%#w6y#&QS@V^h1_86$zQkb*Yoq{%d8jU`RtTnB7eiUoA_l(Qm-j;dZq?z zJBSu`Rb=zhkG~@=bH%75Cz6fqg-CZr0=ocKb`%>&3@)Xd58HH41B=N$z2`b7?`dseZcz5Iqe^v+JmYMK4JegRLunX+YSZrcS}oO Kv*?Cx=zjr;x-ZTE literal 0 HcmV?d00001 From 25fc3a9e95f3b05ce19986b8c80c66321a2a038b Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Tue, 20 Jul 2021 17:38:54 +0200 Subject: [PATCH 03/28] Add RateLimits --- gloo-edge/gloo-edge/README.md | 231 ++++++++++++++++++++++++++-------- 1 file changed, 180 insertions(+), 51 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 1da30b6cb2..52048ff451 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -200,7 +200,7 @@ It should return the discovered upstream with an `Accepted` status: Now that your two Upstream CR have been created, you need to create the resources to route the traffic to them. -First, you create a Virtual Service. For bookinfo under `/` and for httpbin under `/secured`. +First, you create a Virtual Service. For bookinfo under `/` and for httpbin under `/not-secured`. Please, notice that the oder matters. @@ -216,15 +216,6 @@ spec: domains: - '*' routes: - - matchers: - - prefix: /secured - routeAction: - single: - upstream: - name: team1-httpbin-8000 - namespace: gloo-system - options: - prefixRewrite: '/' - matchers: - prefix: / routeAction: @@ -247,13 +238,48 @@ It should return the bookinfo application webpage. Note that the review stars ar ![Bookinfo Web Interface](images/1.png) +Now, let's enable the httpbin route to be matched before bookinfo: + +```bash +kubectl apply -f - < **Note:** One of the following commands retrieves a token which expires quite soon. If you get a *Not Authorized* error, please, re-run the second command to retrieve another token (the one starting with `KEYCLOAK_TOKEN=`) + ```bash # Get Keycloak URL and token KEYCLOAK_URL=http://$(kubectl get service keycloak -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):8080/auth @@ -635,7 +669,7 @@ spec: EOF ``` -Finally we activate the authentication on the Virtual Service by referencing the AuthConfig: +Finally we activate the authentication on the Route Table by referencing the AuthConfig: ```bash kubectl apply -f - < Date: Tue, 20 Jul 2021 18:50:34 +0200 Subject: [PATCH 04/28] Add WAF --- gloo-edge/gloo-edge/README.md | 146 +++++++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 20 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 52048ff451..fa5133e56b 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -850,12 +850,12 @@ spec: # -------- Rate limit config by authenticated and anonymous ------- ratelimitBasic: anonymousLimits: - requestsPerUnit: 10 + requestsPerUnit: 5 unit: MINUTE authorizedLimits: - requestsPerUnit: 5 + requestsPerUnit: 20 unit: MINUTE -#------------------------------------------------------------------- +# ----------------------------------------------------------------- routes: - matchers: - prefix: /not-secured @@ -888,9 +888,17 @@ spec: EOF ``` -Refresh the httpbin application and after 10 times, you will retrieve a 429 error. This is because you are an anonymous user. +Refresh the httpbin application and after 5 times, you will retrieve a 429 error. This is because you are an anonymous user. + +``` +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get +``` -Try it with the bookinfo application, and the number of requests will be limited to 5 as you are an Authenticated user. Notice that the requests for static content also counts. +Try it with the bookinfo application, and the number of requests will be limited to 20 as you are an Authenticated user. Notice that the requests for static content also counts. + +``` +/opt/google/chrome/chrome $(glooctl proxy url --port https)/productpage +``` ### Web Application Firewall (WAF) @@ -898,7 +906,7 @@ A web application firewall (WAF) protects web applications by monitoring, filter Gloo Edge Enterprise includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. -Let's update our Virtual Service to restrict the characters allowed for usernames. +Let's update the Virtual Service to restrict requests with huge payload to avoid Large Payload Post DDoS Attack. The intention of this DDoS attack is abuse on the amount of memory to decode the payload ```bash kubectl apply -f - <Reminderare you sure this is a huge payload???" -H "Content-Type: application/xml" +``` + +You should get the following error message: + +``` +Payload sizes above 1KB not allowed +``` + + +#### WAF Block well-known User-Agents + +Another kind of attack is done by some recognized User-Agents + +```bash +kubectl apply -f - < Date: Wed, 21 Jul 2021 16:33:53 +0200 Subject: [PATCH 05/28] Add transformations --- gloo-edge/gloo-edge/README.md | 212 ++++++++++++++++++++++++++-------- 1 file changed, 163 insertions(+), 49 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index fa5133e56b..61cfececc7 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1074,67 +1074,181 @@ In this section we will explore how to transform requests using Gloo Edge. ### Response Transformation +Before, it was mentioned that httpbin is a good tool to debug and test things out. In this section, you will use that application to easily spot results. + The following example demonstrates how to modify a response using Gloo Edge. We are going to return a basic html page when the response code is 429 (rate limited). ```bash kubectl apply -f - <

Too many Requests!

Try again after 10 seconds

{% else %}{{ body() }}{% endif %}' + transformations: + responseTransformation: + transformationTemplate: + parseBodyBehavior: DontParse + body: + text: '{% if header(":status") == "429" %}

Too many Requests!

Try again after 1 minute

{% else %}{{ body() }}{% endif %}' #--------------------------------------------------- - domains: - - '*' - routes: - - matchers: - - prefix: / - routeAction: - multi: - destinations: - - weight: 5 - destination: - upstream: - name: bookinfo-productpage-9080 - namespace: gloo-system - - weight: 5 - destination: - upstream: - name: bookinfo-beta-productpage-9080 - namespace: gloo-system + routeAction: + single: + upstream: + name: team1-httpbin-8000 + namespace: gloo-system EOF ``` -Refreshing your browser a couple times, you should be able to see a styled HTML page indicating that you reached the limit. +Refreshing your browser more than 5 times, you should be able to see a styled HTML page indicating that you reached the limit you have configured before. + +``` +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get +``` + +### Manipulate the response when a 401 Not Authorized is returned + +The following example shows how to create a transformation taking a value from the header and adding it to a response body: + + +```bash +kubectl apply -f - < Date: Wed, 21 Jul 2021 18:38:04 +0200 Subject: [PATCH 06/28] reorder labs --- gloo-edge/gloo-edge/README.md | 525 +++++++++++----------------------- 1 file changed, 170 insertions(+), 355 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 61cfececc7..a80d1531b2 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -587,7 +587,14 @@ The browser will warn you that your connection is not private due to the self-si ### OIDC Support -In many use cases, we need to restrict the access to our applications to authenticated users. In this step, we will secure our application using an OIDC Identity Provider. +In many use cases, we need to restrict the access to our applications to authenticated users. + +OIDC (OpenID Connect) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. + +The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. + + +In this step, we will secure our application using an OIDC Identity Provider. Let's start by installing Keycloak: @@ -1250,361 +1257,8 @@ You will see the headers which arrive to the service, including your new transfo } ``` -## Lab 4: Delegation - -Gloo Edge provides a feature referred to as delegation. Delegation allows a complete routing configuration to be assembled from separate config objects. The root config object delegates responsibility to other objects, forming a tree of config objects. The tree always has a Virtual Service as its root, which delegates to any number of Route Tables. Route Tables can further delegate to other Route Tables. - -Use cases for delegation include: - -- Allowing multiple tenants to own add, remove, and update routes without requiring shared access to the root-level Virtual Service -- Sharing route configuration between Virtual Services -- Simplifying blue-green routing configurations by swapping the target Route Table for a delegated route. -- Simplifying very large routing configurations for a single Virtual Service -- Restricting ownership of routing configuration for a tenant to a subset of the whole Virtual Service. -Let's rewrite our Virtual Service to delegate the routing to a Route Table: - -```bash -kubectl apply -f - <

Too many Requests!

Try again after 10 seconds

{% else %}{{ body() }}{% endif %}' - domains: - - '*' - routes: - - matchers: - - prefix: / - delegateAction: - ref: - name: 'demo' - namespace: 'gloo-system' -EOF -``` - -As you can see, in this case the security options remains in the `VirtualService` (and can be managed by the infrastructure team) while the routing options are now in the `RouteTable` (and can be managed by the application team). - -## Lab 5: Observability - -### Metrics - -Gloo Edge automatically generates a Grafana dashboard for whole-cluster stats (overall request timing, aggregated response codes, etc.), and dynamically generates a more-specific dashboard for each upstream that is tracked. - -Let's run the following command to allow access to the Grafana UI: - -``` -kubectl port-forward -n gloo-system svc/glooe-grafana 8001:80 -``` - -You can now access the Grafana UI at http://localhost:8001 and login with `admin/admin`. - -You can take a look at the `Gloo -> Envoy Statistics` Dashboard that provides global statistics: - -![Grafana Envoy Statistics](images/grafana1.png) - -You can also see that Gloo is dynamically generating a Dashboard for each Upstream: - -![Grafana Upstream](images/grafana2.png) - -You can run the following command to see the default template used to generate these templates: - -``` -kubectl -n gloo-system get cm gloo-observability-config -o yaml -``` - -If you want to customize how these per-upstream dashboards look, you can provide your own template to use by writing a Grafana dashboard JSON representation to that config map key. - -### Access Logging - -Access logs are important to check if a system is behaving correctly and for debugging purposes. Log aggregators like Datadog and Splunk use agents deployed on the Kubernetes clusters to collect logs. - -Lets first enable access logging on the gateway: - -```bash -kubectl apply -f - < Envoy Statistics` Dashboard that provides global statistics: + +![Grafana Envoy Statistics](images/grafana1.png) + +You can also see that Gloo is dynamically generating a Dashboard for each Upstream: + +![Grafana Upstream](images/grafana2.png) + +You can run the following command to see the default template used to generate these templates: + +``` +kubectl -n gloo-system get cm gloo-observability-config -o yaml +``` + +If you want to customize how these per-upstream dashboards look, you can provide your own template to use by writing a Grafana dashboard JSON representation to that config map key. + +### Access Logging + +Access logs are important to check if a system is behaving correctly and for debugging purposes. Log aggregators like Datadog and Splunk use agents deployed on the Kubernetes clusters to collect logs. + +Lets first enable access logging on the gateway: + +```bash +kubectl apply -f - < Date: Wed, 21 Jul 2021 20:04:16 +0200 Subject: [PATCH 07/28] Review NOT FINISHED --- gloo-edge/gloo-edge/README.md | 478 +++++++++++++++++++++++++++++----- 1 file changed, 410 insertions(+), 68 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index a80d1531b2..5c21ae41f3 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -9,6 +9,7 @@ The goal of this workshop is to expose some key features of Gloo API Gateway, li The lab environment consists of a Kubernetes environment deployed locally using kind. In this workshop we will: +TODO: Redo summary * Deploy a demo application (Istio's [bookinfo](https://istio.io/latest/docs/examples/bookinfo/) demo app) on a k8s cluster and expose it through Gloo Edge * Deploy a second version of the demo app and route traffic to both versions * Secure the demo app using TLS @@ -73,7 +74,7 @@ done In this step we will expose two demo services to the outside world using Gloo Edge. -First let's deploy a demo application called bookinfo in `bookinfo` namespace: +First let's deploy a demo application called **bookinfo** in `bookinfo` namespace: ```bash kubectl create ns bookinfo @@ -113,7 +114,9 @@ It should return the discovered upstream with an `Accepted` status: +---------------------------+------------+----------+----------------------------+ ``` -Now, let's deploy the second application, called httpbin in `team1` namespace: +Now, let's deploy the second application, called **httpbin** in the namespace `team1`. + +This application is very useful when you have to debug routing, headers in requests, responses, status codes, etc. The public online version of it can be found [here](http://httpbin.org/). ```bash kubectl create ns team1 @@ -168,8 +171,6 @@ spec: EOF ``` -The httpbin application is very useful to debug requests and responses. The online version of it can be found [here](http://httpbin.org/). - ![Gloo Edge with Httpbin](images/httpbin.png) To verify that the Upstream was created properly, run the following command: @@ -314,10 +315,12 @@ Use cases for delegation include: Let's rewrite our Virtual Service to delegate the routing to a Route Table. -First, the Route Table: +First resource is the delegated Route Table. Second resource is a Virtual Service. Notice that there is a new `delegateAction` referencing the just created Route Table. + ```bash kubectl apply -f - < Since you are using self-signed certificates, you need to allow insecure sever connection when using SSL with *-k* + +``` +curl -k $APP_URL/not-secured/get +``` +### Authentication with OIDC (OpenID Connect) + +In many use cases, you need to restrict the access to your applications to authenticated users. OIDC (OpenID Connect) is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an Access Token representing the user identity. The protocol does not define the contents and structure of the Access Token, which greatly reduces the portability of OAuth 2.0 implementations. The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. -In this step, we will secure our application using an OIDC Identity Provider. +In this step, you will secure **bookinfo** application using an OIDC Identity Provider. Let's start by installing Keycloak: @@ -615,7 +666,13 @@ Then, we need to configure it and create two users: - User2 credentials: `user2/password` Email: user2@example.com -> **Note:** One of the following commands retrieves a token which expires quite soon. If you get a *Not Authorized* error, please, re-run the second command to retrieve another token (the one starting with `KEYCLOAK_TOKEN=`) +> **Note:** One of the following commands retrieves a token which expires quite soon. If you get a *Not Authorized* error, please, re-run this command: + +``` +KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + +Let's create the users: ```bash # Get Keycloak URL and token @@ -651,7 +708,7 @@ The next step is to configure the authentication in the Virtual Service. For thi glooctl create secret oauth --namespace gloo-system --name keycloak-oauth --client-secret ${secret} ``` -Then we will create an AuthConfig, which is a Gloo Edge CRD that contains authentication information: +Then you will create an AuthConfig, which is a Gloo Edge CRD that contains authentication information: ```bash kubectl apply -f - < Notice that this only applies to a specif route, because it is configured within a **matcher** ```bash kubectl apply -f - < Notice that the requests for static content also count since they share the route `/`. +> `/productpage` +> `/static/` ``` /opt/google/chrome/chrome $(glooctl proxy url --port https)/productpage ``` -### Web Application Firewall (WAF) +## Lab 4: Web Application Firewall (WAF) A web application firewall (WAF) protects web applications by monitoring, filtering and blocking potentially harmful traffic and attacks that can overtake or exploit them. Gloo Edge Enterprise includes the ability to enable the ModSecurity Web Application Firewall for any incoming and outgoing HTTP connections. -Let's update the Virtual Service to restrict requests with huge payload to avoid Large Payload Post DDoS Attack. The intention of this DDoS attack is abuse on the amount of memory to decode the payload +Let's update the Virtual Service to restrict requests with huge payload to avoid *Large Payload Post DDoS Attack*. The intention of this DDoS attack is abuse on the amount of memory used to decode the payload bringing the server down. ```bash kubectl apply -f - < Notice that the response transformation is flagged as `early`. The reason is that an Auth Server returning 401 will cancel any filter or transformation designed to happen after that (`regular` stage). Therefore, you need to prepare the response transformation before the Auth Server filter happens in an `early` stage. ```bash @@ -1163,6 +1411,65 @@ spec: upstream: name: team1-httpbin-8000 namespace: gloo-system + +--- + +apiVersion: gateway.solo.io/v1 +kind: VirtualService +metadata: + name: demo + namespace: gloo-system +spec: + sslConfig: + secretRef: + name: upstream-tls + namespace: gloo-system + virtualHost: + domains: + - '*' + options: + ratelimitBasic: + anonymousLimits: + requestsPerUnit: 5 + unit: MINUTE + authorizedLimits: + requestsPerUnit: 20 + unit: MINUTE + waf: + customInterventionMessage: "Blocked Scammer" + ruleSets: + - ruleStr: | + SecRuleEngine On + SecRule REQUEST_HEADERS:User-Agent "scammer" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" + routes: + - matchers: + - prefix: /not-secured + delegateAction: + selector: + namespaces: + - team1 + labels: + application-owner: team1 + - matchers: + - prefix: / + options: + extauth: + configRef: + name: keycloak-oauth + namespace: gloo-system + routeAction: + multi: + destinations: + - weight: 5 + destination: + upstream: + name: bookinfo-productpage-9080 + namespace: gloo-system + - weight: 5 + destination: + upstream: + name: bookinfo-beta-productpage-9080 + namespace: gloo-system EOF ``` @@ -1178,7 +1485,7 @@ And any other status code, returns the expected body: curl -v -k $(glooctl proxy url --port https)/not-secured/status/get ``` -### Manipulate the response when a 401 Not Authorized is returned +### Early response transformation You can also extract information from one header with regular expressions and inject them into another header: @@ -1232,13 +1539,13 @@ spec: EOF ``` -With httbin application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: +> With httbin application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: ``` -curl -k https://34.141.86.2/not-secured/get -H "x-my-initial-header: Bearer this_is_my_token_for_test" +curl -k $(glooctl proxy url --port https)/not-secured/get -H "x-my-initial-header: Bearer this_is_my_token_for_test" ``` -You will see the headers which arrive to the service, including your new transformed one `x-my-final-header` with the specific content after regular expression matching. +You can see all the request headers which arrive to the service, including your new transformed one `x-my-final-header` with the specific content after regular expression matching. ``` { @@ -1258,10 +1565,43 @@ You will see the headers which arrive to the service, including your new transfo ``` -### Obtain a value from the token +### Obtain a token from the cookie + +In the scenarios when you expose a website, like **bookinfo**, to secure the token (i.e. JWT token in OIDC), you wrap the token with in the cookie. + +In this step, you will obtain a token from the cookie: ```bash kubectl apply -f - <

Too many Requests!

Try again after 1 minute

{% else %}{{ body() }}{% endif %}' +#--------------------------------------------------- + routeAction: + single: + upstream: + name: team1-httpbin-8000 + namespace: gloo-system + +--- + apiVersion: gateway.solo.io/v1 kind: VirtualService metadata: @@ -1315,6 +1655,8 @@ This transformation is using a regular expression to extract the JWT token from As explained in previous Labs, Keycloak will return a JWT token, so we’ll use Gloo to extract some claims from this token and to create new headers corresponding to these claims. +TODO: HEREEEEEEEEEEEEEE + Finally, we’ll see how Gloo Edge RBAC rules can be created to leverage the claims contained in the JWT token. From 21b68798a50646e9eef193ae89d24c9f9559d8b4 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Thu, 22 Jul 2021 18:31:26 +0200 Subject: [PATCH 08/28] Improve other labs --- gloo-edge/gloo-edge/README.md | 673 ++++++++++++++++++++++++---------- 1 file changed, 489 insertions(+), 184 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 5c21ae41f3..ca1937687e 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -9,15 +9,15 @@ The goal of this workshop is to expose some key features of Gloo API Gateway, li The lab environment consists of a Kubernetes environment deployed locally using kind. In this workshop we will: -TODO: Redo summary -* Deploy a demo application (Istio's [bookinfo](https://istio.io/latest/docs/examples/bookinfo/) demo app) on a k8s cluster and expose it through Gloo Edge -* Deploy a second version of the demo app and route traffic to both versions -* Secure the demo app using TLS -* Secure the demo app using OIDC -* Rate limit the traffic going to the demo app -* Transform a response using Gloo transformations +* Deploy two applications (Istio's **[bookinfo](https://istio.io/latest/docs/examples/bookinfo/)** and **[httpbin](https://github.com/istio/istio/blob/master/samples/httpbin/httpbin.yaml)**) on a k8s cluster and expose it through Gloo Edge +* Deploy a second version of the **bookinfo** app and route traffic to both versions +* Secure apps using TLS +* Apply Authentication using OIDC +* Rate limit the traffic going to the apps +* Apply rules for the Web Application Firewall (WAF) +* Transform requests, responses and bodies using Gloo transformations +* Apply Authorization using RBAC and OPA (Open Policy Agent) * Configure access logs -* Use several of these features together to configure an advanced OIDC workflow ## Lab 0: Demo Environment Creation @@ -70,11 +70,11 @@ done ## Lab 1: Traffic Management -### Deploy Demo Services +### Deploy Services -In this step we will expose two demo services to the outside world using Gloo Edge. +In this step you will expose two services to the outside world using Gloo Edge. -First let's deploy a demo application called **bookinfo** in `bookinfo` namespace: +First let's deploy an application called **bookinfo** in `bookinfo` namespace: ```bash kubectl create ns bookinfo @@ -84,7 +84,7 @@ kubectl delete deployment reviews-v1 reviews-v3 -n bookinfo ![Gloo Edge with Bookinfo](images/bookinfo-v2.png) -The bookinfo app has 3 versions of a microservice called reviews. We will keep only the version 2 of the reviews microservice for this step and will add the other versions later. An easy way to distinguish among the different versions in the web interface is to look at the stars: v1 displays no stars in the reviews, v2 displays black stars, and v3 displays red stars. +The bookinfo app has 3 versions of a microservice called reviews. You will keep only the version 2 of the reviews microservice for this step and will add the other versions later. An easy way to distinguish among the different versions in the web interface is to look at the stars: v1 displays no stars in the reviews, v2 displays black stars, and v3 displays red stars. Gloo Edge uses a discovery mechanism to create Upstreams automatically, but Upstreams can be also created manually using Kubernetes CRDs. @@ -203,7 +203,7 @@ Now that your two Upstream CR have been created, you need to create the resource First, you create a Virtual Service. For bookinfo under `/` and for httpbin under `/not-secured`. -Please, notice that the oder matters. +Please, notice that the order matters. ```bash kubectl apply -f - < Since you are using self-signed certificates, you need to allow insecure sever connection when using SSL with *-k* +> Since you are using self-signed certificates, you need to allow insecure server connection when using SSL with *-k* ``` curl -k $APP_URL/not-secured/get @@ -645,7 +645,7 @@ OIDC (OpenID Connect) is an identity layer on top of the OAuth 2.0 protocol. In The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields that your applications can expect and handle. This standardization allows you to switch between Identity Providers – or support multiple ones at the same time – with minimal, if any, changes to your downstream services; it also allows you to consistently apply additional security measures like Role-based Access Control (RBAC) based on the identity of your users, i.e. the contents of their ID token. -In this step, you will secure **bookinfo** application using an OIDC Identity Provider. +In this step, you will secure the **bookinfo** application using an OIDC Identity Provider. Let's start by installing Keycloak: @@ -658,7 +658,7 @@ kubectl rollout status deploy/keycloak sleep 30 --> -Then, we need to configure it and create two users: +Then, you need to configure it and create two users: - User1 credentials: `user1/password` Email: user1@solo.io @@ -702,10 +702,10 @@ The architecture looks like this now: ![Bookinfo with OIDC](images/bookinfo-oidc.png) -The next step is to configure the authentication in the Virtual Service. For this we will have to create a Kubernetes Secret that contains the OIDC secret: +The next step is to configure the authentication in the Virtual Service. For this, you will have to create a Kubernetes Secret that contains the OIDC secret: ```bash -glooctl create secret oauth --namespace gloo-system --name keycloak-oauth --client-secret ${secret} +glooctl create secret oauth --namespace gloo-system --name oauth --client-secret ${secret} ``` Then you will create an AuthConfig, which is a Gloo Edge CRD that contains authentication information: @@ -715,7 +715,7 @@ kubectl apply -f - < Notice that this only applies to a specif route, because it is configured within a **matcher** +> Notice that this only applies to a specific route, because it is configured within a **matcher** ```bash kubectl apply -f - < With httbin application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: +> With the **httbin** application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: ``` curl -k $(glooctl proxy url --port https)/not-secured/get -H "x-my-initial-header: Bearer this_is_my_token_for_test" ``` -You can see all the request headers which arrive to the service, including your new transformed one `x-my-final-header` with the specific content after regular expression matching. +You can see the new `X-My-Final-Header` header only with the token: ``` { - "args": {}, "headers": { - "Accept": "*/*", - "Host": "x.x.x.x", - "User-Agent": "curl/7.64.1", - "X-Envoy-Expected-Rq-Timeout-Ms": "15000", - "X-Envoy-Original-Path": "/not-secured/get", +[...] "X-My-Final-Header": "this_is_my_token_for_test", "X-My-Initial-Header": "Bearer this_is_my_token_for_test" }, - "origin": "x.x.x.x", - "url": "xxxxxxxxx" +[...] } ``` ### Obtain a token from the cookie -In the scenarios when you expose a website, like **bookinfo**, to secure the token (i.e. JWT token in OIDC), you wrap the token with in the cookie. +In the scenarios when you expose a website, like **bookinfo**, to secure the token (i.e. JWT token in OIDC), you wrap the token within the cookie. + +In this step, you will obtain a token from the cookie. + +For the purpose of the demo, you will apply this transformation in the general location. That means that the transformation will be applied for all the routes. In your case, the applications you have deployed. -In this step, you will obtain a token from the cookie: +> Notice that the previous transformations have been commented out. The reason is that transformations in lower levels like at Route Table are prioritized to the more general ones like the one in the Virtual Service. ```bash kubectl apply -f - <

Too many Requests!

Try again after 1 minute

{% else %}{{ body() }}{% endif %}' -#--------------------------------------------------- +# ------------- Commenting transformations ------------------ + # stagedTransformations: + # early: + # responseTransforms: + # - responseTransformation: + # transformationTemplate: + # parseBodyBehavior: DontParse + # headers: + # Content-type: + # text: "application/json" + # body: + # text: | + # {% if header(":status") == "401" %} + # Hold the horses! You are not authenticated + # {% else %}{{ body() }}{% endif %} + # requestTransforms: + # - requestTransformation: + # transformationTemplate: + # extractors: + # apiKey: + # header: 'x-my-initial-header' + # regex: '^Bearer (.*)$' + # subgroup: 1 + # headers: + # x-my-final-header: + # text: '{{ apiKey }}' +#------------------------------------------------------------- routeAction: single: upstream: @@ -1613,12 +1689,23 @@ spec: name: upstream-tls namespace: gloo-system virtualHost: + domains: + - '*' options: - extauth: - configRef: - name: keycloak-oauth - namespace: gloo-system -# -------------Extract Token------------------ + ratelimitBasic: + anonymousLimits: + requestsPerUnit: 5 + unit: MINUTE + authorizedLimits: + requestsPerUnit: 20 + unit: MINUTE + waf: + customInterventionMessage: "Blocked Scammer" + ruleSets: + - ruleStr: | + SecRuleEngine On + SecRule REQUEST_HEADERS:User-Agent "scammer" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" +# ------------- Transformation to Extract Token ------------------ stagedTransformations: early: requestTransforms: @@ -1633,99 +1720,120 @@ spec: jwt: text: '{{ token }}' #--------------------------------------------- -#--------------Remove Header------------------ +#-------------- Remove Cookie Header ------------------ headerManipulation: requestHeadersToRemove: - "cookie" #--------------------------------------------- - domains: - - '*' routes: + - matchers: + - prefix: /not-secured + delegateAction: + selector: + namespaces: + - team1 + labels: + application-owner: team1 - matchers: - prefix: / + options: + extauth: + configRef: + name: oauth + namespace: gloo-system routeAction: - single: - upstream: - name: default-httpbin-8000 - namespace: gloo-system + multi: + destinations: + - weight: 5 + destination: + upstream: + name: bookinfo-productpage-9080 + namespace: gloo-system + - weight: 5 + destination: + upstream: + name: bookinfo-beta-productpage-9080 + namespace: gloo-system EOF ``` This transformation is using a regular expression to extract the JWT token from the `cookie` header, creates a new `jwt` header that contains the token and removes the `cookie` header. -As explained in previous Labs, Keycloak will return a JWT token, so we’ll use Gloo to extract some claims from this token and to create new headers corresponding to these claims. - -TODO: HEREEEEEEEEEEEEEE - -Finally, we’ll see how Gloo Edge RBAC rules can be created to leverage the claims contained in the JWT token. - - -As you can see, the browser has sent the cookie as a header in the HTTP request. - - -### Getting more details from token - +As explained in previous Labs, Keycloak will return a JWT token, so you’ll use Gloo to extract some claims from this token and to create new headers corresponding to these claims. +To test this, first you will need to obtain a valid token through your **bookinfo** application: +``` +/opt/google/chrome/chrome $(glooctl proxy url)/productpage +``` -Gloo is able to perform advanced transformations of the request and response. +After refreshing, and maybe signing in, you will access the application again, which means that you will have the valid token in a cookie. -Let’s modify the Virtual Service using the yaml below: +Now, let's verify the transformation using the debugging **httpbin** application. This time, in the browser: +``` +/opt/google/chrome/chrome $(glooctl proxy url)/not-secured/get +``` -Here is the output you should get if you refresh the web page: +As you can see, the browser has sent the cookie as a header in the HTTP request. And after transformation, your debugging application shows you that there is a new header with the token. Something like this: ``` { - "args": {}, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", - "Accept-Encoding": "gzip, deflate, br", - "Accept-Language": "en-US,en;q=0.9", - "Cache-Control": "max-age=0", - "Content-Length": "0", - "Host": "172.18.1.1", - "Jwt": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZd18zVTBoOFFkbGpsODBiSkQxUDhzbUtud0ZYYkVJZE0xZjlMU3R1N2E0In0.eyJleHAiOjE2MDc0MTkyOTMsImlhdCI6MTYwNzQxOTIzMywiYXV0aF90aW1lIjoxNjA3NDE4NzQ5LCJqdGkiOiI2NWExYzM0Ni0wNTY5LTQwNWUtYTNmZi0wOTVjZGE3MGRiYmMiLCJpc3MiOiJodHRwOi8vMTcyLjE4LjAuMjExOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiZjg3YzAzOWQtNTdiZi00NTQzLWExZjAtOGIyMmZjNmY5ZTYwIiwic3ViIjoiN2Q0N2I2YmYtOTcyYi00OGRjLWI3YjctM2U5N2NlZGM4NjM1IiwidHlwIjoiSUQiLCJhenAiOiJmODdjMDM5ZC01N2JmLTQ1NDMtYTFmMC04YjIyZmM2ZjllNjAiLCJzZXNzaW9uX3N0YXRlIjoiOGJmNjAzMTYtY2NmYi00ZWZkLWFiNDgtOTc5MmQzNTkzNzBhIiwiYXRfaGFzaCI6IkV5ZUtXbjhELWdZQlIxOWhpaEg2YXciLCJhY3IiOiIwIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyMSIsImVtYWlsIjoidXNlcjFAc29sby5pbyIsImdyb3VwIjoidXNlcnMifQ.nrwvo8F1jKjyQCED95gLYAvYi9TxRRDW6_Z8WC8c61WU1hHUMsHJG77G-CG0T8NwORG2cB7dlP3iu_M_e9BaONCsCZsUZUCpwV5w7ZsFxbbMy4jWSuQyd38kTnoFyMHQGxCXGI0VS02TqsAaO6oQIjwoC6Ib_6MKxsgYNrIGhp7FihO7D1rfBW-Ggvqx88INFSMCKWOft6xzYvBS6JQcDjLXMAkc4TOmTBFZkfXpepsKlDjFxW5DreaDZXv1zIUM-dG-1MRk_N5CPg_OWgnjiF4gKWTqCG8hJd__QPwo4RO7FqM5BM8o0u_lugNbgHlB-09GjO7NTZiZHiQB3HxWVw", - "Sec-Fetch-Dest": "document", - "Sec-Fetch-Mode": "navigate", - "Sec-Fetch-Site": "none", - "Sec-Fetch-User": "?1", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", - "X-Envoy-Expected-Rq-Timeout-Ms": "15000", - "X-User-Id": "http://172.18.1.2:8080/auth/realms/master;7d47b6bf-972b-48dc-b7b7-3e97cedc8635" - }, - "origin": "192.168.149.15", - "url": "https://172.18.1.1/get" +"args": {}, +"headers": { +[...] +"X-Envoy-Original-Path": "/not-secured/get", +"Jwt": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJMN3duMjIwNEVGbUVOanpTRkxzUl85SWVvT3BHQTdCYl9rbTZqRGo1OHVZIn0.eyJleHAiOjE2MjY5NTkxMDUsImlhdCI6MTYyNjk1OTA0NSwiYXV0aF90aW1lIjoxNjI2OTU3NjU5LCJqdGkiOiI4M2Y3MDM5MS1mNWUzLTRmM2QtYjEzNi05YzZiZjZmYjYxODUiLCJpc3MiOiJodHRwOi8vMzQuMTQxLjk5LjYyOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiYjdkN2VjNWEtNDQ0Mi00OTM5LTg4NDMtMGJkYjlhNWM1MTQyIiwic3ViIjoiOThlMTM3ZWYtNTM2YS00NTkwLWE2NDctNDU1MmZiMmU3OThhIiwidHlwIjoiSUQiLCJhenAiOiJiN2Q3ZWM1YS00NDQyLTQ5MzktODg0My0wYmRiOWE1YzUxNDIiLCJzZXNzaW9uX3N0YXRlIjoiODRlMDQzMjgtNjAyZC00MmRkLWJiMmMtOGFkYWUzODk5ZThlIiwiYXRfaGFzaCI6IlpiWGdIMGZjdlVfTWJibC16ZmFOTVEiLCJhY3IiOiIwIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyMSIsImVtYWlsIjoidXNlcjFAc29sby5pbyIsImdyb3VwIjoidXNlcnMifQ.auGfDKVg7ULeAVj5HVVNhoW-o-0jh3dzS4_ZOZC_YiP7tD5ku4ul9Ay8Qv9tERNKRyXSOegR43uAxE9fRXagqgbFplgUwQmF0bOUr-0tPukDT94_Qxf4OlL4znTEYWXWnSLPosTpSqvRZOrDq87OZv_KFcEVu97Bj04quMQVhOQMw1znv_jctKKZfBE32hDY7NkgJPWHRJ7etNPYrZmFVk2PYmycI_nwCFerm6zs7jEsiweLbnvUjVe8nNbjngoGsZyzfz3dV5nBWJ0ibkNY_Sea-hK691p_MCZn7IR5mCxkuXA93Vcw4olkAV45bACfRebBP9eUY_rojkBgYC843A" +}, +[...] } ``` -You can see that the `Jwt` header has been added to the request while the cookie header has been removed. +Also notice that there is no `cookie` header sent to the back-end anymore. + -### Inspect the JWT token claims +### Extract information from the JWT token -The JWT token contains a number of claims that we can use to drive RBAC decisions and potentially to provide other input to our upstream systems. +The JWT token contains a number of claims that you can use to drive RBAC decisions and potentially to provide other input to your upstream systems. In this case, let's take a closer look at the claims that the Keycloak-generated JWT provides us. Paste the text of the `Jwt` header into the `Encoded` block at [jwt.io](https://jwt.io), and it will show you the full set of claims available. ![JWT Claims](images/jwt-claims.png) -### Extract information from the JWT token - -JWKS is a set of public keys that can be used to verify the JWT tokens. +Let's obtain those claims. -First, we need to assign the value to a variable of the keycloak master realm. +First, you need to assign the value to a variable of the keycloak master realm. ```bash KEYCLOAK_MASTER_REALM_URL=http://$(kubectl get svc keycloak -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):8080/auth/realms/master ``` - -Now, we can update the Virtual Service to validate the token, extract claims from the token and create new headers based on these claims. +Now, you can update the resources to validate the token, extract claims from the token and create new headers based on these claims. ```bash kubectl apply -f - < Date: Thu, 22 Jul 2021 18:43:01 +0200 Subject: [PATCH 09/28] Fix typos --- gloo-edge/gloo-edge/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index ca1937687e..801758d31c 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1473,7 +1473,7 @@ spec: EOF ``` -With the **httbin** application, you can simulate that the server returns a 401 status code. Let's run it and see that calling `/status/401`, the returned body is what you expected +With the **httpbin** application, you can simulate that the server returns a 401 status code. Let's run it and see that calling `/status/401`, the returned body is what you expected ``` curl -v -k $(glooctl proxy url --port https)/not-secured/status/401 @@ -1598,7 +1598,7 @@ spec: EOF ``` -> With the **httbin** application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: +> With the **httpbin** application, calling `/get`, you can debug the request headers. since you are transforming it to add a new header, after running: ``` curl -k $(glooctl proxy url --port https)/not-secured/get -H "x-my-initial-header: Bearer this_is_my_token_for_test" From a134fdce179488190ef5d5f90f346382ef4330d2 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 11:15:52 +0200 Subject: [PATCH 10/28] Remove unnecessary RouteTable --- gloo-edge/gloo-edge/README.md | 521 +++------------------------------- 1 file changed, 33 insertions(+), 488 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 801758d31c..2b52a5c0d3 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -460,27 +460,6 @@ Now you can route to multiple Upstreams by updating the Virtual Service as follo ```bash kubectl apply -f - < Notice that the previous transformations have been commented out. The reason is that transformations in lower levels like at Route Table are prioritized to the more general ones like the one in the Virtual Service. +First, let's remove current transformations at the Route Table resource. + ```bash kubectl apply -f - < Date: Fri, 23 Jul 2021 11:19:48 +0200 Subject: [PATCH 11/28] Move note block below. https://github.com/solo-io/workshops/pull/69\#discussion_r675391779 --- gloo-edge/gloo-edge/README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 2b52a5c0d3..d359591e0e 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -616,12 +616,6 @@ Then, you need to configure it and create two users: - User2 credentials: `user2/password` Email: user2@example.com -> **Note:** One of the following commands retrieves a token which expires quite soon. If you get a *Not Authorized* error, please, re-run this command: - -``` -KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) -``` - Let's create the users: ```bash @@ -648,6 +642,15 @@ curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: appl curl -H "Authorization: Bearer ${KEYCLOAK_TOKEN}" -X POST -H "Content-Type: application/json" -d '{"username": "user2", "email": "user2@example.com", "enabled": true, "attributes": {"group": "users"}, "credentials": [{"type": "password", "value": "password", "temporary": false}]}' $KEYCLOAK_URL/admin/realms/master/users ``` +> **Note:** If you get a *Not Authorized* error, please, re-run this command and continue from the command started to fail: + +``` +KEYCLOAK_TOKEN=$(curl -d "client_id=admin-cli" -d "username=admin" -d "password=admin" -d "grant_type=password" "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token) +``` + + + + The architecture looks like this now: ![Bookinfo with OIDC](images/bookinfo-oidc.png) From e12a1e284e72ee27b27084d0df0409b1b279be81 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 11:21:06 +0200 Subject: [PATCH 12/28] Remove smecolons. https://github.com/solo-io/workshops/pull/69\#discussion_r675392906 --- gloo-edge/gloo-edge/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index d359591e0e..01d180c01f 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -743,7 +743,7 @@ On the other hand, if you refresh the web browser for the **bookinfo** applicati /opt/google/chrome/chrome $APP_URL/productpage ``` -If you use username: `user1`; and password: `password`; Gloo should redirect you back to the **bookinfo** application. +If you use username: `user1` and password: `password` Gloo should redirect you back to the **bookinfo** application. ![Keycloak Authentication Dialog](images/3.png) From f768f39e322bc5e56fda1e0135e136c184830833 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 11:24:15 +0200 Subject: [PATCH 13/28] Add accurate explanation of the task. https://github.com/solo-io/workshops/pull/69\#discussion_r675394762 --- gloo-edge/gloo-edge/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 01d180c01f..0b95d054da 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -832,9 +832,9 @@ To test rate limiting, refresh the browser until you see a 429 message. ``` -### Rate Limiting For Authenticated Users +### Different Rate Limiting For Authenticated And Anonymous Users -Now, let's change the Rate Limit to be only applied for Authenticated Users. But this time, you will apply the changes directly in the Virtual Service. This will affect all routes. +Following example of Rate Limit shows how you can specify different rate limiting for Authenticated users and for Anonymous users. First, let's delete the Rate Limit Configuration you have created before: From 190eefe20b57db8ba23bac33d017f020d74710f2 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 11:51:07 +0200 Subject: [PATCH 14/28] Remove public httpbin --- gloo-edge/gloo-edge/README.md | 207 ------------------------- gloo-edge/gloo-edge/images/httpbin.png | Bin 96042 -> 0 bytes 2 files changed, 207 deletions(-) delete mode 100644 gloo-edge/gloo-edge/images/httpbin.png diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 0b95d054da..31dbc9a52c 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -171,8 +171,6 @@ spec: EOF ``` -![Gloo Edge with Httpbin](images/httpbin.png) - To verify that the Upstream was created properly, run the following command: ```bash @@ -1247,163 +1245,6 @@ You can see the new `X-My-Final-Header` header only with the token: } ``` - -### Obtain a token from the cookie - -In the scenarios when you expose a website, like **bookinfo**, to secure the token (i.e. JWT token in OIDC), you wrap the token within the cookie. - -In this step, you will obtain a token from the cookie. - -For the purpose of the demo, you will apply this transformation in the general location. That means that the transformation will be applied for all the routes. In your case, the applications you have deployed. - -> Notice that the previous transformations have been commented out. The reason is that transformations in lower levels like at Route Table are prioritized to the more general ones like the one in the Virtual Service. - -First, let's remove current transformations at the Route Table resource. - -```bash -kubectl apply -f - <&PyZB1`sNvageU7-OPEWvh^7EXls_gc(GUJ=<7@ z8B2C!#yS`?&eQ9CKIgp8=gs$g|A6z0o7>!YJ|A;kkL!BeANTwHy58$(sWF{qKTShJ z!}R#keO($FIsy&NasE>$flso%a~o)AcxWEqSJ8)9E|1fDUohBjS*8E{ktU7A$C>fr zrGDlI9?cKlCq898I`{G0MiI{g*+;A=RCE%F*S}pCq@@+4RVP?vyg7erQo--VkgG3f zMAG=TU-wRG!!owUYfhrvzsG;Jo51%SM&42=z4nrZ_7u-yKhB2HPPar14wu^4l(udU z8qhY8w|#!xH9K)undaDk{+Li|B# zhSHwc=DPRB=^=#MM`G*H_Z`IW?i=v5fyPsW^w|e4{~6N1!VGpieRcxMtOg;}TogWc z)U%%7QhrIe!ZV3-(5kq1*!TPAeZ0qL_kLevAlv|bqdO{i<=c$FK%7yBaCd;NjvqO` z5I*3A*!M(iIrN?3;WGftiU$wySM0GwMP_&D+WSYvMKpg&gB$rk#IBP=za0Ino5Y+G z+nE}1edt2W)T7A;cLu_AQvC5lXa680AlE1G$AXG2Q5)?-#g0Eh=-4If!}+r>;H6)a zdb4cQjvVpfOGGpc9E0;UBT|&ctk@H|ml*IWavP^oW&5=>ZpOP=2!F5&;#%jXKY}?LH5Cm#yH;9sBS#>1ppb z;iK}V@i-eq=NL8Vu9rcbFaB1tm5$EG(F&(RLIdtXCgr-z69{+0S=^1omg>Q0^4`JU znTgQN#Y{_7fErmI=bv3{-;=_Lr!*5DLAYIFyk8#~dmOFD#R;YTKm%dZ3YivF!oY%$ zu-TS>I9ZJIEVlLZjpQR!ME+Fp_fy27LbL3tUm8E#i9$w2UlpL#a1X23Br(2><3|oQ zy}((-v7jo~kqVpEZetEAke2#Yu2(4QJxXGW(L}|Efy?1X#Y?<%;v2^VVsy)>*m5xZ zibR2RoT!ynM_h6Epx$ta^{bOi>^Z=+-LJE1B0Kh%-Z*l^n=ic6dWoxW(qrO~Hs@8p zP0FBLkYyqr@^HgZV5Ed+hA&{915|xFTU{(-OYAefc$sORx9rQR&~vLHF(a1PiyKIj5|5MJQ=D zknc(S*V!(!p9{Ik3ebmmOm#o7c;#i8CsAroB#+#vi1x>{kMAYR`3bt9UE8Dis|}=E zU76S=|7P*HDwaXouxeS$wXuL%2*NeL-ezJDxem{_kKt3HZ?Mp5)Xu)$52(1lT(deFJ# z`a}h&Zw#3i86|#2?#LYb=ONS|uR>$w{XOwml-cGY%2qU4uh>#yrVC+&3fPRS)I&)4 zrR;7kTr8vl)!kB| zgSeiMXCM|^HMrA}8ur%0`u)i}J30EfedxK?sMJ62S^1xjza=W7A1@re=rDBG8Ht!m z7obiVDpd6IAmNT1SC1@F6V|7{GZMLdUx1&SB5=j-J?ykh8}WCsEaw zu$DJRjzcA_2j>JZ_xMbQXQ$)?gDLb;&V+hZS&y}(B1=YHM@Pr-ld*TK@9}D1%5gQ3 z$azK`Ymehs3*WVIIP}e2S<2=ow_lT3*4sT@PayRtI!73Hck5DpmVYkDa9VG3~Og`23n@3s%!_?5wh?eGUtE7=Z@t+Diwe2Z-Kb#Od7` zJ#2s=$;##@wxcW{N}d}RERfq#&A&8K6$^Ja0-Kjaa;neFw-36o%RUe3f6*QXeaK{) zcW&BxMd^jHSrsJ@1z$1xLA#^Bn~)u=WL0#Tq(NUQ`pkZ;XUBHuIOB?&!!z2wAyc%& z$)IH`-GIX&F+`cRlygGKcM>*zDcO6H5XKyL!z=5IsSJ4Pc2oeUFF z3-7$xn`sfQHNW>J%(<^DT8~>pF(Gebq3>r7*f$auypvk=VO{s`%0oBx`3h%4(3bWG zu0xmm!Aq|IbExz+Y_==(eFrgUfz3tIrzJ4EpYW&XO`_EGoXsq9Q%r}++OOJB*$h4= zXC1}4G|OYmk%y$kS-s%lgXBv0=haG*FU&W3wG5r>KD>bcjyv&xZn%aB8xOA3-QabmtAFIf~nrD)3 zDlRci7-Q%i!nvV~>!{w2Mkr_hiz4ybK|%GqP90j5693Ru&m=JKp?#*8}+GtLI)6qs;fkB5DK5ja3jlC=3G zVpX%~&EE4xpolH+%g}h8-^}#1&0sUPyz>W?#g6zdyC(9-I=|REDzpi^n>Q5W(p>E@H&Ny`IR~QkS^p{1+t)E4S@=XCs%60rio40K)5G!DCoqcWjd>k$C z_65(hQEA~Np;lHCsi{{Bc^l>e33uQvNxx)$W<#WsE=9Nq!LdnbhsU39_6lh(Iqxho zX_c>QVsv@Ka(p+{cW24MyVO>zB(2sH`xNZT*|_Y-xI>qy{GH(V6TlMf{r~3%WEG`yp2d%S^EuxR>TP;+t~NdbwsNQBL+&_r{dS{ z+6!&ix=T43>w(1CJsb=6R!w-MkB&`<%Eo%302q9|@ z=6TAl>iLP1L!7-i zv`mFWhSx$NIg)28KpoHU#kApk7{%i4{s~qFZkt zYE@h4%R*xtn4MSW_TP~Bz7q!O6Z*0>Zs?i8=fF^l$cO}zSiR=LVW6pzk?tGoL~9ta z{zckeqNIC{lvz;k=Zl8h96=J-wwLf`dFU_$^OKoblr7FW$)LX5$%n)>h{$)Hz^?U{++{$|x-nHhh{`qDpwK^zW(PZOI zM`^66nJx;7Ec)9PT_ayrN33^BuXP^E%C+w_&Dq55&Ff6#ylp!d8}u!TE8VBiuFcg- z&Ogb~Ns)5IarZp)(xm3OqS3_A>%Tr+s-RteuQ%&V?zRx=NgLLCGm!2gXV;N9Vq>Mv zp7=6wC$G3-v13z&z=2Rj)eahDqu1NxuO(yLHF)oI*LOPW{+Ote~A| zm)Upoi>boA@csLy8zXUo`aIR{W8X79GgA$-!WSx>@qU83w^BDL8zW(ZnKq0<14@wX z@64Qc)28{g7JdrM;m%1B(gW{~96JQ~Pn&6#)~@2Rtt(&DM7Dl~t+Icmy+0p) zs`blVy^|4KJ4I3&3VX96NO-3IaZb4)bwtn@yEQIrS-U|od4}*ji!_AW`}!%JUk}*!j?*vlX4qU%YQLdm#6tJYySGVFn&nKV4~{%{EUNC#P;+ODUuBJF zRqPYfx)rmCD@x5yp!JuwT_60ndb&91708h<0zOWy((n%ET4*ZNR(Os6>U_6v6SZEG z^*C8qlLM{)cEhP)gxY`~&5m_x_>}Moj9uLJ949&J%=zall{@0GN-WMJ?VDSK(5RH6 zYXo0k$gAhL;2WmfBXL?bw{&k6FAnCh$M&Zk&a6a*E9=u9>_=*w?UnGtghWuT0}lVM za<8Xf_enUO6Xf*85WeFRLn7Tof+mZy%ZoKJys1xo1Y4&?kWuX~J7NXW&Z!2-;m`LI z6$R%UnB7N3E$`fIvGb;m`sskZ@oX1qp_mk~j}D$K`M9G|w>=USfGoOpqoq#%i$I$M zeCxzgosdy+E`DKd#y&fW_+mB%~ zzVDd&i z)K|)yoesl_jfg?3I-Lg#+@I7wJDg(RVmPJ^%n2KIsF?IEr87>$-dab318boy=jq5D zD{L`V`{&xVYr7unzT(k(=zsK(7ryXJW!qjqQ({p`RZ#KZNCgLGHeb?wfO7$=KRcxOo7s zC$6`7E*)!mHP(5rvbeGUJlNr&df0Z(qj>86rHR&jBDQKf7vDrrkE^mb=9cyBT(Ep0 zr8+LT>)4%*{#HE+GAi$GuCDQz&T<}v4?0Maq=Ehulnq!VKeXzNR?X~`)??r9-F<2GY_9XL3LKD@%^$jUYF$h;J*Vfb1 zgC#{F;Jq)eaeu$sTD^2hZooLI6TO8JV9=`z;)rvfJ=T$5Ea^G#huOjnWaDndjU&!K zSm@7O{XK&IeLK+{X?zaoMGUiKBm95I2pXKGqod2!YOd016?38WcEpTLdX<-W7W=8m zR8okqeh8XoC}&*A3heH?xWsMz5*$K)xM}&-Tr0!q?a9NIN)+ONgF-S8G}}I|Bqulb zY;s6D4a5s*4UJhq!Dk3vu6`0r3VYHX?dHN(Gv>`>uTgv(m2T(WkQnDQV@#H%m+dbJ zyA3Zh#f4>QCEOVcz%*944Of>|p-PCHp0?8Kr`=vp(CJjE;JOs&<^ z(?bN!l#QTi3n!~537UN%9A$oE2T@#&?$~q*`0E@{mQ2Zc%x5KbEm&P%_e|^n6ra8|P zv%~848?Ako_agh}>|1IQ7C3{}TZoE#u6~$!IIhwNyjg1{s<3SMKOqw329OE~y-I$w z#&Jrg{5FR)-?Qm0{;K-*5CT>oM1sb4*b{6vxaA)zQIO+K;i;Vz9RSCLuSNL}tuzc2 z&hcbZuIHsU_+Y?`a*h65un0E6T0HhmRl&xO6HoK#>2LsolUqp!bbppW#8V7pY2TWa;7>DJvwgXHwn9+ zR#R6?oa|r%z8xV?G8~`LqM0~Twi4*w4E38EM7hWf78-QT;NG(GYv&ta$UY0r?z~}a zgYi!(%iJ|y(n}Wut6n%~!2QNzHFt6CJEu<(s|mR3{abF78BjJ=F^T-)Y41fCoSE#H)fX_PEqlg`nNMFl{>&ZWgBVxsD4W!aM`0k}>3 z#P`uBx$Jsne0%7Mrxrf0LrqkVgHp5+E}$~)4AlW9U~{V29F-LiF?yFtH1OHV%C*PI zqk{wKVe8aMIpn1a8AEan`TY*v4|aN5UyHrk(C-a-ijCqtEbY%KPy9GN{7->L{8H{} z$}g%?Q$T{|D%=NYcgXynvI>4P<{#LE3Q7qqCDndxf@~r&R?#g?J_}U=T_+lPN;M+IdaQPfcYQlqG@-Q|+nI@Q??-@W%k;CE!a%#Ms;?*);BWuiNVUk)S zslTVZr(LQ3b-Ok3oK~5-cN3Jys%jVsT^x*7w^KyQe>-k>SrqO7a1IT$52YaZKoeP0 z$$jvv^>k7<=-W$5Xlj*7aKLt6Tlf{->(UV~0~?kT{x2*zGr@lo;OsDiI6Jx3=`JMQ|(J>62?756LVvMHWaGvfsrk z+5SA?Hn!nap=wt?O;6Y~dY>I8v*EEmD?C^*G&%#x)@IM#+wmM}fC9mm&xz!ik-p;1oz!K%(=XFY?!qHt7U9TAIe zjM){VT$KwlwSt$o&1hPOP-8pn|bMK@634R>EF(e5r}qK5^ZoMq|%#jQFQTa z8-{GH^p~;cv2|vcX8>RbC<+t^UEjg&MzAaRCU$s9vOH2((CbW`sV6jEa~rGpWhbXc z!VT=R)cx|Fr4%Vq^{cDtAS7+?$PNh{3Fc3;ecmZ2zyYJ&l#A5c!VfO-I{HHAo( z5wX!hnh5RLpq$$Y`v@m@#q}>lYI#q?fFv9EN&E!%#I`kP{q0W-EYxKVT&JMm6Y4u# z3&4Dnw$BvO$q=Wr0QQ%WF_v1a`hbpaj}vxMIMbeR!>nSHz$RF+05dW5x)hudQ z)Sr>-l`hYRVP1ELspd}X5mG@b`+Od>smRE;<(+iggK=}wAkmUovN3aej_+!r3^ z@I8ne>S zm_7Nvrzk-~G`av8I43BYSqoQ#c;`7FP=e^-F6v*W#>xF zcAO|Hk}f~H;8Mt8#@I3{ZDi-wNs`D$X3ylKop#!NM3xq+-A8nomWI5IA4xBZiSEIk zW)Vuv%3DNpRWY;TnWkAm8}I9J6@yNfY8gT}q;qoFtaAQtX;D_lUF@=b{whO1D0OlJ z>mbhinT7b5EiV90I4N>}VXy6gm7sW)Q(BDXQq0BIiT@IR2*lWvf7&~ z>rT3R0KN*?7X&`j3##sV0|>`&6lVb8u3y#wNG{I10p@49-?C{jC-bBLBPETBBF`U3eAf#MlrZJ4OXs`P{s!(e4b>E1yY~7S$KfF%fe+=wA>gFufVw05SO}MdI>iX(= zVdITA&67(5MOj=HqYq?mvSNpFFzva(3({khQkQD?SeCBd6*>HYGN;dCmG1eSn55kB zE`9Eiv(6S&RI{$+HQ#$XQqE)SZ1vJ*^O^unLPSEIFveFl!uDU}n#b+Pk41;WA)YEa zKo~ZYWF`Y}M%7$&C7`t!K98?&PJS4F{lV$M{B@+~EacvMR{GxselK>~4e-M?8i?xU z7yb{069W?`d~{F^&2IQ-Sh;Fk}jogZrtyrtpu1t>#jeC zce^yl2y8q^64k|)``SN4HuWqgTPt<&8?R7>@3=2cHpxjx|9E4G+VQ)VO(47yu_vIb-+2;kzji z9;Bhsh7DW1ZyzmUQTx1Yt}R)WH$`NMV)Ua!ZF^+SD$k>Nl*KjX$B!So&dq#4ha}u& zV_6^g02qJ0w2&RH;o;{2Ux7_4N2_q|27b2jNBZavhTE_XV8WeyD=ag}e~t*Bi#xbg z1eq%7Q&j8i%$g}AY5NnBsTHd`6jHRbGG3Rbm!J6IqVVNR#pmU#L=s;v94E3RVpOoJ z{vhmvPEnG!do)E6*x1G|2e`SfYf?PwCwwMj#V-TXNLa8z`y_yBQ{c=j$qzLA1Bhx zOG>82j-TSjl2%r00gq5YX#zb<7h<3~#7n!G3?;2RSQxv`NC1IHt^w?_2+s4nukfRe zFU1A``K3^`A&De?R~2=VvDvyen7e}%cW6JGc@E$<--jLA6Q7d51f-YNB*kKLSwf#x z@vTQ$eRe^{ zm8sKpUpzAf9sEkoduxm?_O_*drDef&)-q93+ZDP@5i*jc>@AtSj5J z^$p7UPQ?Vm&I|JJDC0*ZV;dS8DwnG84FY$ZbltFJ7H})1ZEV>Bx+dZ?-N|h*?U{Kex(%zM@n>(k zX4=10j9S)v8UWg5H5GFLZ3QcTY+(s@Q#c_LG*vO%ZS@T(TxtRR_b*`^%=aG%$z#{& zf(~|d0u#J-u|GP2)IhCQo9niCr+WqAu0Wq_5?w2(m-pJ|sst;pld2u_yJwfwqG=X$ z+e9}`f}r^a70@-L1^jZEI^BaAEY#!J+1{Q97!+XLlL9tlTMQw%a?%|XXo@rQQOc97 zjqdHoofrm{q2i@Cc^9vv zsFNH3Y)uG1oCtvY1uDxv6G1b1n*#)1_>*R1TDmI)fazC#S&!{3CIG~ohAV3tVP&Zv{lLiU~&e%UoTJK$W^_Q*^ZO^h3nF0-pynVkh@7a(G3&7 z+FuwzDQchXOx{lbQl=f1_aQK*T3ym%*;x_qll56hW%0_1RPs5glYJ8b)?+6 zrQi*qU^M{JrcJ}+CnelL=&F1<$B93s?6M`<6d{Re%f8zs@8jPs&QjDkUjE9L@zT;Y>~-O*TWl6r1Tuo>#Dlwfmck$Y)oErL~*LL>nJc zm=w#C-OUBp*vV42$!7A;W5>2Y;!RuSP?Dl1qEcB@AEs63yPr9$xj3S+7w-!gJ$sYr zG}2KeB0&A$_xr+n=yKy}2ev(tCMfF{biSDd&`(y;da~X^bQxA7!*VTB`C<+B6>Q$_ zH~q!S`I<;!Iiw2QVlBj^#?2}n9UE@(nOAppM$M}y5bM>3e9^bP^zyQ`_n)#$RYX-5 z3nM{x(8#L_Y1&F=nSRg)C!e{;ko}?hSG#k47h{FI8csy=n{AIQPaa=Q1_=KhMtI%r zU#x&-gCTlOrt3ZkAUtxD;uiI*-@X86BWv!n(8Qev_vi0D#CO3s1{{h2Ji*tGO2CdF}gVM*Aq1tVMja?C9|+paU}to4+Km zmvIqWz3@j*Tgl>QQ26Zx@f-kYY{9jYq_yEId^sZvw7!5jo_rVDUHhd<>P+WU^X$4VFQNF&Szj|i zE6`8*{CM`*pAr?YoIHeh+3NfxOuxeMP#D-aeN7oc_~CQrbZy#eMTRl75Xjo=ck)?Y z?Uc@35bJ3x6nn-6fzKvCO0p3QSzWZ>+oE~B65H@j+(n}atMMh{IGhsS`1dgqV8LD^ zk@TKD``S+e(5uOhpbrN{zF&>XpGJr=bMB-C_z)ZmJ)RXI1kx)U+tfD+m|p?J5;t-&0Oo=!LV;T6 zChL1B;W_c?B4oJiLk+7K2p+Z}7c+thgvZd=@EBlE%x!tMKGRBcs~5K3YlNH>ED z5kdP@YG|Qs&{T|pcpI|jDaw>C)RdBvG?&)gTF|FqFXypV5#YNt(dK@H4K%p*{zNGw zfjfF>Z8-I*|IpBi z0d+d6=9fe~jvv(+(9o6&0_{b9lK0!Ax{H^}od?~Z`y-bBk6`lv?zh0R@5<5d z`G14*?{oJ*2mAjG%Atb-x!p_#Wb*c*A+=n+%LyC&UU%i5VI_U$ z>{KY*Z#+PL%ns{Xsgp9z?>Gop*IQH@&ya0VwNv>!`D%-f*9>QxMmj%sr}t7 zGZ^aIc|%Qm{uP5n1*zxwme^mwu*ax8C`oOhj-fTd2zfXGOTj6Vu&M=T zYwXHTq8qw81J}1g7^dlw{hB>rpbz=H$IIM8XN8Tkq8uWISVxk$W#hLfWM6|f4jLxq zdDVomOn_HL$A6;em)(C_y#FHtfIV0Gvkd?~wuaLsj_Y`=#2hQ&=S}XUZ296QP3vv# zUrP|(0AuVrznR2J#7v?O&JkZrsPJ64%^RgwPQ=Zx0fm7+$BNLco-CXB(tj8>(gH*JY41UX|jI?&TEBVhR0YtOG`@O(TK-t|iUE(vmwIYbL0^r9N zSSeao3oyhCX6kXo9jjTu0WF`kcHqih<}RKz?v8tSCwN1GH$^x95)&uVoHN^Un%Q}z zAjPuCs=p0wLFN-3Dx;r*N*|^^qfzB@UPE@#qRh23X3Zwm%3yR#Rv|8 zYLCYUaVzBmZrXd-LG z73HY(Gbbv*!n>`$f3?2B?=(|pBBJ4ORR*HZiCs=VaH7@A-vyX*j|BAf zk{bC9d!vF+_3|GYxKvd##B2U`x%YcYn+?4dyR@+chHm`&ddEc8PJ@ktj)GvnG^#ypq$+ZOnyM+2lRe2pp@B%7fXV_0+vfBB5^ffH@7LEG{6ox z#5NEBVGY8dpsBSRS98QOKe%*MC9`k4gA9s{MVh#a^NB&5iA?MObtnv|Dn3QP995!C z9s6rbD=izB{lhkGsbgpa%enDlocmaTb-JSdO47*S_RMJQ#j6E?Y0jXk;0m7f18CjQ ze?D>N0Y?l3t!gvsF%>3OFbawi@va0WnPa4Sz~*q>+@`--#uYPG4{I$%*+6VajiLI1|uT9bNNX{*vF}elGUA1;8}TjDk0Jvitu6 zX9c<{iY*!ZazLQXB__^Mk%q{xWi~q8=yLL`ycugo*f@!N!b7nM#%ZytN0r&uvKPwK*?3P zCKT#Etip|^HLDeZG@JHQA|BLML=*IZSu9ZnJCVtLKnCR} z=M$-^VR4dyFGQhAg`@SEi-Ur>5BdYp4wDXW1d;mleLuTWz*iWz+1J|L^^sbCp-qY#o-dj=Mab+PZ`AVEgprl2uBw)$U0etd>SEAKMRMFH|t;XP6!}sjVdkzc< zxegypB!(kYt3g)fSjQ4KKIQr#%G*}JuGD&mg-(&;nrYu{d9(akK|+mNQ-E1b?C&Nr zpeUH}2DnPpcP&HKPyS@=G5WL1gxHw;d)IVx$5rSZGmsomuP6I7a7r1)FZ7MO8w3QrMtfqnZTGQJ0F4bF;1%?ZS5biHGA(F_TXe# zl%hp#`)NH*6jX10+yDY!vM+%dA{TJ4Nq~K=ihc?3sS|_uXH%>5aT8)_+RPu-U`#Vq zFMWR}vCE*)nJ)W|q7^o2D{^YdyGg?o~U%W z`u)M6(ma$4t6@(9DM105D&v!47%1IOg>4hD$r!-jZhQ@X-zI84WygO>3nfQ{yX!ra?fHqRm%XAV<@g1Uv1wmp72a**&Zs> zTdd6%`X;aI)nz^LFs4H#NqPa|@M{tQcE=#=YU{^i3d=!!%dR6?2!qcz_U;u-eljYe zsA?W5NEHKT5Q+GEYa% zKZINWPApJ^Ra+N-w)H1Uxm8GUj1NdyRa2pH<^7uE7Gc?3@7(8$BZaRh8=8+}Y=a*c z60tD_{*^Fo7mHWscT-D7hn@dmoUv-Y;Uz`(Th+Ngo=-ay^R@wyVZx|#Zb z|89BwwrN?DX$9KV+GRCVK?@kem|>^Uyf8t-TZJph7*iI0c4_?l20FM7%Ck&y#&U^C z5t>Ebx-kB9(DJwPU;kUe1Rj5obzeVa?Cy1ZhXDkOxb-@+x+?(0dk=7YO}=>31h6!)a=n`J$D z{OGquLcmT(y|In340O{}rvPw=8dm4Nrvk1kZ~UmwW`JKto}pmANb;!68&cIB^ng;a zep*3Dh`S>$SoJ_cX&O2Mnj;>#N_(}}X?_`=ZoRaN4l4byh%PF+`Iy#Ly*Hi*8)H=3 z^@xC;ky4=OU(5HcGm#uHH2n1%3zS%O`+an=WL481fMz}c-;0rOL-ygp!Ip(qH^YRK zo9~ZTz~;Eo1z^@^N`U5{)n)!HcJ+$Fq6OVH+019R**ziz( zH#@1NK~#FBvd4DUU`VAEeErqK$dub=jqc6^gc0b03}*mzK=Xi?M;5kQuzBg;ebN$8 z)Jp&&k=i=2p$(iLeH)SJ7&|V;cnkqL?Yg@z__{Km#i+jXnmXG|=O+W<#DVgaR=`5{d#JT%vE%kT zx1uz4Ba0DuB(~1E1KF57707R(#taiSL?tAJ(^_ zRs#dCds1(k7BS(djuE(UlxxEI02E9EaE+E@jf!Lkj(-1S5rN1jfdMnwD*70G5+q&Nf`< zYep$dBmu^x8{T1#%hrU8>t739qEyf!o%Rwz7lmS;qGUyl87Yav zW%W-WxHA9a*=3+vE+@d+pU;8``90gvypQe->7UhPSa0l>ej5aZyvrFW3>^a|+5;m4=%t4)*w7g2akRl%Ore9m}$zT+Q~UIx!0 zO#}rOYd5{-;%q)qo5hDrSmnGNf77t_uUm2g56N;~LFf;tyt&yO@LAMCK?4Cxjh#p( z=t_tJvbwS^a3&8>7%D`imlpTNIGY2DpkOdLqWv(bXhXIy7%FwezTeve&ehYqjC<9>E=R2PhpR`%raLbcee zeHWFXSn&s**&>}3zv&j?B`R@~0$#OV=ivdQrP83TbSU$3=>Oi+{?~8B?bAQWM8zVJ z!u*k451)co6yUU{Ob208Qd09x)>BqA?wtOiUwt-Z0sz{yI3t<1(~|Ec*?tJ#?2^ihjjc#NR_9jm>&3%8PTO&~kKaZf?B zTF8a1Zvuy|%~Ozann@JMinHZN_WZ2qfmdn9ZZ6|+FB9NrL7KcIViCp6HisV0IWWAu ziv#3>)wMFOz9T7k>}^2*=`spE`ZBJc8o(ey{73FO9X^PF2nq&F!KB&z=HWwyz5|tX zDia|3k;vsF$-@T(@P&c^-59z)Xni>DJK%d)bpdI^($ZIp{V;TK@L3}Q7&X++;vMOu zVhx5In6^bl<@h81SN{Arsbr!H7&UC5&t;CIVpT?70F;`zxa8=ENBD})0=M7*_f*u& zh98QA4r1l8Jdj~JI=UYp*5drbZ~y;K6Vh@90q|~Os=*z5`+$?jzlyc+pUIfI&jXw` z2ChAM`tAPvg8iQVOt`3O8ep-&VCgVlzLEz2b-pxM1>MNGgY@Az#yZ8Xl@w2-S;_#80ni5im@$HjiY9zA;J$Mm81pRkQ-0UFovt%bu^9oe8o;86qxOl!4H#+rn^qW|57`LZH@cG?wy?eOfr*&+C z<4jsSsrN}Sjr_j58FAa!UJ#1BNxrl@+c>?D*HJ5XF+s-}U<83QtFhEj54qKd)X%m^ zHX%6cb#{+=&V{Ym*Xl9X2V_BHDd_J8zjePS3^#Evp`SwNlON@*%fVvtJ929p?EX+c z&huC`b_pZ^<2hh!K7G`RDssem`HS0xP|XDZ-rDYzxIO`pt(!L1?jh zi|Xy**Q8V!H4{KkUqAl}bMDLu`hXV$d_1DXN%tPqjp?tPthTX*`lm)24rvvIxPf!; z;}Bwt9aZbO1j>e6ow9<&#M>0ti&uqUeeWG;hqU?i=iLNMB6Z^A#%ew(4{6`jpI}W} z)4YoMBVK0n`t2j5sO?)GyE;4B??%OfC_JUUJ*RXEV~t{KCoFojcCS^5&p9<&c@3#kCLv?a_7w6S?NGGN0lJzJRUkcgW8{ToQwY%u#+u> z_UAU9Di)?h=S;=$D6BSdR$C(Js4r25=@c<_T!ti|!e@9Tx+JOTKs^QXM*rj|o~`o36c zQ|2~=z^Cus!&81+!MmACnz{nJLSnN$UQ{>;SdGr5i`vK`ar4<=3~%wgz#3Xe0X%_ab4Dlc@hgNhQ%b{H`9#E%1(3aqo`{O0}Vr1-;eSU zAqLJwrk$H>%TF|Kxi(Fz@gl80f?_*fQdL4p)gruqqQ;{I{fl&B+2{948pmZ6>IAJ# z$D_X(Jx;sezmnIkrh;Zmc}uElkUIBfPwa|=KF~7Fs&=q0Bm{wCvL0=4p9j1eJIv4N z|6_p&1h7N_~%_(2RW44@pr_;TOzYEz_ltZv4m zqNl3Rd<_7d&CMdCZ|;cdOQqHz{2L|*m6LbcdJ^%_xn0VdGA|C5M(ZZeV%<#JB7+36 zIyM^!l+k_X>OuPThUQz93OqR9uPZ3F(%fA7kX)=IN#2J&f9b2K?mEuM7d|F^^L^); z?b`i1CB~g)dv4gcY>l{*pW2SuNi!AdFN^xT^4UDyS+6sqUANtFFHfi&jg{Wivu(XI zN&Wm;Aok`og=Xg`=)L#+`h7u#jklX0+oFZrfdeI$pDN$alCD*s{~zqVcT`hr_b$3E z*if;8f`APX5ZFo+5U@}b1e6kxP(-AcNG~C4Xqk2rY>Mg3>|@fdmqf zUP7n|5R%-*SI_5$-#!1_anCs8`$I>f$;!LlHQO_vIp;gxby`XTKu78g_{&}lV*ys6 z!#ayZeV_#Y!3x&ndRO5lzf)OyW0T2!?x_UPxGKvV6l<~Al~TgzN)^41|;f$lEj zqn-2SQ;I<6YnDN>?v^bt{C*A}N1%XdEf}$r+R6)I^JT%S4@T59)={3Juq&OC)p(Uo zEj5-Wq4KQcL1;0Pcb;vp1rikWl%tBP_Anr}w?8;Knn*kJ9njEXB$-=KpJr4}(wG%q zrFq7lO>t{VG`m2EM3Iw|xb6FIA3b8EUOi|^Oj%=w70;aT_d-~*lK0%?*yZsbuIF6T zcp*14|Hk;UhGUqVw((L$-sjsNnSG@4S?bd&EnKSEm&C)lwNWIvqHnIbB$RhL-2H?_ z?5ZW?;FYBwLq}w2cy`6^i=>(a>lN^Jnb{Wy=xJ%%&f!dS8pkz4}mZ94K zzbvonAyT0zycl1;|K_J>TGqw2i{j9;=r(jmdGnr|{sd{elKIGC(DwtTYW3xP`eN_H zNmkzGdHfuqX&^1~Bzu`^RV*%4-#YS6 z)r=5>_d+(`pOGvbeWIEU7CJ0#5UDOb*JcRxlt_}MdwGW@V)M3uRFgGIw-x}dE}A0U zx$@Rz1W(g@${N#fwJCkLr!wtxReH;lvdMYfi1gu!#ZGe-JzM-Q;lC~fcUFgS4Y{`Qw zmkkvb-nK-Sw(;-1qQb2j=4E7l&EnogSOW!#tP%_m5egt{cz?OwJNpT zS>@h1cbLk~smi%MGBZ9dJVxvI4q02IY;TOpl%Q1>z8>LLH)gCtfk|J(7KS2!vAH(u zHdp0T_3k`RN`Y$zT-}0sK8lrulE^J-n!1%fnjZn?{XEb@6bP2zEG4kji@2%#utz%?878fOppdo*Ri6&dRzIpV2IN~@+Gxv zl82?8Qz@5TT}|u#;fzKV4<{W>OIs!zi>UKiMJYPoje7_@FM3lKO2)JJK-8=z$pC{M zL|=7(8@Tk9lz^+}e4vxOU!b8@f0US2IYfHu;ch=f=T)xdcOJpHN3zm~jU6MSEcUOS zhkZYg1(U8R|JZp*P%qXnO z%4cfDgc}96JF47#o|?OB$EQD@e|Y*h(x2#V2k0+~wBJMj?w!5b(?;6Yr`rsCtA<#i zq@pO*s4j(_@87e+#KZ?vuq4|lG;_Am8MRV)#nFq-KU?6T7d0U5x4f6ezmu=nvlYCEey1tg`Nqt4g7Z1gBIa5)#&jJ?BjJEj)fT?F0#E+t29%a;c?d_Cl? zsA?Jm(cWXG21_flQu!C+W8O`OL}3%28{`FSS%%0{_|r|Wety|dSD)ETe|uD>-RRj# z>_S(+Qj`(FB1eOS!a=6R0toWr`aRzWK8szxFJ^R_NwJcZiRT>fU`l49Xv82E)?7PE zn0zM?`sr$(XsA5Q_Bb73;Uyn1{q^ZUUCc+waOFvCvFbvtQ?*m_N9Jn-JT@*@b|<_t z(ZDcRQ+B(Y?ZKf2r)L8_Sih#;Po4A|gORMBx5u5lO!FAdXDhkU)_)F-VvEO0gLDd@ zUmobOc1z4SCa;jkm><|MUnltw9^%{7aTO|kFxwgkxR)S2m6N*AI(!yhu%wX@j)VWO zmF{(J&_qQfSCUKD9x^=qweo;rt2l0?u|pbPc!QcGw8QyhHSsG(=y-tN0KOkqE;8l( zA!ntb9yAqo4;Rd`y-8%Lstp&1`VZi*BN7`XSR~j|a!=^N94(q*?+2rB2Z9luaB>iK zgC{-rm&8G>-O1B+?9Z;n^Oq?Q44Qq{MuvgB(wb$_jh*KLeH8u@&iV!h{>vRh)*`mE zqCv6bK@OM^nmOfF)0O%_!sF-9pVr4uRL6>vANFh1h;>_Nt#WBP6R5a4 z++(5K__&C`O`Y88uU@dX35OAs&a&xJ-jP}v_?CZ56h0mCbkU6{m+XL;)vEX%+3?Z> zLM#_LhkvA<&ELIKBY6xZ@WC$@+$IkM&2M68N_^SPiO>Ls5m;V zi_Sxdyy*fgD0uB+Xjs^jmMXb+1Zf|h@ZCR)-FiQ;z-(R`9z*}$r~!!#Rp;4&eb8yX&heYmU)!Cq)P`~ zN^SVfR)4z1%oUL&1$mGC7p4|lw%n5@#CCim_?q1tm5J(VUvOnD;jnkqTgqv{_N9Ep zomA5wC+H&E1s_0{)h&We6lb;Ywk&nDju;G32d9%+JP zV@S=7P8C9@^{yl{Y~OAd)58Cm%aXrI`5|&VIyfY&Fzg*XH&)I75$Hh44k9<#!n|f- z=cZSRuv)7F=DD)5=iPh8zKwnv%?Q|?-jJ3`Cdd!M9MWCFevRO+2Jve@41&nCqAEs} zIm-(uZk(#JVZd$I$}D%pg4QF88IWh6yY6EWr^ya|ap9Zz#n49?#-6Z2Y~aVp~n=jhl2dmd$juw?aCV`kC$*Ca{mdu*`o0M2-;^K^Fzy6{nl8MAFBneX~O^j2hl_p$} z5?=NWy5wZEDAOe4!9deEd8{GFyjqxxRw1`=q>SWGyqy4@XB&J_d~~KX#NY23TUVDC zwE$nRsS)I;^uf=}_m7=`Pt^K??{O)J-GxUw`#-){QWo=cxnNis#n)`7@sod&o_r*g zd7h*aA3uP(lvF)Woq7egRCTjWiz|hF!Lu&(5J?;_DL;u!H)u~ncya;Q*~XV6 zdcQJ-k5~u6dB=1gyjIRSCLH4}ZMXg5hd@Bl7 zn*JGxp?2~wb~xsh{Km*t4K4&>;7`4;4OJb*6?;!vJZzLO*quk@!dW1n`X)@-@NDf} zR0E8zT+^vx8~kqm@v+wNWbC!Rl+mZbvJ=kq_PLzC7pp&hCegxNa&4e*6xbgwEU6*1 zt5e3Hw~AL^1+{9Nt0OWob5L5^G4%OHftf0(J5`MLGaniECbw;8u+S@+I_B zY*iblM!!4gR!EphAF&ng-XA(85{sFqHsO0U`9Wj-@E4T?Ob7?X8d_=yqUCc3NRdBn z!2#(N_519eDXP?9;4DCx0*n!Z-05rn;oKTHOR1K9>w94sj6RDi9_zxv>}8s_#b$cY zUZsD|z|G=5hLM**Y0fi`XwBj%4|DoTak#sO+|+8rEz>$EWF!nmvvMuW!R&m(5pjSz zDvtST2hrlf^D1`ylD&%8!dbHW7)Y!Em!aFr^C)(w%s>#M^ves2-ooB3Z-9zIyx&i$F?RZ8Ak;=% z*nVhBRa3WilCTGc9&l-^^Sr1Ck?I8K)w6DP$1qdB1Nc;ZWab zIV!cnOClI~=rqVV6mboAzjN{~BTVOG+$ESuk5wzXXD@>nqVfekS?r?*7LfB*DnlxV z(UVvrXKDhehYb=E%#rfq%+_1??|phUN_3+T`nxQoonmEP!h5pxX+{Pa_*xybM)R>lsb|oaS0_f|LxZG$I z`{XgPpwHA90s@30K0kb}N{bNka|;@Q-VK2{`d;t=bG;vH0wE&!gzXH-in529Ehg9o zR^89VZ@%?iBm)FxD~1Q(*%M|;M%#J08@*AEB+L^nk3k$y9X3Y97J zXN;jFHy-@^x>TuIix=wPUt#hKwn5lAT+7v$nnYy~_suk}339>Ljj$+L>P|jDw z7)@%;mzBPDxkKk{zFYaQR>M`M!P-oQZbq6`!(?P#X}^L!ZR_t4b|B+3l%I&h$gg4M zDEJ%Yk7?`^L0JiIv90`!ZOu=DJr&0mjQUbmHNUT&_|-~&JMjG7EUvQ4{!3VhRT4sv zmJ|iA`7VFn4CFMB{EUp{-?PW;o;kAR^`bCGN=7D70%~H?v$Lg@J~aiwp@2UW?3Ey9 z-cEQz8Sa_?-8b^x28K4`PQi2)&_WpV%e_gMk$1d>B55Y@meK2kQO>E|YlHsqFE&Za6)e>LdHx5ONGg+)~HkwBl$X;#jxxJ--nILmyEduKz;&+ajX z#&oHb_aiRaEx1ju_>En7A(ISb3NSR`wF$)nUBP+F?4q3Ql`-z> z)+7a{C1Z#eXTaxn9~aSd@L%eZx$!W08zaQK_$8^nDp;WZPG30QEicHi01T&f67HHd z-VCCdNwxjTiJrW|_er@%fH2_}g3{vpMQGYBXW53V7-HsmYvC!MGGb5k4(|X^7XE!o zW=yq3F1-zI=oNoh#V~^GXsg_6+lg>FT11}5w;Hs2r;nWPVMV4!hjpW)KI<~HMODt$ z(2h7oX#U!i(jEdZiAZNQraY9yiFIfC%2#Xdy^@(OS3Tb11Z)0KJj;cMo=_3U`y7>+ zS$Xsuw43~gQl`qsi`%Wv7cnW9S^HkLAbB{U$jD{~B_7bXxw9_djB)``E%K2Mc6<=l z{#5Z7?(&b%=VY%2;cpomH>llYw1w@cNV`2Ys( zYQk>I@0i8KDi;6qOM9OE+97zg9$+Z-rn`5j6#e}9z}#$E`N8lynR}qOZ2QllA$VNL zV3ONvdwj%b`EBq_}Fe}R9txvA+PPqIF?N$-zqXMh_!d;cSrkNM)oi|wrB_L}yizXq~a27k=r z&<|aOeo?M}zl{(CZU}QArui?N;lF5H7g>Pq?upB?`St4m{)*N4t3kBum*svHv436T z>Id}pT@0|n+kj2E`vWc?fg9x?tl0bS)&24+qUX@b8i?#Y@}{FVu6~FF z$9L3i;P*0Qxr>Onwt)zvvq^el%zR|B=bWw7?u%Rzlyrfa{VjC4hlTHn@B-wcF|5Xp>L~x#$Mn)P>nv~-rfYxdA*)_WH1wW#Fj`lm%(`(VDZd!% zyb96uUe)KwV@zUWrhW)a%8rX`y1w5}Q8jm71c!UsXzX{g4Y#~o$nS*gA?l&;(puwz zPVw~QXhi+SllOr!gZubS1Cd`X{qq5hcYk8?1o#JGbtaO=_wvdzj}0i5VAYFr3#=No zYWg`VPc^!fd{}<0F+#WuQOUPwvg(v4u^Rl~N%RhN6b*Hr6d-!|;nd7jh*y#tD`lg4 zpLLs8_V%jwQP<1(}2-zD_m`3)E?I7RTSt$U>4Jb5U=15P+A+1dlssOXw^5|M1`7XvT5H<8D6)n zY%KGjv8>2dG@+EsV~?Qatc{<;nG`vlu@fm-6_)9JuL<-1ma%5{cBjrax%oH8kl=dd z-W>E$UAn&Y_p^a8>(}KjhfxLs1W<5RO0#So#nsT>F_qBTBYH@Y9>2Bqo=I-pOEYxAlF%DJP%Jf zkZ}f@o$F~;!v;DZ4*LximCw}hpkdKCTTu2#mB0gWah>78N*Jn60x z0JSQgn%49+!a9NE;gBTik^B~}`X|^ESe_`A zuv*iO)h@bP$up8l!j#?ALgu&k?R0j%&pN_;>BCJSV^J|`l zk!|mb^(g_*NpG;7)(5yFc8*nHF5sod|0PPD+aojrY85W z<{fXQD;oC7*G00ZHCFF4UrJA8Nkr=3dQD826E%M@5+Y_hlNJHE!9@yr52xtUZ6PtT zZupJ_@sbbt!m$S1_A6X_-2Pt8@7RY$iN94!m?tTJG>s;6TD^Z*Z{i3(sBQ%&^-%th z4Z=;e_6wuOuz#}39VnHTqyj9*-M?Uv+X*s-oiAch?XxzfN?taGOg+tSfrviY?QQyb zm8;w)p&qyI=~+oIU1tlQulxC@@XMtw11dSWgUq*Uce8mlZ-;F6_GXuckD86QNP;HT zw%j8-mS*l?KZppt-wKt{h)+F)VC$i1uSvGsd+iZJ*dp52asHjFwk~UMaGpXo$`8S7 zWF&u_8Y?6|rs*p!l(l*3K+Vy9E!&#Q8sFZUq3jf-hL;vt2gZ0XYI$!@*vhg2ahgon zc1dY1!ci@NtxBQ4<0~aSmk`jyWx!k?B5lrU!eosLs}< z*C48Ne^d8IjUGl``yqkC%}#|%I(+~*vF*O-T5OoK_sD&ZuPl}3ChJsx{s~VwMidl3 z0Lq~O?jm5us+3uU+#efj9{qXkg)#qPw=AE8%q4T=|}CAu8q7b9fUH%=s(<6O4 zTu}G6Rkm%iMCBoca_{Mq8h!tpEO=6}gX6UDliNz2l zKWmGvjpXlA`DVfJ{@$9zOA!lhjsZsLxK8Ze%b%R{XM)a<;0l*84(#lSZ&cSAJ{^Za z7&`MKOV*cg<41Gy(G|E_m2r|0RX#&1U8Zfbt$lpxIZ$x#Mx{tY8N2o}WPit;#M79! z$TfzoA*0)%nN^*aA{w85m$8-&mGK@DC0w}Boe(>36U0Cd+<^)P$SWLkk1Rqa;#Zsq{k0V;wZ)WML-x}n^yg%xgg~PGLxpe;!$*&Zz5_C*M zEjv4`D$M#`VR)N0axv3#Y4Yv3atyjoM&x1gidUEBHIf)zhT#x_Bc|ZJZi1I)KnoNB zz-Z2f({|GbbkPApSpjbNf+CviO6hHjD|p?+6KQni!hILC%t*ct5~1XruM@Zqkr`-v z_eEc^zo3-AjzGPQ7Pv7PWz=sxy!ye~4+?R*U;+C=u7&0C9)fI0SW zkC9q+b*v1#XER97g9Tkf5#NZTq0cl|^SaRx1R8rt&d`NW zc8H3x#fd)M0K@x1cEF|~mh7xeGM@lq`X@E7Nh;4rjCj7A z;rRy%_fW!Bf4~xTqF+}FS@6lWtPybd!pVpT+DyAMbE#X-Ise^8Ubn^|ADAB}53jp?Oqs z%)x)6)P1paexJn(`1nUw_<7=RyjoS9Hr1ZCt0+#l{4Of6*QvPN;*Urc=rA4@QXuof zLC@#N1kgXPzlpPoZzcf+vOrh?+mCtOe*5&+sH}ow;pONXb)xrsI zB*Z>6xy&+LHS;t3o?)1J4wJh*ASODmq>2px>^hx0Rarb9u49`8z4-YhyJ7o^#>PtV z)a2ypTDIhvkW0hb<2zMPVc>H8D@9jY{$#)9(>TY@j=(f&jW^VmMX2kRk$OZ!{h6x& z2FU;M3V^XdRER@As;wL#E6vvhUsx3V1?m3t?Q>-Sd+$p1mXTO!O4JeVJ)<*mYs&q* z-uR>Af*UXMU?`~Cm8`G2hfK%S?s0oCh=oZejgHB0ob6pnTRkQ2~0 zlzg(813d72d&F~o#;c}$^mwd^XP>g|K*TV5r#nvS+d%!m zOMM0YGaV^0#_Y_i3PML*n8#C(ikyjlS9V)(=@zj9tDxf2P@}n$r42Yo*EU(V6tIOz z;+1NvtfR!Lp$ev~7p9mW6>5(JjarOzJCGvz1nWDwl4E02eJ@f)rViot{)y{<+579# z2Y^|*OTHvGE-FjzCW9z@H@pzpE)@RO^?vM;ui&_WJ&oCd)I@W$YH!HE7nbZF&uZDu zf`V={LOLN2t(&*aR*``eOyth!a~mgePEKwIU@zW-DU6gV=+3;j6xC6F3Dy>O9d2fZ z@N_GX(=3P%n4IRXGEOToc>>Lugv-AwyMQuz|GikvCF;mJ2H@QZ#nf1zI_CPf zo_BmmlS*0&zKfM%B#wY4Y4RwdxVuck0U0{R=4G4eWdmmPZ|s3}Xc^BUv?s*wF$19G z{t54@(ed&Sx3CDn8EF%VM6&PHS;OhXtk=Vqq}V+1F;{A$#LQZK#jzzu+NT#gmq9)F znzEb5ZSw5^<`CJ-NMA0yYAk>Ljz2o#hEL1q)94rHa?#3~R~W!Qncj&W0~ z&rYIIugpRB==v%)!4F0Jn_e#nAdAP^(<;XV1t-~Xpv9h&36i~b#Gm)`;{6SUv{w7% zgIXxU*y|Ju9-->UyB&UKy0vavCo*KME>yG#78ep|;Dc`QHON==ye=tJPmx|K(RUpy zd?DPfp_9I5ogW)6-SH3HXt8H>IVurh=$2xnak7s176S!=^4eypVPUmrnr$wJ_0LSK z`uj)Pa`JE9Sk0^y+A25>HVomP-^sj5bn2T+n!lUYgc!cQ;1FPF>U|G>;i~4toFkl! z@V6pOPZ%TLCs!H8=5eDulY9(Lwg=mYAvt;e9H@+Nw4DS8^C(Gs1~^WIG8g>@Ki<=S z9(|YK^#Tx*kJ(`<3|p5)nv~AMTfvDO^P^!;K08;fKOvsey-GEw`pV)$sr>d*{#S|t zjJ^99$)h#GK6#wV;Nd5stV@HvHl{=+^=kyV3w{AMr9Z8MXm_BJ^yH6k06J3sYK`z3 zP~lU1+hP{wCB5J`Ada0{om-$#v07 z4>;&v{2JmmFT^XlP3^pC6!WJ4AeQe328AHn%DOIZYwm`ykE90Pd}|8?Em1T=*U}A2 zzB6$4FndhsD3Ezs0Ll|QN0tBtIQe#vzJ|aN(u(!n`4Nho;TY~L_o)W#REcPL-&8V9 zaO!7W37S^^ea8844$AC7=<6BbO8b4msMs6GLXPHp!~G28fXLX$c+}AmB_LvMeleZU zD~uj)G`1aFo$GypBd$g0*?3w8@#>mAF1D5U^8~rZ-1D@^iFB?B`M#Z76f1fq zXpj@Rt z0i*h#65;9k`bx$Jg198O5>?C+fmf zjD2!~5G6q8Z2S~L6vP|}uRI!Ze_*r#R5iBpm2cI-GYcGnFZs|3Q}|Kvq~!4)27RQl zh@Cj`+%}JU=}G{PVn-mV(}b!uNt%=V4BuCXH4fSx0FoBzJkaFUg$C=b410M=4{FRb zJin_4zN3W3^Bt8wnrIH3@mI{OQ7!3Is`h+8Z2Qde{YlClOtJg6I(GIlu#c}zVYJbr zAwtTY)RlT^z(}rx6Xglj>1v%guD^Ej?`vaEilPV)?v`Gn0NjNbBc47HJP+FA$Y|3KpasNBd}`~mb!foB}WS%Kyj$|zbu zW=10m1p4JjlW6fSl~!>oO|2$1z|tai02pm`RP0#7&Sxy(S$zWAwR%f9TzF2!IXnid zhPB6h0boN|!|P`=aoKb1Lev6e3x?yIFcyDsESMrDX!y)DCX}ISY2#-9eH%oPA& zITgsNlcLS=ZRf7l8q8>L$jmB1X`x~#%DCZSdDSXh5MVkE$ZHBpt`=jk) z9_MQyEm=&BXU109bhWb;t&UiS+To)!$-4!qDp?wc8;}wAXY{!IzE>|57Zhn2N#W}9 zfWDN5P@n<=cbHrq?M8oBU3N2`+8WQ=_v-DHsKEuoZjFt}mxw#N*X`C4a07iviiC@~ zeHP*_M5K)hWOmq<9BNp=Y>bp}r@FbSgt^rs^gWmllH~`mi^$e^NmTc!=g?B@lTvFb z5z1|%etkE3o~loN9qdHMX3 zXz;3+PVlQ*wyNEc$|;C?d8$Z!=a7u`eLO`Fm#7+`7~lz1 z23-`FuVJJdA5%7@))>~vrDDmR*6d-a)FUDpf*MgDSBtv-T4wP#X?YsEj;Y65EG1;% zL!ve%KmCA2^uDR&(XfY(#xp?2cPd2(v;bHZ z9~*Fh<-}3S{hnHO6^JCyLEJ7^)4)F*;ESW2ASr)es%7&|P}<=5;yUHeumVtDiu+gr z(QXPz59vcG4@quI6#J!RM1DTnrcs;ZL@%l=ycqmM{sOWm*cdgB8G(mXPPJNNIX1=N zuQ}z$odBMkgJ_B@yO4;wHb5;zef52tR%kWuR3ceC^>L@P4YyyIQ$kk3Ox!9i+}@VI zrq9EiPwJ#r8Y6u?`!5$DL;UXX44*$MMABVZkZ+CZw9$oR$B{xj$c{Eir|@UK)%@R( zsFM;S#1iwKzPw^NMdVbG;T?-%^D5d-FI&oqJNzA#?61V*zyf2Cv*o|x4Xp|e4NcBi z_yR>z93+pLUEW$*&aCVKg?ha1jB{f)H}uMBv>^o{)48bVhC=t4S4dk7L_|^1xz!aF zKudyp+Gs}DDl#zSyx@$y5ul%(-@b4k@F1v{5yBO&yb{~!}@YeLwTxz+WGMj!^;h zdHQDj8!!HluYf4AhninDHE{*`T7fA!xj`TuWAo=Ztd zx09GGZmlzWlR3~$*Ye5NBU*OTWRy3IR%U`7f_Yj_dl#P1#qN~!mKwPzwyV_ zZ|jcKNdL({fA_Bo+Aaw=(iCxv|G|;|-?k+H@FcXhntFH?T)NaLQolNvV`mNmWzVR4 ziu;%eZ=7CPPd}eLww|Ze;&{9f3t8L^3AJI5~fs0_%xZMyOC z+@|ynkYBwnci`Y4ELbNJn4ATCgET%IuPb#%!$!4Il?+J-=5O5trt;4_zu2*HrgZ%Z zXVKx%SGSR2Bs(g(g@^wFOUC$w%~EWW7b`15O1Tbr4Y zQQFT3LuI@$=y;TPct>28-PGr8%%0;pG3J!=KC7}}84U$!q2_!19gYCmB13m?$6K&p z*O^$YJPW&UW7W!FpwmStRcTI}-h;7to*n1(OIG>cZ%^w0BndS6wTM?G*mn#&GU|xZ zSaqwPJ%eVYRZlLd&`3lc7gbJv;4A9)!}jH?SEOa{#+5pDN5(T(?&Gg=-!ONyG&Bq| zjMemZidUf2{M}H;jqx9v<&-e`GdDL6S)dCn&dWfmk1_(*#h)aVG9@V(G z;+2(^?e^_?{D4y9-s72o?0o<_ABP^VIHxD)r1V=GhAjuA1~skd8yb4c3o)tg7NW{O zu6}K7jC7H9-JIYtSx>?Xr2HwMW&7b3&mS9eT=}Nd_ghKaVUGddMm*YpA?E*#MGIqP z7^MZhF-m<@Grz#EmN%AJ%s{)+kKh+uOV8rg7I!ao8vbm`Xs5l$Mk0*oW!Q0Mt3>hQP#Fo2t|J!9tI= zmq!swKrh}Npd!JR+lm<&YZ{)$FvRlDqaH0yVg{U=&qcCwj4pqH4-_xZH7{PgsBfh2 zBmdil8c5eU16nBi3F1q5$I4-);oKX+r#Ds21G%Txb<^A*-4Ly1j9+6`i&zJM-tHIa zC3x-vgKP_L2^e-6EKvOr14xfngl{(KFg5+do5uY;FyKFGET}$X6z|cAA-}~p+knOCv=jZ3v%`-BsMik^u-Opfj zD8BEw-1E+#y*mhcA}Bmom%ril#sc-`4Digbd`p7laLy72koF6*){Bu%O--kr-yXY# z-3k;+PgWbqM{9B|{Ta9nO76Sg(syp6MYT33r|Y2d6}))_#BVOk;xIXieYmfd3w|En zY-r&=CZ>My2d4ecP3oracddhaTv?f!g)J;Y6I^t2+s+fYbCNN40|G{~Gj1DO8J?7s zG>$b)%O=@|>s2$#Uln3kFG)y96tCil^{$(oW~cn@YHt(^4u?xiOLsnhGh_}3qGYzF z_9Ohov=qZ}F~J|{zcbAw&Yg7`HI0>0QZfg$D*2AU#GXyUllCj?NsNX0dBwGg`2KHW zxMj12?U&V0Z{H!R)EPbWK1bZb$>|)xz_v&~*~myd*ctC^pj{AEKi zJutWRt_T&+nbBLF9U`E4xM~EA3$1)1Co4>fr=&F}LTH(H@*y_Tg2^pB@35pW87pd&C{5`K;0`>z1hNKUN1q_%ARq-f$*uZ&3z){uQ z(7~0QDS{R+2e8^eUE47Yw|5P(3)tVEKO0K43-_<|3oYX?(`$-FO&twO?`#&kh|l5uygt zT-66SH1`2Q4&fcLF}tNZV&`-g5XPxkr@i^W4rUDmPOVO%NJtDdzu2L%#|1Lkou@`G z>+)-s#f+!;wzfu!2)#>fpN%8JK44kl6u-0A-9Zj|a=ZSCpQ@M2WGVQwv(Z0aiE z3v}FE00Id}%{}VVnPI-=o~%23tfxR9$@Z?l^pX5sWOlu{+8xDmu&NxzdRjtz>WlUD zZ<{p6(213%QGedHzO3TYp(9i|1KziGN3@_u0Dg88n&fl#NuXV%X%P0~89KT4sh*oS zP>$m7bX;gd&F+vofF8tRf<1mTu|Iu!APSrQK67i=h2(`Vdg&ASQ(Od=IgOY?F_FTo zn3R+&qR?7x7Kt>bImlb7{c1P)sku;Skkhbo{~#4|!g=QLf7pY6nH&+llWukF=(=Vb z<+s3Oy@t5aO^$6Yx(K9VRi0g9x%dOR1Ckuwv5EK`1Q46bX=RL?2JpF_(k#b~9eD3D zU;{;HDeC2q0n;S&q4Vs9o3Lxm6Zl-Xh=$7k^|6uvFDi|P?x+aA2`uzR?aecrtnbA- z%^Y6a+huP1Hy@HYJ>6pXG||grZv?Q5sq1d!?Ah@bdGQHIOxOLB zt@Fgejc@v7yY{+&diC<; zPP^|vYXSPw9UL5XGtLB(k8gai*WFVGn1k5XxX4ApACzZkrk##XBwJl?nBVdaB)N<1 zgl39=fejN>&ukbrofO`F`g9FzYbYBpL@u4w6c)2vvFHW6Kz5G!d~%>3m)LNB-^c;Q zK(I{XBSV|^Z9NwQq<8$iyY9=4cLGSyp92Kb{?c8)!yDUn0B(l>l9=IKczlz|uK*qK z4j3dG^fOCg+R5lMz^?=|sWHjl`hF*U? z`gr;RP_B2kk8Dz#0o>t#H{_Q%@V^`K|ILOx;Ii|)e8RgItD(3AjLc~ucmV!gTx3c8zI=C_CoU$t$j#M(~)C01;?Yr{0 z458=ZmYvK~nsT;MQr|_e0{sX6^NIfJex5hYhLPh-;mOHkPT|e6Rj#uiwuoHWy?&w? zHDv4tk6?U4;ri~~-XY7y$6G_(su&fiI4(2loL%Ws57?#Me&-ZhJgftO!kdoyyShq| zA1t(%4U~gjU$s^%=g~i3+-du}SIZ;E%p8)-(2%i^%a<_&6&KbY9Htq=b|Bdg|29Q& zH8Xr1#gh$8jJZ5|Gc|a%;;rK0ZY7m|ACxV0$cEIwqf z8Zy!}#`EU1#?TCE^~9>X9QCu;XsP@J?w0AAR{B!?HvQZB?HzT-UT+r$qr@_UQMiF& z_x+O?OkvepD3&wRST(vz5y5)R9_09wr7~1@{cyKCc6szO4M+!nB|`}VZYg0a=9uxi zSRs!`3|~UhhmU&VJuc~!YW8%p^?Ig*huR^arVV5rbfQh8!~&Cie0>K905-30(b?Eh z95}TebBa+ZzP%70*01#_&tvvYfqadY{qUVswZR}B8pu5f|33ayjk4!l4UZFxSDYDM z;Lv-PIsxZ#oojA?Y@-Vwlz24YPnuX6OD8E1u4Kq!`b+LPu$M@7N}jK1g+T%AVpz<;Y}Lk$L?!tS_NRYc!e1a(H%PhUe>l`*i?0%pJxaFy^Ks z?5e%N=8v zPo1KsnvxERhyVxQsJpe2PaG9WtT2s>k6TYcS5#C8vZ^bE$iBWSL`)TAoBwosVP&GP z=3iW;_VcSoMln0~9y`hZ(=MFjzckU6bL$MaCaAc&ZEJY7oVt4TEs}SfF_0euhI>>8 zcq#{Z71l77u>j*UGiFom*SXlpaGUL0=l=Ygj!!i&T6_0ZPKLMRM66A#J=(Sf(sD%u zdmF;3$&m2e^@)=_R+o|HwMKE3Oez#8DHSDS5OcNmGrsX0ky1@otxVMdRnJBpO+dJh zV6hd;Gwk%GW>on3bGqvsSRa4H=R3ZA^KjtI6Ze6jW-OPRdMPX+V5T^O%?_Y=WGyb5 z5p9FD#%H-RRYzqk)G4Xe5R@#Yx1jB!)w@+rtkx8U#%*sRx)ag9dY~hes5vlwcq>p{A7!z1RWDLY)fTjdtqTF zPtrepp4F6>w@b7MF1^r=WK?i^5M=u8 zxajR~UdcS})X!2hkXY;oW_gLoSRlO-l`1_4j{&p2c+0-;tNiK14NF}F{KW7JAy=lU zK$XzR0LzoywG@k`-X|E(0=XV&Iynq&?4ch-!w}l`wH2%Oj(v;y-sMy&WR4jaW>3Du z+7(020|n0IhUIOl3uiI!OR-m~*to_4r#3yY4m>dxu&$}^ME;fj`iC_<0NQG}Z+7?0 z4Fx1%UxlfO2?>+WPYtaZf4RnCc9Ip-6pYIILCHZ{~bM#qYI_R zh9)K^aq6BEoe=*vJ`3g5-2kfxsb09&`kt-(gw(&1jv!WBuyiR%SncD;|A)Kx3~I9L z+JU=5kgBs z3jspNdvZPZJ@d_@zQ4X-?>K{_j{DqY?Y-At$FYuOGgYI-Eij=zB#v6_K-mWOmw7R( z9KeicrW)- z@^#IoroD-(;{pE$kdXjFYpALD))=VpWZi#3M8rj%yVJY%eQj(ioxQsnh;3(@SVJ{H zs$5&E%6L=Ok_7~3nWE&IE%OeDN0OGl+rw5DsG3^Z{fEN^^U;*G`zVt^QvfRQoL^_@&-6JaS4cj|aCMa~Y1`nw~S7eEeW3da3*jb7EP4CTf1AD+74Ns-R zQ~@<6asb0XFlbbD%Y`V6?ZxqDRs^{Jp#5xtJi8cZ4dYk=&{hVD=&N<$#;c=ciG$Z(D)!uk~6E6Gc0C*&9gbq=Kam>nc4|+<7qxiIKG`?jD^Y4a zSG>=kJ?rfE*zft<9WP$Kj(z*-%wyX}w%hjY+ovi1<&4;5$M-LHs?~4aIV?Jz7)1$G zNS$3C5uGHDVFwaV)f`QimUHfYgl5hB zBtI;1qchkHLILYy#HS093gj%7D*+xU>@toZJJD z>PBl^ddVrOb=hdg%nOS$9xqALhk#C=s@lq@%v|$~j|}Z?5Q+uV*LQoNoVcL<#g{nW z6|=0|2jj2I%l!i|OBt~FD^p{K&2h`h6xFPhz!$_u%`wweoKuGoD}|p7y=a3IoU3lk z$vVvt@*RA)QDA|_KI7!1@vb^zs1qjFu#f%5OthA#j&@)?kRKnEQGz-myLum_FAu!Z zc6WQhrqeSnMV^{sscn8dUR!c#xMo3_9$>mMU#EGbFWb7FC(o_{pBYegsiIJYy&)b* zB}My8PK(UWj|!_?wj%x9dF0b3PgZ}!%aU3vH+WK*>TH`Ivk_3_ zB4Yz{g4V7Uy2iA%OIx7ciSKn7zv8}ejO1sc%U@2cP?L3eaqirCACg?cOod(I?5~(8 zBOP}=y$_{kOkc)u(nV_db!~C@#$AKVj;v9bg8v50(k?6BxCgK#>GZ~{>)&2f(hq&9x{OO{OzAaN%$c*%vz?WhXHxhQr zc;uR}{y~C!G&SU|>yI5Clft1X6H$VNJ`Qg{^#> z0*0)$8|KL`Nd2_HRTOtV#d-Z#k2Ea9UWzb(nu(dXhh%g&q9gh1%r6u3I@BptI}Md- z3)9{mHRWYYCv9Qst-%9uh-XOEz$+CGcxJtUY(Ea&eWrhN%?XML_P_YzYW%^{(aol6 z4oMYo9$hFIMbfX)^+9gNWju6#tFGz+UUpD#PblnWdYjAUDjY;&S^FbAGJ}hRQoQZ3 z;0>IYCq)7~zlkF7X1kMy14lPQ?H;FP$9+91WB)!W4bI?1W3Q-;D{b?onOJ(oSo_oW zQfhaBFtV>$5&ZD1&jzVLcB#_Fw1;~p+u*iPCl;jI6>&6knp9b&Bmmjp5GnL^vh7p` zHXA5qirL0WRfbL_#wTDHzCdkblpv(-Dh@q7O_s|lsOHYZnyou9&HaMG6e;daj_`?( zg=CD%g~8GZVf2quG(9wKPiZ)xbxRX%*+AEOjN{QL-}5~fjkUt9vuQ+>H}Brk#g^-D zD+|mXeHz2B`MFZev3`s`t}1t!gm7-`pG}f3RO|?P}`6ndE;Di?kIa1HjXUK_RAwWU<66p$| zXB4+REyebS0S%Zb3zh5s-*nwOIWWT+%ExQ+%7Ha?Ckc#(8%v)+nxG?OVl{54dxgcv zjaMoSb0zwzp7?HF7HsLe0O!4e8=6S{(5A$C;Rr#zi=47Tgsz(I{XC3}dPdUL*6#Y~AU@*iFYa`8wTWu!EC4EW6MXKd&HHL* z^A$_kZ*Ea#u9)N49%w<4u%>Iy2C+E07|7_+#Fd$+=rarxibPLsv`WDmM8~ia-ZJC= zYUN%SPpv$Nll_VrH2#Fw&YeEe5ZBgZs!T%6Z?*-1mTMwnNW|^dY;f&8ep{k#A&{fh zo^%wJ5$x%O#Y|kJTVn{!<1RhxVib>pSe>QJ$Ua)8Z*VwEmh5kFK3p)Ua}@dVJk!L6tEoVqg7gd;ZTEk^dMdCSjv*xBYnL4F1`C~%n4t{C@Qv5dl zz8D36oJU#sMbshWz#KQm%RE`i;xdsgz)nH$c_ME|2?o?14*y=-Op~BKyp2+bvc?Cl z|BBHyEU~Ts2ww;v-N(zGCu^21S0cfeX1K8RxXD(lQ8uokmYq!J$3-hKB(~kEP?*F~lX6tOnnC*x>}|S=>u~G$7!LN2=;FJEgU@$mSr)stHMH(@W6kZRqI^XvEA#k50%o8TICeaSEZC}}(9REW zWnuAX=3H`-{#i3XhRK2_!8$0l{W`7AJIl4ZBE)qC!_y~jyqW*Gj0zq?i^IVDs{-W4 z`UbWmleoA070WnvVj(TvD(5&Th((XkE3#0U$`!vV{n2H@Gyh>U|1vZM`5s4NN-hbK zp=tA>JJ&P4kQlmgsOmUzm#;N^B;O{*9oMc9GqTd6>#xQxU|r)NWu_Y%nkOy$bG_1D zu}*@?)Mco9gaT3E3{-J~XOt;n}sXpaH-wVaOA{tU1$db*Rwes`! zWB&9412baX>BJt+w+7AR_bGjS1-d93pSR$c(~-grX?O>dLmOZiZvBvyVL8x^rOlGF z9cwOt_&SF%+Ybm;u-NM#N{)4i7q#~;4^Y<#=p&MVFtQJa7NH@GYvif6ZUNLx7${fL zBz+Hr&)b+^ZFyn4((F5~;~O^5g*D9|_Ljx{4f!`Y=N))Yc!D8SOKEv$xz!sv?mgm# z)8`n~Z#c?%rHYDxo=ArkOC>juIh*T~*V6kXnB-b(%1{k>I+{}Ynb;37MSa%#Qb30C zjd@mT3mG5G$m77seCZ=2p1h2sSJxbtrQ3PHUKswln>|cHcOPDJzxht&9;>Hkp^*#~D^Q}y5HioFu%KB4CWg0-ixsuf%7aIO42Xu-w2h>WV zW*x)!O&FHlld~!CguBn=*RWStL(e)i_*%`1`%v8!oCE*^$wec0UNWQdlN=PUe-#1QI)k|ffXyf zruN*303Xm%#Y!{hoRJzR_WQeFRJQvtU-lTD*+stonbj^rmrN{oh*})~8OB;+dx4|d zl{PEVnSf8;LLM$*N;D^ki(}C`YP36d6Qm~i?gfv2IP9+dqTIoEab3B3R|AnhQU4`oc^4s5ehq};j3SY^GgjDWr<@t83(7MS9( zUVTK_y4Y=dVO&_QWsYs(7-zO@a(1?!g1IU#9~wA%yVhq^{aqfl3PyG3-|dH;-i=;$ zZa_IN8LP;6m*;Qd}Y41;dyZ=R1}`X`ZD(wWL{AZ z#>a2%Jv3z?L8Q&Q3cLbUE#}e+4HG!*cBoJv1D@}fRl+XoGfJ3xC10>XlOq0!UuF;J z&%!^2vrba36tnA+3X-gbPUp>%3Jrv9U_lIW>HJ7@#_88@3~X<`XpVj3Tjo^|AcyWD zhod?Rk^HI9k+}XQU4Mui+l{YyK*ID!sk@}j>p57e@Aj^8*+s8)L^Y7hd#tJ6g#3wq zdWDyf7Q(8B`LXo##HFQ{xvp~|p_1J$kSl|sZ_3@Mg(R_~R>N(mj=_8ibY;$<{_Vt) zC49s&6+!xW&BV7p&uX)a%jdGZ6tldNY|^b_e;;ZMRX%g>oF(A&hs``Lo42$5X;^4! z78WiXbSBoKrAZPEqp@GCu6b?z9KKW~g+i!|mhL%oa(0M8tg_LJ6A(W2TkH{lEXM%I zQg{+Dbj*VMPS{+w2#FMD$1Uo5EvDqMLRwG6TbO~wAso8AQ{*{TgZ8NzGC?J%5mj$%<3BAY z$@X=?vobkh6`lGxzv)PnG@kqM;dXaqGDn^lcB==K3olGLUW4YWXC z8maGd|DG$9C%Tc^1Acj3csr^)C3KrKE;=%@$BMHX4Ae3HT-c}MKhxBhXTs8P8OaXz z*f_}Fr05opU;FeRr#qwEcA}$n&#~LPSv@iu3ZfsqJRkjWP7bZ=ZcR$%_I)Og8>6g- zOMQ~goj-3>=4ccrp5!&XKd%YzMRkvpw$VXGWv4ncC2TBrI=+LDOSOSFtZ`dnpCM9n z;1Qyn-E&3>IEY?`aQh%6#uBMi>qtHyHw@H_~(@hwfH%2uA$9_!w z=`tzYSDZ?@2;M<6pW^+4Wo_G0eF;FaUC-Zx{}svB!~r<<8(~|izoAU(X9fX`In=Fg zO8SqV0FHL`H$Zlg^up~{p1;E3yOMy<6i1%m{5fwQK)5b10C391;MbMvf1YK4e)IS! zfZU@Fr&s;yI{EkSE?NUI`Z``2{=X(m9dZReQ!Q`1{5Ksi^)Gcm!DFCE?BtHWPTC7? z0Kpl&_ippAWt!*5jp})dHA* zPlvAmwV3m^9e06jG8=Ey>EA04|Mw{y60|oqdtOyeuJ5crd{XOW%76diH^}sb&KZEL z#~fnIPD!1)9jsA!#F9cVc&Cfta(&}*6O+(c zoL8yYR%O1gY*@f|Tw=3xoLj%~vqAV>}VtlG6&t>C`=M?gHJ z7APLCy6qkXF|WFiS=d_9!7#lWr(YM_v_?we{KdvXZc71P)sH4wL}$@F0mj}ohk)1aKTqc68^8fmQ`XA*0Ay%rQ&~|jS-}P+ zXa9Vt?Rvh|>i(?;{~vCZXD{RE(U@zn&G1~kjE{x5FLzN?%hI1t9HeuZj@sCXzC74V z3XHv)mobd@D}u0_kBiUzrJphV4 zu$ae#>6Kh7k6SN3D!4xSncdahFG*ke(UpEY@Xq9@;&e|(?6ozyxWpSnZu|oimqbeg#@)DpA-cc-z@`3VI;tmj-=8~CdOYw~rpHtb~JdktfZK&EWDhIG!zrl*D}s;UWT=RI)0A5vpL^#@Aup7ITyI;H!Y42#fOXG zqEE}-8xu)>zow+Ge~g$Ot`Fy0Wl-QYXS=#SqaK(OEcb>A8!Rg?k^E!^EYH)1#)(q- zFz8)UFf{(&ULZ^Bhp~y%n$-*eruj)pjtH}p!rma=ez9@z*3BCB9z?Jnz;{TWd?%PG z7AIy;4BL3c;<{3D>b}_*5R1E1E?j;$AKb-Kn-2Lf-karRfyB>z-6);FP$u1!uX*%W zLv07>_;ot953@SgGg2iU8)-}_r14_sRYgS~93_7$A}U)kmcT3!h>M9v?0=*YW;V_|-Id#7-2%6<(GAgKu;E(Mp zv^#huww2q4Qg|ptMZG5Rvg~i4u=IZOJrFT1}rp2ZxANM2q5av}K z=dNF@Qtin)%6H_PQT8XOzpy|aC&4OSr*8%6WhTz5;)-6ls=w#e0fWUCJV10;?@su^ zJ+hTY@RK;r!xjaqY9S$7UPC19Fp2q zC;WXX*00LtL!aG4^ZRmF8h7^wVh$v(udqwiv9^_^N(-MZVHR;^*G6+n-oA-6 zD3~$wv8N@{)1rCCe02mOa=g?!`Lzgs5OY(}6sdxuR>R>-KyjQEczxrh+>KIS z^>7wx&wf2DfOiTog6EoV2~zSutTX4nVKjQ51tX-_+Bw#P6&4S^L=9MuB~7c&^nF%Z zn96LQUaD^)F=9DU_$v;m_(IDJ5|mZhZHV@BP8T~aUI7j0%`2KMKN{6P$J)$#S$79X zSPnv7U%QUK;)4<}fu8>rFJE9dODSo0ccpClrzsnIPwTr|7Ga9Rl&qk4qgbDXX> zUx2_$5u$&iaG>!<4j#&Dk5OA^PTdbk!)-R!{1)Xq-2fZ~+pnyKE8%q4$M#%Yrp*@K z_~zvlM<43pp_Z6fj)52k@(}&z$xxqp1LGpSZY^oe3GrX2$l@38J`mr`3rW2mSgz0A z=*hBNACI>37gn%+sm~|z48hi<|0;#td?i*j#?fXS=#L^nQToXA>ITk8(1>d)WRtfuUTDek^ClMt@!+;c`{vS;Ba4_OM|ko^H8(V`Vyl}YP9@0#&lQo=y4C^%&`d89H4d*U3)%y-h286I79_u(R9I^mhi@>|Z~cvn*Tmh@GlRHj@bGPgHw31w&^H6lvR1?3o5AUAlxX6A8-2G7~25DG%Yt4HE2m+%% z#En)`<5w`h=41io(ekkmO5=5QFt#u$o6sC583P_lo?BTu7)xq}iYLi#Y^oBL;-m#q zCNTR}8p6UB{d{J>Xil_LE^5lt$pqsVcn9HxoSUhxmdWN^LqA)kY>0#Ef2kr-xiKPZ zgw*G`d+$|?(5InO2Yney7XhZNbjqKLKzV<#mM^1^enr>9! z$-_KxU80Bcgctnu51vBRmZzY3e9X80BpF&A;BxDQtu+2xOCn3u0xd>=C9nZv$X>5M zc;ZWMeFO|Kd4f#cGQKlvV;pHP_t{uMSec)<^QWqPAyB&~ zHMlEm+S(sdMku0tAc%|%kv$dfyNB)4ZGgKee5K0DDP`GaD$&B9;x{krZp@&i5Gzi$ z_2a_-5iBGa;vu;90ga>-H6J>AD88+!rDVgWLlnp88Z-C7OnUlV#_m?;X7$)~Zg624 z1CzL{uILe34WNT?!AJP|9Xla>2j1vCDqxJWvG=^yb($4ihb=52?iFut1UMwY7@nwkK8DbQq^!Ptmq75u@9bpRB&n!<#cg>-fggg zxEi`taq9{c$(kn%nFh28seZ$=a2=AJgn}L)Oxi>S{X8S2>&1hP%6SqP%c27zeyC5& za}hcE!lqO*dOn!gZWXxjX8Y%$IaUYxyFaU^Xt|M+G*S!1^#DxBk=G>3ZTLGr{G{cBo*HvoLt zqmA^nh;N&M^2}&xj0$@t&xgS-JHV*o1|Wq3eR05ja7cDOr{wdx?_!CzgTwQ=vDSBJ zHE-TWQTax-c$LQkpA7sVu;M-c7*O$y=F2`$eR41;=V<|5MolS*L34W^p+rhM%W?O* z_+$r=r^_=eZ%lUe0+FPr0bHfJwLCz03T`88X_6kCa(-lI0smHrRr?eM0GgYKtO$tLGRn!c4}=siNqOWFpmBSj@Vja-eV^I!k)iAh{*-xZhcLU zD|b&hg7INPs)tL)W7iw1ORp4~wL#UICo2|}6NHnW(1_BJ9#La3DK?*dHUK+W_y=-m zJB{$37x7AqW8PUSHBRjL@th8}CdD352jRoSohWf+qGVAK7Ri&WR(1v8whz%BKXr4k zJ9nNdK4yn7Yhw#o2qurY0`(|++JjaIEnADr@~a*$ALEQf^I<&2mPBsQKvreS2*A05 zl55P1@XRr)A{|mzM7#OjfhuHqWoTyBqRl@k0OIgUiq@?_vN&w)`*a=0Yw6EuJBGOS z^Q_76B`lu+e~|*2eW#3nLl+V$P*_yOK1=+}a*lrDGZ-EPHIkIR(a4l>YmvgifxX3S z74MOA8o6RJtI}Bu1)9O4eBf^05F^}Dv+O!_iI220f4}Vn^JNr3+%i!Wb@PYt=FCMN zDLQaUQAaMKaw^lybYtlJ%Q6?qiR@4{U;SfZ!PEYgxbk_|NW~25T5H_Wh`83y?*x^Pe?@ zW1d!~`Uihq_r+JE)pPuULF0v(2_cp)1XU0@_WZCN=~k)r&}s2Ko}>a6mUiie;{8a0 zex}t6H{rx5GS+!XWO~$|k$0PDk#`SGcqzW+o}#FErv_CA9|_RMMr~-1WGOg;=I9!r z7+*zS+si<^5_6*b)V?MaR%s4cdKT8)sx4pXIG}`@*8A+3?sS|C*>r+Nv8z@lq2`<8 zMKhGV^sicR{VxZom5ZW$WMWMYix+;=2W(^lWSo<}W}OGHk9eB0r9T3QFQo1a&vh?2 zg{gECM{g^LbIP$Sc>zi`*<4IY6g0BY18~_cbLgX`$%tBJ$BGq(Hg-5s*7sA=$yAgX zynqf(N$hjj&Z+IteuP)j$kwIGPotJKXhiDQJrLpe)r*R14xx3SnGcPA&6(}nySJ%y5>IAAezh7~uzvn!|-L9k+-mCYbVKzmYW{ zGwtK{#K1zmhwp3aU~1wOZ3cWZl0E3?0~yAU`aIF`zSZWSM_B;lW=8<1TcBU%RuyLr z9c)vjcl6c4=4-@}TYW}=djYUZzGlZYCzw$CO)AC%nZq=O@zse{$4I2xfV)Yc{m3{A zt3Cvl&m-=z2lI8C<6+{;-KgmN~y zo9<%b-hgFw2RmJK&5zaAVFwT?3ijn#KXV&j0^^V~<!?4X3Y_`f?_y;J#tCJ~UX_4;CF2Xx4VBPnRYChG(-wJ9&(L)Z+Epa7+6@ zvr$zgK)dNf_)g+gf{MdW$zSRxm~DnyucKX~ILcWiBn&J|DA*kbW&a%3>gXep+*=n^ z+r)4k^vzF;{X6hVRFXG@w#rs+@crL*cIKJ?7S8kCUl@pn$Saz$V`5+?u5oGSZ{0Gy zB=PVGw|xgC=2P}dxKnRdhA2N@rv8&B!z+ya>*bWV10VzY`>%a7Kj$D;*e=eFs|?MD zhWakKx%ci=g!A;fUMf}l_W(OW=9a;-hAC_BK~ln1StjvWB)>EF&Wk);3XArM&Mq{F z2GbpR)ke@*DW%!i(1G~mpDvKR&o2Mv0(`Y_J^^yYJD&AKqatrplEz^jzb!FNK3se zU^Ps!>UK-$*>n^>d6TFz94jp6;a<%QW0T+5-K-W!!&QBjrYVoK5kj>>p=04(Me z$uCL1HhBR;hxsz!Ip|A_P%51eV)5b$;G8c(H+TKevHn8Je*zPH9cfT`wd-@BBc$Zc z%W%;f8>552`di((A%hZlFQNjLQ6^wPB-10Vc4hS7d14aS*Yeo4jvV3FZ;Zk`r-cW9 zp}BLvD-vJ)pAgE*qcFfB$f@rS!@XqnP~q7o)^Lm4Y)WRCj*?WPs)f1$KYvkfocLr# z3dq%uVc_XmnroEv$?g7}pgrK40x=V#iMJD_BmFz-@a%&Xr$!Zd5O3Z*7{=ITiPQ8e zZ-q(J+QOraTtiJ>i|A--Heba_*BLy^hVyvl?&Ll4+Yto-t6SPcl>*1t_<)d_jszSy zQihZ%vZh!Tt)rA4)WwRGJ+`I9p*NGMCO^hWE1P`yoBchy%5y|{B%4!4e&p?4e(v14 zs|9H%B}@cAzJLGh8MF6{E6}vsQ-CXp`ZAf%Qq@Zb%4Jla6yb+8UavjNUmO-9Zgkn^ zt5*MM&t3_g3cCRzqst}@jE~ntI-S=4pp~@i8;Dr?u@?epJ0{0A2pg8=uIRR-wK{Q^1{u70Kj z2BjfXEV{b70GRO6)2CBsuY<=B=PsN*dlos*3w;_j6~-zlDG}>I6_{EwJ1e~S{*3;p zpLxV1fm6HU6s4IUwFQNR+K<72WElxuG-2W1UED^gVXmQvPx#VbaqweV0M2*>x?A@7OxZh+652|DHv>iF!iCEYOqaW=^UrHA-g;93RGFP>mmwNTf73GkbsNAK zMM3;x0W*dd_Y3BBW@;Zld2-s3bd*f3E&GBs^@pf!;kyqX8qOrjy-ifH$f3ZcFJ3sd zJU{n)g4lmn;?VvbA3p3;oW4+x24}s$q-|NiE-t>pKXR1J-?J_AzfWNljEL`Q`1`f?(z4j;qHC;@?{0wAHEx_4J?ghJ}Vf=ItzmHu2iRS|N4PSkm+NH zT3T8fU6&!kQrYPj0l?t+PE|!kGe91wRE^fizVU2&`p;rMK&$FEd2nA;B_tlM92F9x zZ|+~&rUnRyl~==TZNK(2KB$r(-2?l+6qU*Na=U%=uf3=~bLg;`T+YXQty!T*_kr+%cW=FU>e%vXeF?l1sH7q$qN-{gV;pA?BX(9Puf6&%`2S+W3E#g~-7a_3 z$aPl?M11}F)pBpjW2^7-z#}oq2Qmf&gn5NFGT#a*s(n7m3LjvcGx-}=W_6eA?#*$V zm(KSi1jVc{{YF!8bL)<6pY3d5ctD3wVlOZtnSOMeWw0uxO(}!8XCa4F|fKWKK$NV;OX{n)V4q8FYCT8zDXjcaS!G+u zPk>k@tqP@l<^V-aHYMJjWUZYRPYU7Ih2aX{>#F+xS(z!s7O1`_y?gmx)-n*~3i&!= z^Zf4fB}ilHpDpRx6tJ^-@d25#N67q~Gr$#%mvQ<_hibMubfYCm7)ZILcn34?`!f`d z3;g+(QQrpeC-;2cYViNzR!!f}tDcq7gS36l%I(XY`KTqe%uWuec;cyFdaL%>$mTupL{!iM^apw{l@|O+0)6J(>}pX}VSk5OLHAvLn=hJi zViU7B5St7yK)%AEl2J)bDG(s~^}YUZySLnVJV>zW!d&@J_Hi*IOnIUl*!+l8IQUO1 ze>v@6->5j`1UWoRQyR5T&;P087awJVRQ2J#%4i4x6ugfy6OgHNj zOJC=-LwaKkVQUiuO4GlN0xVudv{kf_!fd9L%0cXW@J#GUOd3q!?%lhJ;nY-^wH&y= zGg1)pBSA*_c$B)W{>M!1&pGaBZ_(tPp2vRQ%wJyq`{;YV+twd`*KYci-ND^U5!}~( z2~~|1RVLyBg((Y%*PTtABi%&fqWfk3a78=T5ue6C@^*XB5}b%OBnD2HIS zPLbqVdrh|XmjmFG+NNnr;IQa$iCwrdcc!mu zI&N>wwZ+d*2pqD_eA*I?oSw&S1?9rI9NxYH3k|$Gt#CX_xdGfr$92CK2HUm1FBqCZZFUn~y~XxqreQEQ*9Xe=RdBUAFK$;L8~4#^*r??P(oq z{ouu4&g;wsIXXq&TETC2E{eV81VTE@ssYiDIaP%Y3&?EFXIaPTh>oh>cu5PNR*%N1 z%p|4tW(hN!A{U>^$u?-CS+YliGiG{HCy>^cLr;}SlBX5+>=ijpZBHP5;w&^G0_VEY z=)q|889oK0w&Cqr+|a5&`1=w2 z{Vd>+s@08}rAQsBWs68_8Wk+2nOBPHr6;^2MxPl3x9N*|`Y&euK=W$F?~Vswg{it+G%`BZE3{ zE?!SpRn<~DN_c$7&+@igV_3!vV+RC!sO!sE6*;ZL63;Rq(ny*tUykIJ{uFgAWV@mAQ|0$~k=N_==#3bC7~ z(D$B)H9MiMTMbwe^@(UkCmF!}T1zy*wG;s#Cj?Z^qdP*(0QGL`irMiKAieUN1686m zgap4iwk1`*uQJTJObOl32$XzINON;?@?5Cre_GE{dpb9`pu~OQ<8K4$g}NBg;v#)O0PXB z-pz05Pwph>pr1|^Hv+Q$Z6p~4%<*+sK6gy*pIe~ zFzR6P|SK_JmF+7IWF>~iVo^}ei)kXj(I1nk;bYh?z?3ImhZvYg(s0Hh+yAO zr{t8HIi#BPqAKfOj;Elq-)KwQIl|s$6(Id3@~jQO?MX;-H%vkeRBF3rvc7ER1=ER; zsiG?RsX_v0dGIK2o=cw?ovqiQS|rpdwQFKj_SgyD;a4+vcCZu^NET5%o#6`!eUltgEU zCyiUZE;!JM^y0PhURcA>*TJxXBTRvMrs zS_I9$q{M#uB|dFGPOco63>-~k!(`dCwAM`y8|lYTjf6eH>8NoG(etJJWZfjyCZ2_p zN%#Y$>jQFufxj-dC8@Q*++fJhoR#-=!+9~8E=@l(=mj9K1=`(+kqVm-l+BVUlRG(y zm!p`-i=f$!g+7fdg45(@Kio%lj#l|#{u_Y%|D0vVOo7aa?=N}O)X%(PMJFeGU5~3R zcLA5CS|7`mb-6ebZ*cC|VZN_S>__Gxe;Q#vcx?EDU&8nR?Th zZSf{~g@&mZMS6^f^2$g&B;!K&C zzrBe;I(3kNwuw&T0NbDy%CK&l>R!iyM?w#S>caO!A2x0%w~%!<*~2~<200{A3HFr_ zR#q36bCUIQ>LGW?^ov#1O_(2VAnilA(7=Mo=~RA9tMHLlQscHx)xOxwK z_I>E);RKC1n(BR{@Y&g29zZ(bWSauh zv#bOm%y!Mh+7s1?-cFQYcNDtM0DXmQKKyuON2i8xa1AV&yhgQGdIgK`Yh{1XOK8$Y~4`(u&CRp>O{``X* z-`T<|VJto+3&{Y8F`C8s#GmSsVP1$u;q#h;>*Ep}iRg-o>upKwsJt7l~Q zK2%x&V=5+Et*0y<;fZAO!^;e7!_`uxaKbX4uZwmQ!dOZ2?w$?_`2oE45;%0Jo?@g~ z1K_*^+ZpNH(?FMe^Gx3t(|gBHs4B7Uz{pbdjU8>K;s_e|vq! zVIL#L;M+HD^T;eQvb&CPF!)fuEW_=rfjED6nF(5g-xWF3dH$8!_=~!1eZAaAgyg(6 zT3nLH&B;`JVI~IYgb+x3r6D&@a+9A-JIO~wo?187sxo2FF}V{HJQ&%fqvWg$Srtkv z$k|>`SsJ)EJ53E>@r4zyu*v~F0aZm&#YT>sJf<(7(Ze#{%JOKtj}FtrC$hXKfy6!t z`lIwp@l)UpX1-c)0+bv2aemfiBckZ(1g{!qTa{T^=5V<)kh=5HQt@2gtUK?Ge0L11 zvkuURzUpAw9QZeZtBYOhUO|$e1P}|`?3LA z+B=gaa^4$=54Gd^k~e30T$g^}Rau8(OBlnP}#)E`b%?gP zLt&XkI*C6W{fH8t7W=Q=xM7(#_9WLV9dk;-{a4Zx6}xo-_by#fUV(%bK2QU5a%Psh zs@3uCRI2+Wlwd~`n3xK$R?IcbDP5rt6{O;M+jHBsmcm$e_i}?dfdnhr-Sx8r7Ab7D zWg8RpLoF~FqGwqL_W_8)adEwo~cu)x)1YnQ8}4$eHYG09zk&Lv|!cm`$pp z%+`&grao#(dvb$k+X50*z=dqA%0Jo01-ZcQmVomb3ZT?rl=aQ%RE4}JwOpZ6f9l#) zt?o7Vxm_$>i+NUd`YDY5HTfm-@C%k|r$A9v4xpV?!O&HlxI-ghDJD7%Gn0Uo`%?r? zq1s-5(8Z{$0_7>7?D1a)I^Mk7OI-lgL+x`LlOm5s)IzD*Dw%iy^{i0xF_`yEzIRNV zV6I*|20CT$;6>o9V7+<8!0fEbRPHRC2F|xEsT9m?Uz7Y2 zK|jjQ5xGj+{z;{{M5au^(h~!BwXk?Pz$dz5?mO7tPEAHrwbfy5!< zZ99*>9>bSh5NQxU>li%~%d7YKzVi~` zfF#whBidqcMh*m)JcBwpU|sgiuSQ(DVt72f)Xc{9UH}k!xQahJs;lNXOu4oC`o}+h zpL_@WmI2KIkAkRxoNWDlAa2oy{;*eKj^uZjvYCSNh=JAtM~D-0HMi}T?rYs2rQT6- zfh8x|@*veL$EqxuJ+>s7e9P8J?Ic(ll17!>pVadZVi6>N!LVHpJqeJhc2MhLbXq-^ z%FDV~3}Vq$hn7{oKBn)Ln3r`gy;~jC;p8cZ~N7 z`^$D^t-0o!^O?`Df#``OnHJC5n=F)rPcy%mEr8{zuLHAMr4Ll{UB%N8h4FOfqCf&> zb|i4MF46Z#)Kl?eUheU6a6KRj;S)dlD}$+3Btf_tZX|0?GfSbpRG6Tw^{;PuuZ zgM<{W?~~Z*jl9G~x&YJ0mpq+FLP*;3)&7OL{9AV9Gu?s8wU!1X5$eRI$E9-2Q z9PN)@F;i-4YQPK`l?K`(uVGj~K&1dmI77fd>2XMI`!1i>->u=3iqDi0uk4z_?hm@J zD1fGN`GUel09s!N^q&BlR%x2Tg$uV3WUa2=bK_mv_ktl#QS9rt{1n^m|Jhpp+vdFG zfb=M%qUnOak7nj(e3{Xz$jeJWzuSZrtZb3A{pypyK!ksYh=}_1DRUK?8ZHyr7Rzm^ zrXjSxc>TaX&jNoB_st>ZJ1^8UvoFrJV-MfY3;g#0_Ild?0kC%#&i?~o|IY!i`N=(U zKjl_D+7Qc?

V)}atJbVAVn3QqIsP|0ML4@PO`!Mcv##-;+ zzpuI?%OnqXo8w&pJ|*>U!oz!(k8*Zi&JGm2WQMxNbzN}JZ%=|bfTuzeUrW&?{lEqX z2fOoo272u$d_D;by}%Ly*g7+3@FsjYTrF>Dj~L@aE4#17Pj9*%?LEH5kb}4OW~T3g zVne@gXD@bX9j%r4+_J|d_8kbi*a{`MYrb}vsD|diw0$k^=KEcL+f<2JP!JGM!JRP# zJemKUet!K&dT>~nK&3c(aaE=gS-veU8b(Me>x>+kanMP?+`pUIeAz%*=A-VXno&wcIW{>4`s1@w~y#C7?w*OC%?CZlYiBABfKPa2AyU)V2fE|Kc9D2d~@dRwx z*v98#H7!|Y;`ko-?hEcc$To(;2iytbnkn2zDfIM5w|BqgBl~uS=8xaN1$lS={Qu>u zF9KgsL8_JiY^cxu6902%0eu_Fq`m|3mb6mt&54GzY!g(WNjy|#e^?|9eedT_z{1vj zU}s0>EZT$iG`5rVscouUUP9kMmcvDv3slTthH&ueM5j`VWJR#CP6 zCgFZPCZZvP=`ar$Pbsgg)|-$Ik5+$_@-lN{&kxf-xK?$&7F5Y{4CnN6j{6uyl%YJu zqc=5k;F|_)=I&@=1N5i7<*k((asS6(P9;29D)9IG@g;z}hA>?e&Q^b5Gq?ZxBr;7x z8=soq#F^toNR||8W#S4zO{+m z#`nooIg%m-W4|iy=tX9--GFgB?Pi#xQw(OL^6YF+TL@nzQg`-p)X5Vqop`CEw5vnN zbL8cFs_{u`mhY>arTJ?!Te`d%nI?w@&SZ=Xw5n2{NKf4WiLY5NDW7YybUT`$ueBV*3 zFNjMjFCw-5kkFpWtUa;h)mwd>Ql~&I{QdVcQL!Jg^Qs=CMrd6(w{D2`qR$X3BFwp# zvty+lQ@iI)#&hz%mUToU#r07AQm|1;|FMv4-6E{4r~N2({CK5p{+v&hN|VE;+qigt zg>9ZcbvnHPVm2pN3yxtk?WNIS3Z+?zTpRh6<$>DNfS_ak%c~o)3Vt667#Cdsrt_+- zGpSTxT$>$b0XLuLxuc1gjq;?^y?;_UwyQ7VZmjy@^Z5Rd)=*PxU+J*{GbHS5tJ&r* z1D(3#YxI;e`C1K)A6jbno#>1$^}pTqR(SNPzmrLFg3wX_qUQ2r?^pVoPhj)i&19Ze z4c6v)zO0}5k>8&EyRJ#J5o&TRreMQ}Iyp1;$KZWjL0ItRjI(JD_30Lj7GlEFz6T5h z*LI^zZB+w@Nos30uGsa?2eZsm@72@DPqrP%3q7X21=t)&YR0?P3sFtw7_sdecJ_x zUu9X(iVV^pI*;^DXB*$!}%0khDXP|zYz4|($zn20GE&r4>pITb$0CJ*JrY{O3479h8%It z)=e+YF0{TQZgukp>H#BqrYkR}S*Emu-8Nx{(CpBPSYSM&16{MpY7d98am2)AJet#W zW=bT~stAK|9z>Vq^au&r=ZSdyt}olqodPEO48q8jwD|j(-%Ez(l{YsVD8-h8Dl)T# z=AJ4K&Ye}s+?TX9*Wo$CuDLo)Lt^)>m#Ng*eKErs(zg zWwWM_Isk|2zH(GrYN}oBn9S;8vi4vLn`uCp|H@2uX67~`u4c9|fzHz^3acoeZ*rfD zWHYEzDi5GybbOj~H~gsyERmqo=^=hiJuO+id`Zf1cALJzJA)S`bQbxrkygV3$OZ}C zDw4)Oc^z5b5ljwkJNL~Hg{LGxXE2Y9QolLQypUO;V-zc_ke$T^{)63S9Rf}5Y)ClD z9VnRH=Abl9lZ{D|3$Ms+t7g|KMi}!C=Qx2TjvUIDII3S}gnT6i?zH7obZ7;uDjo_| zDcP1$@L~C5M6LHSWb@UGOl}5RUT*9U%vS9;n-+rajg>K+Uzmq(HLZmektGEN_=3VM zQosfdxQcgWH$^!RlAentYZSCLOxZs1;`4vq?fgqGE)akjqsSwiTYP$VvJ` z{?J`c#y8z|2=*ChWSv6%FiwVsQ?h#@&~>9>b^Yh|$LZov!q{vl&3U!KoVe1hcjwAp z1-Jfa2gi@{*50(!2DB?_A6+ci}y6Kv|%%*d0rDhlKreMTo= z%X9_>;ihPW*89m+!75;KFG4VpeWbc&GLdIoNt>C7GR}%v8gH;>@5#y{(xF%c-(N85`=sVd4$v%qRff%-I5;tb5UBtw0t+Bj+ox(ck=c-7u=P7s1 zY{uo6i{WQ}ml2SbW}Ps}l!LWj29#M@WY!t;o=pV9YrFJ&u;_0J^hW*2487(h0M#3GI~IP#sNCJ!n&o`6EY*|EiPBr8Ur+!YI2bx0>H}1p9Oh8#?DQ7) zyicF(WXxFsu~z{4&N9tCy%FBk6i+pQTU}Y`{)#P~@7fT{b)u3|SdMqR6D0p^6U_<7 zuh;PVeQfeWd{y;#ZaiB;2}m$8^-pAM!O~RZ6}4(C0yOG)NUb>eg`cX(*|Jei?BPq| z$9YpETdp^uSQcAiR{^i#@MEgwBw41cA8-Ue_K-x399t57xjp9EOg2Yd#qz0DR%Zac>3`oFhc(chAmFNX%bG;&BDeI#tRK^*jd0__eg z+z6t2I3P20g6uj=6<6;qt-)R_=U`kp59#%BG5>LxwD>ws6RwX$Uq{yf#WZ!TJSfX> zt=7f{;_GywumlAu73P;}l1cFgL?CRrI)Z9U=GbJNVU#>FsIvCBd>=lEqMDYuhP3&I z#G@HdRNkQqHX@;MAtMpm8&zJA-w|j{8|=i?mOsS(h5Ebzrx0;fL2jZ`GWo!h}PBK#fm>0vGis7N*OsV_a@jf*!1CI4jhXg^kaAT@MSIQ684bo=?w%V~ zgHvx?R;lh1sBq-0Az)GDKl+|e2m5}JMHmw`LYk4p#4dNWV$Co3$kDEsk-wqtsq3V? zF3jdRje4MLOi_N@kayBFze?a#J&h=FOrcGU)O&eq1)1yz zrua?|nd6sDZgw+MkUWd|98wC+W;M3RfbjzlX?<{4QF*@G7GfKTm}!^lanv4#k-=0qnNHROSwBeq+hO2OnD;74?tnd1_o9DG|-}dEPb6LssN}fm6L`>hiu!RA!dDNq3X#V7;o%WY;K`0s0m7c zq|CW& zguV&tm+^ENMN8xvMiyRYwL<{y>~+@W5@ok&`qC@tsUl0diYD@!x}#y9!JxlaG4NnD z$iDwIio94&>!WD>Ts$>~l9`we;kT#|>&}7@qT2lYzwx2x-UE#I;m}JhV`|i3$8BEj z_g3%CIA>3q_0Npy$DQ>>j-LdjphaH^oHkDN4_JS$pa8w}fkfBI6#t!*??3jfcN*G3 zKt&>c@qwEY98~vdZjchs7HMbodz~%NQhV1Jy=?RBx3yhPiIg<&f%T{ll9Ed&D1u#f z=wrjWCUL*#eI>vR9Bfp=tbl{Z*gRr3VI47OD-(&z5sTtHq~VKv)riCj$NR|+gE=KbJ8|Boh6OsTYZO9s1SuMFom2(P z?+ViDw4akadZTB;TRZ}m!2Widxl8o5Lhmq)4D2Zu80%-k+={-?2DuC2u~)*m%gUdo``dQLG@tMqR!9a+LmTgCk;?4Qhu%}k69>1BqJ~dZIL~d zUuc(oeDQc%eKieP1&N)E-S0QZ@_ljpFxM`gmkT?rxgqmwp!&f)L_svV)gHZgG1Y&i zq_arrV4Ag!-AsC}>|D2hr^8(R@D032P}SXmkFLHXNo*Jz6;MnN)Q<_))Hb+p_sKAA zuC0auXAWj^M8RpVlf)~27c#PdZYcP?VIwMTuD~4p>+hk-)ciX0Ru&R{&IUmUOelTe zOyN9?H6iCU{V{ICLwFQJ9bmkJI7$2XDz3Cm4l*z+v*;X%wJ1+K&e%9nTalqOY2g`0 zF3ZRhk1uJz0eJXNqzDK3D>3YyqvnaJ*7(alUelZjPjaCP?>>G^w7nNI0KjISTQov0 zWf&~pUs*`gGs%b*hG6VgzlOz*t|Vxz^hj>gf$asl_EoPD&ZTOoYXEAldAdp4&GDpD zUu9Ql8t#HFXz>`;5$k{UJ}UGXAhd`cce>@3fGsgCPZ$_p=f%^fHy@1-MP>Y)wY+z0 z7>DD2($6k9yBXFq@dp&D|7GR}w5V+v2+$*2on=_uLu$RJ`VG6X4ceL$jQQPWWN!4Y zHrSN5e4?3zjY8}>AakXk3$M$pPN#>6%aKs453QXl^9MJ*0n2-4Qwvq%FwTKteTIX5 zfK9;G7Kq)PzVO}#4#`EopcjuF)*AiLS2cC3p^*5p&$Ms#7Y5}PhPn8&kM%16#yp<( zRc);odwepURQct~z5NRa3D18DRRizuII$ffKiLWPDCuM8K?fvjy+NlU)@tpC(s^OL zI76C~LFn7=59`}k-KiGY=S8GxZt?hI|r;oP+?m^(eaZG(F7-d zM=OCaozRqQ5x91xixVP;HYkP4)5)5;1S=ndSWL$c07Ia1=E0G8??z@|*8`SW&yd9a zgTFaSr}PItc9f1F&3tsFyH?~BxmvnLljlREDiM}|H*bVThkvz6B|Iu{?l&8yCCDrj zt7*V&NRva(EJSguk?MzulbynHn#_;J82MVXGS*HFl}JRa4p(ar7HC~ZWj(S2{y`1u zzz_oZ>5=O#-^tPzQ72b;a~3-FEzCu7)V9T!fP4S2Y33UQ=bQ81WtO@3+MPQpGl3z^ zZY)+#+i8ko9iQHh4vu_d-GbaDOT{&9(`6LPd7aG;VjSB!PP~e_3`~<8KBwU$a^d~3z zNr7@or&kH?C|v_@rPI4ojjc#xyke%gMi#MSv_7TIh1XAv)D^**BF*0%W*?Z7K#`J5 zk5YdV9PEiNH2!kNJR$vD!}gN1)oN=6b!N`yh4?lsXs7AIyymP6$@8=J5Wq{AjMwu9 zkOFHPs{3Ea9~CwePyub2AfEofHH-}VoWfgS12t&@Q89TEQ(K1EXQgIHQ4`M7@0aoHHXlwQbuwp5mz37bF4fDwHzF}(wdb0i=PxX9S($#K zUBS~VspJPyqDG~yAvbA`ExXu0JO;i0!(Y~U!xk9tOucQ=nGI2AweJEc_H}Exppb^I zqR-j^P2^Q|s-pB=+pCKFEw>qnCYq|JCtWr;gfKb-pER%?Q1TPOKSDwl%JDXm&rv7K zf(FMMCb=v7tJ6WUk>PlDlxYlW?9y?H+w~{U0%yMPuD9(9@7{!iM(+M6u93Z9eR9Hy zfy^Aj@e#Pp33sX1j7FX~*WSdQz>@u*<*JX3mSX)7ca*rsLIf%me|+XT`Ad8GVACyB-_j$znhxUppm(5~K5Rvy0;s@H3kPp>+# z_EA+$Ew=un$iZC%LQlV30Hu=R3m}0AUZ`3>{FSsoBqe^U6TH;q5Em^3YjyCZL0wAs zkRpBnDt=%MqyeP-&!6Pi&_*bGY76=Pc34L4{Kzx#C-nNk-BCHN9q;4kw#H)skYS7Y zZvrxiYT7eGw1caS%Dxrpb*zr?#ru3Y@&6Tj;@kgXPvCj*=IS3xnQpp1&tn!%&dJt~ z!G7&=^WT-PvG0It?ynXj4w!0sbsX4orIH^WszO@XNRnHG4Pu6f+TzlCjMkUaI}PUo zKnU+E+7s6NMl!J3+y9%by@BeyR48$cr11H&o=egV8}U3dSN z^}sLQ1u#mt`I~oPZ*LEH7o}rS{-y5vJ1}c^LlSBCYk}hV@cDchNi*u)gY-7tI$(!; z<3{`fW8aOCN=F;;K~W+iBBX?^pK~ZjMT-`y?f$G_`d(Z5?c+t~j^MEeCtl~K{Cod^ z7Jz61{{X$Dw zKi=si{9$g0sus?7wg%@8R~Bu(y2(W zWZt^&wC5bS`S~JP;iJde#{2i={RHZPg7DI-P_11KhJU|;$j8rs^Mb974Ypv3A@=iN z-QK1KTlkxI@4lverOEX=tNk5cAjrp8L!~_A<=WiSl_DRppLuRx+s-bNMxYgK|KA=0 z^73XoA0vJ~oJ#wWmSMZclmH*$zvUMwf?b$QdC0QxToz1>fsFKY2ZIr5+!<;dTzw!l z@@?_K|1!Yfz_TB%Po&;tWl4|6PJQ~6{T~txK72^VpDCSrBg&h3d$q$$YvYjcIS%&U zFlWtnht_vKYn^8}cA-sK?@${$HH9bJEhtRXO!IFN#$o@hnt!tr0A>j-u4c)#){ZkH z!J#K#@lEc1$;Jc7Ig_MusPr`2LG+&~27q(!+3?bs!_O3IGr&9XU!)kEjDFe#w&NZr zoMFcE*BM-20=%)K@jou%S+(! z(bB(O6~s_kiGl(G*>x{_j#8MP*Ol(^=58K6o4){ePtXc}^X5XO;;$G3MdxJ<7_pKy zn^Yb&`cRjjdXUOg{L+c8`OKogY?9|5v__!wXL$5PRwTJxMX@HPE@9ArMYl7z5 z=O1~}Hs8C;5qxJ6{TEeLuu}2(1Xv>XC+P3KCf8lts1p#KX;FigB|HM%9dZ=Doz-2th$F931O;GzlxARsALP7>ij4!5rnZQ3G*op`K)Wi6AWR zV=c;PI{%WCn7*X;JinZg!%}Ttu-CG4d3i^wqHq2;_fj#Gw!&Y0d`#!{N_D2bAR-oe{Mlv zTUr&ays~cQyK%+TAjiOPG$PFC?%lg5Q@Rk_DFz5s7kRJ%5GF23*?R}p8?A3s5}mnt zk)J_(q-P=&;_3Mu3uN@@wYhtjo(yO?xd*)AVir60&l2I99+++iAC4WoP>Glws|r3E zGN5W@UClaJ{^(;^Xcn3cFd5<{9(PaF^oX_Fg2%myQ};B8idef|n~tlnE-H6aHfq$T zO%BdpeY`67UH13Gz}f&7kP6=-vxOqp0)-8-b#mz|lS9 z3VnK!Kkm`!NY`9sEqU^cwyb%bw1e-rASzhvV&Vvcj?=ndDNZKyt26mX@eROH(z%Z{yGJ zX#)07I=YXs9PN0SnlMuo5NmUFJ}vmPM1Pe}cp?q{Z43D zhT)c441nf*+TVLDg{)IhG3u!w{VeE8=>j80(4u<MPw7yauv-N*>MJQ(}u*U6h&T6mflx2a#3%SUv4r^Uv>EPkH6R zOJ#XrVOOq5b}datuc&koh1pJ{(kd8j2N5k%N=lJ2iI#}+k1_AFWYdK0w}fQMk$GDa z*Qq{tA7m<3SD$3HO{^1g@Wl_!vs~RMk@0Lfh?&my(57fxB|^kaXViF zfc)vB98#Uelkw>dXs4u4?QH-&#;C||$F2!vlzAA-O_Xg`Ef<%q+%WTM`W_^G`4aHc z&WT_ZTYmu3Hn9uIMSwUV5+$VHpHRbG;r!7zK~~C39gp6jEYRW+Tc7M@3+(v-1{uD& z8A9=z9D;ZenQU3hwrdeG_KoWL#UtVPfdY_=t`-8kc55trdxQEhRKJ@nif$NS@-Wei znaPvlkn_(L_a&8EMbr9-A1@hI#k)*(ssY+br!%cqlirxtqF@ z7l;a68w1zU($XATVX)Qpca!(C+?7}H%M)BQeu0ZwKGcd%>RKWQUY_vZ2s(=P)NL_O zSmM?O$JmNZ#au&Yv7Sl{t3%C8O$W~rH|+dcVzzO`OF43n1!G9bo%42uIH43@E7KvL z=O(w&8FAHZPD7MF?L%GoQCpyz7nc1XD^QN%Xq7%a))8yR7+{I-hywGS-8M1z&8Q9b z%B@MvHFfR^^9&AE>re=M^fBoiNFMMMiW0Ffj5dW=p((A|U!b+<)d>Z&t5!2yRJyNM zyGQ>SwmgiDXlr2_qHMI6-bY>Ip}~F_PKlqE+eJh09oQjRXygZ7ce)uwomJ==m{&Kr zaKl70Zq++_@khPS%7R-DR+cJ`+SCbowC#ykluj;Gk)EGn3~o+FcjavMIT+7g1z@fX z7EUO-6(IvpF?a)kad{;RJIvja!6Ne*_Kz(;owOqWAmX4ui4wScPtwA@C>gglgu884 z=G3I*NvL&5gm5ydZ_7@U9U_xhy{lxl`KYcUNh3^@$#|cahXzS4bU2}#8(T6tNG2Hy zq~7<8{J71CW~TA_&A3R(Z`|qQ+{cIH&gm@nBuV7v2KO}Mhc27>cLfDW3ty^Kq&G%% zRe3ln-?=ljk!00bxH?Ye@_j7AMPiE@E4G9jmUf>X+9wMM@h*6r>3Xg+>q&H z^=AF=_2(i#y?ZdkV0BlmyOXmV+GF1^;mko>I&1vJS+d`GaVX5$fBL%-(*0{yi6T(> zY0EDK(gtjdNj^Pi&>t&TVWarC)s+-+hn4kV@`bxC%^1fYRz6v}qgKV1bOGh4V0TNp zZ3w=-Vp*}hqeWqgN5eQP9?*-j;5GhYWu$zU6y`yFef<*eCjSKD)))*e<>QM4=Ycp` zmd+CiXoK0=ybm}DHxFd9ETvkK$}U(jp%NPI1!K(jjQg)Vv-L8o$N_=EqW4k$U9eKB zU?rXrneB511-*t{J^wEgeCTrfoAVi zM|f3dL7fa}k?Z*n_Z7%4&*=~LGZP6MpyO{kUs2rM>@2ssew%NgCW7HZ1OjqLhq(s* z1lt~-`D0ue^#&s45}3n(Bw$MoeD8c>9%05#&Y8@cnqe_rKQp9t$A!;H*?r+7@BcK2 zkt?O#Hyz+f=pEa}O9n9t^LOb!J$b#;@s;p3&tOhnVC1cfnnYLX+kVW;b02O)YiLy< zRc28gF8Z&PRys+PnVhoR?^-#kkzJ|j#zj*V+tRuPZ=jy8bP+G_lF@-u^SH`I$0p*^ zbDG4bY8u`sw+;3@QKvyVnj*>E4?NDii(xL-nt-ceZgF{I=c{|Rd17wbhL7Yn`<#rm z_+vSBraLEXp5UFW9e#`K6Mh2M({zY2AFa4D^&B|$yM4=49h`G=H1rvaSZBH9{uvcD==bY>n5ItZWsk z6+U&-&G6e-oxa_cE!91Ux#>Z6TQ0>wVLKFs;beYt(o6Z{3)M7R^MG&i$MbEdcT&!9 zWK*372V0Pc%}`=YkxmPKtLzwuV4St0%gWjB-@dKaPs~vgixwDIPP7}#p-SnkH_-!x zvx6=Uc`xf8ufEx(qw!nBPNVRx;dziibp3J}Vm?oM#e0Af>*Ih>e(}n9rS76F zZv!497g_)_z<+JOj8%VZP=uktcbi^C`rJVmx3*}Nw^aIEU)UdO!6FwrP?IMdI>-*B z%a27wA2roe;=NV$+4}o6#^>gBUQ&xDLa9+}1q&+`u5eHZ5mD0-#7=@Mj)E3}I(Dq7 zNh!)X${)-#J~Hsx(yV0G7e(=5n&;)_9_M*nxk|o6YFwk>&9b8tIitZFk?eY73k~gMu&b@&jTV#=4a3aTo(7=)))O$@gwR~ zVY|4IDULFd4;YOVq|o3nq4D~f-pgLDqQ8lRb^xxx4K~XX+VqNKEOwtPwCM1)(OL~J zS4CgRiFpr14Xy6giM1waOe>CFB17XTY>bhzun5>R>!uc(iyEoaK_5o+l+i2T5$T%n z4%~a43>VS){&P9O=Ne{{1P=j+fWBqHbsm>qsgklOCqL%t{%cxs*B~jiCk83kevuDa zjD5GiEzmmGQ%7L|M~@!$hpy4ca!xF|E|po&wVal=k%zw^Hm7&ddFg!qMQS?#>@0D+ z(kc|*UtkD{c(mHlT%vY4Dy#L!5lzKu8-rlsl+}B3o|D1G=*!Jkb;aF6<1@nie45T5 z!F09!MpiFOhN6`~!d%psvg4LBL@C65A`^8%H!gIy^Yol5ZH zZl3SZsq&OIK{^b#ozeJkxUkV_*6DCKDc)JBajs$H;Vp?HMHMe**48Y%?m zpM6VR%xgG6pBsj)VQ$UIxwr98f)ci{{yO*{sWMuuMAf=)Wrt0>*L=V$R`mRK3S)SO zTq+|3YzM?5Q5F)GwRe%0x_HT59ITIU34>DpHow^yzXL**ym;?76HXg#U3Bk|9}L%$ zKIwC@nLahSOuCYh)2vx1SdMxrBJ%BHR9qPM!+ASQ1V5tEzO9@!x|;Fm&RY?rRmgxs ziRF8O^aB8g_pWRV=S@vOD%M%$niO6DzxJ+FOkZD3qVLZjilOv()}`X0`-e#zF9^=< zvnjwxkKK=j>2f@t@?OqUW!Xk7lT>1b$-5IK(?MXJFE(B`wE5<^W?b>nI4yXNy0-DG zIQa#zo_4{1cC#9*%(JL$?RPfhyAsDCSAes*qaYt&FD-Fv2u>j7$)VlKw19aUnlB!qa22Lo2sBK;5KUO$TC2r!B13X_=E+$aef5| zR1j&`E@#Z~ZmAw~z*&yW)6tskM*D=!nq;NYc$-bm_bZVPotP~TdbmxfG|1DA%Sots zv^usx3n*Hr1LnK@O9hOVPmiMC7H5BvAW{Ct`t&P{gxRT{mlamca9AR%*n@bh2^e{S zk@zeeYqGt@8syh^?SXL`7@W0J0(iH=S4UZk332y_JpQE^O1OE9VnHJXmXsSi3DC{F#5=4@VmD{{AjS#2 zn7r;3M3cVF{j!(b9fpEYIjGicCWiDV+8CY zA<+ECv{Lr~ARwfqr~}KXmNsO=wzp&)%J{qkzkaUqpfj_TbHxtZQdN0LYnNZ(~I=4Ytd zfHlKb1_Jc}HTg2kyG|OzEGDZCc2*R?v9DZ@sKpOg&U-LdPqvti(FW8;-}+kyx>{Ng zY!==zcDN3Z#_qs}j-gsNv@k2vb82V$Zl9jb2@My05l44s&Ixi2>F##}gk&>>|3JGN zp1FHM>X0EHqr@m<798CM>bx68^2&SV?G{+?tdZpbh3eL|<++Hi^g*dAXgwU+Q#P)E zWark{0pj3#hJ*M*!0&+5}+V87lpY7w~tU~J{5LF#lA;-9VMLOIg^(EDYviN{>@J{ zZ8hEU{7VKQVtHLh31>OZkxLhC7Hn-E3tOwk6BM!?Hg2aYX1TH8TS{PrldIEi7-j+m zmXAoJ`GH0DTfsY0EECG-1UUt8?`doIH14*q2)Rx_rz$Mc$y=5|rJM~E}i;G8H>^!J#B>354 z#8%>OQDSFO#_@Tbt#vA!)qa#-U>+k3DP2*xfTfn>#@~I2PyTd8;uv$2zxub>dA4)x z1uc*RYcZil4}5zS(hT(U^`hRr%RF|DrCHu_*zb{2GC;W_1fy2vg(QB;A76BspgGPs zPcrqN2+yH}8Ki48(|(i|eYi4w+On$T#G21Z=#TfOkeOGksq)>7wI<5)R_#yDoKK(h zu5TKBf;RI+re&l}PUSUiYHJM45>r3#g2z3(ywfsHIdfzfX8FhErx=?wuO+9LnEJ-c zL(A3ibLX8QpB5OPJJhlA({-c1f2@lMd;=WAt6}JrvNCxzk1zaIPFFFhz&S(M5UumD z$vNju;)f42tOr(Y9!;t~^s0}bre`{Bv@4%%Vfo#)fM+6{WH`o7WShOG{^cuk_CbpS zV&Uq$K%2h;=Jy?U%LmyCHw~wLaSs|F<*2(bXK2B#?pH~EST@NoZB2M|7!O!=^hf=+ zd_d1wUcmNG6!FxhUw!A_LHAzq2uLgdbPuWRd1drTY*g~kJOI*ffAX`<$FPo2zf~}q z+B2AYN3ez*0yl09Y$x>o{?GQ;&GQd`+236Py>rBl=L3EIP1m4Skx9Sxqa&(-7cRFu zGQI!-1PIsc5yCq_A8^9)@y>z&LifZI?gD#AmZxnXhMI8;kU`;Ad)Yx8-a$=100G{Q!jd1DC%EE zV-+P7{*in7uTfDeeHuj7pYaA=qn&Vzvm6{8k!)PR8|njlqPD)++T_1$4Q zfE@0aKD>OHb5BFFM5yOZ-M9N*CFGjwYSSm$zKBn?;?SqA{GOM8U=)cI7JbY$(SLrF z0IdR-`EudZ!U2Eg+4=CO`lD+@#NI%xQ_Wsha#*O`E$=MJH54cfkq%^;_@xhN9|@c3-((u9^)D_*I*oe?;w${DFIm+^Ks$ z+`yW0?se}sb#~B)@%*;E+&1<-`v4YKiw~;Nj(d_!j;Mj3`OGD~XXeED|49J~mvo0= zfI`D5LZN)P@nr9z`LfNtlUu-BiGMzre&+?1wHu1Ka^*_E_R0S;w}8f$|AokS@$w}W zk5izN4cf>f=WN8iC=9XEF8n-=$aacLVpy=L6k+rBAD-N60X!Lf)8xYyR&T?Ba};4&*?yp? zcCXM^7)Ok=nWI~!DThb@Xtmw**`8l~x7gejjGMX5Muf~m0qgBI$fv(k3(lN5 zV_?~K4(M+GH>m}HI?rFtb4d)0 zHS-?#asKJA-S{tH_h9w}zc#pU%6Y--LMmMSz}66_^zJOUFQ-L!%AOkFT7+CAuQry6 z&pZfH6)7H%PbN3P_h3eRxxfaPhGS#2#MZn8MncZP&lz6{OsxA)5(`o$cl|e9Z+`8W zz_kig9{(?s2dd9MetZcK#egkBcK+0{@pD%RH`{`NF`I>_+}iF`m1nmB-4QX>M7_=@ zxl_7;`h~Pt8q$}qKwYlr`%zip_hH!k=`G@WP`e0A?{VRMJ5-Msw>~>*6@(uch83Lg zII#QMy7n53$l=pPnXevAz;wsANZ|`agh=Tgm#x{k-}Snizs3*1*?>D_UmMSIAEl;j z2AjVAoz(Z}#%&XSY_$@IGT_jAYdhS!>w7p476$OM!oH{0Sax=2mD4Cvy_>o3zjljs}nYJTa3vzEeNO-1S=R38N;qWSxKPoxzP_m}3%}P3PV|iXo>`X?Iy0YHL`NhhCIyAy-3TvVzRY|S zyz+wctY)V7<&I?*txy*HCUc}mSG2Fs&(T%0a19kiY*hmYQ zCEqS1|BO#{r|heh9jc~f9t)mZuur@)-B2q+kCq6Y+kAeO1KrtjNW^3Cl?x$XL{KEx zL^92laVw@^_AD{eEV1r~MwtFgE;CEk7NCEy+*r-7VhqdRq!#TBvhEk_3?f6gWxNt? zn&~>DD#yFsPRwo=H7F2nEH8NijkXYKOS$ScTc@CSC30!$cD7N) zOTCVE&+Ul3vOb#jKo22rp-S(&JK1z2RQ*7mX~CF=VeJelBFYab8GYNMC!<)fdUI6i-XD?J@|T zUQAG`{xfQ&kFWlLltt2om}AU}#Zo;X9K@DH%mXWdrmoTFu5C=V$dL+&%G;Q%5>Ajf zdBVt{KQ3g2hIH&)m@=8^D^F{7Bz8Ju$Rtq?S@&#?&YUbL&1ZEU+EXK5t|!9B!}+;g zqOCAyXxo{P1;Q=8@Ok=0v1;4mb_!Un6QDmA8dRkYP$TEs4I`3x2R^QJdSF7cD{I~w z9o}6^=|xRiz-n;zI!OV>gS`y35?uOsg-MJfr@UpDi8&l?o^YiHrm);q$2_2TLE;`? zT~m8BiJt!B#}O|VXpCG7?jSbXW>wff;M;ErJzI~B{dgVMa8vyhU3uD%eOu2Z{ruZzi6rt2xBzk>F?KedO{p^AiMXhOWF#v;NDC@v^i z+B=u3QTst+PC~7=#Spo{coeAmL#@NRjw|=4Z(*Ae-wudF(fAgrUFOg zXr4M*db+WHSv{+=z?ycbDCWwRWXtI@cg{b1Dn;QC2?&dm?0QnxNyOL z^SjVY?}VP2-%sPhFTkxAEDeofKpGu5 zcqm5`DO7$%sfL%F5dk~;jjoRL8aIE3cnmjCqJOH*_m*kI;qG$ExO((hHWAVJhsAMN^BhU7>$eO<3|hkm z-8NUl@m5@hpPub#hfOO5if!(}N_RC>!wds&|gSJQS%3%u2_V{$h23`gd+=KR3z z@LS=PxwOOH9Wfb+nIPhPaFDI$<%+?etkhNb%nfDbAjc=$oXacCt~8np1zkx_i2~HA zH>V@6GB#+BziyKpr895gOtK#&IVIr_&;5P2`w!>T-->?WmgeVQQKxfA26ughg1XCf zj)m&@S4*e0ln3A?De6kT+mjaCnG{?Lc1f7-+H8y`{jH~GYLaeXjJ6C$@hENlA-FwV>xO5)6;Su zo-M@QeCR~Mq=3Uuxs*X$R$^R4sK=TOi|yLQi^9@k<}G1~SsrmRZY&2YL5Nel?lER& z1Ji&&Amz{F;qi>1h`zS9NF1&|xjNrxxRx&@Dyj){aT+~|f7B&QUHg%2EPlyFyIO(B zgY+_x>L%=Vvl9dNkG2Oh4xtZVUtC&m^ORM(>u zb9*;%=Zb9mwqH?^gL#c!Ap^6nSq zWXJG`Ed~oal)I0o$71*gNAEpDAz9E)bpa99EGQbcD4DIpOr*A$pz;{+DpD0x_38>g z_VFzjmxTbYWu78ULxO99ZVud8n_qPiM=w1MMR@TeB7Zy2MBm;e?6mOlkL#yI+#Mh)cLHePj0rwJHYh#w%l_95WRv_ z$86N{jm3zW#Y@IE)vXS&R2X(2A>!*kl@gH4}#ZLh7Y9PVmS6 zN{F|0GH8rtIw9_Sep#wpeD#8bv1r2NqQlKc2RAOnImRPk&wCRcx=zM^KZr@rN<#;h z-+-N8e9hDhQ1ge%SG;PHV>~W6ttNu}!9G16&pr=)FBj+sIICry6|BTP=C~^NSYikV z-Z{<7s(-X^g2t^hf|!4}hfBEkZo4-u&qg8tBn$>%OqgMOd1`{f#RtLS9`>@B!Yfg7 z`8D{XYSwCi&`Sxp)q*Q_rp~7sz+56NM0YaE$v(J3UZ0hO`T5b}j~^Ynl86W=EJ+h0 z!b0exwz*6;1BD9LI9)i>n|21sI^!T%^Qe6BXT@Row2DLP^?T#jZ7O!%nE2%yXja)> zEw-HN%&|L#&kgc*vo<|zkQ}fgcw*pM`*vp%(v(5Zbp6$iDwjB^a~~bZNyQ8*!~m|V`TsaoL6(Wk#|A; zjgO~E{KZyRwBvlbyZ0~3snbWjy5W)dF#AmQ7eh^_6mXv{<4@6lEpKQs&!%O`0MH?g zoi1J6sDKR?X5J-s+b`>T<;g|3ZYwX>(Jk2g`qyM3t5iZl{$M_KykUF|okZm8r!v4S z?$luXpkDwV?2O!S%$+D;gXiq@JyGddo_?Y0;&5)3D_|aPyma`(9{JIIf|z3EOVD>$ z*;0m);7y)2K%ofq9Y0zr_WLzmz-Jl)7WbE3vk4{%acHU%)c8S(P6uUsMT~$j!%duu zu2gi8hU!tJksp5Ku83S-F;jB6n1n<_*KbF_3fBL9D0AE$5cIH0SBFRUj=qjS8A$=2 z4IxTZB=$2qk`7>_7gg0~;rYeUowpUJg7?~k=>bWT4R^%256>aQXU@RAzgFcfr>s|O zzBE`k9u2Tx4;S^YCh%C?1B1ZO_b{(KNyVc_Am$d=Ba7T5I}Oi);89PaYprBcbmOJ`J!ZuQB}M9MrJ)XNCDwDoHe4w76AYFC`jj>*1M= z;rjXl?f*2xHMQtvNn`+@{??0qvg1XIZos5oHCShVejG@+hG^W@g51k2Zp-;y zJXgF0$f^)3Jbp(d$eEF`+Qf}$5dXbGZZkV1P{uN0fdZhk!9fw5gXOA2fH=PVI7-f` z*Ag^M>Se$_EG_bDTJ_4(r5^?G6I{{6$M;CpSy%ih51Wa$(@>6!BxAW#(BsWR{52q5 z1p0j?u~6@rN9W0HfE*LscOl8-g56CkXG`wh;q1+Cl&^|EG-@ zZj}uQ%+ZEIb+!MAvaZ#`%__%LV)+VFp_H#1i)peVQR7bV78MZ;&HoTEpu0Lzp5svi zP5YWHp)`hNFJr05N{#g}6lwVqAiGwI)x@gsL8s2j1xzKIZ?_Sv;Um_4_2GNvIz>48 zvp};?ZgB)n`l^s;w7I=O21uPk34K!I)@z5--a<2v-8g&aS%5n$--oySh?|Gau*DmyHPQ`TSy4aA;$zIw|5@=CQA0{AH7+Vhnf3CkPa;&5v(2w(Ldywu2l z?IZX-en1S==|=(*qqH}L{V&s}#}F%rN?#VdDoN#%t0QZin;B5GX^C!&p*5P(U$BJg ze)@c7vOSy($}SU@A86|r<&P7J#C9i?DOf$f_>R7?*OcobU3;|Er%mbf7m=sB(ko>p z?_A`1muDhxnLg~i#(#rU|CDH5xVeRO%@$c*N_CdPtXJ<{1Pq8E;hTT2F%5RM zJs$rl%4FnsMPUhSucExHikRT$hyMG-eUo%|F5=~nq7u*#9%Ow3Z080=tx~qiWzn-| zSBQ^0o13?7B`Dl3z}y2vs}vv;X^$Us0A-CLqrT4WDPr;BOYC0>N#ja(7t(1R3tq^` zFNgh8qWSaC`TUO)e2v^xEQ(SRE%os^jmL!xCZJC*mH6tr7=X~I|1_Q51(AL3q3vbe z1=@lQ3CISGN8Of+;btwS5S9zzIQ`iH z6D%*DW5HJV!6))Sh?M%9_N-r2E1x>|llp_aSrP%@r48Ox{;~aErK%@Q@lylPTZIZ;k{lQjTWDh; z(XApk5zC6_Pmvz2wnvJYh`!0Z(q5kvOH4$Hn1GcfB&;0UX9}uT*A9xEm(-J^#y|7+&9;LF61 z(c!6Veoa+Becu6+-f3*cYVx~x3-zR#8Ha>JugDwush0-8X8jEa{^K#6zrZBnL|`+m z{#Z+01&|(rCI|hf6z}8>7TsS`VhiZ)GD_8Z8^Rxt6gt-W`-Q+ufDLY15IrFxx{$(g z&S*~)C;+cC14!0d>&iV=fYp*JK!DS|b0@)9611JS&^ws+aeIbJMVa*LH~?l6>M%9a z`1>nYgn9dn^ZJJdDp?p9AayE}WIOKK{bE@AH|L_aYS?I$e0W;7pK|S$C%wuygMwmMV9u)(Dz4 z0ePQt=OH!L)>2rqC6QoBBvl^mkAWuguQFUlOLdoaKr<<5MAc5v8$O{t_u()9h6rA) zU9Z;B=b^px>o5Gg+GO@*GRW(_6`tqVA38yQ?$(KCL@n=;s}Fv8r+@ssXg4L}TGZC^ zCjPh<0pI(eLl3n4RbR9Ey&vvSLvD^CFq&UAJYX5oVFOLRXRimYZ!C>p#+fPv_ z6mx*{n;TCiRnn;bMf-YmYez=R%MEmNY@ZY-Sg!KOqOq8SZu9J{tZB1m+2I;>I;wav zLSi>8iud@&wHB)x8J*F50(Nw4qEM}QJ8W5un(=k&rO}Ox3}j-xcTyw zT&A{JQ4}yRDb0&+?Ww)7XLWe$*q0oFrcb#Z#LcVZ>+mEERC~UtZ)qJr4x#V1L2v42 zWJMhq)>x-f+OaU%Fd!&N1wb6Encvz-3165=MRCQh~=htW$F#7QV(W2%sOm|!p*9{mh*W$VuzkB!x z?~G|h^Qqo3=3VZmrL*C$D;)KkMU@v?*v^&F(PSJ}J|*75dDhoY*@zNM4&4?-L_XCz zH&gEJN8eP8`b;x*|8(kiSIgX7xU|cnYZr0g?rL;WE)Qf}Qx!y# zT*X&Osq$3sWnV&ViOR8oV5nysXPxs_M!t|wsX!kkrisTRpExQqI7lRy_5@$kKX}Nk z03Hv|b#dv>HKt-(tjU*V_uvmtMy}d^=rFBd^nK!gH+{uxbzU#W^y`^9r|ivMXw5`K zSf6MCv&~bn1aa3JWnw&t95ak(8$AlHGdt_Ayb026g9TaM&Jh0 zLMf%!?su=;T=z3o;3KphpPEO7T z1Mt^doTx?1VcKs#fFOjMCF9zc0L!7bzlNRwQ5;gX_Vb}F z2Jdy6_~cVB*Yz=F6hv>8)acFLPF7}5D|5@$J$gNf;nW=5nAu@%ZS{|>rW%`6v7@GB zFRGovYNu;$H80LKs9bM3r63a6GZREe@kf2Fbd=o#_x3-&3fZCT?Ci94HKNyuxS9dO zjCjwI8|j1)&THzH)vunKNF>)~Lus$LujBPJNYm;v%|Y^1d_pO#Y`jsx8G8C8$!Ai| z^Xkqr=_GWAw{dGeI79Cf{43JW?@O71w)ROulcx4p+6HNk9|msTnY`{Upc{X=6<5(1 zl@w#)J2ls(lw+PHn6f|G1~radQt-5E`>Ye0Ku!=#h_J#IojS#60>Vdq*0VsasZX_~ zt(T+d76%GrSc~*8%gME^l$G!v7tE;?4W!UyBMjqO!WkL*OynD-N*~V%!2jp3l)VZSPGDuJ^=Jq?Wlk_W@Oy^jH@idBww#L%l-?2w%DiMz1G`IM({i z!D)=2TYC*<>rw@CAcV1WPBKx-!~9E0bBIRE48v0zNRTaAT|*hV!?>f*mvgU*JB4;+ zdKtwKIb34pdF@jBT%?S;FLT38)X9ytRWNbgt(S?ByGO|;E2iwdsr7NIA5Q0qBZS^p zW?Ke*wEsT$8HN7~Q+~H4~n1IX;2WgYJ=IQ|U}A9E5#6V?smJpDV}cq2G#vUD7uw z8{A%{EvxnfbH~DxMO#=AQw;ZuO|;%~2q!k$2t}?}duMHK`pLremTpbb{4FQ=b5YQy zWL#x{$q;1F9Qmk(7#A9s`l2tcO#XL!9S4%S^2&0oq)gsKWtKERH)^*C{j-#qCg=-oma&I&icAP zS9^X&*dZAhj5qpmAo&6|5>I3hv*vRF(sg-n7V4}*le3M@$Gwgz;C1-Oh6Hfot75jB z6Y_5vZDX#SuGSF$ob}dQ5*f~_sI%w)Iu5!?hT~n=7EoQgUq;Z^^YJI2Gv&} zkTFS3&8Bul!T9Njp{}aa96U*F%O{p;qwfP<6`nI%bJ3H-w{cBlTAP3XLZoAEX1~or zGU4bOH!qaQ!1YJo=8IajXF1W%G}(h_zugdBx2k_}Kqn+JajE9a8*efxv< z7}4o|UrT#Tpq-1$g{3+12+`M&qeCic+ODQUs+-c#!!z!Y*3Z0W@o{&$Q&1EJ#S7e% z81EG+P;s5ljAqQ|8>l1!`Ha6Oj6c#%HCA@phsC39eO2p+{qXtAu&GYV{1@J$5T}5S zozi()yQ2`H&7(h>s!s(Z2q7minV7-?m9)K6rktV0JLg}1$}=-g6t;^OQk@K%Vp08L zDqb;il=GzQy|XbB=cEKXyE-p7jcOcfsgJzAa(jm_COVoia^SFv$OrU}SNg77xHi*L zebBDJFg9%F9LlZ`c=Qb=+4)QL!;m-M=B6UE@8I9ex_ORQW)2QxJ1QD6&ttrr^g>J| z3OBkY*ASN+*y8ueaK5bi@?!BHnG3KgemmrE^UfTTb(YGJTVvr>jGgP^&g{1kj`QCX zx&3ZcDvfr-a{aG6gFiD6H7^d}ZIHMItJbaKHO;sXlDN-*umv3q>XE~>A&=JuXzIi>5kNAsXEm5W%%JWf@E~XXJS>p4oi1muz-&O1n4x%3K{b)Ub<|7d zQ{GNxZ1!_!Zdp+xmdJRgR^A1FV)lqjc@@f%te~~_K6oIUBl$qmj4wPs{+xgG`B3<1 z*~`hGM~#1=Lh`+5?#qinpa{C<1DX!Gj=85T-}VVLuJ|Yo>IL<>yLlca4d__6@#dAG z5@~BZ{Ay#zi46{R-SL2pDf{vxBLZpCQ{VJ#DUEuRQ+nWIhG?#}{6y-Nnub8XUh`F-@3q&M_#A0V%D-*LLm=k<3)225s^QLPfX(rC!Exf^MYye}r}_6U<7ukFu`@FfqW7}5_2iDW zWQ*b>;6M)a`zVQZB02sdxxMQFe^xf76vf%sG9yN%D#xW6Wlz%5_?1;uxW<+qvJ=G6 z!5dRF?#q__C06lT8w4)mnKkUZlzqP`KjC2JIp6m&goI|rcqZH}wlB_SHfZpUa{{v_ z9XG<91f+%#w6y#&QS@V^h1_86$zQkb*Yoq{%d8jU`RtTnB7eiUoA_l(Qm-j;dZq?z zJBSu`Rb=zhkG~@=bH%75Cz6fqg-CZr0=ocKb`%>&3@)Xd58HH41B=N$z2`b7?`dseZcz5Iqe^v+JmYMK4JegRLunX+YSZrcS}oO Kv*?Cx=zjr;x-ZTE From 323919aba76d3e265ac8534fadc3bd7200443bca Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 11:58:03 +0200 Subject: [PATCH 15/28] Clean up resources removing previous tasks code. https://github.com/solo-io/workshops/pull/69\#issuecomment-885498960 --- gloo-edge/gloo-edge/README.md | 121 ++++------------------------------ 1 file changed, 12 insertions(+), 109 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 31dbc9a52c..6724d007f9 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -931,13 +931,6 @@ spec: domains: - '*' options: - ratelimitBasic: - anonymousLimits: - requestsPerUnit: 5 - unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE # ---------------- Web Application Firewall ----------- waf: customInterventionMessage: "Payload sizes above 1KB not allowed" @@ -1008,13 +1001,6 @@ spec: domains: - '*' options: - ratelimitBasic: - anonymousLimits: - requestsPerUnit: 5 - unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE # -------- Web Application Firewall - Check User-Agent ----------- waf: customInterventionMessage: "Blocked Scammer" @@ -1193,18 +1179,6 @@ spec: prefixRewrite: '/' stagedTransformations: early: - responseTransforms: - - responseTransformation: - transformationTemplate: - parseBodyBehavior: DontParse - headers: - Content-type: - text: "application/json" - body: - text: | - {% if header(":status") == "401" %} - Hold the horses! You are not authenticated - {% else %}{{ body() }}{% endif %} # ---------------- Transformation with regex ------------------ requestTransforms: - requestTransformation: @@ -1279,19 +1253,6 @@ spec: domains: - '*' options: - ratelimitBasic: - anonymousLimits: - requestsPerUnit: 5 - unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE - waf: - customInterventionMessage: "Blocked Scammer" - ruleSets: - - ruleStr: | - SecRuleEngine On - SecRule REQUEST_HEADERS:User-Agent "scammer" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" #--------------Extract claims----------------- jwt: providers: @@ -1330,18 +1291,10 @@ spec: name: oauth namespace: gloo-system routeAction: - multi: - destinations: - - weight: 5 - destination: - upstream: - name: bookinfo-productpage-9080 - namespace: gloo-system - - weight: 5 - destination: - upstream: - name: bookinfo-beta-productpage-9080 - namespace: gloo-system + single: + upstream: + name: bookinfo-productpage-9080 + namespace: gloo-system EOF ``` @@ -1404,19 +1357,6 @@ spec: domains: - '*' options: - ratelimitBasic: - anonymousLimits: - requestsPerUnit: 5 - unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE - waf: - customInterventionMessage: "Blocked Scammer" - ruleSets: - - ruleStr: | - SecRuleEngine On - SecRule REQUEST_HEADERS:User-Agent "scammer" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" jwt: providers: keycloak: @@ -1470,18 +1410,10 @@ spec: name: oauth namespace: gloo-system routeAction: - multi: - destinations: - - weight: 5 - destination: - upstream: - name: bookinfo-productpage-9080 - namespace: gloo-system - - weight: 5 - destination: - upstream: - name: bookinfo-beta-productpage-9080 - namespace: gloo-system + single: + upstream: + name: bookinfo-productpage-9080 + namespace: gloo-system EOF ``` @@ -1586,19 +1518,6 @@ spec: domains: - '*' options: - ratelimitBasic: - anonymousLimits: - requestsPerUnit: 5 - unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE - waf: - customInterventionMessage: "Blocked Scammer" - ruleSets: - - ruleStr: | - SecRuleEngine On - SecRule REQUEST_HEADERS:User-Agent "scammer" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" jwt: providers: keycloak: @@ -1618,10 +1537,6 @@ spec: upstreamRef: name: default-keycloak-8080 namespace: gloo-system -#-------------- RBAC is disabled to not interfere with OPA ------------------ - rbac: - disable: true -#-------------------------------------------------------------------------- routes: - matchers: - prefix: /not-secured @@ -1634,27 +1549,15 @@ spec: - matchers: - prefix: / options: -#-------------- RBAC is disabled to not interfere with OPA ------------------ - rbac: - disable: true -#------------------------------------------------------------------------ extauth: configRef: name: oauth namespace: gloo-system routeAction: - multi: - destinations: - - weight: 5 - destination: - upstream: - name: bookinfo-productpage-9080 - namespace: gloo-system - - weight: 5 - destination: - upstream: - name: bookinfo-beta-productpage-9080 - namespace: gloo-system + single: + upstream: + name: bookinfo-productpage-9080 + namespace: gloo-system EOF ``` From 6411e9c995d83759a2ec76f6b11aa244b3253a22 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 13:55:43 +0200 Subject: [PATCH 16/28] fix task --- gloo-edge/gloo-edge/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 6724d007f9..88b893b6fb 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1072,6 +1072,15 @@ spec: - prefix: /not-secured options: prefixRewrite: '/' +# -------- Rate limit config by authenticated and anonymous ------- + ratelimitBasic: + anonymousLimits: + requestsPerUnit: 5 + unit: MINUTE + authorizedLimits: + requestsPerUnit: 20 + unit: MINUTE +# ----------------------------------------------------------------- # ---------------- Transformation ------------------ transformations: responseTransformation: @@ -1091,7 +1100,7 @@ EOF Refreshing your browser more than 5 times, you should be able to see a styled HTML page indicating that you have reached the limit you had configured before. ``` -/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get +/opt/google/chrome/chrome $(glooctl proxy url --port https)/productpage ``` ### Manipulate the response when a 401 Not Authorized is returned From ec4d1365f7cc61646933417125f429a253683558 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 14:57:23 +0200 Subject: [PATCH 17/28] fix task --- gloo-edge/gloo-edge/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 88b893b6fb..81a15c07ce 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1068,7 +1068,10 @@ metadata: application-owner: team1 spec: routes: - - matchers: +# -------- Rate limit at route level requires to give a name ------- + - name: "not-secured" +# ------------------------------------------------------------------ + matchers: - prefix: /not-secured options: prefixRewrite: '/' From 454c88550a4e9158f510d646e8dc4c5c86d2e2e0 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 14:58:27 +0200 Subject: [PATCH 18/28] fix task --- gloo-edge/gloo-edge/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 81a15c07ce..eba5fbf95c 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1075,15 +1075,12 @@ spec: - prefix: /not-secured options: prefixRewrite: '/' -# -------- Rate limit config by authenticated and anonymous ------- +# -------- Rate limit as you saw before ------------ ratelimitBasic: anonymousLimits: requestsPerUnit: 5 unit: MINUTE - authorizedLimits: - requestsPerUnit: 20 - unit: MINUTE -# ----------------------------------------------------------------- +# -------------------------------------------------- # ---------------- Transformation ------------------ transformations: responseTransformation: From 7f622930df361e439ecea49597b6f4993dc02823 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 14:59:51 +0200 Subject: [PATCH 19/28] fix task tranform body --- gloo-edge/gloo-edge/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index eba5fbf95c..9546c27d86 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1100,7 +1100,7 @@ EOF Refreshing your browser more than 5 times, you should be able to see a styled HTML page indicating that you have reached the limit you had configured before. ``` -/opt/google/chrome/chrome $(glooctl proxy url --port https)/productpage +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get ``` ### Manipulate the response when a 401 Not Authorized is returned From 2f25bcaa7bb49af2c9c6339d2a601dcda5e7d97f Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 15:03:32 +0200 Subject: [PATCH 20/28] fix wrong endpoint --- gloo-edge/gloo-edge/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 9546c27d86..9d684b12fc 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1164,7 +1164,7 @@ curl -v -k $(glooctl proxy url --port https)/not-secured/status/401 And any other status code, returns the expected body: ``` -curl -v -k $(glooctl proxy url --port https)/not-secured/status/get +curl -v -k $(glooctl proxy url --port https)/not-secured/status/200 ``` ### Early response transformation From 7170a1c5ee637bdfaf083e366f91048adca49397 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 15:08:45 +0200 Subject: [PATCH 21/28] fix missing https protocol --- gloo-edge/gloo-edge/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 9d684b12fc..3241718b00 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1310,13 +1310,13 @@ EOF Once again, you need to refresh your **bookinfo** application to refresh the token in case it expires. ``` -/opt/google/chrome/chrome $(glooctl proxy url)/productpage +/opt/google/chrome/chrome $(glooctl proxy url --port https)/productpage ``` And now, let's see the results with the fresh token: ``` -/opt/google/chrome/chrome $(glooctl proxy url)/not-secured/get +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get ``` Here is the output you should get if you refresh the web page: @@ -1437,11 +1437,11 @@ RBAC: access denied Let's compare: ``` -/opt/google/chrome/chrome $(glooctl proxy url)/not-secured/get +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get ``` ``` -/opt/google/chrome/chrome $(glooctl proxy url)/not-secured/anything +/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/anything ``` From b130d622f96532a91ed47c1b969669cf0c6c6b65 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 15:29:43 +0200 Subject: [PATCH 22/28] Add authconfig token to header --- gloo-edge/gloo-edge/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 3241718b00..5031792319 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -681,6 +681,8 @@ spec: issuerUrl: "${KEYCLOAK_URL}/realms/master/" scopes: - email + headers: + idTokenHeader: jwt EOF ``` From f3d7286e50e433f6b30c35730fa425b1e15378d1 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 15:43:52 +0200 Subject: [PATCH 23/28] Fix task regarding claims extraction --- gloo-edge/gloo-edge/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 5031792319..b4f60b5126 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1248,6 +1248,8 @@ KEYCLOAK_MASTER_REALM_URL=http://$(kubectl get svc keycloak -ojsonpath='{.status Now, you can update the resources to validate the token, extract claims from the token and create new headers based on these claims. +Notice that you will move the `extauth` block to a global location in the resource so that it affects all routes. You want to test this with **httpbin**. + ```bash kubectl apply -f - < Date: Fri, 23 Jul 2021 15:46:09 +0200 Subject: [PATCH 24/28] Add oauth2 header to authconfig --- gloo-edge/gloo-edge/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index b4f60b5126..75288585dd 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1479,6 +1479,8 @@ spec: issuerUrl: "${KEYCLOAK_URL}/realms/master/" scopes: - email + headers: + idTokenHeader: jwt - opaAuth: modules: - name: allow-solo-email-users From eaaf385cc9ce9124454b19760ba331ca155a4acd Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 16:05:05 +0200 Subject: [PATCH 25/28] Delete native RBAC --- gloo-edge/gloo-edge/README.md | 110 +--------------------------------- 1 file changed, 1 insertion(+), 109 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 75288585dd..1c3a87100d 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1343,115 +1343,7 @@ As you can see, Gloo Edge has added the `x-solo-claim-email` and `x-solo-claim-e It will allow the application to know the user's email identity and if that email has been verified. -## Lab 6: Authorization - -Gloo can also integrate with different mechanisms to provide Authorization level. - -### RBAC using the claims of the JWT token - -You can set RBAC rules based on the claims of the JWT token returned by the identity provider. - -In the following example, you are going to configure RBAC policies for all routes. But you are going to disable it for the **bookinfo** application. - -Thus, the RBAC policies will be applied to the **httpbin** application. - -```bash -kubectl apply -f - < Date: Fri, 23 Jul 2021 16:12:30 +0200 Subject: [PATCH 26/28] Remove not existing 429 error --- gloo-edge/gloo-edge/README.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 1c3a87100d..9b305da87c 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -1587,7 +1587,7 @@ Check the access logs running the following command: kubectl logs -n gloo-system deployment/gateway-proxy | grep '^{' | jq ``` -If you refresh the browser to send additional requests until the rate limiting threshold is exceeded, then you will see both `200 OK` and `429 Too Many Requests` responses in the access logs, as in the example below. +If you refresh the browser to send additional requests, then you will see both `200 OK` responses in the access logs, as in the example below. ``` { @@ -1604,20 +1604,6 @@ If you refresh the browser to send additional requests until the rate limiting t "upstreamName": "bookinfo-beta-productpage-9080_gloo-system", "responseCode": 200 } -{ - "httpMethod": "GET", - "systemTime": "2020-10-22T21:38:19.168Z", - "targetDuration": null, - "path": "/productpage", - "protocol": "HTTP/2", - "responseFlags": "-", - "clientDuration": 3, - "number": null, - "responseCode": 429, - "upstreamName": null, - "messageType": null, - "requestId": "494c3cc7-e476-4414-8c50-499f3619f84c" -} ``` These logs can now be collected by the Log aggregator agents and potentially forwarded to your favorite enterprise logging service. From a11f446edd16c255609447537c33425acd1989d5 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Fri, 23 Jul 2021 16:16:02 +0200 Subject: [PATCH 27/28] Remove reference of RBAC in the summary --- gloo-edge/gloo-edge/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index 9b305da87c..fae25fc7a3 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -16,7 +16,7 @@ In this workshop we will: * Rate limit the traffic going to the apps * Apply rules for the Web Application Firewall (WAF) * Transform requests, responses and bodies using Gloo transformations -* Apply Authorization using RBAC and OPA (Open Policy Agent) +* Apply Authorization OPA (Open Policy Agent) * Configure access logs ## Lab 0: Demo Environment Creation From bbcc5692389ab21b71130eba24915053d8bb3c94 Mon Sep 17 00:00:00 2001 From: Antonio Berben Date: Mon, 26 Jul 2021 10:19:37 +0200 Subject: [PATCH 28/28] Add for loop --- gloo-edge/gloo-edge/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gloo-edge/gloo-edge/README.md b/gloo-edge/gloo-edge/README.md index fae25fc7a3..a2b8f667c2 100644 --- a/gloo-edge/gloo-edge/README.md +++ b/gloo-edge/gloo-edge/README.md @@ -893,10 +893,13 @@ spec: EOF ``` -Refresh the **httpbin** application and after 5 times, you will retrieve a **429 error**. This is because you are an anonymous user. +Access the **httpbin** application 10 times. After reaching the Rate Limit, you will retrieve a **429 error**. This is because you are an anonymous user in that application. ``` -/opt/google/chrome/chrome $(glooctl proxy url --port https)/not-secured/get +for i in {1..10} +do +curl -k -s -o /dev/null -w "%{http_code}" $(glooctl proxy url --port https)/not-secured/get; echo +done ``` Now, try it with the **bookinfo** application, and the number of requests will be limited to 20 as you are an Authenticated user.