הטמעה לדוגמה של Keyfactor EJBCA

סקירה כללית

במדריך הזה מוסבר איך לשלב את Keyfactor EJBCA Enterprise (שנפרס כמכשיר חיצוני) כרשות אישורים (CA) של צד שלישי ב-Google Distributed Cloud (GDC)‎ עם air gap.

‫Keyfactor EJBCA Enterprise היא פלטפורמה חזקה וניתנת להתאמה של רשות אישורים, שעומדת בתקן FIPS ומאפשרת לארגונים לנהל תשתית של מפתח ציבורי (PKI) בסביבות הטרוגניות.

‫GDC עם air gap כולל שירות מובנה של רשות אישורים לניהול אוטומטי של מפתחות ואישורים בתוך גבולות הענן המארח. עם זאת, ארגונים שתשתית ה-PKI שלהם מבוססת על Keyfactor EJBCA לעומסי עבודה קיימים מחוץ ל-GDC, עשויים להעדיף להשתמש באותה ארכיטקטורה ובאותה מדיניות ניהול של רשות אישורים לעומסי עבודה שפועלים בסביבות GDC עם air gap.

במדריך הזה נסביר איך להגדיר את הרשת של GDC, את ה-DNS הפנימי ואת cert-manager של Kubernetes כדי להפוך את ניהול מחזור החיים של האישורים (ACME) לאוטומטי, ולתמוך בהנפקה פרוגרמטית בנפח גבוה באמצעות דפוס של רשות רישום (RA).

הנחות

לפני שתמשיכו, ודאו שההנחות הבאות מתקיימות:

  • ‫Keyfactor EJBCA נפרס כמכשיר תוכנה או כמכשיר חומרה, וכתובת IP יציבה מוגדרת לשירות.
  • רשויות אישורים (CA) בסיסיות, משניות וניהוליות נוצרו במכונה של EJBCA.
  • הוגדרו פרופילים של ישות קצה (EE) (למשל, לאישורים לשרתי TLS).
  • האישורים של משתמשי ה-CA המנהליים הורדו.
  • הפרוטוקולים הנדרשים (כמו ACME) מופעלים במכונה של EJBCA.
  • במדריך הזה נעשה שימוש באלגוריתמים של חתימת RSA. אתם יכולים לשנות את אלגוריתם החתימה בהתאם לדרישות הספציפיות שלכם או למה שמוגדר במכונה של EJBCA.

ארכיטקטורה

הארכיטקטורה פועלת לפי המודל של רשות אישורים חיצונית, שבו שרת ה-EJBCA ורכיב ה-HSM (מודול אבטחת חומרה) שמגבה אותו מתארחים מחוץ לגבולות הפיזיים של GDC, אבל אפשר לגשת אליהם דרך הרשת. אפשר לפרוס את שרת ה-EJBCA באופן חיצוני, כמכשיר חומרה או כמכשיר תוכנה. כדי להשתמש בשילוב הבסיסי שמתואר במדריך הזה, צריך רק ששרת ה-EJBCA החיצוני יהיה נגיש באמצעות כתובת IP יציבה.

דיאגרמת ארכיטקטורה של Keyfactor EJBCA.

הרכיבים העיקריים בארכיטקטורה הזו:

  • ‫EJBCA Enterprise Server: נפרס באופן חיצוני כחומרה או כתוכנה של Keyfactor, מאחסן את רשויות האישורים (ברמה הבסיסית וברמה המשנית) ויוצר את כל נתוני המפתחות של רשויות האישורים בתוך HSM עם אישור CC EAL4+‎.
  • אשכול Kubernetes ב-GDC Standard: סביבת המחשוב שבה פועלים עומסי העבודה של הלקוחות, cert-manager ושרתי proxy לשילוב.
  • ‫GDC Internal DNS: מנהל את תחומי ה-DNS הפרטיים המקומיים (באמצעות שם הדומיין הפרטי שהוגדר במשתני הסביבה) שמשמשים לפתרון אתגרי ACME DNS-01.
  • ‫GDC Egress Gateway: מפנה תנועה יוצאת (egress) מפודים של אשכולות לכתובת ה-IP החיצונית של שרת ה-EJBCA.
  • ‫Harbor Private Registry: מארח קובצי אימג' של קונטיינרים משוכפלים (כמו מנפיק cert-manager של EJBCA) לפריסה עם air gap.

לפני שמתחילים

לפני שמתחילים את השילוב, צריך לוודא שסביבת GDC עומדת בדרישות הבאות:

  • קודם כל, יוצרים פרויקט שיכיל את כל המשאבים שייווצרו במהלך המדריך הזה.
  • מגדירים משתני סביבה שישמשו כהפניות לאורך המדריך. משנים את הערכים האלה לפי הצורך כדי להתאים לסביבה הספציפית שלכם:

    # GDC Environment Configuration
    export GDC_ORG="your-org-name"
    export GDC_ZONE="your-zone-name"
    export GDC_PROJECT_ID="your-project-id"
    export GDC_USER_NAME="your-gdc-user-email"
    export GDC_CLUSTER_NAME="your-cluster-name"
    
    # EJBCA Server Configuration
    export EJBCA_DNS_ZONE="example.internal"
    export EJBCA_HOSTNAME="ejbca.${EJBCA_DNS_ZONE}"
    export EJBCA_LB_IP="XX.XX.XX.XX" # Stable IP of your EJBCA Server
    export EJBCA_CA_NAME="GDC Subordinate CA"
    export EJBCA_NAMESPACE="ejbca-ee"
    export CERTIFICATE_PROFILE_NAME="GDC TLS SERVER PROFILE"
    export END_ENTITY_PROFILE_NAME="GDC TLS SERVER EE PROFILE"
    
    # Harbor Private Registry Configuration
    export HARBOR_INSTANCE_URL="your-harbor-url.internal"
    export HARBOR_PROJECT="your-harbor-project"
    export HARBOR_ROBOT_ACCOUNT="robot$your-robot-name"
    export HARBOR_ROBOT_SECRET="your-robot-secret"
    export HARBOR_PULL_SECRET_NAME="harbor-secret"
    
  • הערה לגבי הרשת: המדריך הזה מבוסס על ההנחה שהוא מופעל מצומת באסטיון שיש לו גישה לממשקי ה-API של GDC עם air gap, וגם גישה לאינטרנט כדי להוריד את המניפסטים ואת קובצי האימג' של הקונטיינרים הנדרשים. אם אתם מריצים את הפקודה ממכונה ללא גישה לאינטרנט, אתם צריכים להשיג את הנכסים האלה בנפרד (לדוגמה, באמצעות docker save כדי לייצא תמונות ממכונה מחוברת ו-docker load כדי לייבא אותן) ולהעלות אותן באופן מאובטח לסביבה שלכם לפני שתמשיכו.

הגדרת כינויים ל-kubectl

בקטע הזה יוצרים כינויים נוחים לשורת הפקודה בשביל ממשקי ה-API הגלובליים והניהול האזורי של GDC:

  • יוצרים כינוי ל-API של הניהול האזורי (מחליפים את MANAGEMENT_API_KUBECONFIG בנתיב ל-kubeconfig של ה-API לניהול):

    alias km="kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG"
    
  • יוצרים כינוי ל-API הגלובלי (מחליפים את GLOBAL_API_KUBECONFIG בנתיב ל-kubeconfig של ה-API הגלובלי):

    alias kg="kubectl --kubeconfig GLOBAL_API_KUBECONFIG"
    

יצירת אשכול רגיל ב-GDC

בקטע הזה תפרסו אשכול Kubernetes רגיל ב-GDC ותגדירו את תפקידי האדמין של האשכול הרגיל ב-GDC ואת פרטי הכניסה המקומיים למרשם של Container Registry ב-Harbor:

‫1 מריצים את הפקודה הבאה כדי לזהות את הסוגים הזמינים של קובצי האימג' של המכונה הווירטואלית:

```shell
gdcloud compute machine-types list
```

‫2 בוחרים את סוג המכונה המתאים לצומתי העובדים באשכול:

```shell
export MACHINE_TYPE="n3-standard-8-gdc"
```

‫3 יוצרים אשכול רגיל עם שני צומתי עובדים באמצעות ה-API לניהול אזורי:

```shell
km create -f - <<EOF
apiVersion: cluster.gdc.goog/v1
kind: Cluster
metadata:
  name: ${GDC_CLUSTER_NAME}
  namespace: ${GDC_PROJECT_ID}
spec:
  nodePools:
  - machineTypeName: ${MACHINE_TYPE}
    nodeCount: 2
    name: ${GDC_CLUSTER_NAME}-node-pool
EOF
```

This creates a simple GDC cluster. Cluster creation
can take up to 60 minutes to complete. To check the status, use the
following command:

```shell
km get clusters/${GDC_CLUSTER_NAME} \
  -n ${GDC_PROJECT_ID} \
  --watch
```

After the cluster is ready, the output should show a STATE of `Running`.

‫4 אחרי שהאשכול מוכן, מאחזרים את פרטי הכניסה שלו:

```shell
KUBECONFIG=kubeconfig-${GDC_CLUSTER_NAME}.yaml gdcloud clusters \
  get-credentials ${GDC_CLUSTER_NAME} \
  --standard \
  --project ${GDC_PROJECT_ID} \
  --zone ${GDC_ZONE}
```

‫5. מקצים תפקידי אדמין באשכול רגיל ב-GDC למשתמש ב-GDC:

```shell
gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=cluster-admin

gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=standard-cluster-admin
```

‫6 יוצרים מכונה של Harbor ופרויקט של Harbor ב-GDC כדי לארח את קובצי האימג' של הקונטיינרים שנוצרו להם עותקים:

```shell
gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=harbor-instance-admin
```

‫7 יוצרים חשבון רובוט ב-Harbor ומתעדים את שם המשתמש והמפתח הסודי שלו.

‫8 מאמתים באמצעות המכונה של Harbor:

```shell
docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
  -u ${HARBOR_ROBOT_ACCOUNT} \
  -p ${HARBOR_ROBOT_SECRET}
```

This saves the robot account credentials to
`./docker-harbor/config.json` for subsequent Secret creation.

הגדרת התשתית והרשת

בקטע הזה מגדירים את התשתית הבסיסית ואת הגדרות הרשת של GDC. כך מוודאים שעומסי העבודה ב-Kubernetes יכולים לפתור את שם הדומיין המארח החיצוני של EJBCA, ולנתב בהצלחה קריאות יוצאות ל-API לכתובת ה-IP שלו.

הגדרת DNS פרטי ב-GDC עם air gap

כדי להגדיר את פתרון הדומיין, פורסים תחום DNS פרטי וקבוצת רשומות כדי למפות את שרת ה-EJBCA החיצוני לשם דומיין מקומי. כך השירותים ב-GDC יכולים להתחבר באמצעות שם מארח יציב במקום כתובת IP גולמית:

  • מקצים למשתמש את התפקיד "אדמין של פרויקט DNS מנוהל":

    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=managed-dns-project-admin
    
  • פורסים את המשאב הגלובלי של ManagedDNSZone:

    kubectl --kubeconfig GLOBAL_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ManagedDNSZone
    metadata:
      name: private-example-internal
      namespace: ${GDC_PROJECT_ID}
    spec:
      dnsName: ${EJBCA_DNS_ZONE}
      visibility: PRIVATE
    EOF
    
  • פורסים את ResourceRecordSet שמפנה לכתובת ה-IP של מכשיר ה-EJBCA:

    kubectl --kubeconfig GLOBAL_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ResourceRecordSet
    metadata:
      name: ${EJBCA_HOSTNAME}
      namespace: ${GDC_PROJECT_ID}
    spec:
      name: ${EJBCA_HOSTNAME}
      ttlSeconds: 600
      type: A
      rrData:
      - ${EJBCA_LB_IP}
      dnsZone: private-example-internal
    EOF
    

הגדרת שער NAT לתעבורת נתונים יוצאת

בשלב הבא, מגדירים את הרשת של תעבורת הנתונים היוצאת ב-GDC על ידי הגדרת רשת משנה בהתאמה אישית ושער NAT, כדי לאפשר לעומסי העבודה של Kubernetes (כמו לקוחות של cert-manager ושל רשות הרישום) לנתב באופן מאובטח את תעבורת הנתונים היוצאת לשרת EJBCA:

  • הקצאת תפקידי מפתח רשת ברמת הפרויקט וברמת הארגון:

    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=cloud-nat-developer
    
    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=subnet-project-admin
    
    gdcloud organizations add-iam-policy-binding ${GDC_ORG} \
      --member="user:${GDC_USER_NAME}" \
      --role=subnet-org-admin
    
  • יוצרים את רשת המשנה לתעבורת נתונים יוצאת:

    kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG apply -f - <<EOF
    apiVersion: ipam.gdc.goog/v1
    kind: Subnet
    metadata:
      name: ejbca-cluster-egress
      namespace: ${GDC_PROJECT_ID}
    spec:
      ipv4Request:
        prefixLength: 32
      parentReference:
        name: data-network-segment-${GDC_ZONE}-group
        namespace: platform
        type: SubnetGroup
      type: Leaf
    EOF
    
  • יוצרים את CloudNATGateway שתואם לסלקטור של מנפיק cert-manager:

    kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: CloudNATGateway
    metadata:
      name: ejbca-egress-gateway
      namespace: ${GDC_PROJECT_ID}
    spec:
      subnetRefs:
      - ejbca-cluster-egress
      workloadSelector:
        labelSelector:
          clusters:
            matchLabels:
              kubernetes.io/metadata.name: ${GDC_CLUSTER_NAME}
          workloads:
            matchLabels:
              app.kubernetes.io/name: ejbca-cert-manager-issuer
    EOF
    

שילוב של cert-manager ב-Kubernetes

בקטע הזה משלבים את מנפיק ה-cert-manager המותאם אישית של EJBCA עם שירות ה-cert-manager של GDC. כך תוכלו להגדיר הקצאה, חידוש וניהול מחזור חיים אוטומטיים של אישורים לשירותים בקונטיינרים.

תרשים של שילוב cert-manager של EJBCA.

הגדרת EJBCA למנפיק

כדי לשלב את המנפיק, צריך להגדיר את הפרופילים הנדרשים, לרשום את פרטי הכניסה של לקוח הניהול ולהגדיר קישורי תפקידים בשרת EJBCA. כך נוצר ערוץ ניהול מאובטח שמאפשר ל-cert-manager לבצע אימות מול EJBCA ולבקש ממנו אישורים.

יצירת פרופיל אישורים של אדמין

קודם כל, יוצרים פרופיל אישור ב-EJBCA כדי להגדיר את המאפיינים הטכניים והמגבלות הקריפטוגרפיות (כמו אלגוריתמים ותקופות תוקף) של האישור הניהולי:

  • פותחים את ממשק המשתמש לניהול של EJBCA, עוברים אל CA Functions > Certificate Profiles.
  • משכפלים את הפרופיל ENDUSER ונותנים לו את השם GDC ADMIN PROFILE.
  • עורכים את GDC ADMIN PROFILE וקובעים את ההגדרות הבאות:
    • אלגוריתמים זמינים של מפתחות: RSA
    • אורכי ביטים זמינים: 2048, 3072, 4096
    • אלגוריתם חתימה: SHA512WithRSA
    • תוקף: 200d
    • שם חלופי של המנפיק: מבטלים את הסימון של שימוש
    • נקודות הפצה של CRL: מסמנים את האפשרות שימוש.
    • שימוש בנקודת הפצה של רשימת אישורים מבוטלים (CRL) שמוגדרת על ידי רשות האישורים (CA): מסמנים את האפשרות שימוש.
    • Authority Information Access: מסמנים את האפשרות Use
    • Use CA defined OCSP locator: מסמנים את האפשרות Use.
    • Use CA defined CA issuer (שימוש במנפיק CA שהוגדר על ידי CA): מסמנים את האפשרות Use (שימוש).
    • רשויות אישורים זמינות: בוחרים באפשרות GDC Subordinate CA
  • לוחצים על Save.

יצירת פרופיל של ישות קצה לאדמין

בשלב הבא, יוצרים פרופיל של ישות קצה ב-EJBCA כדי להגדיר שדות ברירת מחדל והקצאות של רשות אישורים, וכך לפשט את תהליך הרישום וההנפקה של האישור המנהלי:

  • עוברים אל RA Functions (פונקציות RA) ‏> End Entity Profiles (פרופילים של ישויות קצה).
  • בקטע Add End Entity Profile, מזינים GDC ADMIN EE PROFILE ולוחצים על Add Profile.
  • עורכים את הפרופיל וקובעים את ההגדרות הבאות:
    • פרופיל אישור ברירת המחדל: GDC ADMIN PROFILE
    • פרופילי אישורים זמינים: GDC ADMIN PROFILE
    • רשות אישורים שמוגדרת כברירת מחדל: GDC Subordinate CA
    • רשויות אישורים זמינות: GDC Subordinate CA
  • לוחצים על Save.

רישום אישור אדמין

אחרי שיוצרים את הפרופילים, רושמים את זהות הניהול באמצעות ממשק רשות הרישום (RA) של EJBCA, ומחלצים את המפתח הפרטי, האישור הציבורי ושרשרת האמון כדי ליצור את קובצי אמצעי הזיהוי הפיזיים שנדרשים לאימות של cert-manager:

  • עוברים לכרטיסייה RA Web.
  • לוחצים על Make New Request ומגדירים:
    • סוג האישור: GDC ADMIN EE PROFILE
    • יצירת זוג מפתחות: על ידי רשות האישורים (CA)
    • אלגוריתם מפתח: RSA ‏4096 ביטים
    • שם נפוץ (CN): cert-manager
    • שם משתמש: cert-manager
    • קוד הרשמה: abcd
  • לוחצים על הורדת PEM ושומרים אותו בתור cert-manager.pem.
  • מפצלים את קובצי ה-PEM לשלושה קבצים:

    • ‫client.key (המפתח הסודי):

      openssl pkey -in cert-manager.pem -out client.key
      
    • client.crt (האישור הציבורי):

      openssl x509 -in cert-manager.pem -out client.crt
      
    • ca.crt (שרשרת האמון עם אישורי ה-CA המשניים ואישורי הבסיס):

      awk '/BEGIN CERTIFICATE/{i++} i>1' cert-manager.pem > ca.crt
      

הגדרת תפקידים וכללי גישה

לבסוף, יוצרים תפקיד אדמין ב-EJBCA ומקשרים אותו למספר הסידורי של האישור ב-cert-manager, כדי לוודא שלמנפיק יש רק את קבוצת ההרשאות המינימלית שנדרשת לאישור ולבקשה של אישורים:

  • בממשק המשתמש לניהול של EJBCA, עוברים אל RA Functions > Search End Entities.
  • מחפשים את ישות הקצה cert-manager ומתעדים את המספר הסידורי של האישור שלה.
  • עוברים אל System Functions > Roles and Access Rules ולוחצים על Add.
  • נותנים לתפקיד את השם cert-manager ומוסיפים חבר חדש באמצעות המספר הסידורי שרשמתם.
  • לוחצים על עריכת כללי גישה ומגדירים את ההרשאות הבאות:
    • תבנית תפקיד: אדמינים של RA
    • רשויות אישורים מורשות: GDC Subordinate CA
    • כללים לישויות קצה: אישור, יצירה ועריכה של ישויות קצה
    • פרופילים של ישויות קצה: GDC TLS SERVER EE PROFILE
    • כללים אחרים: מבטלים את הסימון של הצגת יומן ביקורת
  • לוחצים על Save.

הכנת אשכול GDC

כדי להכין את סביבת GDC, מבצעים אימות באמצעות אשכול Kubernetes הרגיל ומאחסנים את פרטי הכניסה המנהלתיים של EJBCA שחולצו בתוך Kubernetes Secrets, כך שפודים של מנפיק cert-manager יוכלו לגשת אליהם באופן מאובטח:

  • אחזור פרטי הכניסה של אשכול רגיל:

    gdcloud clusters get-credentials "${GDC_CLUSTER_NAME}" \
      --standard \
      --project "${GDC_PROJECT_ID}" \
      --zone "${GDC_ZONE}"
    
  • יוצרים את מרחב השמות של היעד למנפיק בהתאמה אישית:

    kubectl create ns ejbca-issuer-system
    
  • פורסים את הסוד של אימות ה-TLS:

    kubectl create secret tls ejbca-secret \
      -n ejbca-issuer-system \
      --cert=client.crt \
      --key=client.key
    
  • פורסים את הסוד של שרשרת האמון של EJBCA:

    kubectl create secret generic ejbca-ca-secret \
      -n ejbca-issuer-system \
      --from-file=ca.crt
    

התקנת המנפיק של EJBCA

כדי להגדיר את הפריסה, משכפלים את קובץ האימג' של קונטיינר מנפיק האישורים של EJBCA cert-manager למרשם הפרטי של Harbor ופורסים את תרשים Helm. הפעולה הזו יוצרת מופע של הבקר בהתאמה אישית שנדרש כדי לתרגם בקשות לאישורים של Kubernetes לקריאות ל-API של EJBCA:

  • יוצרים סוד למשיכת קובץ אימג' של Harbor במרחב השמות של המנפיק:

    # Authenticate with the private Harbor registry
    docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
      -u ${HARBOR_ROBOT_ACCOUNT} \
      -p ${HARBOR_ROBOT_SECRET}
    
    kubectl create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ejbca-issuer-system
    
  • מעתיקים את קובץ האימג' הרשמי של מנפיק האישורים EJBCA cert-manager אל Harbor:

    docker pull keyfactor/ejbca-cert-manager-issuer:latest --platform linux/amd64
    
    docker tag keyfactor/ejbca-cert-manager-issuer:latest \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer:latest
    
    docker --config=./docker-harbor push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer:latest
    
  • מוסיפים את מאגר Helm ומורידים את התרשים:

    helm repo add ejbca-issuer https://keyfactor.github.io/ejbca-cert-manager-issuer
    helm repo update
    helm pull ejbca-issuer/ejbca-cert-manager-issuer --untar
    
  • פורסים את תרשים Helm באמצעות מאגר התמונות המועתקות:

    helm install ejbca-cert-manager-issuer ./ejbca-cert-manager-issuer \
      --namespace ejbca-issuer-system \
      --set image.repository=${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer \
      --set "imagePullSecrets[0].name=${HARBOR_PULL_SECRET_NAME}" \
      --set image.tag=latest
    

יצירת המשאב של המנפיק

בשלב הבא, מגדירים הרשאות RBAC ב-GDC ופורסים משאב ClusterIssuer גלובלי, שרושם את שרת ה-EJBCA כמקור חתימה מהימן בתוך מסגרת cert-manager של Kubernetes:

  • מגדירים הרשאות RBAC כדי לאפשר לבקר cert-manager של GDC להשתמש במנפיק ה-EJBCA בהתאמה אישית:

    kubectl apply -f - <<EOF
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    rules:
    - verbs:
      - approve
      apiGroups:
      - cert-manager.io
      resources:
      - signers
      resourceNames:
      - issuers.ejbca-issuer.keyfactor.com/*
      - clusterissuers.ejbca-issuer.keyfactor.com/*
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    subjects:
    - kind: ServiceAccount
      name: cert-manager
      namespace: cert-manager
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    EOF
    
  • פורסים את המשאב הגלובלי של ClusterIssuer:

    kubectl apply -f - <<EOF
    apiVersion: ejbca-issuer.keyfactor.com/v1alpha1
    kind: ClusterIssuer
    metadata:
      name: clusterissuer-ejbca
    spec:
      hostname: "${EJBCA_HOSTNAME}"
      ejbcaSecretName: "ejbca-secret"
      caBundleSecretName: "ejbca-ca-secret"
      certificateAuthorityName: "${EJBCA_CA_NAME}"
      certificateProfileName: "${CERTIFICATE_PROFILE_NAME}"
      endEntityProfileName: "${END_ENTITY_PROFILE_NAME}"
      endEntityName: ""
    EOF
    
  • בודקים את סטטוס המנפיק:

    kubectl get clusterissuer.ejbca-issuer.keyfactor.com/clusterissuer-ejbca \
      -o "custom-columns=NAME:.metadata.name,STATUS:.status.conditions[0].message"
    

    הפלט אמור להיראות כך:

    NAME                  STATUS
    clusterissuer-ejbca   Success
    

בקשת אישור

כדי לאמת את השילוב, פורסים משאב אישור רגיל של Kubernetes כדי לבדוק את התהליך מקצה לקצה של cert-manager, ומוודאים ש-EJBCA חותם על האישור המבוקש ומקצה אותו:

יוצרים משאב Certificate לבדיקה כדי לוודא שהשילוב בוצע בהצלחה:

kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: ejbca-test-certificate
  namespace: ${EJBCA_NAMESPACE}
spec:
  commonName: example.com
  secretName: ejbca-certificate
  issuerRef:
    name: clusterissuer-ejbca
    group: ejbca-issuer.keyfactor.com
    kind: ClusterIssuer
EOF

מוודאים שהאישור נוצר ומוכן:

kubectl get certificates.cert-manager.io -n ${EJBCA_NAMESPACE}

הפלט אמור להיראות כך:

NAME                     READY   SECRET              AGE
ejbca-test-certificate   True    ejbca-certificate   12s

‫ACME אוטומטי עם אתגרים מסוג DNS-01

בקטע הזה תגדירו את שירות ACME של EJBCA ותשתמשו במשאבי DNS פנימיים של GDC כדי להנפיק באופן אוטומטי אישורים מאומתים לדומיינים. כך לקוחות רגילים של cert-manager או Certbot יכולים לבקש אישורים באמצעות פרוטוקולים אוטומטיים רגילים של ACME.

הגדרת EJBCA ל-ACME

כדי להכין את השרת, מפעילים את שירות ACME בתוך EJBCA ומגדירים כינוי ACME עם מפענח DNS ייעודי. כך מכינים את שרת ה-EJBCA לעבד ולאמת את התגובות לאתגר DNS-01 ב-GDC:

  • בממשק המשתמש לניהול של EJBCA, עוברים אל System Configuration > ACME Configuration.
  • לוחצים על הוספה ומגדירים את הפרטים הבאים:
    • שם: default
    • פרופיל של ישות קצה: GDC TLS SERVER EE PROFILE
    • מותר להנפיק תעודת wildcard: סימון
    • סוגי אתגרים של מזהה DNS לאימות MPIC של אתגר-תגובה: בוחרים באפשרות dns-01
    • מפענח DNS: מזינים את כתובת ה-IP של ה-DNS הגלובלי.
    • אימות DNSSEC: נקה (כי זו סביבה פרטית מקומית)
  • לוחצים על Save.

יצירת משתני סביבה של ACME

בקטע הזה יוצרים את משתני הסביבה הבאים כדי להגדיר את לקוח Certbot. משנים את הערכים האלה לפי הצורך:

# ACME Alias created in the EJBCA configuration
export ACME_ALIAS="default"

# Arbitrary email address used for ACME registration
export ACME_EMAIL="your-email@example.com"

רישום הלקוח של Certbot

בשלב הבא, מתקינים את לקוח Certbot הרגיל ורושמים אותו בנקודת הקצה הפרטית של ACME ב-EJBCA. כך מגדירים את חשבון הלקוח המהימן שנדרש כדי לבצע פעולות אוטומטיות של אישורים:

  • מתקינים את certbot בתחנת העבודה. לדוגמה, ב-macOS:

    brew install certbot
    
  • יוצרים תיקיות מקומיות להגדרות וליומנים:

    mkdir -p ./certbot/config ./certbot/work ./certbot/logs
    
  • רושמים את הלקוח בנקודת הקצה של ספריית EJBCA ACME:

    certbot register \
      --config-dir ./certbot/config \
      --work-dir ./certbot/work \
      --logs-dir ./certbot/logs \
      --server https://${EJBCA_HOSTNAME}/ejbca/acme/${ACME_ALIAS}/directory \
      --email ${ACME_EMAIL} \
      --agree-tos \
      --no-eff-email
    

הנפקת אישור באמצעות אתגר DNS

בסוף, מפעילים בקשה ידנית של Certbot ופורסים משאב זמני של GDC DNS TXT כדי לפתור את אתגר DNS-01. הפעולה הזו מאמתת את הבעלות שלכם על דומיין היעד ומפעילה הנפקה אוטומטית של אישור:

  • מריצים את פקודת האתגר הידני:

    certbot certonly \
      --manual \
      --preferred-challenges dns \
      --key-type rsa \
      --rsa-key-size 2048 \
      --config-dir ./certbot/config \
      --work-dir ./certbot/work \
      --logs-dir ./certbot/logs \
      --server https://${EJBCA_HOSTNAME}/ejbca/acme/${ACME_ALIAS}/directory \
      -d test.${EJBCA_DNS_ZONE}
    

    המסוף יפסיק לפעול ויציג ערך אתגר. פלט לדוגמה:

    Please deploy a DNS TXT record under the name:
    
    _acme-challenge.test.example.internal.
    
    with the following value:
    
    q3pCmzXfIhsTpT4f4JAulHmHaAR3udC_9Wf1G498ER0
    
    Before continuing, verify the TXT record has been deployed.
    
  • פורסים את רשומת ה-TXT ב-DNS הגלובלי עם המחרוזת שסופקה על ידי Certbot.

  • ממתינים כ-30 שניות להפצת ה-DNS, חוזרים לטרמינל של Certbot ולוחצים על Enter.

    פלט לדוגמה:

    Successfully received certificate.
    Certificate is saved at:./certbot/config/live/test.example.internal/fullchain.pem
    Key is saved at:./certbot/config/live/test.example.internal/privkey.pem
    This certificate expires on 2026-11-16.
    These files will be updated when the certificate renews.
    
  • מוודאים שהאישור נכתב ב-./certbot/config/live/test.${EJBCA_DNS_ZONE}/.