Files
certigo-dummy-ca/API.md
2025-11-20 13:30:08 +01:00

8.2 KiB

Dummy CA - API Dokumentation

Diese Dokumentation beschreibt die REST-API für die externe Anbindung an die Dummy CA.

Base URL: http://localhost:8088 (oder die entsprechende Server-Adresse)


Endpunkte

1. Health Check

Prüft, ob der Server erreichbar ist.

Endpoint: GET /health

Response:

{
  "status": "ok"
}

Status Codes:

  • 200 OK - Server ist erreichbar

2. CSR einreichen und signieren

Reicht einen Certificate Signing Request (CSR) ein und lässt ihn signieren.

Endpoint: POST /csr

Content-Type: application/json

Request Body:

{
  "csr": "BASE64_ENCODED_CSR_PEM",
  "action": "sign",
  "validity_days": 365
}

Parameter:

  • csr (string, erforderlich): Der CSR im PEM-Format, Base64-kodiert
  • action (string, erforderlich): Aktuell nur "sign" erlaubt
  • validity_days (integer, optional): Gültigkeitsdauer in Tagen (Standard: 365)

Response (Erfolg):

{
  "id": "0202",
  "status": "success",
  "message": "CSR erfolgreich signiert",
  "certificate": "-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIRAK...\n-----END CERTIFICATE-----\n"
}

Response (Fehler):

{
  "error": "fehler beim Dekodieren des CSR: illegal base64 data"
}

Status Codes:

  • 200 OK - CSR erfolgreich signiert
  • 400 Bad Request - Ungültige Anfrage (fehlende Parameter, ungültiger CSR, etc.)
  • 405 Method Not Allowed - Falsche HTTP-Methode
  • 500 Internal Server Error - Server-Fehler beim Signieren

3. Zertifikat abrufen

Ruft ein signiertes Zertifikat anhand der Zertifikat-ID ab.

Endpoint: GET /certificate/{id}

URL Parameter:

  • id (string, erforderlich): Die Zertifikat-ID (aus der CSR-Response)

Response (Erfolg):

{
  "id": "0202",
  "certificate": "-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIRAK...\n-----END CERTIFICATE-----\n",
  "created_at": "2024-01-15T10:30:00Z"
}

Response (Fehler):

zertifikat mit ID 0202 nicht gefunden

Status Codes:

  • 200 OK - Zertifikat gefunden
  • 400 Bad Request - Fehlende Zertifikat-ID
  • 404 Not Found - Zertifikat nicht gefunden

4. Root-Zertifikat abrufen

Ruft das Root-Zertifikat der CA ab.

Endpoint: GET /root

Response:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIRAK...
-----END CERTIFICATE-----

Content-Type: application/x-pem-file

Status Codes:

  • 200 OK - Root-Zertifikat erfolgreich abgerufen

Beispiel-Implementierungen

Python

import requests
import base64
import json

CA_URL = "http://localhost:8088"

# 1. CSR aus Datei lesen und Base64 kodieren
with open("request.csr", "rb") as f:
    csr_pem = f.read()
    csr_b64 = base64.b64encode(csr_pem).decode('utf-8')

# 2. CSR einreichen
response = requests.post(
    f"{CA_URL}/csr",
    json={
        "csr": csr_b64,
        "action": "sign",
        "validity_days": 365
    },
    headers={"Content-Type": "application/json"}
)

if response.status_code == 200:
    data = response.json()
    cert_id = data["id"]
    certificate = data["certificate"]
    
    # Zertifikat speichern
    with open("signed.crt", "w") as f:
        f.write(certificate)
    
    print(f"Zertifikat-ID: {cert_id}")
else:
    print(f"Fehler: {response.status_code} - {response.text}")

# 3. Zertifikat später abrufen
cert_response = requests.get(f"{CA_URL}/certificate/{cert_id}")
if cert_response.status_code == 200:
    cert_data = cert_response.json()
    print(f"Zertifikat erstellt am: {cert_data['created_at']}")

cURL

# CSR einreichen
CSR_B64=$(cat request.csr | base64 -w 0)

curl -X POST http://localhost:8088/csr \
  -H "Content-Type: application/json" \
  -d "{
    \"csr\": \"$CSR_B64\",
    \"action\": \"sign\",
    \"validity_days\": 365
  }"

# Zertifikat abrufen
curl http://localhost:8088/certificate/0202

# Root-Zertifikat abrufen
curl http://localhost:8088/root > root.crt

JavaScript/Node.js

const axios = require('axios');
const fs = require('fs');

const CA_URL = 'http://localhost:8088';

async function submitCSR(csrPath) {
  // CSR lesen und Base64 kodieren
  const csrPEM = fs.readFileSync(csrPath, 'utf8');
  const csrB64 = Buffer.from(csrPEM).toString('base64');

  try {
    // CSR einreichen
    const response = await axios.post(`${CA_URL}/csr`, {
      csr: csrB64,
      action: 'sign',
      validity_days: 365
    });

    const { id, certificate } = response.data;
    
    // Zertifikat speichern
    fs.writeFileSync('signed.crt', certificate);
    
    console.log(`Zertifikat-ID: ${id}`);
    return id;
  } catch (error) {
    console.error('Fehler:', error.response?.data || error.message);
    throw error;
  }
}

async function getCertificate(certId) {
  try {
    const response = await axios.get(`${CA_URL}/certificate/${certId}`);
    return response.data;
  } catch (error) {
    console.error('Fehler:', error.response?.data || error.message);
    throw error;
  }
}

// Verwendung
submitCSR('request.csr')
  .then(certId => getCertificate(certId))
  .then(data => console.log('Zertifikat erstellt:', data.created_at))
  .catch(console.error);

Go

package main

import (
    "bytes"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

const CA_URL = "http://localhost:8088"

type CSRRequest struct {
    CSR          string `json:"csr"`
    Action       string `json:"action"`
    ValidityDays int    `json:"validity_days"`
}

type CSRResponse struct {
    ID          string `json:"id"`
    Status      string `json:"status"`
    Message     string `json:"message"`
    Certificate string `json:"certificate"`
}

func submitCSR(csrPath string) (string, error) {
    // CSR lesen
    csrPEM, err := ioutil.ReadFile(csrPath)
    if err != nil {
        return "", err
    }

    // Base64 kodieren
    csrB64 := base64.StdEncoding.EncodeToString(csrPEM)

    // Request erstellen
    reqBody := CSRRequest{
        CSR:          csrB64,
        Action:       "sign",
        ValidityDays: 365,
    }

    jsonData, _ := json.Marshal(reqBody)

    // HTTP Request
    resp, err := http.Post(CA_URL+"/csr", "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("fehler: %s", string(body))
    }

    var csrResp CSRResponse
    json.Unmarshal(body, &csrResp)

    // Zertifikat speichern
    ioutil.WriteFile("signed.crt", []byte(csrResp.Certificate), 0644)

    return csrResp.ID, nil
}

CSR-Format

Der CSR muss im PEM-Format vorliegen und Base64-kodiert übertragen werden.

Beispiel CSR (PEM):

-----BEGIN CERTIFICATE REQUEST-----
MIICVjCCAT4CAQAwEjEQMA4GA1UEAwwHZXhhbXBsZTEwggEiMA0GCSqGSIb3DQEB
...
-----END CERTIFICATE REQUEST-----

Erstellung eines CSR:

# Private Key generieren
openssl genrsa -out private.key 2048

# CSR erstellen
openssl req -new -key private.key -out request.csr \
  -subj "/CN=example.com/O=Example Org/C=DE"

Fehlerbehandlung

Alle Fehler werden als HTTP-Status-Codes zurückgegeben:

  • 400 Bad Request: Ungültige Anfrage (fehlende/ungültige Parameter)
  • 404 Not Found: Ressource nicht gefunden (z.B. Zertifikat-ID existiert nicht)
  • 405 Method Not Allowed: Falsche HTTP-Methode verwendet
  • 500 Internal Server Error: Server-seitiger Fehler

Fehlermeldungen werden im Response-Body als Text zurückgegeben.


Wichtige Hinweise

  1. Zertifikat-Speicher: Zertifikate werden nur im Speicher gehalten und gehen nach einem Server-Neustart verloren.

  2. Keine Authentifizierung: Die API hat aktuell keine Authentifizierung. Für Produktionsumgebungen sollte dies hinzugefügt werden.

  3. CSR-Validierung: Die CA validiert die CSR-Signatur, aber nicht den Inhalt des CSR.

  4. Serialnummern: Jedes Zertifikat erhält eine eindeutige, automatisch inkrementierte Serialnummer.

  5. Gültigkeitsdauer: Standardmäßig 365 Tage, kann über validity_days angepasst werden.


Testen der API

Sie können die API mit dem bereitgestellten Beispiel-Skript testen:

./example.sh

Oder manuell mit cURL:

# Health Check
curl http://localhost:8088/health

# Root-Zertifikat
curl http://localhost:8088/root