254 lines
13 KiB
Markdown
254 lines
13 KiB
Markdown
# Uitrollen met een venster
|
|
|
|
Twee programma's: eentje op je ontwikkelmachine met vinkjes en een knop, en eentje op de server
|
|
die het pakket aanneemt en installeert.
|
|
|
|
Ze vervangen de PowerShell-scripts niet — ze roepen ze aan. `Publiceren.ps1`, `Uitrollen.ps1` en
|
|
`SocketServer-uitrollen.ps1` doen dit werk al maanden, inclusief het bewaren van de vorige versie
|
|
en het terugzetten daarvan als er iets misgaat. Die logica nog een keer in C# schrijven zou
|
|
betekenen dat er twee versies zijn van iets dat maar op één manier goed is.
|
|
|
|
## Drie werkwijzen
|
|
|
|
De agent kan het op drie manieren, en welke je nodig hebt hangt af van hoe je bij de server kunt.
|
|
|
|
**Wachten op een opdracht — dit is meestal wat je wilt.** Je start de agent op de server, kiest
|
|
"wachten", en laat dat venster staan. Vanaf dat moment doe je alles op je eigen pc: vinkjes
|
|
aanzetten, op **Bouwen en uitrollen** drukken, en meekijken. Het uitrolvenster zet de pakketten in
|
|
je publicatiemap en legt er een briefje bij (`uitrol-opdracht.json`); de agent ziet dat briefje
|
|
via de doorgegeven schijf van je externe-bureaubladverbinding, controleert per pakket de hash, en
|
|
rolt uit in de vaste volgorde. Wat hij doet schrijft hij terug in `uitrol-log.txt` in diezelfde
|
|
map, en het venster op je pc leest dat regel voor regel mee.
|
|
|
|
Geen poort, geen certificaat, geen gedeeld geheim — en op de server hoef je niets in te tikken.
|
|
Met een VPN werkt dezelfde weg, alleen wijst `Opdrachtmap` dan naar een gedeelde map op je pc in
|
|
plaats van naar `\\tsclient`.
|
|
|
|
Het blijft met opzet een apart briefje en niet "er staat een nieuwe zip, ga je gang": anders rolt
|
|
de agent uit zodra je om een heel andere reden een keer bouwt. Een opdracht hoort te ontstaan
|
|
doordat iemand op een knop drukt.
|
|
|
|
**Zelf uitrollen, zonder netwerk.** Je staat al op de server — via RDP of aan de console — en het
|
|
pakket staat ergens waar die server bij kan, bijvoorbeeld op de schijf die je met je
|
|
externe-bureaubladverbinding hebt doorgegeven. Start de agent, kies "een pakket uitrollen dat op
|
|
deze server staat", en geef het pad op:
|
|
|
|
```
|
|
\\tsclient\D\publish\mijnbesluit.zip
|
|
```
|
|
|
|
Hier komt geen poort aan te pas, geen certificaat en geen gedeeld geheim. Dat is geen gat in de
|
|
beveiliging: dat je op deze server bent ingelogd ís de toegangscontrole. Wie zover komt, heeft
|
|
geen pakket nodig om schade aan te richten.
|
|
|
|
**Op afstand, met een druk op de knop.** Je pc stuurt het pakket naar de agent en die rolt het
|
|
uit. Dat vraagt wél een poort, en daarmee alles hieronder: TLS, een handtekening en een firewall.
|
|
|
|
> **Let op: RDP is geen tunnel.** Je ziet het bureaublad van de server, maar je pc kan daarmee
|
|
> niet bij een poort op die server. De luisterstand heeft dus alleen zin als je de server echt
|
|
> over een netwerk kunt bereiken — een VPN. Zolang dat er niet is, gebruik je de eerste werkwijze:
|
|
> bouwen op je pc, het pakket over de doorgegeven schijf, en uitrollen op de server.
|
|
|
|
Het uitrolvenster op je pc is in beide gevallen nuttig: bouwen en inpakken doet het altijd. Alleen
|
|
het versturen werkt pas als de luisterstand kan.
|
|
|
|
## Waar je je bewust van moet zijn
|
|
|
|
Dit gaat over de luisterstand. Rol je uit terwijl je zelf op de server staat, dan is er niets van
|
|
dit alles nodig.
|
|
|
|
**Dit is een kanaal waarmee code op je server terechtkomt.** Dat is niet een bijwerking maar het
|
|
doel, en het is dezelfde server waar de kluizen en de masterkey staan. Wie bij dit kanaal kan,
|
|
kan alles wat de server kan.
|
|
|
|
Daarom zitten er vier grendels op, en die zijn geen van alle optioneel:
|
|
|
|
1. **De poort staat alleen open op het besloten netwerk.** De agent luistert wel op alles, maar de
|
|
firewall van de server hoort alles te weigeren behalve het VPN-bereik. Dit is geen poort voor
|
|
het open internet.
|
|
2. **TLS**, met hetzelfde certificaat als de SocketServer. Zonder certificaat weigert de agent te
|
|
starten.
|
|
3. **Een handtekening per opdracht**, met een gedeeld geheim. TLS zegt dat niemand meeleest, niet
|
|
wie er aanbelt — en op een besloten netwerk zit meer dan alleen jouw pc. In de handtekening
|
|
zitten de soort, de hash van het pakket, een tijdstip en een eenmalig nummer. Een opgevangen
|
|
opdracht is dus na twee minuten niets meer waard, kan geen tweede keer, en past niet op een
|
|
ander pakket.
|
|
4. **Een vaste lijst met wat de agent mag**: de site uitrollen, de SocketServer uitrollen, de
|
|
databasescripts draaien. Er zit geen "voer dit uit" bij. Een agent die opdrachten van buiten
|
|
uitvoert is een achterdeur met een nette naam.
|
|
|
|
En hij draait alleen als jij hem start. Geen Windows-service: een poort die dag en nacht openstaat
|
|
voor iets wat je een paar keer per week doet, staat vooral open als je er niet bent.
|
|
|
|
Vijf zelfcontroles bewaken de handtekening: verkeerd geheim, te kort geheim, een ander pakket
|
|
onder dezelfde handtekening, dezelfde opdracht twee keer, en een opdracht die te oud is.
|
|
|
|
## Eenmalig inrichten
|
|
|
|
Stap 1 en de firewallregel zijn alleen nodig voor de luisterstand. Rol je uit terwijl je zelf op
|
|
de server staat, dan volstaan stap 2 (zonder `Geheim` en zonder certificaat) en stap 3.
|
|
|
|
### 1. Een geheim maken — alleen voor de luisterstand
|
|
|
|
Op de server, in de map waar de agent staat:
|
|
|
|
```
|
|
MijnBesluit.Uitrolagent.exe --nieuwe-sleutel
|
|
```
|
|
|
|
Zet de uitkomst in `uitrolagent.json` **op de server** en in `uitroller.json` **op je pc**. Niet in
|
|
de projectmap, niet in een e-mail, niet in een schermafbeelding.
|
|
|
|
### 2. De agent neerzetten
|
|
|
|
Publiceer `src\MijnBesluit.Agentvenster` en zet de uitkomst op de server, bijvoorbeeld in
|
|
`C:\Beheer\uitrolagent`. Dat is het venster; de agent zelf komt als projectverwijzing mee, dus in
|
|
die ene map staan daarna allebei:
|
|
|
|
| Bestand | Waarvoor |
|
|
|---|---|
|
|
| `MijnBesluit.Agentvenster.exe` | Het venster. Dubbelklikken, hij staat te wachten. Dit is wat je dagelijks gebruikt. |
|
|
| `MijnBesluit.Uitrolagent.exe` | Hetzelfde werk zonder venster, plus `--nieuwe-sleutel`, `--zip` en `--luister` |
|
|
|
|
Vul `uitrolagent.json` in:
|
|
|
|
| Instelling | Wat erin hoort |
|
|
|---|---|
|
|
| `Geheim` | De sleutel uit stap 1 |
|
|
| `Poort` | 5210, of iets anders dat vrij is |
|
|
| `CertificateThumbprint` | Hetzelfde certificaat als de SocketServer gebruikt |
|
|
| `Scriptmap` | Waar `Uitrollen.ps1` en `SocketServer-uitrollen.ps1` staan, bijvoorbeeld `C:\Beheer` |
|
|
| `Werkmap` | Waar binnengekomen pakketten landen |
|
|
| `Opdrachtmap` | Waar de agent naar een briefje van je pc kijkt als hij staat te wachten. Over RDP: `\\tsclient\D\publish` |
|
|
| `DbGebruiker` / `DbWachtwoord` | Alleen nodig voor databasescripts. Neem een eigen account dat mag wijzigen; niet root als het niet hoeft |
|
|
|
|
> **Let op bij opnieuw publiceren.** Een publicatie zet `uitrolagent.json` terug op de versie uit de
|
|
> projectmap — met lege velden. Alles wat je niet elke keer opnieuw wilt intikken hoort daarom in
|
|
> `C:\MijnBesluitData\uitrolagent.secrets.json`. Dat bestand gaat **per sleutel** over
|
|
> `uitrolagent.json` heen, dus je zet er alleen in wat afwijkt: `Geheim`, `MysqlExe`, `DbGebruiker`,
|
|
> `DbWachtwoord`, en `Opdrachtmap` of `Scriptmap` als die bij jou anders zijn. Het agentvenster zegt
|
|
> bij het opstarten in zijn logboek welke twee bestanden hij heeft gelezen.
|
|
|
|
Zet de firewall goed: poort 5210 alleen vanaf het VPN-bereik.
|
|
|
|
### 3. Het venster neerzetten
|
|
|
|
Publiceer `src\MijnBesluit.Uitroller` en vul `uitroller.json` in: de server, de poort, hetzelfde
|
|
geheim, en waar je projectmap staat.
|
|
|
|
## De vinkjes staan er al
|
|
|
|
Bij het openen kijkt het venster wat er sinds de vorige uitrol is gewijzigd, en zet de vinkjes
|
|
daarop. Het zegt er ook bij waarom: *"De website: Home.razor is gewijzigd."*
|
|
|
|
Waarom dat de moeite is: na een middag werken weet niemand meer precies wat hij heeft aangeraakt.
|
|
Dan vink je te veel aan — kost tijd — of te weinig, en dan draait er een website tegen een
|
|
SocketServer die iets anders verwacht. Dat laatste kost een avond zoeken naar een fout die er niet
|
|
is.
|
|
|
|
Wat waarin terechtkomt staat in `Wijzigingen.cs` en wordt door een zelfcontrole bewaakt. De
|
|
gedeelde projecten tellen mee bij allebei: een wijziging in Domain of Application zit zowel in de
|
|
website als in de SocketServer. Protocol zit in de SocketServer en in de app, maar niet in de
|
|
website — die praat niet over de socket.
|
|
|
|
Twee dingen die met opzet zo zijn:
|
|
|
|
- **Bij twijfel staat hij aan.** Is er nog nooit vanuit dit venster uitgerold, dan staat alles
|
|
aan. Te veel uitrollen kost een minuut.
|
|
- **Onthouden gebeurt op het moment van het nieuwste bestand**, niet op de klok van het moment
|
|
waarop het lukte. Wijzig je iets terwijl hij bouwt, dan zou dat laatste die wijziging als
|
|
uitgerold aanmerken terwijl hij er niet in zit — en dan staat het vinkje de volgende keer ten
|
|
onrechte uit.
|
|
|
|
Het blijft een voorstel: je kunt elk vinkje zelf aan- en uitzetten. Wat er onthouden wordt staat
|
|
in `laatste-uitrol.json` naast de exe.
|
|
|
|
## Uitrollen met een wachtende agent
|
|
|
|
1. Op de server, één keer: dubbelklik `MijnBesluit.Agentvenster.exe`. Hij staat meteen te
|
|
wachten — er is geen knop om eerst in te drukken. Laat dat venster staan zolang je werkt.
|
|
Controleer dat `Opdrachtmap` in `uitrolagent.json` naar je publicatiemap wijst; over een
|
|
externe-bureaubladverbinding is dat `\\tsclient\D\publish`.
|
|
2. Op je pc: start `MijnBesluit.Uitroller.exe`, zet de vinkjes en druk op **Bouwen en uitrollen**.
|
|
|
|
Meer is het niet. Je ziet in het venster op je eigen scherm wat er op de server gebeurt, inclusief
|
|
de regels van `Uitrollen.ps1` zelf.
|
|
|
|
### Het agentvenster
|
|
|
|
Twee vensters die op elkaar lijken, en dat is de bedoeling: op je pc staat het uitrolvenster, op de
|
|
server het agentvenster. Dezelfde regels komen op allebei de schermen voorbij.
|
|
|
|
Wat je op de server ziet:
|
|
|
|
- **Een balk bovenin** met wat hij doet: *Wacht op een opdracht van je pc* of *Bezig met uitrollen*.
|
|
Die regel is van een meter afstand te lezen, want dit venster staat op een machine waar je niet
|
|
naar zit te kijken.
|
|
- **Het logboek**, regel voor regel, inclusief de uitvoer van de PowerShell-scripts. Dat is niet
|
|
anders dan vroeger — het gaat alleen niet meer naar een consolescherm.
|
|
- **Een voortgangsbalk** die loopt zolang er iets gebeurt. Uitrollen duurt minuten; zonder teken
|
|
van leven ga je je afvragen of hij nog wel iets doet.
|
|
- **Stoppen met wachten**, als je hem wilt laten staan zonder dat hij opdrachten oppakt.
|
|
|
|
Sluiten terwijl er een uitrol loopt vraagt hij na. Een uitrol halverwege afbreken laat een website
|
|
achter die niet meer bij zijn database past, en dat merk je pas als er iemand op zit.
|
|
|
|
Er draait geen PowerShell-venster meer waar je omheen moet werken: het venster start PowerShell
|
|
zelf, vangt elke regel op en zet die in het logboek. De console-agent bestaat nog wel, en die heb
|
|
je ook nodig — voor `--nieuwe-sleutel`, voor `--zip` als je een pakket uitrolt dat al op de server
|
|
staat, en voor `--luister` zodra er een VPN is.
|
|
|
|
Valt de verbinding weg terwijl de agent bezig is, dan maakt hij zijn werk gewoon af — alleen het
|
|
meekijken stopt. Op het scherm van de server staat hetzelfde.
|
|
|
|
## Uitrollen terwijl je zelf op de server staat
|
|
|
|
1. Op je pc: start `MijnBesluit.Uitroller.exe`, zet de vinkjes en druk op **Bouwen en uitrollen**.
|
|
Kan hij de agent niet bereiken, dan staan de pakketten alsnog klaar in je publicatiemap —
|
|
bouwen en inpakken gebeurt namelijk hier.
|
|
2. Op de server: start `MijnBesluit.Uitrolagent.exe`, kies **2** en geef het pad op naar de zip op
|
|
je doorgegeven schijf.
|
|
|
|
Of, als je liever niets aanwijst, in één regel:
|
|
|
|
```
|
|
MijnBesluit.Uitrolagent.exe --zip \\tsclient\D\publish\mijnbesluit.zip --soort site
|
|
```
|
|
|
|
`--soort` is `site`, `socketserver` of `database`.
|
|
|
|
## Uitrollen op afstand (vraagt een VPN)
|
|
|
|
1. Op de server: start `MijnBesluit.Uitrolagent.exe` en kies **3**, of start hem met `--luister`.
|
|
Er verschijnt een venster dat zegt dat hij luistert. Laat het openstaan.
|
|
2. Op je pc: start `MijnBesluit.Uitroller.exe`, druk eerst op **Verbinding proberen**. Dat kost
|
|
een seconde en scheelt de teleurstelling van een kwartier bouwen voor niets.
|
|
3. Zet de vinkjes en druk op **Bouwen en uitrollen**.
|
|
|
|
**De volgorde ligt vast en is niet die van de vinkjes:** eerst de databasescripts, dan de website,
|
|
dan de SocketServer, en de APK helemaal achteraan. Een nieuwe kolom moet er zijn voordat de code
|
|
erom vraagt; andersom staat de site stuk in de tussentijd. De SocketServer is als laatste omdat
|
|
het herstarten daarvan iedereen met de app uitlogt.
|
|
|
|
Wat er op de server gebeurt lees je mee in het venster, regel voor regel. Loopt de verbinding weg
|
|
halverwege, dan gaat het uitrollen op de server gewoon door — daar staat hetzelfde in beeld.
|
|
|
|
## De databasescripts
|
|
|
|
De agent draait de scripts uit `db\` **vanaf nummer 03**, in volgorde. Nummer 01 maakt het schema
|
|
aan en 02 maakt de applicatiegebruiker met zijn wachtwoord; dat is inrichten, geen bijwerken, en
|
|
dat hoort een mens één keer met de hand te doen. Een agent die accounts kan aanmaken is een agent
|
|
die meer kan dan hij moet.
|
|
|
|
Alle scripts gaan er elke keer overheen. Dat mag: ze zijn zo geschreven dat opnieuw draaien niets
|
|
doet — kijk maar in de kop van elk script. Dat is eerlijker dan bijhouden wat er al gedraaid is;
|
|
zo'n administratie kan ernaast zitten, en dan mis je er precies één.
|
|
|
|
## Als er iets misgaat
|
|
|
|
Het uitrolscript zet bij een fout de vorige versie zelf terug en zegt dat in het logboek. Gebeurt
|
|
dat niet, dan staan de vorige versies op de server in `_vorige-versies` naast de sitemap.
|
|
|
|
De agent doet één ding tegelijk. Krijg je "er loopt al een uitrol", dan is er een eerdere poging
|
|
nog bezig of vastgelopen; kijk op het scherm van de agent.
|