OpenSSL & self-signed certifikater
Ressourcer:
Hvis det imod alt forventning skulle være sådan at nogle rent faktisk læser mine opslag for at få noget ud af dem --- foruden at få indblik i torpedo-ADHD-skriven --- , så vil jeg anbefale dig hvis du ikke ved noget om (m)TLS, at læse op på dette eller se en kort youtube-video, eller læse min post om det [Link kommer], inden du læser denne post.
Jeg har brugt OpenSSL til at debugge og teste forbindelser mellem mine microservices og mellem microservice X og RabbitMQ.
For mig har det været et helt uvurderligt værktøj som jeg har brugt til at få svar på spørgsmål så som
HVORFOR FAEN VIRKER DET IKKE??
og
JEG ER SIKKER PÅ JEG HAR LAGT CERTIFIKATER HOS BÅDE CLIENT OG SERVER, HVORFOR MELDER DEN STADIG OM CERTIFIKAT-ISSUES????? .
OpenSSL er et open-source library som første gang så stueetagens lys i 1998. Det er skrevet i C og er cross-platform-venligt. Jeg har valgt at bruge diverse værktøjer igennem Windows Linux Subsystem og OpenSSL er et af dem. Det er ganske enkelt fordi det kom præinstalleret på min Ubuntu WLS, og fordi jeg fik øjnene op for OpenSSL da jeg skulle lave en tls-gen file ved brug af make og i den forbindelse skulle læse fra en openssl tekstfil. Det lod til at være overraskende forvirrende at få installeret Make-værktøjet til at virke på Windows, og overraskende nemt at bruge make og openssl i Linux og kopier filerne over på min Windows --- så det blev jeg ved. OpenSSL er en værktøjskasse med en helt masse muligheder når det kommer til SSL og TLS. Biblioteket har diverse krypteringsfunktioner og helt uundværligt har det for mig været at jeg med OpenSSL nemt kan generere self-signed certifikater, som jeg bruger i development miljøet for den backend jeg er igang med at udvikle, hvori jeg har mTLS verificering sat op til alt kommunikation mellem services.
Let's Encrypt udsteder kun certifikater til public domains, og vores produkt er langt fra i produktion eller hosted på et public domain endnu. Men når man taler TLS taler man også certifikater, og de skal komme et sted fra.
Skridtene til at genere et "simpelt" certifikat er ganske enkle:
(I CLI med OpenSSL installeret)
Generer private key:
CLI: 1: openssl genpkey -algorithm RSA -out private_key.pem -aes256
Generer et 'Certificate Signing Request':
CLI: openssl req -new -key private_key.pem -out request.csr
Når ovenstående kommando eksekveres, promptes man for at angive Country, state, organization og Common Name, som bliver embedded i certifikatet. F.eks., så er det Common Name på det self-signed certifikat der automatisk udstedes på en maskine når man kører en ASP NET CORE app som håndterer https "localhost".
Generer certifikatet:
CLI: openssl x509 -req -days 365 -in request.csr -signkey private_key.pem -out certificate.pem
Og hermed kan dette certifikat f.eks. bruges af RabbitMQ (det skal være i .pem format når det skal stores i rabbitmq). Man kan også frit eksportere det til .p12 og .pfx. I .pfx formatet er indeholdt key og cert, og det er dette format jeg bruger til at mounte ind i mine microservices containere --- det håndterer .NET frameworket pænt, og forstår selv at udlede hvad det skal bruge til certifikatslæsning, når formatet er .pfx.
Eksempelcase på en troubleshooting:
Situationen:
5-10 timers frustration over efter igen igen igen at have læst RabbitMQs docs tutorial til opsætning af TLS hos både client og rabbitmq-serveren med tls-gen self-signed certifikater.
I kender det, det må i gøre. Sved, cluelessness og tilsnørret syn. Certificate-error. "The server unexpedly closed down the connection". Hvor går det galt,
og hvorfor står der ikke noget mere info på hvor i handshaket det går galt?
Problem-case:
Er der en måde hvorpå jeg kunne teste handshaket udenom alt tanke på konfigurationer af microservice A og RabbitMQ, og på den måde få indsigt i om det er certifikaterne der er noget galt med?
Der er faktisk en ganske ligefrem måde at gøre dette på med OpenSSL. Jeg ønskede at simulere server-client forholdet og etablere en TLS-forbindelse mellem disse med mTLS-verificering og hvor jeg brugte de respektive certifikater.
Opsætning af server:
CLI:
openssl s_server -cert server_cert.pem -key server_key.pem -accept 5671
Jeg promptes til at indtaste passworded for certifikatet.
Opsætning af client:
CLI:
openssl s_client -connect localhost:5671 -cert client_cert.pem -key client_key.pem -CAfile ca_cert.pem
Jeg promptes til at indtaste passworded for certifikatet.
Hurra, forbindelse. Hurra.... en lidt ambivalent følelse, for det er jo fedt at certifikaterne virker... men hvor fanden går det så galt... jeg angiver kodeordet i sourcekoden for microservice A...
Og jeg angiver den i RMQ-konfigurationsfi....... nej, det gjorde jeg ikke. Løst.
Jeg har nu i sinde at begive mig ud i at generere en custom Certificate Authority på min lokale computer. Se evt. mit blog-indlæg om TLS, hvor jeg også kommer ind på mTLS, hvis du ikke ved hvad der er med alle disse certifikater. [Link kommer når jeg har lavet postet :D]
Det fede ved OpenSSL er at jeg kan bruge dets værktøjskasse til at kreere alt hvad jeg skal bruge for at opsætte et valid development-miljø til TLS kommunikation. Altså CA's, client certs og server certs.
Planen er nu at generere certifikater med korrekte hostnames, altså det navn servicen antager på docker-netværket, så jeg ikke løber ind i handshakeproblemer såsom HostnameMitchmatch. Jeg vil bruge denne Certificate Authority til at signe alle de certifikater jeg generer til de forskellige microservices, og så tilføje denne CA til hver containers truststore, og så tror jeg på at opsætningen af TLS ellers vil gå smertefrit herfra, og at jeg kan komme videre til JWT-token-generering og viderepassering af denne.