Infisical - Security Infrastructure
Auteur: Danny Holstein
Voor verdere professionalisering was er bij BEE-2B het idee om een Keyvault in te richten. Een Keyvault heeft als voordelen dat alle credentials (secrets, connection-strings, etc. voor een applicatie) gecentraliseerd zijn, niet langer hard-gecodeerd in een project zijn en te bepalen is welke applicatie en welke omgeving er toegang heeft. Bovendien is met een Keyvault ook een audit mogelijk van de logboeken. Wat betreft Keyvault zijn er meerdere kandidaten beschikbaar. Dit nieuwe blogbericht zal gaan over het integreren van Infisical in verschillende projecten.
Infisical template op EasyPanel
BEE-2B heeft gekozen voor Infisical mede omdat er een kant-en-klaar template hiervoor beschikbaar is op EasyPanel. Alle gewenste features zijn aanwezig in Infisical voor een Security Infrastructure. Een nadeel bleek het RAM-geheugengebruik te zijn, dat behoorlijk hoog lag. Een ander nadeel bleek de versie te zijn waarbij het Infisical template op EasyPanel al ver achterliep (versie 159). Het Infiscical team heeft wekelijks meerdere updates met soms brekende veranderingen. Om meer controle hierop te krijgen, moest er zelf een PostgreSQL database, redis (voor cacheing) en een Infisical instance worden klaargemaakt.
Aanvankelijk heb ik dit laatste niet op de online test-server uitgeprobeerd door middel van trail-and-error. Om meer bekend te worden met Infisical heb ik eerst lokaal met Docker Desktop geëxperimenteerd. Een voordeel is dat er al een kant-en-klaar docker-compose bestand was om Infisical lokaal uit te testen. Zelf heb ik dit bestand aangepast, door een recente Docker image van Infisical te gebruiken en op bepaalde punten gebruik ik liever 'restart: unless-stopped' in het docker-compose bestand. Zoals gewoonlijk is het beter om een specifieke versie te gebruiken in plaats van latest in het docker-compose bestand. Bij de voorbeelden zat ook een benodigd environment bestand, waarin de instellingen van Infisical worden geplaatst. Vrij snel werd er een lokale Infisical instance met database en redis (voor cacheing) in Docker Desktop uitgevoerd.
Het lokale experiment met Infisical
De eerste gebruiker die zich aanmeldt via het login-scherm van Infisical wordt de Server Admin. In de vervolgstappen worden de instellingen voor de organisatie ingesteld. Wanneer er een SMTP (voor het versturen van e-mails) is ingesteld, dan kunnen er ook andere personen worden uitgenodigd. Naar mijn mening is de User Interface van Infisical weinig intuïtief en duurt het even om wegwijs te worden. Globaal wordt er een onderscheid gemaakt tussen enerzijds de Projecten (onder Secrets Management - ieder project heeft zijn eigen instellingen) en anderzijds de Access Control (met daaronder een apart tabblad voor Machine Identities). Door eerst lokaal te experimenteren bleek dat er eerst een Project aangemaakt moest worden en daarna een Machine Identity (die gebruik maakt van een project).
Om zaken lokaal uit te testen is er ook eerst een eenvoudige C#/.NET WebApi gemaakt die eveneens in een Docker container werd uitgevoerd en de instellingen kon ophalen uit de Infisical instance. Hiervoor waren er meerdere Id's nodig, namelijk 1 voor het project en 2 voor de 'clients' (een andere benaming voor de Machine Identities). Voor de projecten had ik een tabel verwacht waarin dit Id zou staan, maar in plaats daarvan waren er cards te zien met summiere informatie. Uiteindelijk bleek dat het Id van het project zowel uit de URL gehaald kon worden of via het settings menu. Op deze plaatsen had ik het Id van een project niet verwacht. Hetzelfde gold voor de ietwat verwarrende naam 'client' waar Machine Identity mee wordt bedoeld. Ik meende aanvankelijk de client-Id te hebben gevonden en dit stond wel onder Access Control. Maar zo bleek Infisical niet te werken, want de juiste client-Id is onder de sectie Authentication te vinden. Misschien wordt de User Interface van Infisical in toekomstige versies iets gebruiksvriendelijker.
De volgende vraag was: hoe zijn de instellingen uit Infisical op te halen voor een C#/.NET WebApi? In de officiële documentatie (Infisical .NET SDK) is te vinden hoe dit gedaan kan worden voor verschillende programmeertalen en zo ook voor .NET. Maar al snel bleek dat de eerste voorbeeldcode uit de officiële documentatie niet direct bruikbaar was. Deze code moest aangepast worden waarbij asynchrone methoden voorzien worden van het keyword await. Na de nodige trail-and-error is het gelukt om de secrets uit Infisical te gebruiken in deze eenvoudige WebApi. Om typefouten en of ontbrekende variabelen in een vroeg stadium te ontdekken, wordt er eerst gecontroleerd of deze variabelen zijn toegewezen in builder.Configuration. Wanneer dit niet het geval is, dan wordt er een Exception afgeworpen. Uiteindelijk voldeed deze oplossing niet aan de zakelijke behoeften, want opnieuw waren er hard-gecodeerde client-Id's in de code, wat juist voorkomen moest worden. Een betere maar nog complexere oplossing is voorhanden door de Infisical CLI (Command Line Interface) te gebruiken.
Online Test Server met Infisical instance en Infisical CLI
Er is een groot verschil tussen een lokale setup en een online omgeving. De lokale docker-compose gebruikt versie 14 van PostgreSQL, maar voor een online omgeving wordt versie 16 aanbevolen. EasyPanel gebruikt tegenwoordig standaard versie 17 van PostgreSQL, maar dat brengt een risico met zich mee voor de Infisical instance, want PostgreSQL versie 16 is het meest intensief getest. Hetzelfde geldt voor redis voor cacheing, waarbij versie 7 aanbevolen is. Een hogere versie van redis wordt bovendien niet ondersteund en is het minste getest. Op EasyPanel was het dus belangrijk om de Docker image voor PostgreSQL op versie 16 vast te pinnen. De volgorde van deployen was als volgt: eerst de PostgreSQL database, daarna een instance van redis en als laatste de Infisical instance. Net zoals bij de lokale setup wordt ook bij de online setup de eerst ingelogde gebruiker de Server Admin.
Wat betreft de upgrades van Infisical is het goed om een globaal upgradeplan te hebben. Het is verrassend dat het Infisical team vrijwel iedere week meerdere updates uitbrengt (te zien via de link: Infisical Releases). Belangrijke updates zijn aangegeven met: "add upgrade impact for" en dit zijn vaak brekende veranderingen. Het komt er dus op neer dat er in een vroeg stadium back-ups gemaakt moeten worden van de database. Nog voor een upgrade is het raadzaam om een handmatige back-up te maken. Voor het upgradeplan moeten eveneens andere zaken in beschouwing worden genomen. Ten eerste is dit de versie waar naartoe wordt geüpgraded en hierbij is het beter om bijvoorbeeld versie 165 te upgraden naar 166 in plaats van versie 165 in een keer naar versie 170. Ten tweede moet er rekening mee gehouden worden dat een upgrade 'eenrichtingsverkeer' is. Een nieuwe versie van Infisical kan niet meer een oudere back-up van de database gebruiken.
Zoals in de vorige paragraaf beschreven, is het toepassen van de Infisical .NET SDK in de WebApi niet de weg om te gaan. Het nadeel hiervan is dat er opnieuw client-Id's hard-gecodeerd zijn. Het toepassen van de Infisical CLI moest nader onderzocht worden en dit heb ik eerst lokaal uitgetest. Een eerste benodigdheid was een extra script waar de Docker environment variabelen die bestemd zijn voor de Infisical CLI worden opgevangen. Een tweede zaak was het aanpassen van de Dockerfile van de WebApi, waarbij eerst de Infisical CLI wordt geïnstalleerd, daarna het script wordt uitgevoerd en tenslotte de WebApi wordt opgestart. De code uit de vorige paragraaf kon worden hergebruikt om te controleren of alle variabelen uit Infisical zijn ontvangen. Na meerdere rebuilds in Docker Desktop en de nodige trail-and-error werkte deze complexere oplossing naar behoren. Doordat dit lokaal was uitgetest, lukte het ook spoediger om dit toe te passen op de online server. Het voordeel van de Infisical CLI is dat er geen hard-gecodeerde client-Id’s meer in de code zijn.
De volgende stap was om de Infisical CLI te gebruiken voor een echt project in een test/staging omgeving. Voor bepaalde projecten zijn er echter veel variabelen en het leek mij weinig effectief om iedere variabele te kopiëren en te plakken inclusief dit iedere keer te voorzien van twee underscores. Daarom is er een eenvoudig C# Console hulpprogramma gemaakt dat een input-bestand leest met daarin de variabelen (uit appsettings.json of de Docker environment variabelen), deze variabelen formatteert en uiteindelijk zowel een output.json bestand maakt als een tekstbestand met de 'required'/verplichte variabelen. Het output.json bestand kan direct in Infisical worden gebruikt waarmee vele tientallen variabelen in een keer worden geüpload. Uit het tekstbestand kunnen de 'required' variabelen worden gekopieerd en geplakt als extra controle in de WebApi. Dit hulpprogramma zal op langere termijn de nodige tijd besparen en voorkomt onnodig kopieer-en-plakwerk.
Tot slot
In dit blogbericht is de inrichting van Infisical als Keyvault besproken. Het instellen van Infisical kan de eerste keer complex zijn en de User Interface kan eveneens de eerste keer overweldigend zijn. Wanneer hiermee eerst lokaal is geëxperimenteerd in Docker Desktop, dan is dit later ook op een vergelijkbare manier online toe te passen. Er zijn twee routes die bewandeld kunnen worden, namelijk de Infisical .NET SDK gebruiken in de C#/.NET WebApi zelf of de meer complexe route waarbij de Infisical CLI wordt gebruikt. Beide routes hebben voor- en nadelen. De eerste route is eenvoudiger, maar heeft als nadeel dat er nog steeds hard-gecodeerde client-Id’s zich in de code bevinden. Bij de tweede zijn er geen hard-gecodeerde client-Id’s meer in de code, alleen het nadeel van de tweede route is nog meer complexiteit. Hoewel Infisical sowieso een extra laag van complexiteit met zich meebrengt, is dit op langere termijn wel de weg om te gaan wat betreft Security infrastructure, waarbij hard-gecodeerde variabelen en secrets uit de code weggehaald worden.