היי לכולם, כאן אלכס. ברוכים השבים לעוד מהדורה של מתכנתים עם אלכס ב־sysseder.com.
אם אתם מפתחים לקוח ACME או בודקים אוטומציה של תעודות, Pebble מספק שרת בדיקות מקומי קטן. פירוש ACME הוא Automatic Certificate Management Environment — סביבה אוטומטית לניהול תעודות. Pebble מגיע מפרויקט Let’s Encrypt, אינו מתאים במכוון לשמש רשות אישורים לייצור ושונה בחלק מהתנהגותו מ־Boulder. הוא אינו אוכף את מגבלות הקצב של הייצור, ויכול להוסיף השהיות אימות מלאכותיות.
המאמר הקודם הציג את היכולות האלה כ״עדכון ענק מיולי 2026״ שהגיע לראש Hacker News. חומר הגרסאות הרשמי שנבדק לצורך התיקון אינו מבסס את המסגור הזה. המדריך בוחן במקום זאת תכונות בדיקה מתועדות, ואינו טוען לדירוג הזה או להשקה חדשה של מדמה אימות ממספר נקודות תצפית.
נבחין בין Pebble לשרת תגובות האתגרים הנפרד שלו, נבחן תצורה ונציג לקוח ניהול קטן ב־Go. הדוגמאות מיועדות להמחשה: הן אינן לקוח מלא להנפקת תעודות, בדיקת עמידה בדרישות או פריסה לייצור שנבדקה.
למה Pebble חשוב למפתחים כיום
HTTPS מקומי עלול להיות מסורבל: מפתחים עשויים ליצור תעודות עם openssl, להגדיר אמון או להשבית אימות. ב־Node.js, rejectUnauthorized: false משבית בדיקה חשובה; זו אינה הגדרה כללית של Python. העדיפו אמון שמוגדר רק ללקוח הבדיקות. רשות הבדיקה המצורפת עבור HTTPS היא pebble.minica.pem; המפתח הפרטי שלה פומבי. לעולם אל תוסיפו אותה למאגר אמון כלל־מערכתי או לסביבת ייצור.
בפריסת ייצור המשתמשת ב־ACME, לקוחות כגון Certbot או Lego ושילובים כגון Caddy או Traefik מנהלים בקשות לתעודות וחידושים. בדיקת הפרוטוקול מקומית יכולה לחשוף מוקדם יותר חלק מתקלות הניתוב, התגובה לאתגרים והחידוש, אך אינה משחזרת כל תנאי ייצור.
Pebble חושף נקודת ספרייה מקומית של ACME, בדרך כלל ב־https://localhost:14000/dir. לקוחות יכולים לבדוק מולו הזמנות, אימות אתגרים והתנהגות חידוש. רשות הבדיקה אינה שומרת את מצבה בין הרצות, והנפקה מקומית מוצלחת אינה הוכחה שכל כללי האימות של רשות ציבורית או הטיפול במגבלות קצב יעבדו.
אילו יכולות בדיקה מתועדות?
אבני הבניין השימושיות כוללות יציאות אתגר הניתנות להגדרה, שרת DNS ואתגרים נפרד שניתן לשלוט בו ובדיקות תאימות במצב קפדני. יש להבחין ביניהן לבין אימות מבוזר גאוגרפית והדמיית תקלות רשת.
1. מספר כתובות DNS אינו שקול למספר נקודות תצפית גאוגרפיות
Let’s Encrypt משתמשת באימות ממספר נקודות תצפית כדי לבדוק שליטה בדומיין דרך מספר נתיבי רשת. הדבר מקשה על חלק מהתקפות הניתוב ונתיבי ה־DNS; הוא אינו מבטיח מניעה של כל התקפה כזאת.
הכלי הנלווה pebble-challtestsrv יכול להגדיר רשימות של תגובות A ו־AAAA. כך אפשר ליצור מקרי בדיקה מבוקרים של DNS, אך אין פירוש הדבר שקיימים מאמתים גאוגרפיים וירטואליים, הדמיית אובדן מנות או הגדרת קוורום requiredSuccesses. תצורת Pebble שנבדקה אינה חושפת מתגים כאלה.
2. ניהול תגובות לאתגרי DNS-01
תגובות DNS דינמיות מנוהלות דרך API ה־HTTP של שרת האתגרים הנפרד, ולא דרך מנוע DNS חדש בתוך Pebble. עבור DNS-01 משתמשים ב־/set-txt וב־/clear-txt ביציאת הניהול שלו. מגדירים את Pebble לשאול את השרת הזה באמצעות -dnsserver. ה־API לניהול אינו דורש אימות זהות, ומקומו רק בסביבת בדיקה מבודדת.
3. מצב קפדני ובדיקות תאימות
דגל שורת הפקודה -strict מפעיל התנהגות API עתידית ששוברת תאימות. הוא אינו בקר כללי להזרקת שגיאות ואינו מבטיח כיסוי מלא של המפרט. אפשר להגדיר תגובות כשל של DNS בנפרד בשרת האתגרים; השתמשו רק במתגים המתועדים לגרסה שבחרתם.
הגדרת מעבדת בדיקה מבודדת של Pebble
דוגמת docker-compose.yml משתמשת בשני שירותים: Pebble ושרת האתגרים שלו. היא אינה כוללת לקוח lego או שרת ווב מוגדר. לבדיקות הנפקה מקצה לקצה יש להוסיף בנפרד לקוח ACME ואת השילוב שלו עם מנגנון הטיפול באתגרים.
תוכנית העבודה של Docker Compose
הגדירו את PEBBLE_IMAGE ואת CHALLTESTSRV_IMAGE לתמונות מאומתות המקובעות לפי digest, מאותה גרסה שנבחרה במאגרי GHCR הרשמיים. מצייני המקום נועדו למנוע הפעלה מקרית של גרסה שאינה מקובעת. בדקו שתת־הרשת אינה מתנגשת בסביבה שלכם. יציאות המארח נקשרות לכתובת loopback, אך זו עדיין מעבדת בדיקה: אל תשתפו את שירותי הניהול שאינם דורשים אימות. PEBBLE_VA_NOSLEEP מבטל השהיות אימות מלאכותיות; השמיטו אותו בבדיקת אימות מושהה.
# Illustrative test lab. Set both variables to verified, matching-release image digests.
services:
pebble:
image: ${PEBBLE_IMAGE:?Set a verified ghcr.io/letsencrypt/pebble image digest}
command: ["-config", "/test/config/pebble-config.json", "-strict", "-dnsserver", "10.30.50.3:8053"]
ports:
- "127.0.0.1:14000:14000"
- "127.0.0.1:15000:15000"
volumes:
- ./pebble-config.json:/test/config/pebble-config.json:ro
environment:
PEBBLE_VA_NOSLEEP: "1"
networks:
acme-net:
ipv4_address: 10.30.50.2
challtestsrv:
image: ${CHALLTESTSRV_IMAGE:?Set a verified ghcr.io/letsencrypt/pebble-challtestsrv image digest}
command: ["-defaultIPv6", "", "-defaultIPv4", "10.30.50.3"]
ports:
- "127.0.0.1:8055:8055"
networks:
acme-net:
ipv4_address: 10.30.50.3
networks:
acme-net:
driver: bridge
ipam:
config:
- subnet: 10.30.50.0/24
הגדרת Pebble (pebble-config.json)
שמרו את הקטע הבא בשם pebble-config.json רק לאחר השוואתו לגרסה שנבחרה. הוא מספק נתיבים לתעודת השרת ולמפתח, יציאות אתגר ופרופיל תעודה ברירת מחדל לשלושה ימים. ההגדרות multiPerspectiveValidation ו־dnsToggles שהוצגו קודם אינן קיימות בסכמה שנבדקה. מצב קפדני ובחירת פותר DNS הם דגלי שורת פקודה, ולא שדות JSON.
{
"pebble": {
"listenAddress": "0.0.0.0:14000",
"managementListenAddress": "0.0.0.0:15000",
"certificate": "/test/certs/localhost/cert.pem",
"privateKey": "/test/certs/localhost/key.pem",
"httpPort": 5002,
"tlsPort": 5001,
"profiles": {
"default": {
"description": "Three-day certificates for an isolated test lab",
"validityPeriod": 259200
}
}
}
}
validityPeriod מבוטא בשניות; 259,200 שניות הן בדיוק שלושה ימים. תקופות קצרות יכולות לעזור בבדיקת לוגיקת החידוש, אך אינן מבטיחות התנהגות זהה בייצור. נכון לתיקון הזה, Let’s Encrypt הודיעה על תוקף ברירת מחדל של 64 יום בייצור החל מ־10 בפברואר 2027, ומציעה גם פרופילים קצרים יותר. בדקו את תזמון החידוש במקום לקבע הנחה שכל תעודה תקפה ל־90 יום.
הדמיית DNS-01 באופן תוכנתי עם Go
תוכנית Go הזאת מנהלת תגובת TXT אחת דרך pebble-challtestsrv, ביציאת HTTP 8055 בכתובת loopback. הגדירו את DNS01_VALUE לערך DNS-01 שחישב לקוח ACME של הבדיקה, הריצו את התוכנית לרישום הערך, בצעו את בדיקת האינטגרציה בנפרד ואז הריצו עם -clear להסרתו. אסימון שרירותי לא יעבור אתגר ACME אמיתי. בתוכנית יש זמן קצוב, אך היא אינה מבקשת תעודה ואינה מגדירה אמון TLS. לקוח שפונה ל־API ה־HTTPS של Pebble צריך להגדיר אמון ברשות בדיקת ה־HTTPS המצורפת, pebble.minica.pem, רק בתצורת הלקוח המבודדת שלו.
// Local test-only management client; it does not request a certificate.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"os"
"time"
)
func main() {
clear := flag.Bool("clear", false, "Remove the mock TXT record")
flag.Parse()
payload := map[string]string{
"host": "_acme-challenge.dev.example.test.",
}
path := "/set-txt"
if *clear {
path = "/clear-txt"
} else {
value := os.Getenv("DNS01_VALUE")
if value == "" {
log.Fatal("Set DNS01_VALUE to the test ACME client's DNS-01 value")
}
payload["value"] = value
}
body, err := json.Marshal(payload)
if err != nil {
log.Fatal(err)
}
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Post(
"http://127.0.0.1:8055"+path,
"application/json", bytes.NewReader(body),
)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Fatalf("Challenge server returned HTTP %d", resp.StatusCode)
}
fmt.Printf("Test DNS management request %s succeeded; no certificate was requested.\n", path)
}
בדיקת מסלולי כשל: למה כל מפתח צריך את זה
בדיקת הנפקה מוצלחת מכסה רק מסלול אחד. הביאו בחשבון גם חריגות זמן, הפצה איטית של TXT ותגובות אתגר שנכשלות. בדקו כיצד הלקוח מדווח על שגיאות ומנסה שוב; אל תסיקו נכונות רק מכך שחיבור בדפדפן הצליח.
למקרה כשל DNS מתועד, השרת הנלווה תומך ב־/set-servfail וב־/clear-servfail עבור מארח שנבחר. השתמשו בשם ייעודי לבדיקה ובחנו שגיאות לקוח והתנהגות של ניסיונות חוזרים מוגבלים עם השהיה מדורגת. אין זו הדמיית כשל בנקודות תצפית גאוגרפיות או של קוורום requiredSuccesses. Pebble אינו אוכף את מגבלות הקצב של Let’s Encrypt בייצור, ולכן יש לבדוק אותן בנפרד.
סיכום והצעדים הבאים
Pebble ושרת האתגרים הנלווה יכולים להפוך בדיקות אינטגרציה מקומיות של ACME לשימושיות יותר. הם מספקים תגובות אתגר מבוקרות ובדיקות תאימות, ולא זהות מלאה לייצור או הדמיית רשת גאוגרפית מובנית. הבנה של הגבולות האלה היא חלק מתכנון סביבת בדיקות שאפשר לסמוך עליה.
בחרו כלי לפי מטרת הבדיקה: תעודות פיתוח ידניות או mkcert עשויות לענות על צורך שונה מבדיקת לקוח ACME. אם מוסיפים Pebble, יש לבודד את השירותים, להשאיר אימות פעיל עם אמון ברמת הלקוח, לבחור גרסאות תואמות ולהוסיף בדיקות מפורשות לכשלים ולחידושים. שום בדיקה מקומית לבדה אינה מוכיחה את אבטחת היישום או את עמידתו בדרישות.
נשמח לשמוע מכם!
אתם משתמשים ב־ACME באופן מקומי, או שעדיין מסתמכים על תעודות ידניות או על כלים מקומיים כגון mkcert? קרה שתעודות ה־TLS האוטומטיות שלכם הפסיקו לעבוד בייצור בגלל שגיאת אימות? בואו נדבר על זה בתגובות!
עד הפעם הבאה, שמרו על חיבורים מוצפנים ועל קוד נקי. נתראה בפוסט הבא!