SSL-protokoll for web-applikasjoner på web.py

 58 total views,  1 views today

SSL (TLS) -protokoll er svært vanlig i bruk for de fleste web-stedene i Internet. Om du lager en web-applikasjon bør du sette deg inn i hvordan du konfigurerer den for bruk med SSL. Om du bruker web.py for å lage web-applikasjoner i Python, får du en veiledning i denne artikkelen.

(c) 16.01.2024 Anders Fongen

Innledning

Det første leddet i en web-adresse (URL) angir hvilken protokoll som brukes. Oftest står det https:// der, sjeldnere http://. Den første formen forteller web-leseren at forbindelsen til web-tjeneren skal bruke SSL-protokoll (også kalt TLS) for å beskytte mot avlytting og forfalskning.

Jeg gir ingen detaljert beskrivelse av SSL her, fordi det finnes andre steder på Internet, og fordi det ikke er av vesentlig betydning å kjenne detaljene i denne protokollen.

SSL gir kryptert overføring av data, slik at andre ikke kan lese innholdet av dataoverføringen om de lytter til kanalen som brukes. IP-adresser til sender og mottaker er derimot ikke kryptert, og kan oppfattes gjennom avlytting.

SSL gir også autentisering av én eller begge parter i dataoverføringen, slik at det er vanskelig å utgi seg for å hete f.eks. www.vg.no uten å presentere et digitalt nøkkelsertifikat som attesterer at det er web-tjenerens virkelige navn.

Mindre brukt, men allikevel viktig, er at SSL også kan autentisere web-leseren ved hjelp av et digitalt sertifikat, som attesterer at brukeren av web-leseren heter f.eks. Anders Fongen. Denne funksjonen i SSL kan erstatte tradisjonell innlogging med brukernavn og passord.

Bruk av sertifikater og nøkler, og hvordan sertifikater kan validere andre sertifikater, er et noe omfattende tema som jeg heller vil behandle i en egen artikkel. Begrepet kalles Public Key Infrastructure, og det finnes mye informasjon om dette på Internet.

Jeg har i en tidligere artikkel vist en web-applikasjon bygget på web.py-rammeverket og programmert i Python. Denne artikkelen vil videreføre det samme fokus på rammeverk og programmeringsspråk, og vise hvordan SSL-protokoll konfigureres i en web-applikasjon bygget på web.py.

Nøkkelpar og sertifikater

For å konfigurere en web-tjener for SSL-protokoll trenger den et nøkkelpar. Det kan utstedes av en kommersiell leverandør, noe som koster en del (fra 50€/år og oppover). Med et slikt nøkkelpar kan din web-tjener autentisere seg overfor alle klienter i Internet. Det er derimot ikke praktisk mulig å be alle brukerne av web-applikasjonen din om å betale et slikt beløp for å oppnå klient-autentisering.

For web -applikasjoner som skal brukes innenfor en gruppe, firma, forening etc., er det hensiktsmessig å selv stå for utstedelsen av nøkkelpar og sertifikater. Alle som skal bruke den aktuelle web-tjeneren må da installere et sertifikat og et nøkkelpar i sin egen web-leser, og jeg skal vise hvordan dette gjøres i Google Chrome. For Firefox er fremgangsmåten ganske lik.

Bruk helst en Linux-maskin som web-tjener, da fungerer den presenterte metoden best. Her følger et skall-skript som bruker programmet openssl til å lage et rotsertifikat (også kalt CA-sertifikat), og nøkkelpar for web-tjeneren og et nøkkelpar for én klient. Skallskriptet er ment som et eksempel som du modifiseres etter eget ønske.

# Generate keys and certificates for OpenVPN
openssl genrsa -out ca_key.pem 2048
openssl genrsa -out server_key.pem 2048
openssl genrsa -out client_key.pem 2048
#  Generate CA certificate
openssl req -new -x509 -days 1000 -key ca_key.pem -out ca_cert.pem \
    -outform PEM -subj '/C=NO/O=FONGEN/CN=CA'
#  Generate Server certificate
openssl req -new -key server_key.pem -out server_csr.pem \
    -subj '/C=NO/O=FONGEN/CN=SSLSERVER' \
    -addext 'subjectAltName = DNS:ssl.fongen.no'
openssl x509 -req -in server_csr.pem -CA ca_cert.pem -CAkey ca_key.pem \
    -CAcreateserial -addtrust serverAuth -out server_cert.pem \
    -days 1000 -sha256 -copy_extensions copy
openssl verify -CAfile ca_cert.pem server_cert.pem
#  Generate Client certificate
openssl req -new -key client_key.pem -out client_csr.pem \
    -subj '/C=NO/O=FONGEN/CN=AndersFongen'
openssl x509 -req -in client_csr.pem -CA ca_cert.pem -CAkey ca_key.pem \
    -CAcreateserial -addtrust clientAuth -out client_cert.pem \
    -days 1000 -sha256
openssl pkcs12 -export -inkey client_key.pem -in client_cert.pem \
    -out client_keypair.p12
openssl verify -CAfile ca_cert.pem client_cert.pem
#  Remove unneccesary files
rm *_csr.pem

Når dette skallskriptet kjøres (du blir bedt om å skrive et passord underveis, det skal brukes når du installerer klientens nøkkel i web-leseren) skapes det følgende filer på samme katalog:

  • ca_key.pem – Dette er utstederens private nøkkel og skal aldri kopieres eller sendes til andre
  • ca_cert.pem – Dette er utstederens nøkkelsertifikat som skal installeres både i web-tjeneren og i web-leseren
  • server_key.pem, server_cert.pem – Dette er web-tjenerens private nøkkel og nøkkelsertifikat som som skal installeres der, men ikke gis til web-leserne
  • client_keypair.p12 – Dette er nøkkelen og sertifikatet til én klient, beskyttet med det passordet du nettopp skrev inn.

Installasjon av nøkler og sertifikater i Google Chrome

  • I Google Chrome, klikk på knappen med “tre prikker i vertikal ordning” øverst til høyre
  • Velg så “Settings” fra menyen
  • I listen til venstre, klikke “Privacy and Security”
  • Klikk deretter på “Security”, så på “Manage Certificates”
  • Klikk på fanen “Authorities”, og så på knappen “Import”
  • Fra den fildialogen du nå får se, velg filen “ca_cert.pem”
  • Etter at import-jobben er fullført skal du nå se dette rotsertifikatet i listen. Navnet som vises er “org-FONGEN” dersom du ikke har endret dette i skallskriptet (noe du bør gjøre).

Nå skal klientsertifikatet og nøkkelen installeres.

  • Klikk på “Your Certificates” og deretter på knappen “Import”.
  • Fra fildialogen, velg “client_keypair.p12”.
  • Du må nå skrive inn passordet som du valgte da sertifikatet ble laget for litt siden.
  • Nå skal sertifikatet vises i listen med det navnet som du har valgt å bruke.

Installasjon av nøkler og sertifikater i web-tjeneren

Nå er web-leseren klargjort, og vi skal sette opp web-tjeneren med sine nøkler og sertifikater:

from cheroot.server import HTTPServer
from cheroot.ssl.builtin import BuiltinSSLAdapter
import web, ssl

ssl_adapter = BuiltinSSLAdapter(
	certificate = 'server_cert.pem',
	private_key = 'server_key.pem',
	certificate_chain = 'ca_cert.pem')

#ssl_adapter.context.verify_mode = ssl.CERT_REQUIRED
ssl_adapter.context.verify_mode = ssl.CERT_OPTIONAL
HTTPServer.ssl_adapter = ssl_adapter

urls = ("/.*", "hello")
app = web.application(urls, globals())

class hello:
	def GET(self):
		try:
			cn = web.ctx.env['SSL_CLIENT_S_DN_CN']
		except:
			return "No client certificate available"

		return "Hello, " + cn

if __name__ == "__main__":
	app.run()

Jeg har laget en demonstrasjonsvideo som tar deg gjennom disse stegene enkeltvis, og også hvordan web-tjeneren startes og testes. Du kan se den her (beklager lavt lydnivå):

Demonstrasjon av SSL-autentisering i web.py

Takeaway

Avslutningsvis i denne artikkelen vil jeg påpeke at en del av dette stoffet også er til nytte ved bruk av andre web-rammeverk enn web.py. De fleste web-tjenere har støtte for klientautentisering med SSL, og de konfigurerer dette på forskjellige måter. Men laging av sertifikater og nøkler, samt installasjonen av klientnøkler i web-leseren, er de samme operasjonene, derfor kommer det presenterte skallskriptet til nytte.

Leave a Reply

Your email address will not be published. Required fields are marked *

two + six =