From 3b2652a3df59e94afc835f1c573c9b9fce99c67b Mon Sep 17 00:00:00 2001 From: Marco Streich Date: Mon, 25 Jan 2021 07:56:51 +0100 Subject: [PATCH] Update README, improvements --- README.md | 108 ++++++++++++++---- docs/diagram.png | Bin 0 -> 62459 bytes infrastructure/modules/compute/cloudinit.tpl | 2 +- .../modules/compute/nix/guidelines.nix | 54 ++++++--- infrastructure/modules/compute/nix/vault.nix | 2 +- vault/example_service_policy.hcl | 8 -- 6 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 docs/diagram.png delete mode 100644 vault/example_service_policy.hcl diff --git a/README.md b/README.md index fc94c5f..57e5c19 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ ``` . |-- Makefile # Wrapper to simplify interaction -|-- config.json # Read by Make, Terraform, Packer -|-- deploymentagent +|-- deploymentagent # Can be used to trigger deployments manually or from a pipeline |-- infrastructure # Terraform modules | |-- compute # Loads the compute module | |-- environment # Loads the environment module and provides outputs @@ -12,17 +11,16 @@ | |-- storage # Loads the storage module | `-- modules # Contains the code for all the modules |-- nixos # NixOS image builder with Packer +|-- config.json # Read by Make, Terraform, Packer |-- secrets.json # Read by Make, Terraform, Packer `-- vault # Policy examples ``` ## Overview - ### Tools and Dependencies - Terraform 0.13.x [https://releases.hashicorp.com/terraform/](https://releases.hashicorp.com/terraform/) - Packer 1.6.x [https://releases.hashicorp.com/packer/](https://releases.hashicorp.com/packer/) - Make & Unix command line tools -Optional: - Vault CLI 1.6.x [https://releases.hashicorp.com/vault/](https://releases.hashicorp.com/vault/) ### Configuration @@ -65,9 +63,7 @@ git secret reveal #### Gitlab Secrets, such as the SSH key pair for the default system user are stored in the [Gitlab CI/CD](https://gitlab.com/infektweb/glv5/hetzner-cloud-environment/-/settings/ci_cd) settings page of this Git project (for now), in the *Variables* section. -https://gitlab.com/infektweb/glv5/hetzner-cloud-environment/-/settings/repository/#js-deploy-tokens - -id\_rsa\_operator_pub is baked into the image generated by Packer (see `nixos/nix/system.nix`) +'id\_rsa\_operator_pub' is baked into the image generated by Packer (see `nixos/nix/system.nix`). ### NixOS #### Building NixOS Images (Snapshots) with Packer @@ -146,13 +142,55 @@ $ make infra-destroy MODULE=compute ``` ## Operations Guide +### Components +![diagram](./docs/diagram.png) +(the file `docs/diagram.png` can be edited with [https://app.diagrams.net/](https://app.diagrams.net/) + +### Sytemd Units +The different services can be found via their name in `systemctl`. +Containers managed by Podman are prefixed with `podman-`, for example: `podman-api`, `podman-web` etc. + +#### Rebuild NixOS via Systemd +There is a special unit called 'nixos-rebuild' with which `nixos-rebuild switch` can be called in the background, either manually, periodically or based on an event, such as via socket activation: +```sh +$ nc -v localhost 4444 +``` +The connection will be kept open and closed by Systemd as soon as the rebuild and switch have been completed (switch only in case the build has been successful). ### Data #### Ephemeral Data -- /opt/ -- /etc/nixos +In case the server is deleted, these files will be lost and need to be re-supplied via Cloud-Init again upon server creation. +###### /opt/ +Data in `/opt` is supplied by Cloud-Init and should not be modified. +The files will be read by different components such as Nix as well as the Certbot wrapper, which is located at `/opt/certbot.sh`. +``` +- /opt/certbot.sh +- /opt/cloud-init-misc-data/ + - aws_access_key_id # used by Certbot to manage DNS records + - aws_secret_access_key # used by Certbot to manage DNS records + - domain_alternative_names # used by Certbot to create certificate + - domain_name # used by Certbot to create certificate + - hcloud_token # used by Certbot to manage load balancers + - elasticsearch_password # default password for users 'elastic' and 'kibana' + - environment # name of the environment which is consumed by guidelines.nix + - guidelines.json # default launch specification (see `./deploymentagent/`) + - vault_db_password # default password for Postgres Vault storage backend +``` +###### /etc/nixos +`/etc/nixos` contains all the Nix files part of the base image created with Packer as well as the files supplied via Cloud-Init. #### Persistent Data +An external volume provided by Hetzner Cloud is mounted Data which is stored in `/mnt/data`0 - /mnt/data +``` +- guidelines.json # launch specification (see `./deploymentagent/`) +- elasticsearch # Elasticsearch home +- kibana # Kibana home +- letsencrypt # Let's Encrypt data (configuration, logs, ..) generated and used by Certbot +- postgresql # PostgreSQL data directory +- vault-deploymentagent-token +- vault-guidelines-api-token +- vault-master-key # optional: Can be added to automatically unseal Vault +``` ### Setting Up a New Environment The following sections assume the environment to be called 'production'. @@ -167,7 +205,7 @@ Set the environment name, domain names and desired NixOS image/snapshot ID in `c "domain_alternative_names_production": "*.guidelines.ch" } ``` -Use your personal Gitlab deployment- and Hetzner Cloud tokens. +It's best to use your personal Gitlab deployment token and a generic Hetzner Cloud token, since the latter will also be used by the created server(s). `secrets.json`: ```json { @@ -219,7 +257,7 @@ $ sudo -i ``` #### Configuring Certbot -In case you have an existing configuration for Certbot, you can simply copy it to `/mnt/data/letsencrypt`, otherwise you can set up a new configuration either locally, or directly on the server itself. +In case you have an existing configuration for Certbot, you can copy it to `/mnt/data/letsencrypt`, otherwise you can set up a new configuration either locally, or directly on the server itself: ```sh $ export AWS_ACCESS_KEY_ID="..." $ export AWS_SECRET_ACCESS_KEY="..." @@ -237,37 +275,65 @@ $ systemctl start nixos-rebuild $ systemctl start hetzner-certbot $ journalctl -u hetzner-certbot ``` +Keep in mind that when running the `hetzner-certbot` unit, all services exposed by the load balancer will be briefly "offline" (~ 5-10 seconds) as due to the before mentioned limitations, the certificate references will need to be deleted and recreated by `certbot.sh`. #### Configuring Vault -You can access Vault on port 9443 via any hostname behind the load balancer [https://guidelines.ch:9443/](https://guidelines.ch:9443/). +##### Accessing Vault +To access the Vault API and web UI from your local machine, you will need to configure a port forwarding via SSH. +```sh +$ while :; do ssh -L 4443:10.0.1.51:8200 -N ; done +``` +The vault web UI can then be accessed via [http://localhost:4443/ui/](http://localhost:4443/ui/) +##### Initial Setup of Vault As a first step, you will need to create a master key (set) which is used to unseal Vault on each startup. To use just one master key, initialize Vault with "Key shares" and "Key threshold" both set to "1". The "initial root token" is used to authenticate as an administrator with the Vault API or web UI. The "key" is used to unseal Vault in case it has been sealed (manually or due to a restart). -You can now set up the key-value based secret engine which is supported by the [settings](https://gitlab.com/infektcommon/settings) package. -Be sure to use V2 of the KV engine. +You can now set up the key-value based secrets engine which is supported by the [settings](https://gitlab.com/infektcommon/settings) package (only V2 is supported). See the [Vault documentation](https://www.vaultproject.io/docs). +##### Unsealing Vault To unseal Vault manually, you can either use curl, the Vault CLI, or use the prompt on the web UI. ```sh -$ curl -XPUT http://127.0.0.1:8200/v1/sys/unseal -d '{"key": "master key"}' +$ curl -XPUT http://localhost:4443/v1/sys/unseal -d '{"key": "master key"}' ``` ```sh -$ vault operator unseal +$ vault operator unseal -address=http://localhost:4443 Key (will be hidden): ``` +Note that 'v1' of the Vault API is unrelated to 'v2' of the secret engines. -##### Unseal Vault Automatically on Startup -You can manually write the created master key to `/mnt/data/vault-root-token`. +##### Unsealing Vault Automatically +You can manually write the created master key to `/mnt/data/vault-master-key`. If this file exists and contains a valid master key, Vault will be unsealed automatically on startup. +##### Example Role +```hcl +path "kv/data/guidelines/production/api" { + capabilities = ["read"] +} +``` +'kv' relates to the name of the secrets engine created. +The path segment '/data/' must always be placed between the name of the secret engine and secret path when using V2 of the engine APIs. + +##### Creating Vault Tokens for Services +Refer to the [Vault documentation](https://www.vaultproject.io/docs/commands/token/create) to see how to manually create a token with a policy. +To take it a step further and generate Vault tokens upon container start (with some help of additional tooling) refer to the [AppRole Authentication Method](https://www.vaultproject.io/docs/auth/approle) + #### Configuring Elasticsearch -Kibana can be accessed on port 8443 via any hostname behind the load balancer [https://guidelines.ch:8443/](https://guidelines.ch:9443/). -The password is derieved from the `elasticsearch_password_` key in `secrets.json` +The 'elastic' admin user as well as the user for Kibana are derieved from the `elasticsearch_password_` key in `secrets.json` +Kibana can be accessed on port 8443 via any hostname behind the load balancer [https://guidelines.ch:8443/](https://guidelines.ch:8443/). + +#### Deployment Agent +The deployment agent can be accessed on port 9443 via any hostname behind the load balancer [https://guidelines.ch:9443/](https://guidelines.ch:9443/). +See `./deploymentagent` for how to work with it. +In a new environment, every container of the Guidelines service will be provisioned based on the 'latest' tag. #### Configuring Guidelines -``` +Create a database +```sql CREATE DATABASE guidelines; CREATE USER guidelines WITH ENCRYPTED PASSWORD 'changeme'; GRANT ALL PRIVILEGES ON DATABASE guidelines TO guidelines; ``` +For the time being, until Vault support has been rolled out to all services, change the file `./infrastructure/modules/compute/nix/guidelines.nix` locally before deploying a server with Terraform or manually edit `/etc/nixos/guidelines.nix` on the server directly and rebuild with `systemctl start nixos-rebuild` to get your services up and running for the testing environment diff --git a/docs/diagram.png b/docs/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..bad1dd05f01ae03f9071a71e468b23f85588570f GIT binary patch literal 62459 zcmd3Nc|6qZ_cv0u%32}W*X%PG`@S>AZjfchEY=yjLAIiZEG0`qsi-@VEG1+Om8EF0 zM3#^cvhU9|)O~-y_wV;Se?PC+G(PiLuFtv7e%|MlU~Xn`jGmL8f`a0hk)f_71;wE} z3JR(U+9TkMSNGT<3JSW_Ks{uj4+-btjinHR>Kq&iL1f&C0f9nLT_FfW&l~F&=uaeo zLvY@Qi1EOAU@-^RATkhHNf}v5h@3UJ3e}R42Vb&^Qi>1-hlBf3cr4-fLh@2FU;$A$ z%FTliNDOcnf@*``Mub4DH~0%qgKvZt_(FnzvNA5RaxMyD;84rg*BfhxMVoj83PJSc zp)e_^0yr&dVrUIF6@uu1V{Z>HEcj!9b@L*UAHn#eLZm#1;C5L#DOo8+a7xGBpXdW_ z(pQ8@$w;ysp1!OsxK|dOvqIre{vQAFGV;!`fhhdJu8A_{XfsmT3&Shdf%Kd&Y~92n}0JvfWO279;xIsm)$0K+jJD7-()2i)TE zo2MwOt%H@0xgrYTM>JQGR3t(4FbAs>P+$Z5OPd3>N&-sBi@g&q{ zX%V0}DB4m^+dv4SZRZoB2zSTGk@*J)($Ln?3v&yz@WguJwX|%^%=K_`-d;iSW<)(j zbCi`O3La$a6QHLXYK07QM~0bLklc{^Ha1u*8}O)asGcoKUl$*u1q;?O*7Y>gm$k)0 zjKP&aJE*&lhqkesfhQhH0{Ws&gvde70*%pjTDFRwiX=Ovr@T*?ZCH?hP?)8ucc_`K zsgXsfJjPqbGQ^B%1ohN60S^Vq`Uau>b#O#uoM!+bI0#0xgMrf_N}dRW4#C`98)%od zwT~Og+8i7x0M*epw*@N`zQiyB z#1P`HhcGeF_R=MI;1zAqa;CO&x}k153c*3B5MNTLwJ%0T3+L@cM22~o_y=pFa7ID; zGPXc5v_17vvIKW6Bm!^fXJHA)=or|BxcM5I68!ai<; z@8b~QDcz16dtw`v9vz51bOp%hNDW#=^qfD=fs{7vo@OZxMvW8hd$oV{}QLVg48gBQH3~ zSJp06(Fh#^Q$YF~%6KDjAzGd&CHbHLKbSSi(;-;fz*GyW7-R;uGc$mCgkY^?gXP^w z`UE8%GE0co^4!G*WSj$i>PDhYpa0s z!s}T&=sJ+(h>D^5?goKYMhZkfC4b8RC<5cHWMOAU7P5(!3|!9wW~gTZ#f6bf0xfK8 zFi@4i3=w4+#b=4955ZmV^Kq>$@u|;e3e-vUUNs0or~fl0Vc|QAbf88e(n( zw=wkafdmKo5rXv~7{w4MRt6?Rg2CKCSRs1^xEFaXC2Oob(E6?*Y zmgZsd0WwN3QUDsKtp)W7#*;628+%#=qmAKy;5Z17VCjXFH4IRM;(YC){=w#WG#na+ zg=t{}?J-p^0T9HJzHwb3#0v?GKC%7&Qu1OJ6Y*_->JZ4jPeibjY~c#we-$x7bB!^jF@ z;pZlAVku8Rn&XTi26~?IZss-~NDGS~RFI)9T;In7hO|fddn;k(LIcBm?Lr|)lASG7 z-`_nX0O1SxtqlSZ_$HCO1FVQxf}uy4i8V3+Zxf0q66EdW<@Ehws6YrI025^HCnqC| zL+T=oy|DgaN_cM=6plazTY#svm2ADeLSRPjUJjn_L2e{PjI2+fp`|-nlaPw`mP8X> zeH$Mr#wXa&&`Ms$pJ*9E(hmcwPsE^uO_BB(OGGFF9!l`FMY_9VjV*$8<-$CS;O0g! zxQ&IeDc+7~8fs+Z8zzI23kVD&TKMUh;^mcsydfrfD1Cjn9|-|N>sk5)+gj_xeC3UN zeFF)mz7|Bhx3`%IAxsZuM)EONz@yE=Wh*h9o0M6SF<^!{_3zpR} zAp3SjEs$P-zkf1}{d5ET{+;4M^#+Ru?ov?jQW)uKS(BV+bLslbY}Q)sCgXLjV`;_o zF1n}kja|RPc9RC{X=^F=UgOxMRLl46BF8T2UgYPW_OiU0%J0E)hlQ_pZ)P|mWj0<Qe{dy1aals-tinM*F3WEN^4bCx9?DHov3PaFy%agN>KB^J};;jEG{%z zWr{fp?5_!y{rlsaMS)j66MP*0?@KX?Ot%-3E}rVAVd0HIviSNWm`d=KTm8Ls47hxh z8cNhAziOKG_JV0XN9o_ouIEI1jnmR2^o8kCDgNuzl0*@Q@8Ej#^Izw|&u@rmXkHT2 zKg9i6&V|mLw0R}->UFS`<|OqwNB--f2$ImBbv1jybzwECz9{f09vmyraB}MZW|`Mp*D>E?+@=7wc0 zv?A$CM7vA<;s2jk>Rtt}{Gh5I{;x+3dC}COssfWTH%+JnQ@N-HOfVILCdndwR)24& z6x>k9@@<8zUL&lOK6f4r@Xgt zN9=Jd9Y1*HKfjMNk0cf8bln#F&y(b1CIc$AJiq0$Te{$w;efEj!iH~F-wt`>H`&3gBU_?buD<^ler25#eZmf`_ozG(?EAlch2RJkWf$qi$l-y1 zo!6w271kW(aGQGS1s-`Xe7jCpzoyQ;_x`@j_HWi=0gGN!nAamO>cRBxomFb+)*@{SK7rEDOK~|{3X-(S$BU;a)IMQ_U5VOBf zj11j#?(UMoQ-$*+;vSuQTfWzY_NWV^UmD5$9&MqVHzvO+P2{#3Q-Uf}FmDg_xfJ~8 zxx|VkkMl9q>`{mL(T5p;08geOZK<)-0( zA1~nGVbHKb3La8dc~gAChH7B3Xh;3ZS-bitf<;HK3nayNHHE<{`3yprpuf2c! z%lPNnIGmxT%I-Nah)$gpnYI#o2q&JxxxW5@hFSf0}?IVG{>AKb9Uqq<(v>?V9t+s>|$>} z#{Ga@44rM<%lM_$h&2%y58PE*g z7*R4Wbh8ipq^KY8qJW2TRx1)vlEionXeB3G|B-#cr2@gx1%@Tn%=-j2#-V;&|p?p%x>;Bs?WOldlw_;U53~YQmD*(79NaxO=H@B+D zlz>6L|E@~AZ$)hlS74NL>%EaYuW}+M>jKEmVe;j-8)VLIomRS_?fr#pa(qV)5#eN$vk)em9E4$jJA!IoAbJ{9eHXWBWp>$lIDspd z7kzqcpJlw1$8}l0FSCdAlMUk~`{g4wt>3hhD22fOjd}ZzlK1b<`p%jE?hrRk(*QR< z9K~{=2&P{bhj&?Bw>P>K=|VtuaUrwc05H{%W#6rMFzOzu`vScdS@3?9nm~kodgeQT?@#H$fW!kSekqtpmM5!RpooGy9rU?5D^>II)F5U%Hi=*VZHs;@56Q|s&gn6`?`hXfHN$zeN2kl1wF!Amy*Y;}@?peJ z3qS5LyKW10j_)pKHudt9c<*~*G-Cf=j``F(3(J!(b5or;^0mqyK=?*W&oy@L|C1MV zQ&(iRyFV*ZV*+<_LCj#9qtl&g1Kl|=FH%qsVCl67zs(pW#cOcyg8h*CC zJe}6*BOr8E8*GIx;f|G>aUO_RsFSB^Cy4BJ9#0`t_I)2O4Nza&IDGA)BtUyqmgX2n+nqovC}QBLEgqaHI#pAOR4cCFvsr?|V&@wJ{P zv8T=X`GKU+6}HaG0`NL?g*@R4@}$(c=Ytg&8P$hPYx?K4p&bOp~h2gsJ-cU5jRk<8ZfWJ>^o>qqgy5Tn`khf1;) zw1Tl%qqhS=_u;u=drY?nx*gj`Q)lM*RCDA!`0K*gGC+F2@$0SheUIM4U+d#3ZznQc z@~U2+R`5>!HSzW>qsBJxjk7k!TVc*4`3r)B7!X!X3%~a7d&~v04w{Zm_Y08~CA&U+ zGO|*)Fydu9tyEgwJ-s;re_C@Os#mTt3*LiOkC$gY6Q70VDhENL@*vnN5>79yOKN`^ z+gG@!eRybPpr6boCX#>t>BbhH&ZYM22z4>XD(|#BweUAS&xVAH^1}Y=$blh#e0(HA ztX;fR>{Mf0Qn%`0Uyi$ajx-wgYq5>z?ZRj?AU`s#X8xrkr@W^iLSv`m{IAy{zjn9g z-(H0cySET$K0WTN<3+;=UqnN`_+3_A`x5YUZ+GkMNaMx(5nHQLW7d^obc;pwNmnO~ zqnobBXpvn^GRwYK$XnHnZR&lmX$?tiDtAqdz^RJoJR?F+B(j}N*NOh=RM8iu=g~N) zTX`gQ%A+V(7_4_AS0&_)0Z#-*_e{&^t5Yr#@?M|P?v8nKpL#b@mjJ|{o@ zwZ7ha=!MOdQ_|cvv$nxrd&7=H={L{@Ab|^(!d?a%G^V{DWcTeq$>iJQFe7a@PgNfK zyxHcvnx;5WK8J1o*gU2p(yli7tEPXykFYs$Pd|nNx&sFB=`zDzR_ui(93AnW- z-{9A~VwfrAgz37aq^~Ju|5W#^^#j)ySI>uYB~CTp;sugr%5z>_IRS;<%o^>GQmxOb$W-q4Rfqn#g;-V^ zx1z7Bb;rs_v$?gGc5Y&SC+?}{z^l^*oxe0RnS^f~Q5^5@i`SAU(tC(38zZFA#cVVj zVr)OBw$Z6te67YXlnxIj8{wYO4^KKOooa${DcI4b zxX#)6ms>x*GJu|+>+c|p@km^ZW2&7gsrfcr-aRa-dP)MxJ5&SoKn*9I<|`^cp6x^$ zj@+8ViAk?sF4zV-^=o4)Kj;37x0%wJz--=buFQ1yIL~stIyy6YnTLCZ2D!C1ERAH# zi%k3Ik=bN*S-_E8GsLto@4MSpl~_^Lr8VjDfk|mqzFnDcCGS2NXpK_%s<+bAtpMt5 zFP^aPeA!9?g{oV#<@!kqUY|^rLw-t}atchFefBj{Ursyy(_c1kB|2XP8M-dF3#5EI ztBUWuiCw+am9OzN9{z=OO*8mh#}j^g=9cL~cuo?$FEOk`wykB8^3!hJ8pFxBA{R{1 z!2N{}qwTi)`C{%tzPKN4e(-&>zQ~rhQFC#M1PIh(9AhlcMw&6aUu$7Sv|}@!gf;fI z%jMkPX};Xs4POdjx&*~_r20?1$+owaNQ`rDDHh8ZiQJqn!XdujGrDf-&)*T52Y%ON z4vaZRY%ZrU3+S^Kp*9T6=fk*xkE! zTe9;NZyqi$lsL=^LT)`ZbDT&VzVUqrCwU*BiV@fkBuVFJ?_p))@D9&+E$qpW6fRfV zDluUqU5Cl|j7ChxopR2a^2W=Bf6xDDk)Q!8UbN<2Y}em8Fi4dL4l&brlW3UZieP&n zqZuw9{b(e>bYuPQLZAvnOm%3L@iB;!hBB0M_YDW;_G9t*nOU~H;q6B|wV~yg>_o0= zT92hP_0F~5TL>J~s7MCeYdpx7f3L0bUu%QNI52-VT|-ngK)=xC7W8TqeYffBMdker zP;o!&C~E(t@$8M?$J6Z{d$nh69@$;BiM0T+zv%DSKd?BJ$y=~+Z^3k+{Pixm5YyzR zbtfkZdcku8LOgYQXF~WDfhRcqVWinn&2W{0Y>}snO+R zf%viI1-RshkGCde5?}7>n-PMqor@Yg=HH-o0{cZ^9J4ej`E+&(`*gkemH(TEMeUD6 z)~=&pB^o`G8p8Go=uAXkJns8xEt_3`G@Gt+&*|>}lR=sM9^^DGA!nhbak+@QSG#03 zAnt=oRo<7V?j6geCpZ0ZF>G4XMU zm^$&$_O3&5K|V;+RQ^uW;*Ga0NH5N0v;EnjU{-XM`3C|boRWm6l?|ExdL7fzVt|%Zjp_?Sk01i) z=xN>@gYVglL{yGfH=HiCZw%V%nLYlAGyLl;jh=Ig-@ErEqI@_4Chxm)9}Ql**mCj~dJ*L?JbtsVm02rL}ZNjYc_2MN;Yx zAQqW@;j-otYn2U3YG#$Q<-D$OIX_EQ)j(aV{naF16E~GyAKacR@Ka8r$n@6PyFbqe zm1|_3nBnLi9NbZBK8;DZvOtbG*r~4Eo+1QKH3-~$e43T{&v+vm!u9fhTL5xAsc3Nb zP7v8fM^SxZRJy&QTADUvXjQc|lTFgrIxiGkVDGv0>x135SE0T44Ac1i zbyCzV?+-LWe7|ebBPQZgt}JlLd!~Q!e=8|mE}QpwrnFxDG6irI>9Xb3S**V$9RHsZ zUbPgQTP5o;Yo6EV;v0!w&yflxU)>AVYfGkHk29)Eg&aNYz8dy&ZFTFZ=c}_zAqHGQ zv8r;YiuC?xN4poTBPZ|jtG=HjrMmKO+y)e(bISHdMr7UH=KF^Zh#a_kkG_ha>;z1@G-=)+88T#?%osc%^gPQj8fnT zlbBOs(z*9j^!?8xFLGIL+?L}PxM|b;#`AQ>g7L!8OY zVmH3I(D7}fFKTZGyR*3>EUY-5on;`va;8%-Z)qmWFa;|K!p^cc+!ynWK&r05FmimDDJo6`Temj#q0V%LJh z|JT^?zr~$>beEjhLx&rWk8U)7V*RLWU(*!huhScKqR+WhY#d`+WWrEfbf&xHnH?{a zEpLoB@B;P#FNEA^g5vu&Un%uozWBd!peJv!;zWAYO2v5p%Ieq|pV?dm$~n@i36llM zlH}Q@K6p?c`bGo20Cfdr(WW~U*xmF0u{(f)&ha?xCyre#`%F`w@jTHC*oOM>r~KqS zyJ#>v9gMO3b8o6EfDY3t27Ae+bE`@pNR9s~hyO6yXmq+N${pyq=7s+#HPu$4`%-@4ly&Gb_DsMHlur3LQr2 z0DY?e|7Dx6mRhx`P%Q0l-dNVu0U!~}9)~wOwE@Jc36iUHu2Qm?Vq(c%B@)HG{s{VR zxtKC#x|Xcy-zMIga;#>*!}D4QRKe%I;(G!>V0y5~2_6dskYJ&X`1*@mi%0X6<_*c& zRT%&iIT&C^KGD&4H<&N!3#KALtwN{)FpkgOJCLcwPy-a|%Do}(IQ)f+(2FHjBpk)n zOkn@_$c-7vb1`-Rw&YSG?ynYnkPJoAB2*xY4?d1Yq;VV@e}8Jw`O7e&*ykhF%*suO zS!>`6>&JP)s$S3RTn+4FsQGm@fdcC8HE`ZwP4#+9~sZAPUf+i_bD}x?w`;P}b z-HW)3DP<9Y5JfMF`y6&W0;dT}@X_#|@n|a#4v%S?=rnA=Qys_}k*|~4dC(b%)rvke z)A5j)CkwCY2!k6}ZDywbcqhAb3G%$hHXi#f@OEb3YID^-O{YZ94JT3agL=Eyr_HbR zHy6mQA_|&M+0{qNb7zRt0`@Aw?arX2+-Ph*l)F-K0-e1g_56|d7RnK!l2`NOKNMk8Dn4^yheSFJsqidG5nU7xTzOOs`4xiT^`HhSa=1)h^4sNS^z} z_ZK>*VPtbT^Izt|g)HKsz!9guz;^TIOm9Tv)qLWRn{^DU^n;OopL&z=bE_BbzpY7& zuBYB+(PhhH%iGnLay;lq(8d9dOrv1g-o%$$t7okZ?;&Mh57gSz-#9B|Klm(hc0g$2 zauO}3wCFLDNoh#q=c>8OK5BEMPXuXFQ>_4-u%wwu>HDLegY;!bZysM}`I}m*xVJfJn!2FZ z`C?A-wG@;K1jCH+LZ>(P$X06cs+Y(bh_E+#x9$P}zyw9|NCk2L zVZ5o}A* zz;Lk2XCnI0ao3laHJR)wZ%M%RUn0O&JOkSGO#-jM)+YaN>r+4$@9#Q!JfVlbe$ z9yr*2kSq(uQm{~7J)>d^06V{akR48pB}!*7NIh>5+)W7AqPm;FD)Od&Z-=-6u*!Rm z&j>x`c*ON5qSJch)@fTz0Z7Fjyp7Qsc`RXYV_(-%qr55 z*Oc79^nCUixS69Se=X>08-D9=s46V2-*tGov+B43z)qH^2L2l13_${b41#}t5sPCu zbyBnCJ)_}sD$?aM!R$0;H!Yg0KG5<~c0aJVivbl9F1S2=?WZsw!jgeSNNu&x4R><+ z$D`5=0919Uwn-2`!h)>nH`yzuHz93)zU%5(mHWElG5&P-z+As&d1ZH%+9v@JCf(b3 z;_%ALd-kUW@BlFU^~sT#EqI+LYP(Fyh5}s%oQUOP2YCU0KH)nFZ_>rwgrOjd_cW7< z#$7k*&}gtoM6otxz5wuR!*)RPF<3hsHq;Vv`}mQ| ztC}s1Qk$MEKxJyHsNPlO`G5$FH);H&KDY`xAw7H`BTZaN67k2X?rksq0($bMDUM;H zqSp+1^N5k~9lzTbE8Y_8cZ7M)FT@y~R3Z+m3Iqb14pds|fOgu-&<+G%>1|>)-UfJH zhTnKAUEw8_!0)c<3KTl-g;u^F4z-9U=Vt+QiA~(rbl@40cr8aT^pe<_OT~|LT-#Im z{69N|WcPQzjM(zmm*y#6?@=H_d<+BiQBlqK&6}?)UoT zlm?ZB5x3VDasIb0?;H2jgb)Sdm&Cj15VtJi?Rk&BA=b<(Kn>SwT#qcj7RgWNfa2Qa zKc92USgj^W6@2CDd#OR4Dl^r3nwb77@zmR)kguH`kGW;ss?{P-C97|`R|7P+1G1%f z>UYKQZKdnX_^jC~T-O1SSJ>M44`*Zk;cUe?f}E$BaK(zOdKK`9+m)m{5~}sO0JIr+ z?u79WK%hS*`K2Y%vK|ig@dz{~0Vuvszh7g0H04nAIiQnHFPYpB2-bU(PLcZ8NTEKlUFroXh7pu*Fwol)~t|j zC$>CpQ7;W5x9RA8IzfQ2vE^0MFju(^0kru-luOjkN?M{^-?3wd)h-LBg`dR7iWK6@ zwpXT$^2zb~5iP!wm*#R9R z0&b62Ef+Cq9d*z8z9sWi0=v%^giACYboGwRH}lSeV)Sa&e}HZE54uSFrJX{V=g`;g zCUZdbJwH5P?q_O#Er8@a|1Hhn&D|9Bn|FE4Xc49YI)Ui&v#X9TET7P@^~%Z#v@$9#ssONzmB6y)2=xx#15ET0jamV&6J#=qGzS&Q2i%izac zg-=`v+TGshd5Se*^#+K2vh@RVzIdrcZgm#q6W5q?zKw@*r828$%c*rJvWbgsYJOw7 zOIjjQ2iCMt^mARp&mAx~_8*lzFm?;JJfuCy2jF+1W45WaC;CI~teI<{$Wy${_JiBw z!fAQWZ*pD~&FX6RWPkRR-8Evm{xeM~JeaBX2h$Tnqa=8BpX&LE8+OXwO&$hu?p)jP z>!itSd`G{&L?cVXDS1_$Znd>rO2T5t_aov#GfL;f6p+h8th~9H>zFc;dOc*&SbNligPr-YJ|M;KU!>fL zxt+EOQsBPJy*K5(?m5?mg*7b|Zy-Hse>!y3wuEhIk6@P$a zGAF7`BszfC05p}$@!iQQoW9}wqn}%7*jf~m2OFzRKw`qK5m`$P<-1Gydy3ieHN2kt z72f_}f)+FLTs?W#K;!ROg9Bgu%fLETB>9|fmEE?A*x{Fps^bZ!riSrL+e_U!Zh~E^ zOQs$}FDlujomIuS4oy!*tPSCxejP)e%2=S|4fk33@$vAMpZyo%ccm^GOM1-x1p7d` z{l-Gj&bWgYId&ENf%O60E#ySvk8B8RzH}@hYq90*XVAUEN~y{=hqj#w$y%=OD++ye z!meF?Yxa7@l+3$b(3|+ED49I9O-6F zakL3|S?%910}!+HS!kZvXhIo=WtD`MmuN+Ebdr)!!^}39rv-*y1VIh%q)XUCJi1*( zcV2y_;?lUtt2UYCrd`H24b$rpk>F|DodDfg;WGx9%{|cRZU@m^(j-G7&7sm$ua)rm z*hexD_2Q==aTT;n#*6-Jll*4SrlmLHrKY;JgO5sH7;{Iik1ofFKptyXs{d*i5SElO zc|v{ZCZlCT$PZ}U*FoS= z;4A2{Irr@A^9m)`6kb2uz1^KoZxItYI@eFEQ{!X2xJKb zek{h+(%0p5f9l%>4VKR(zPG=;TXs2I1$KRcr1Kj?B!_m0yk}FuyW3h9&MWo3VE=q! zTjLm~9Mi22sJag)tr}-Om%@xn zhT1u7T8J`)>un>850&DPDUhe%06iCj8iC`;Qu6dkV8cW8n*aw>IY*D+xtI)p#0)@Y zJE(Wcr2>UZVExDzUTBv4MlCm4 zx2eLTmwJk|HPm64`9n>oI~XAup*1LHkk!|OYOj7Wrm3L|nG2X9vnjT>&NUg)#D{Q4!R9@pdA*MiH6%0aN0 z6g>X@#s}scTWFquL2`PE`lg`_(#`K;!}i7!TwyeHX|ft+-tl;yJShVr-vxnKEF|3x1eeF-Yv7kB{%i6)xY=uyh_l!t+Tvz&X^RFas zHHQV_$vrw=j$^B^aTGd%hH^VAQ`%)%Fwwtyf68uO_EH9SLk7uws54-8q)m)oohQSZ zuU?%Pr3=3aBT6xxlt=~m7dvxx5k+U>G{8J0zSH226RRgqDuFVj*}rBbB0qGJgF}_{ zB>Um3Z%9I$`bkmMvJ@uhp?1vMvEwloclEPByk*Ll*kx^46zf|Ux@W|?M{HH0)*gBM zY#4%P4*2>4_Jy25fcCTRjwgVD5ue@CS0~__TWjicO-nm#Utwdc%JfAs(Wqcb2PUg; zr>eme&csxHR0g+NSXN8HhUCyO<;b#h_BIvu&F^>p8z^ZE=ZEW-I`b`VFKmO7>>H?- zPHyMCIz!ct8!U4(s0KqaL$YTJGh83)f_4mf4k*Ec@%rFn@UE}hRW>E(l&YCjS8H!) z;$C!u8DA3#hZQlvq`N1|Dil=qmF2tkJGA(*jOrKWdFOu_+1G`w5UecQEVNzJKp80f z$VY3U6ZTau$nUt)udA9gyjuKS6vtkSNSM*0zwK(hJbH`x^|2#N;0eQ7F#LT>JOKD+ zU)$Tf*C=;)TCbk&WYLn?`2wtzsx|;Zj2nmf5+qra%UTjC)Q4|{42P<6w_SAH*JJKm z%rPcp(gc_aIdFYP#Q47mdAL%4xi*H5aCy$;kZH-k1T&Mq*nvOW0*=cR9B@%TG# zbIglmklS3t%-r+C9(%)WIiJ4PExq`lprM}?eG`gLcAa5L-fVtpUi?mFd!hM0$mb_@ zS&F|mu^=&-l2(ODAf{M?O8&*x_B#L=zLhw%3*-e?aFUpQWn2%q^~rnM@kQW6dyY#x zHx;iOckFVga7PI@K*Ru#<*pop%jRC`dJ=0g0<<_?hf&R%oO5(-YBg?p7C&x{tmI{Q z8ne6gbuUBzD(A%WIWX|U_sI4!3zx>Voo=mxjIO#TA*?f#OAgSK`$xer4Qxu>LaeN4GBWU zc<~xZu{-gZhn!D3GsG3yUD$Qm`wZrWB>-l6jTY|!EQ03Vtk zpbdw=To!tQs%p_Y96Gm_HWzWRIMc)bj;VKxpG1DdYPN)9mFdgfO)mlNJEuRDIC<#` zwaPJNvm;!qC0ft3+i51Dj~?}NC`0Q#w0?Mv`SH7`pdTO7z<8PGnxANP-;Etk@zKyh zpJ&+@;bqk~gw9bRKLbR~r?FUsiWaKCB%Kus(iV+F@>0^HN`x?Vk3l#cI``#6Hn;3G~6+j-N*L4s`EAT>R-DKcOppYK%zY*PAZKlA3$NxYv&w# zUlWO*)^$G2f0BoF!A3%A0xS;;7h0H~6`I9+Azm_V0hGkGWJ?p^DcIc-kj;_hupv4W zW2nUwc1?YJqq*B_;+;a#+tT@$0zy|#Fub`MGbADf&HIf=OQz<`EoqI~^BUWNzL}5e z;7!hu(d=ozvsK%*ADUnG$k<9a&~<|$JNA!>G1DLgnY*7~`{@uR*F;RjCBWHwVv?~VPf*RKM>SRXjyzH2M$_|%oRoIHHIpQQ`>RZW z=WsU+Vh2oNrsppk@c^9k7=t$J+u5=Y>*-czvU|Bsq)8mj%K{XKes`W4wk4kVY0!*q zFQd1zK{lAFT-*W>py%pga$0MgE{e)1_(B@LdMN+^r*Q9!Fv$G~5M*%uG#STI&Nwb; zO6STnKu)yyo%ORe_Pw;@eP2LT8cd%yrr9YzP}<7x9UZw(cyTE0g8H&KXjvArrc_<% zB!gJMeU1x#y2?N~I3*yp^YJ@P>xm8Q9XO|z_$b{%it4X;dt18qBWLNiQV)21zK@i13EtRtbL*$*9(&*0XS^P11>Fd>oW3x9li z?A4-3EqHt+&ivxS#pkh#Z9SfX8QQ|K3;O3==@dRKyF_kGT;fy6of1+lt36e~Vj{)6 z&S$H!vustKP8In|KWLo+T9;MV8Zml3eWArN`O9pyy97v1vTsCzat(e?b+Lu@5>G~i zYjx`(Mpf6@Si@Gz*M00M95r4g)va7lkIG)Lw>kgrIY1LSSzId^D7~-CO6F$8kS;S_ zm@kj&pxf$yV?r9c+tHH1+R4JMYSq_G8FiPDX={D`qQ>3hxL#R?D=o+cdE``Zp{;VQ z|D&9rCgryo)%=+9a*5vsPKA8uoy(EGG365O#2vP(l)ci2gkB8&=(J||=sF@DdJ~pO z2X($iBdjhE1+v+xXKGHHLGxe`?&)v`Y53FK8dYWNU+I!{DMw#SdMZJMr`!Wtp=%;$ zj_lzPC826`?%TuH(T&tS5tmPXDHxP5juUy|2maH{&8vk>?8w$O7A{J~zrt32=<~YT zzK)~vlXY#Ns2;h%&|!MwQ;ZJNRON@0D>6)%qBR@6MPga0SyvOB!8D|P61o@CV$yeb zX1J`LwScGm&VZ2gXu`xx!Vi#;~Q)2%Wzb?H*_TDu2hABRQBk zaeZO*O?f507-h>j#?{11b>?kT8T~{_%}>a#N8gh>*^9NaPv3UrFFIaL5nDK=PBAi0 z)$_y+XCLliB`n>!t-f3v(EqAu_S5b_isS9MmF;?!`^fhNzeXPKeCrw9d>a6D0sl=< zO{|T}*DnC=-DhH>VbSpN~b{`2!NzIY2 zKZonc!BhXplbe z!UN8sH*O6)NL#M{HpUyt5>ZD3CZU>^u1>fZj&oMt*G>BZMdE+eZu~G$Y&{Jlc-z*@ z+AqB4*qUB^PbVI}AgeNTA>@p@wc84#?R(c-qYjfneIF~m?4Umr!rmv>3(|I9VEN$z z4N_}`08KYT5qXa5z0!$n<-liQud!3imv^g|tf};@YEiqooI29UZjG)IEiSIg3T^Ir zIorf)0%N9ueeu26AD*=d#WnI0p13fVd-T=B?}TUFZ;sUJ_<=e?Z$dNwd_1|~ytVmL zR*mw3u~&(B5t}EbC&swKB^J{trM=_PTqcL^#F$nv1!l>|#%rq09zJYvbW-+F{6vPK zgdCyL_6x5yRWR+?40W)GmEAYd@V@Hv*#sW(`6zu9wvEYgT2^om7&~CD}Owj#}4zCUZaG`k8UPirmXhDD-l7Y(R=jNOwOuV zKFvCu7_skO>G@M6?P$C-)5WZv<~;cNiMJk&hotRj&vRwQP^*e&t+ZNV&yyNDgjdbb zL>_twgMd8~3l*v=usd@nZ;CV~E*op)=^~!tS1=NnEU2(Bc*5=+>gQ#(?9l!gd-K}m zHMYEUc1p?=Mqwtn=*X3CIsjkkgG)-b`kxbQi7|}R)IT?J=rWHG{S>L-YdCk&H7C+o zGX+b^sLo+rD)0)|d@$nrRAT2l8ivnn*cRQ}>XG;^#C2*^$#q!=vi!QJL%sWFZkK`y z;j>R4?<0KowJQ^EU+<}H$D3xWIUcz{%KbA7P^hsUoi1f>SyDSg=&vF9RX+p$ELGVW zrI9PnzqY+fjZ##8CUq{J1rBcS+Wm}yt{u+=)2;LGqf*QUOdLL_^IxWbuZ1p+hd_rE z_(1K?&2x86g0zMQnq@MUdz3OE<@!Y$Mg>O%7(CPBoYy;#d9~N3a(G_2mgw6m*Q!gx zy9&_`y!yc>*s2>*TfcAz_AJg(2R|+El9Ni}eaa zYp49*eo0=F87?F3jXGTl;eu4qWY=jp}Rql;)TX7z>daM-8Fnq0j>&Hmlh_cFTISy`ed!sF!f9TBOf zrOvglnF@6!>5O?%w#k3lm`K$`L`yi8S?(@%^d6Zn%~5z=4I36*QeSV_hFzmmQ}KSl zHt;BwIWKGI{7kdn@`fJOs9ofru@MJ(;e$2BTPgj<3!B<7Dt`cbfsWn4+16v`oV)XUNZ9dF|(X#D~qP%(@Ms56vAK zRh>fjNg((a#Foxv**9K{6}kahc?~H7IHt;O#ScH}R?m)&Hut;{J<;)IbRw>81GDKz~Lx%SC&|07M`Fy|M-`>aG z`;UF>S#JyV!uWBm4GX~3R8Yh-YK=YOdO%z z_+{dB;tX>h;jx0}G5peEoE%=c!P9_>>Y{F1LT71o2(A@~j|z#_MbVypjJHBkOup`}l@x;PTT`LRL9tJw9 z8hAwyHi^$h%}nf?S`p;I8@t_kCRE(INCr*ZL3J0|&CPR^Ekug%()LK(>KYhxn(w9a zRPKM3NBPlHJEQL$J=HAby0I`Dbb~(+WoWcoQybHZvR!JznF^wNL zlUf}j3H5b9M)pD{7IU{O9rCA}EaS(c_?geS&20%S)VF5SqcyBDy-3KO_sc$$zUQLa zZ|W*n#TWx)9wY{DKi=1ThVJm~f2Ps6W}87DZuQj6p1o>XBFlx_lI-dW3f0P_0lc`a ztdrlvUU~jfC^o`UpTaeDuNP+vFPMCK;r1c-neRIA=HHy#asxV9hp57gi?J-l4u=Mu zd@DwJ{(CPu`}_PCiek3w3?BMj>5=$Y>Auj2S*aVSi;1n{*MlBV;40aBvb2(;g0F-H zhzUF#ERQvQ_?W1fESu#Z`Rq2Uh~$@{rveqV?5xC}cpOE{K#}47JKO$S5I$SaXHVa< z?&S{)^13d@_m8yG18I(W6U|t_MylD+Cr+)8CtOS6rW`^a%r=M$>1H^R*mI}m+vp*9 zZ5VeV@eg=i!GFMPe)IU^#?=XB6;o?DA!pOs1`q_k$Q^S4jTHN5k+Ag?LJIu}_q7Pl zHXEvq2gYM;gYuCd20vEtdrCGqnP#*l$~UrqcFWlNAW%I2nXppkKyi+*TDL=A6zf{t zG)CP`ov8EdN$q@SWI+8@ye0-;7UmL~8)KK`jd8F#8@15lK$?pRy|1oR@eEcF^tmoZ zv-_Br?62=ELHi61oQOk3(*Y;KSj-XhsEXv~yZnEZIlT4%p*0+ek^;WeMjRrPGVp!@6mclY`MVHwH^IitNdg&y0S5p_+0Vbujx@?4HvA({acMrmZSWkBkFE!y6Z&TL%iY`}c3=POq&*@hbsZ?}_>~hchppd5CSGfQ>;5L%K zo44opyVry-P*P|(&Gj@}EjM3(!v5m^U=3wc=4Ip*a)qv`))yeCUOst+) zfQq+QMlv+wjnj@-n+H&2yEeX`j``H1%j zxrOKN_VAw`zpqkFc(YH04@aCE@KmOt=@-2;QclNTH*wsHuX0Ng#H#EFn5&tgsbKSA zRrd1U`sck;THWgb)q)+OCQ%|%7~|i9N+l>eQ^LAwKXR5Sz}b)Y#l(#1BV-5K z|ASLgILWtE6W*A?_m2*E+j<5v^t;f>Yt4S}hn;Kp!u(-{O}Prc19S@kno ze#r`j_K0>ApCK4pz{SRHqOm`qh!_U%}W3kU) zzB}Lh{Ncs%Sb^`oHw`Z;U1Lf>>GGF8**s=5 zvs}>v-~t|Sy8%o^#KG!F&q6)*Iq*+EC(!!u-7m823o@pmyeqgd#5}}fCT@S{Jaqlv zD#sdcO|k?zNrXKGfxJffKvQwrK@4!0pBh387!K8~h)M+tk(sa+Zcf?cn!?wf{reSV zE6O8V(2t}597X)JoXVY}=pAyVWKy7e4ghh^6q;Q5HX~QIfvq}Kd;D4i3;kP4UG6eUEz+I{1#q8-{cN)$#k{H1ZpGSd`%}h*Z-1!*6 zt3o9mzGH_A+c9aSCrGb&@C{7!@xNCWkPl8IF3G;Ntr2vKW|AE9+_C<+FbZVVZ%FqF z0vBD9R;Bx+%fRya7Gn~`&rD44TzzIJ@bu;G*3(Ra-#`vN&s$H-y#t(t)_rBxYxYd@ z+DG-jvTc)9Ke`T`ok)Zp-=AmV+;|~rma@OnqkMf~;B!JKuqIS#r#&Nb4N49uF4nvt z`j*ZSu?G3un$O={xP*>}#YH@#(RT0HpXAm?C+zy#^Rv2vg7?mbOL#V3zqbmyp zQEj&W3Z!iN;BjSRDl6%NHwNfEBP_#mTGK@6k}grSHRgZxJ{C{g4qgpCtl~xrq+ZY~ zs6YJ}IaW&n&QG--!Zy!-a8R{(|BU!iz|R#bm|~%6eQu0tb2|A)4GBsX8-EXGo_Nsv z<0wd$>1_XV=FLno9Aw5=G6LNYd}{AaZ_+DG`uPLgwGQHbW~Q0-m0An;?<%n4a?>t@ zRYOmXp&?LS8G&}KBOqbgIS=Q&`VzEi9Zf0Cf;vRkT8VEr?}j0BdZ6=~20h@TK-qCc z*cAr<+`ljk@YRYgZ_gY1bG3i3RToL1f4;_}&n^EJ<6+*^N)+nFhUI3(!IOGM%s-Ki zu({W)HN}!K<5y4TVFHVSuWrPUFT(b7JZXl(9+yIB>Oji#S~2y%#sOLARaUx-cKq25T;eE@-bjc(*O= zCH(Okq=78&ep74#Kdgh}RFoo1fBacX^IK>pi}>6BZzJ0~<|>i>NK&#mlgIjFGoq|;J;L|xJE9N z!b#8pZ$q?T-IXlU-|t@aJK?fpD|uKbb>hI;3Sc^z9en^jGxk+R3l-E&Y*!7kvX!c})ecDD zgsS@2@{8_~<$8$KEM148bojCh4l+Lgiu8HWwz*^YuvbeRg8UY`W1-H@i8+kC0y^i2 zTL>Z~X$|C*W|E%xcBF^1Z0g?_6n_@%=aNvow>1~Iw*M)3Hxnn2{ifvv( ztNHlTyN_e^_47^r6>Of;YPBj#^aE$ByI5-8BN%VAS^=+V_=-^tDptrkE*8K3*b9(! z)GFv!oV@7q>jBanjU8D4Hmcr(E}3?-U6Og9OoS^|kz3;8FJeG<2Jb)(gY-5VIG*)W zy5V6vd_4m8dji8&FyFJ_sOmb|$zjifP_Ti~)(pNIG~lr_Vow$>+<;dQ0Yafmmg!9F zkN3CDS$Hp553+)?195**Op^3T(aAGb&(J*kv1}d)7$+YFRX9V7`ofIgm&}`dJr!p5 zB#ImJuTZ(iPqY;C#|IxrTu8zZ8O=f8RyO;q6lwd^OX$vj*!|Jc{q6?K<@v0F*2@V- zOJjxOC%+KgM7AUiH4WXXJe6I7enk6%T~!{Z{oQYT{I^2&#&+&quzyn=xujS_Da0}` zg^*>j3-v{J=uEwjk|>8Y^>Y`!$SmmRqrky+=lrP5DNSd#&L1#Vcwgi4AGMEzdWnRv ziNdd^_(Y~aD$chW5V+r)5lP-5+;Sq5G+DjSu;j+9vxHNak_2XJ(~}|>QNCJD#@2jR z&B?dENzgBL2D_o*vLAdxyU6INCA8bHTg)2AIYQjQ1m~%i4d;o(PQY~+0<4p`SyLO;78ghBN5@`0J)4~>I_3F5-^Qz~=9y8G{6RTCJ_a_5K7~EGR zmdQ@vACI$q&u=0%HTKa$olsTow3MKH^*LN_HsAhQ22;OlqTl6p9(+&oja%>4%G8d8 z&Q|9AzvemcuPJO6R%S-J>|mmO zBJs{Mej1g!{#+yPKw3feZa1;KG|EPO=ID0F`P)tkYJp4W24&4o_!CtWBQ+Btpig(D znL)kAQpe)izp_adNfy2J(Ys%n%1>=qO*}#}K{93H7%G`+f{K~icq2rLlz)Qy@tGM4 zSWpK*f|0$yV^*H+2I}vjEZiiwZ19EfN$wQa7) zd;@V!6c8k0A1~kH6#XpwiAbKY5|#YJm|*aTk$o59#pqMdcJKF^r_DbWN}J1Tt$hlJ zCRW*qesYQK;kdu2`|fJvw7Y8S=}~YhaDV_eWK5Dh3RyM_0zV5D3FoXqs?^*|P1w7H-+PkT|V-?@wgKxy_}gO#y-AA^{7Wh&+o!#T|X3gsL|`$ce~T<3eRkeXK0S7!Q(~ z3={?34YoVyI6-qFHgh5|!^YHvoaxSvJ7(miaI4Ew^9s<$A|Ub(pU!h$DxLWR*{3y% zA;^okY+h(ORK&JTKMo{-JV0e|=97j?M!6qJnD_$%>2LKE7shi-4k+4u z+`JMyuQnaSpJcy2&~Aa!t>H-ak7yXj@f<4rVg~c^*osZz`*;45ZkhbdY3U+>Dt+G3MhZJTzS%4Z1hLnwy7w>mV1MO>kcEJUv%p~TbJR|?%YGV2yR?}rbBi?e{(^5y9-o2at zPzzz&a-XenRF(Vs0Pl2KF+{Izu-1Cv0;}slDfjeSUb+S`qtNP@&RZh#xGNQm4;>^@ z6(a-hW#1}z3-)A1K}oG6&LkBM~V?&8(U`X_yA1c~Q9a1aP9Ry%$D_HMf}Rt8e>N_-l+_L#%5 z-AMqo_kw_dJYFTG{9It#@|{Q<@Sa44wS|bEM)#9`nCR?#@Jk$?nyn+6KPq*27<;q> z1h>k!EQuEjQp8rwZM!~5wj1M|nQ>!&qkd{ zy!_@9Uwdo=v?|_CfpbP($dkqDbIR1j$r9sgSnu1x8lCf~Nn=*FSNZfuBwJI%Lv$} zJUItkVX2m93XHBO&fKTuI@r*pL;ko+7d1OJ;TGRXyutmVKYB$_@Ut7Z&`>mC#Pu); zv7e)A_eTIRgQzeiad{3RVpdKNzR`YlQx6d^Z~q2h;=LZEK*&-*Z5<54B-o8?d>>XM z6E|D4D;^Moy^t^Ue3*DE^3KLV<7Y;Q0s;<8j); zLqg*(=m^zonH4KsU%eQb>=bdhsY`Sw(Pl_#>E;^zSE zV1+^?21)Q7AToZ!r_p0XFeyZ+jZ`VBSARydz7*-(rQg5iS|$-JpL>M}`^u9o!l{!ZykVmKm}el6iW6>FXt3Ir;4Cp z;u(+i&|$}ptBAt*G9t!AP8JQ7%Q6U&84Q<(Mn)kMi?*!z;0k3<|MG$1|dKv^(f3WGk~Q|ip2bF zMQDO7octOC$udN-AZpfgU#s?+#?cvjY!LE4pPf1CQ&9KnDYmM@mC;wKG3Cwi~#X5XyZr5&17i; zLe(nomy6-zJp^iZ@L6)LCZ!Ks539*M%2t;P48Rj<&r&4(pz69jNvr%}g_kvi!0R1R z2h#lYQ}k%Wa2 zjTK$`iwiIS6+?I_HLVqbY_mMOWIJlL@pK6`*xReS&IUi#<%$;ul$KW4_ZM>UDf~!q zhrDiDU9lPDiGDwaBY3w&2k z&a;(fHIV;Sabx30X7S7(r|90gz!1BaA99?_Wa%chkpu)BI$c5FpzH`TKLX~=|2VBI zbaMGA)WBvW{kcX3KcVWw6sr($3qelH5e74}M>={3R?dU)F9oyFX)RCk&W)TuX_FB_ z$A|X%wH8CGXaF-pA|q3e${?vpAh=Ei>`o-yXH;`BQw-`06(>G86Z(I;mrL`OPIgWI z*A?q~R`lYr{r8PTi{LK|c!p)sp&iXV zrT@_oeADgFgKvG>yeelpFl`JoAVwhVcaUnbu+b29yf)zt+C;!ht$or*lZ}}bgh~0m3L{;R_BDkXBQngEPZ>P_RAR9SFrqy+2T`7?2&!_;9 zv7sZ|V_+qBU~_|xK>nVW9-aBv0#JIJdnK1O_fhBPEzRY{F*twQB^fZLAl zE^PMdS3fm=OG>&^7me=fm^=n z@In0A^$Q2}Z!>@?JTlKutiIXSDNg^#@n%B*c0rE;sd;suKo4JI6EUN~tr8yk^{B)3 zj~xw}6tYB07@4Doucjjz*1bkUAeG|_c|w5eMvfEFNBJkfWTstg$7&nALQxARLR}oNiYkc zN48IHHhCDsftqQ(`|1;2OI3)Z+alX>rw>hKN(Y%CQW@P}WY!KON9yJUUJaLLi(b3S z9e?b^7}XA@f{?8)6)UkRII;svu0=2rq4(c$`q6I^90`ZA0n*g@h;!_zVEM}FOEw9B zz^g;@aU9VYeS-u3Qj3HAA_5@?Q1gUAEvg|K%)kRG&G7Q2G9{$H@CZ_*6cCL$fQbnL z$lu-BSakS^Ptydp0M@8we~v`Xn|k&>!;rfmt`CR<0U}2ThertN<{_(_f}&QT&&TUa z$I@8D*MtIhe?LS8-x!=FO`dTe8rfjZ;16$g9C6{n1+y?xa=%Xj zZ1+t6Wc`UkG|@gYV4J{#oDYaeLwBWzTe?9-*)0pAqi4sV`Js%ov0hY*B03#_EV?V) zoJ)UvI+qIFH35Jx2cX@QqWVhAp_wf@W?t>gV_AAXja~Y>8OUAkVrIazfeY^Rh)9+R zIF(26(GB>ziXgQ~fne+K`TC`105DBgzJAQNpOjtut;e&nTp#`LqF}<=kEJGkye2m3 z#`SkyeAl`KM*jM;j>6%(PyB~jvCSxFiQzNGXiU^9pqTgQ`mfD?3^^3=jWK`J14KS0rQimBA7_UJbB zc)sPf-zpqV&NU@$fr$j2c zB90`9ZJru8iFV^3YVvHar!AY#JjPF>(Y3rOtY&lXR}NnM>lJP?a?o6QAws|+aQPtx zAGHUmh6zN(F``^{>DGVMO0X+<{Q$I3wQ%$=Tfv0rK`)3@CnmMdVR*dOH-13zMC$|N z%Qj%K=fgplt@LqU9o@mE6crPz*;?o{+x_i~3dnZkQb69= zF6J~Sn24oMT`6R%cV!I$^L-FU9@xHeyfOjDF+Zp)@}yIS@Z%I91PTcz_WKS1`bT^I z&J)~csX5SX8U;DEJ)9WOaj4kw5b}Tg7|o#jA*_1bApNTtQe03ME*#Q0f6SbxhFJoZ-Nw@J%EN!sO1506ZNQ{{s0!P;7>cv z7BHm=JXtTM&U(7WiX-flKIjiFV`iXpVvJ%Bqcp1Gi28xG>{Ai@z3Z5++qW+q_IgrH zBr`jE??fUt1uR)0!#=VP9_Q=Pe7YQ7^5o#_qvT?7Aa@fn(4$Ul643qNVt=dDAyt7p zVsO&mQ8bhh-Eto+Fm4t!Iv}lq5Cm;O;ATxAe{sL4r?|C%D}%?l&{vnoT|DZVslbl< z==$kwT1;#!l3;KCBuj&GN3g~brqIlglTctj5#+YzM>gPJp%C~k@43D42uiayKPzgj zkjDTnTLMRS5tlPQL#zs3DD!I`R_5Mq_drNn{?v{wHJ^o|Lch;|YMzR_EnB}F+w2<8 zwe_1Uw|^+Mf^nb|`iSR1IT!_KP+W?Huq1wqeSu+B8VO)RLJtApw#xrjW>E8k4=K$h zpfm^3rU9fW#!ac%%Ws;I3ZMI575+a~ErC)@9h-{&vYgI->dJ$w0{0A0Acmehhptj@ zRz$mG!3gur#zH-Q#s*Qeo&yJ2)Or7aYkL3og!H$oVDaH};V&b&zw(46#tzD2rwM0N&4X5EvIU*Y}*xivEnvm!a_E_Ime0=jqYY)Q4UzLeaSxh0fK8o*kcWU^$y2 zdwM5Z;m?@Noii78bR9v)g!=!%m@M6G6+8+Mx;=rAHLnptc*$1nPfrZ|HPt>A?+qC* zM8j+7@fNlV*nuXj9vEUXQXgPor-VxF8vgGkA^#YU7TSM&*Jtd4^$nL_GTLeSgsSvG zRz4_WiGz@9x<)XaywTH=0(9PpA=NKMNYdsJOKR*NOKQev z2qtSU0jaE;dc2ZO4J$8TK-d0#g^m7&|IGLcf#dS|Qnf_>*LyWDlydJoA`7b?&>t3L z&dV5R3;Cc>LsZp(9w8Rt{|X)lX<2Twk6@xiqu%LdqywD!UsGNf$oTU^9A4FS;L2$`zM_NJfA%zhWJhXY zxjX~AtN$kO|K}F^QM?Q`Y9U>3alIY_q2j4aHr!wUk$}KW(26kMA4B>%b4YWo zYbp257x4A}v*qYLF!!hlLaGxF#-B+ULc6{HxAQx21=$Nv^~b*XL>&>|MYpHIzahvA z9F(+41Ft2HAlx3Gv|_TB&A9_J)?kU(ofphSsTlJKDEx>HHpldJ_+9@RVud|=MS>2H zh5;CLJq5@D0w5a`_^UL*y2>;m9GwT+;{@mJk8BEW;a2@c~_!z#~i&{jLPtI;I^7}`TtMkBKHzPl*S?ZMKE9+VZCU=(%xId@mu6k_jP z@c&Z>`Sj;>V1da)+tL&Q1?2!AIU_$+eINa?u{7dnIm6veA=fjVbwSGBhx z*y7Y>0RO-3C-7LJ0AW{SzaGa59bn8ZUHckKqMo77GRc{H;p&?Z>SyL8mS%BGxN0NApss zTkHXOXK(|pax-K#DGz45r&f=F=vSh$AasQU&3K>Qss(E|{Y4LJ>y*C1h!oJn+R_iNIstHRq$0W}p5x7V0+*U@UlFk9iDq0iX|7%IZO3Y zPY}cye^r6My{jel+<;-Z@SuwFTpV=PQO)wa#P9_@fR>FCD>* zYNz$~dotm>%jV0mf>i_N)6d$YlQ9afKl>UDGO200lP7*tX-oG>`*4HJ0XFbbtppKI zq1xwVmyG;vKq1SWC5uuwATbf#TYp|>{z}Z_v>yz3zgfKXw5O|#Rwopl*I7i_gl1yR z8FZnz7} z)?{ihEY^53!?`S?pWD;ZD?a;T5Kkix`JX}N-#S%u0_jD*P#d@yZ8D^xz5(PsvhFh+ z#X0*@)_O$i6)F9d7%{z+40CAJog%WJuUumIC2_A7zwYyRzc7pF)gy9(=nHsWos!H{ zW_JEcA!%VZw?dEOV$8)7V%eA1MMvqG!Re~}9&Lfc2$YPi*;=}(AAAV&w9^L?fT}4NG2ze`6 zqA4zlu~Yhq5B~VAwpsB?O{oB^47s=qwM^n84Q8@mu4mw@6tkp$QP7!V%$vRoP@@!8 zkQa40jsD?;CtsNoHhzD{YeiY4(k1%1S7+Z2e3saWwO4FH?dXnO$0xK*WISG-L`sE0 z+V@ZDO=O^M(u&1h5{7~B=D=Ax##DXfB+3Mc94l5^Cvb33`@uLwM0lBTYhLc@�{f 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�)VQr8Ub#c$u*`=o77(VNNHwJybotF~Slu4Z(J za%(9s7uR~nbxpv<*?DSg?9HSY4>z}m{%BoYU4HfbZ(Rfe-@z+>m*P1k&%I`SBpn?@ z-8?;wXE|_Sd6$um+IYCThsP9VFM0Q;Pvd!lOUXetHs@AlW>X@xTpw%3p{^$@8=l$Z zyV(ih&p+kKK011MNLGftdt=2EkEK7Aa_7#S^@Q^p`_|Y>$M)SZ3ihFq)38)h3drng zy%w~xvhq}qZzTMXuTNi3&!V33{$_1Q=Dq{Pj};UYtmoskT%R@dHs$8#(hR<>q>s8$ zq(l}N$v+jRtkUk;I`)CnrZ*Ip9tG>1}FQMOiEc><39(>FLNff2pv&lx(iA zKMlRuW zhl}uS+fU0@7haoMy8QPSZhZ3!BbHP0ca3GITF5^h4ykhwLT}$4UYUI4PoMhJxxD>e Z$~gNIV@FptYsugrRV7WuJb6>U{|oxdl9B)b literal 0 HcmV?d00001 diff --git a/infrastructure/modules/compute/cloudinit.tpl b/infrastructure/modules/compute/cloudinit.tpl index 5349e54..8afd8b8 100644 --- a/infrastructure/modules/compute/cloudinit.tpl +++ b/infrastructure/modules/compute/cloudinit.tpl @@ -77,7 +77,7 @@ write_files: } owner: root:root permissions: '0600' - - path: /opt/guidelines.json + - path: /opt/cloud-init-misc-data/guidelines.json content: | { "api": "latest", diff --git a/infrastructure/modules/compute/nix/guidelines.nix b/infrastructure/modules/compute/nix/guidelines.nix index 73204b0..e809524 100644 --- a/infrastructure/modules/compute/nix/guidelines.nix +++ b/infrastructure/modules/compute/nix/guidelines.nix @@ -23,16 +23,14 @@ in ]; environment = { "PORT" = "8080"; - "BASE_CLIENT_URL" = "http://[space].test-glv5.guidelines.ch"; + "BASE_CLIENT_URL" = "http://[space].guidelines.ch"; "ENVIRONMENT" = (builtins.readFile /opt/cloud-init-misc-data/environment); "VAULT_SECRET_PATH" = "kv/data/guidelines/${(builtins.readFile /opt/cloud-init-misc-data/environment)}/api"; "VAULT_URL" = "http://host:8200"; - }; volumes = [ "/mnt/data/vault-guidelines-api-token:/vault-token" ]; - #extraDockerOptions = [ "--network=foo" ]; }; oci-containers.containers."web" = { @@ -45,6 +43,17 @@ in ]; environment = { "API_URL" = "http://host:8001"; + "PORT" = "8080"; + "CLIENT_URL" = "https://guidelines.ch"; + "REDIS_URL" = "redis://host:6379"; + + "AUTH0_AUDIENCE" = ""; + "AUTH0_CLIENT_ID" = ""; + "AUTH0_CLIENT_SECRET" = ""; + "AUTH0_DOMAIN" = ""; + "CHALLENGE_CONTENT" = ""; + "CHALLENGE_ID" = ""; + }; }; @@ -63,21 +72,18 @@ in "DEPLOYMENT_STATE_FILE" = "/guidelines.json"; }; volumes = [ - "/mnt/data/vault-deploymentagent-api-token:/vault-token" + "/mnt/data/vault-deploymentagent-token:/vault-token" "/run/podman-containers.sock:/tmp/podman/podman.sock" "/mnt/data/guidelines.json:/guidelines.json" ]; - #extraDockerOptions = [ "--network=foo" ]; }; - #oci-containers.containers."containerapi" = { - # image = "alpine"; - # volumes = [ - # "/run/podman-containers.sock:/podman-containers.sock" - # ]; - # entrypoint = "/bin/sleep"; - # cmd = ["10000"]; - #}; + # oci-containers.containers."html2pdf" = { + # }; + + # oci-containers.containers."filestore" = { + # }; + }; systemd.services.docker-podman-rest-api = { @@ -89,8 +95,26 @@ in ''; }; - services.redis.enable = true; - services.redis.requirePass = "p15c4e6538de2061edd65a52ab216ba071d78b1532a937c1c3d5821d5c571c0cf"; + system.activationScripts = { + guidelinesJson = { + text = "test -f /mnt/data/guidelines.json || cp /opt/cloud-init-misc-data/guidelines.json /mnt/data/guidelines.json"; + deps = []; + }; + }; + + services.redis = { + enable = true; + bind = "10.0.1.51"; + vmOverCommit = true; + extraConfig = '' + protected-mode no + ''; + }; + systemd.services.redis.serviceConfig = { + ReadWriteDirectories = "/var/lib/redis"; + TimeoutStartSec = "60"; + TimeoutStopSec = "60"; + }; networking.firewall.allowedTCPPorts = [ 6379 5000 4444 ]; } diff --git a/infrastructure/modules/compute/nix/vault.nix b/infrastructure/modules/compute/nix/vault.nix index 2d5e352..d929ef5 100644 --- a/infrastructure/modules/compute/nix/vault.nix +++ b/infrastructure/modules/compute/nix/vault.nix @@ -18,7 +18,7 @@ wantedBy = [ "multi-user.target" ]; after = [ "vault.service" ]; script = '' - file=/mnt/data/vault-root-token; test -f "$file" || { printf "Stopping automatic unseal, no token present at $file\n"; exit; }; count=0; while [ "$count" -le 10 ]; do count=`expr "$count" + 1`; printf "=> Trying to unseal Vault..\n"; /run/current-system/sw/bin/curl -XPUT http://127.0.0.1:8200/v1/sys/unseal -d '{"key": "'$(head -n 1 $file)'"}' && break; sleep 10; done + file=/mnt/data/vault-master-key; test -f "$file" || { printf "Stopping automatic unseal, no key present at $file\n"; exit; }; count=0; while [ "$count" -le 10 ]; do count=`expr "$count" + 1`; printf "=> Trying to unseal Vault..\n"; /run/current-system/sw/bin/curl -XPUT http://127.0.0.1:8200/v1/sys/unseal -d '{"key": "'$(head -n 1 $file)'"}' && break; sleep 10; done ''; }; diff --git a/vault/example_service_policy.hcl b/vault/example_service_policy.hcl deleted file mode 100644 index 81970ee..0000000 --- a/vault/example_service_policy.hcl +++ /dev/null @@ -1,8 +0,0 @@ -# Read-only access to all secrets in key-value store -path "kv/data/guidelines/production/api" { - capabilities = ["read"] -} - -path "kv/data/guidelines/staging/api" { - capabilities = ["read"] -}