Serverloses Self-Service-IoT-Zertifikatsmanagement - Teil 1.

Diese Datei wurde automatisch von KI ubersetzt, es konnen Fehler auftreten
Ich habe im Laufe der Jahre mit mehreren verschiedenen IoT-Lösungen gearbeitet. Eine Sache, die ihnen allen gemeinsam ist, ist die Notwendigkeit von vertrauenswürdigen Zertifikaten, die sowohl zum Herstellen von Verbindungen als auch zur Identifizierung von Geräten verwendet werden können. Geräte und Server müssen sich gegenseitig vertrauen, um sichere Kommunikation herzustellen, die Datenintegrität sicherzustellen und böswillige Angriffe zu verhindern. Ein wichtiger Teil dieses Vertrauens ist die Public Key Infrastructure (PKI), bei der Zertifikate und Certificate Authorities (CAs) eine entscheidende Rolle spielen. Es besteht auch die Notwendigkeit, eine große Menge an Zertifikaten auf einfache Weise zu verwalten.
In einigen Projekten haben wir unsere eigene interne PKI-Lösung entwickelt, was mit Komplexität und Sicherheitsanforderungen einhergeht. In anderen haben wir SaaS-Lösungen verwendet, wie DigiCert IoT Trust Manager, AWS IoT Core und Amazon Private CA.
Wenn es jedoch um Entwicklung und manchmal sogar um Testumgebungen ging, war es nicht ungewöhnlich, dass wir selbstsignierte Zertifikate verwendet haben, mit einem einfachen Self-Service-Portal, um verschiedene Zertifikate zu erstellen.
In diesem Beitrag, der der erste von zwei Teilen ist, werden wir einige Grundlagen zu Zertifikaten und PKI einführen. Wir werden auch damit beginnen, die Grundlagen für eine serverlose API zu schaffen, die verwendet werden kann, um ein Self-Service-Portal für die Generierung von Zertifikaten einzurichten.
WARNUNG
Die Lösung, die ich in dieser Beitragsserie baue, ist NICHT für ein Produktionssetup geeignet. Dies ist rein für Entwicklungsumgebungen und zu Lernzwecken gedacht!
In einer Produktionsumgebung benötigen wir:
Für diese Anforderungen sind verwaltete Dienste wie AWS Private CA, DigiCert IoT Trust Manager und Let’s Encrypt ideal.
In dieser ersten Version der API verwenden wir keine Form der Autorisierung! Dies wird im nächsten Teil hinzugefügt!
Warum eine Self-Service-API erstellen?
Wie bereits gesagt, müssen in einem IoT-System Tausende von Geräten mit Servern, IoT-Brokern und miteinander interagieren. Jede dieser Interaktionen muss sicher sein, was bedeutet:
- Server müssen Geräte authentifizieren, um sicherzustellen, dass sie legitim sind.
- Geräte müssen Server authentifizieren, um sicherzustellen, dass sie mit einer vertrauenswürdigen Quelle verbunden sind.
Zertifikate werden daher an Server und Geräte ausgegeben, wodurch eine Vertrauenskette entsteht, die bei einer Root-CA verankert ist.
Eine Self-Service-API für das Zertifikatsmanagement ermöglicht:
- Automatisierung: Geräte und Server können Zertifikate programmgesteuert anfordern und erneuern.
- Skalierbarkeit: Wenn unsere IoT-Umgebung wächst, kann die API den zunehmenden Bedarf an Zertifikaten bewältigen.
- Lernen und Testen: Bevor man einen verwalteten Dienst einführt, hilft der Aufbau eines eigenen Zertifikatsystems dabei, zu verstehen, wie PKI funktioniert.
Überblick über Zertifikate, CAs und Vertrauen
Was ist eine Certificate Authority (CA)?
Eine CA ist eine vertrauenswürdige Entität, die für die Ausstellung digitaler Zertifikate verantwortlich ist. Diese Zertifikate binden einen öffentlichen Schlüssel an eine Identität (z. B. einen Server, ein Gerät oder einen Benutzer) und ermöglichen so Vertrauen zwischen Entitäten.
CAs sind in einer Hierarchie strukturiert:
Root-CA
- Das ultimative Vertrauensanker.
- Selbstsigniert und hochsicher.
- Sollte niemals direkt End-Entity-Zertifikate ausstellen.
Zwischen-CA
- Von der Root-CA ausgestellt und signiert.
- Delegiert die Verantwortung für die Ausstellung von Zertifikaten an End-Entitäten (z. B. Geräte und Server).
- Begrenzt die Exposition der Root-CA.
End-Entity-, Blatt-Zertifikate
- Zertifikate für Server, IoT-Geräte oder Benutzer.
- Von einer Zwischen-CA ausgestellt und für die Kommunikation zwischen Client und Server oder gegenseitige Authentifizierung verwendet.
Zertifikatsketten und Vertrauen
Eine Zertifikatskette ist eine Folge von Zertifikaten, bei der jedes Zertifikat in der Kette von dem nachfolgenden Zertifikat signiert wird. Sie stellt die hierarchische Beziehung zwischen einem Zertifikat und seinem Aussteller dar.

Eine Kette kann aus einem oder mehreren Zwischenzertifikaten bestehen. Im obigen Bild wird die Kette mit zwei Zwischen-CAs veranschaulicht.
Während eines TLS-Handshakes
Vereinfacht dargestellt würde der Handshake wie folgt ablaufen
- Der Server präsentiert sein Zertifikat dem Client.
- Der Client validiert das Serverzertifikat, indem er die Kette bis zu einer vertrauenswürdigen Root-CA in seinem Zertifikatspeicher zurückverfolgt. Bei Verwendung einer selbstsignierten Root-CA müssen Sie sicherstellen, dass das Bündel im Vertrauensspeicher vorhanden ist oder im Verbindungsversuch enthalten ist.
In einem Szenario, in dem gegenseitige Authentifizierung erforderlich ist, führt der Server den gleichen Prozess für das Client-Zertifikat durch.
Vertrauen über mehrere Zwischen-CAs hinweg
In einem IoT-Setup ist es üblich, dass eine Zwischen-CA Serverzertifikate ausstellt (z. B. für IoT-Broker) und eine andere Zwischen-CA Client-Zertifikate ausstellt (z. B. für Geräte). Damit ein Client-Zertifikat (signiert von einer Zwischen-CA) einem Server-Zertifikat (signiert von einer anderen Zwischen-CA) vertraut, müssen beide:
Teil derselben Vertrauenshierarchie sein.
- Beide Zwischen-CAs müssen von derselben Root-CA signiert sein.
- Die Root-CA ist der gemeinsame Vertrauensanker.
Gegen die Kette validiert werden.
- Der Client überprüft die Zertifikatskette des Servers und verfolgt sie bis zur Root-CA zurück.
- Der Server überprüft die Zertifikatskette des Clients auf ähnliche Weise.
Dieses Setup gewährleistet Skalierbarkeit und Trennung der Verantwortlichkeiten. Die Server-Zwischen-CA konzentriert sich auf Server und Broker. Die Geräte-Zwischen-CA konzentriert sich auf IoT-Geräte.
Implementierung
Nun lassen Sie uns mit der Implementierung dieser Self-Service-API beginnen. Wir werden sie vollständig serverlos mit Amazon API Gateway und Lambda-Funktionen bauen, wobei die Zertifikate in S3 und Certificate Manager gespeichert werden. Dieser erste Teil der Blogserie wird nur den ersten sehr grundlegenden Teil der API erstellen, den wir im zweiten Teil erweitern werden. Sie finden den gesamten Quellcode auf Serverless-Handbuch Self-Service-IoT-Zertifikatsmanagement

Wir werden ein API Gateway mit drei Endpunkten einrichten, um unsere Root-CA, Zwischen-CA und Serverzertifikate zu erstellen. Alles wird in einem S3-Bucket gespeichert, und das Serverzertifikat wird auch in Certificate Manager importiert.
REST-API
Zunächst werfen wir einen Blick auf die REST-API und die Struktur.
| Endpunkt | Methode | Beschreibung |
|---|---|---|
/certificates/root | POST | Erstellen Sie eine neue Root-CA. |
/certificates/intermediate | POST | Erstellen Sie eine neue Zwischen-CA. |
/certificates/server | POST | Erstellen Sie ein neues Serverzertifikat. |
Ich habe mich entschieden, separate Pfade zu verwenden (z. B. /certificates/root, /certificates/intermediate, /certificates/server) anstatt einen einzigen Endpunkt mit einem Typ-Parameter (z. B. /certificates mit Typ als Eingabe), da ich der Meinung bin, dass dies besser mit REST-Prinzipien übereinstimmt und die Lesbarkeit und Benutzerfreundlichkeit der API verbessert.
Es ist einfacher, die API zu erweitern, mit einem neuen Zertifikatstyp (z. B. Gerät), da wir einen neuen Pfad wie /certificates/device erstellen können, ohne bestehende Pfade zu beeinflussen. Separate Pfade segmentieren Ressourcen auf natürliche Weise und reduzieren den Bedarf an Filterung auf der Client-Seite. Ich finde, dass das Abrufen aller Root-CAs mit GET /certificates/root einfacher ist als GET /certificates?type=root.
Gemeinsame Infrastruktur
Zunächst einmal lassen Sie uns die gemeinsame Infrastruktur bereitstellen, in diesem Fall ist es nur der S3-Bucket, wir werden später weitere Dinge in dieser Vorlage hinzufügen.
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: Zertifikat Self Service Gemeinsame Infrastruktur
Parameters:
ApplicationName:
Type: String
Description: Name der übergeordneten Anwendung
Default: image-moderation
Resources:
StorageBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
BucketName: !Sub ${ApplicationName}-storage-bucket
Outputs:
StorageBucketName:
Description: Der Name des Zertifikatsbuckets
Value: !Ref StorageBucket
Export:
Name: !Sub ${AWS::StackName}:certificate-bucket-nameAls nächstes können wir die Endpunkte mit SAM und AWS::Serverless::Api einrichten und die drei Lambda-Funktionen, die die API unterstützen.
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: Erstellen Sie die API für das Self-Service-Zertifikatsmanagement
Parameters:
ApplicationName:
Type: String
Description: Name der übergeordneten Anwendung
CommonInfraStackName:
Type: String
Description: Der Name des gemeinsamen Stacks, der den EventBridge-Bus und mehr enthält
Globals:
Function:
Timeout: 30
MemorySize: 2048
Runtime: python3.12
Environment:
Variables:
CERTIFICATE_BUCKET_NAME:
Fn::ImportValue: !Sub "${CommonInfraStackName}:certificate-bucket-name"
Resources:
LambdaGenerateRootCA:
Type: AWS::Serverless::Function
Properties:
CodeUri: Lambda/API/GenerateRootCA
Handler: handler.handler
Policies:
- S3FullAccessPolicy:
BucketName:
Fn::ImportValue: !Sub "${CommonInfraStackName}:certificate-bucket-name"
Events:
CreateRootCAApi:
Type: Api
Properties:
Path: /certificates/root
Method: post
RestApiId: !Ref GenerateCertificatesApi
LambdaGenerateIntermediateCA:
Type: AWS::Serverless::Function
Properties:
CodeUri: Lambda/API/GenerateIntermediateCA
Handler: handler.handler
Policies:
- S3FullAccessPolicy:
BucketName:
Fn::ImportValue: !Sub "${CommonInfraStackName}:certificate-bucket-name"
Events:
CreateIntermediateCAApi:
Type: Api
Properties:
Path: /certificates/intermediate
Method: post
RestApiId: !Ref GenerateCertificatesApi
LambdaGenerateDeviceCertificate:
Type: AWS::Serverless::Function
Properties:
CodeUri: Lambda/API/GenerateDeviceCert
Handler: handler.handler
Policies:
- S3FullAccessPolicy:
BucketName:
Fn::ImportValue: !Sub "${CommonInfraStackName}:certificate-bucket-name"
LambdaGenerateServerCertificate:
Type: AWS::Serverless::Function
Properties:
CodeUri: Lambda/API/GenerateServerCert
Handler: handler.handler
Policies:
- S3FullAccessPolicy:
BucketName:
Fn::ImportValue: !Sub "${CommonInfraStackName}:certificate-bucket-name"
- Version: "2012-10-17"
Statement:
Action:
- acm:*
Effect: Allow
Resource: "*"
Events:
CreateServerCAApi:
Type: Api
Properties:
Path: /certificates/server
Method: post
RestApiId: !Ref GenerateCertificatesApi
GenerateCertificatesApi:
Type: AWS::Serverless::Api
Properties:
Description: API zum Erstellen und Verwalten von Zertifikaten
Name: !Sub ${ApplicationName}-api
StageName: prod
OpenApiVersion: '3.0.1'
AlwaysDeploy: true
EndpointConfiguration: REGIONALUnsere Lambda-Funktionen sind in Python und wir verwenden die Kryptografie-Bibliothek, um die Zertifikate zu erstellen, unten ist die Implementierung für die Erstellung eines Serverzertifikats. Für eine vollständige Implementierung besuchen Sie Serverless-Handbuch Self-Service-IoT-Zertifikatsmanagement.
import boto3
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
import datetime
import os
import json
s3_client = boto3.client("s3")
acm_client = boto3.client("acm")
def create_server_certificate(
intermediate_private_key_pem,
intermediate_cert_pem,
fqdn,
country,
state,
organization,
validity_days,
):
# Laden Sie den privaten Schlüssel und das Zertifikat der Zwischen-CA
intermediate_private_key = serialization.load_pem_private_key(
intermediate_private_key_pem, password=None
)
intermediate_cert = x509.load_pem_x509_certificate(intermediate_cert_pem)
# Generieren Sie einen privaten Schlüssel für das Serverzertifikat
server_private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
server_private_key_pem = server_private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
subject = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, country),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization),
x509.NameAttribute(NameOID.COMMON_NAME, fqdn),
]
)
server_certificate = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(intermediate_cert.subject) # Signiert von der Zwischen-CA
.public_key(server_private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.now(datetime.timezone.utc))
.not_valid_after(
datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=validity_days)
)
.add_extension(
x509.SubjectAlternativeName([x509.DNSName(fqdn)]),
critical=False,
)
.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
)
.add_extension(
x509.KeyUsage(
digital_signature=True,
key_encipherment=True,
key_cert_sign=False,
crl_sign=False,
content_commitment=False,
data_encipherment=False,
encipher_only=False,
decipher_only=False,
key_agreement=False,
),
critical=True,
)
.sign(intermediate_private_key, hashes.SHA256())
)
server_cert_pem = server_certificate.public_bytes(serialization.Encoding.PEM)
return server_private_key_pem, server_cert_pem
def handler(event, context):
body = json.loads(event["body"])
bucket_name = os.environ.get("CERTIFICATE_BUCKET_NAME")
# Zwischen-CA-Privatschlüssel und -Zertifikat aus S3 abrufen
intermediate_private_key = s3_client.get_object(
Bucket=bucket_name, Key="intermediate_ca/private_key.pem"
)["Body"].read()
intermediate_cert = s3_client.get_object(
Bucket=bucket_name, Key="intermediate_ca/certificate.pem"
)["Body"].read()
# Die Zertifikatskette aus S3 abrufen
cert_chain_pem = s3_client.get_object(
Bucket=bucket_name, Key="intermediate_ca/certificate_chain.pem"
)["Body"].read()
# Serverzertifikat erstellen
server_private_key_pem, server_cert_pem = create_server_certificate(
intermediate_private_key,
intermediate_cert,
body["fqdn"],
body["country"],
body["state"],
body["organization"],
body["validity_days"],
)
s3_folder = f"server_certificates/{body["fqdn"]}/"
# Serverzertifikat und Privatschlüssel in S3 hochladen
s3_client.put_object(
Bucket=bucket_name,
Key=f"{s3_folder}private_key.pem",
Body=server_private_key_pem,
)
s3_client.put_object(
Bucket=bucket_name, Key=f"{s3_folder}certificate.pem", Body=server_cert_pem
)
# Zertifikat in ACM importieren
response = acm_client.import_certificate(
Certificate=server_cert_pem,
PrivateKey=server_private_key_pem,
CertificateChain=cert_chain_pem,
)
return {
"statusCode": 200,
"body": json.dumps(
{
"message": "Serverzertifikat erstellt, in S3 hochgeladen und in ACM importiert.",
"fqdn": body["fqdn"],
"s3_folder": s3_folder,
"acm_certificate_arn": response["CertificateArn"],
}
),
}Fazit
Dieser Beitrag deckte alles von Zertifikatsketten bis zur Validierung von Vertrauen in IoT-Systemen ab. Das Erstellen einer eigenen Self-Service-API ist eine gute Möglichkeit, Zertifikate und PKI kennenzulernen. In der Produktion sollten Sie jedoch immer verwaltete Lösungen wählen, die Automatisierung, Compliance und Skalierbarkeit bieten.
Zertifikate sind das Fundament der IoT-Sicherheit
Zertifikate und CAs gewährleisten sichere, authentifizierte Kommunikation in IoT-Ökosystemen.
Die Rolle von Zwischen-CAs
Die Delegation der Zertifikatsausstellung an Zwischen-CAs verbessert die Skalierbarkeit und begrenzt die Exposition.
Vertrauen wird auf Hierarchien aufgebaut
Das Vertrauen zwischen Geräten und Servern beruht auf gemeinsamen Root-CAs und validierten Zertifikatsketten.
Bauen Sie zum Lernen, verwenden Sie verwaltete Dienste für die Produktion Während diese API ein großartiges Lernwerkzeug ist, eignen sich Dienste wie AWS Private CA oder Let’s Encrypt besser für die Produktion.
Um den vollständigen Quellcode zu erhalten und ihn selbst zu deployen, besuchen Sie Serverless-Handbuch Self-Service-IoT-Zertifikatsmanagement
Abschließende Worte
Vergessen Sie nicht, mir auf LinkedIn und X zu folgen, um weitere Inhalte zu erhalten, und lesen Sie den Rest meiner Blogs
Wie Werner sagt! Jetzt loslegen!