OpenVPN קורא את הסיסמה מהמסוף, לא מ-stdin
היכן OpenVPN באמת קורא סיסמה, מדוע קובץ על stdin נכשל, ושלושת המסלולים הנתמכים לכניסה בסקריפט ב-Linux וב-macOS.
OpenVPN מבקש שם משתמש וסיסמה במסוף הבקרה, וקובץ שמופנה לקלט התקני אינו המסוף הזה. הפרט האחד הזה מסביר את הסקריפט שנתקע כשהסיסמה נמצאת שם בצינור. הלקוח מצייר את ההנחיה והקריאה נעשית מהתקן המסוף, ולכן הפניית stdin לא משנה דבר. הזינו ללקוח דרך אחד ממסלולי הקלט המתועדים שלו והסקריפט ייתחבר בניסיון הראשון.
שלושה מסלולים מכסים כמעט כל מקרה, וכל אחד נכשל בדרכו. בחרו לפי ההנחיה שהלקוח באמת מציג, לא לפי האפשרות שהכי קלה לסקריפט.
ההנחיה לא מגיעה מ-stdin
כשהלקוח צריך אישורים הוא פותח את מסוף הבקרה וקורא שם. לכן בדיקה אינטראקטיבית נראית טוב, ואילו אותה פקודה תחת cron או קובץ unit עומדת ללא תנועה כשההנחיה כתובה ביומן שאיש אינו צופה בו. כמה גרסאות נופלות חזרה לקלט התקני כשאין מסוף, וחוסר העקביות הזה גרוע מכשל קשה כי הוא מסתיר את הבעיה עד הפריסה.
בדקו את הסביבה לפני כתיבת קוד: הריצו את הלקוח תחת אותו משתמש, עם אותו stdin, כפי שהמתזמן או מנהל השירותים יעשה. אם ההנחיה לא מופיעה ביומן והתהליך לא מתקדם, משהו ממתין למסוף שאינו קיים.
המסלול הראשון: קובץ אישורים בשתי שורות
אפשרות האימות מקבלת נתיב, והקובץ מכיל בדיוק שתי שורות, קודם שם משתמש ואחר כך סיסמה, ולא דבר אחר. העבירו את הנתיב במפורש במקום להסתמך על שם קובץ ברירת מחדל, כי קובץ אישורים תועה בתיקיית העבודה הוא הדרך שבה החשבון הלא נכון מגיע לשימוש. קבעו את המצב ל-0600 ותנו בעלות לחשבון שמריץ את הלקוח.
הלקוח קורא את הקובץ פעם אחת בהפעלה, ולכן החלפת הסיסמה פירושה הפעלה מחדש של התהליך. זו בדרך כלל ההתנהגות הרצויה, והיא שייכת ל-runbook לצד נוהל ההחלפה.
המסלול השני: askpass עבור מילת הצופן של המפתח
מפתח פרטי המוגן במילת צופן מעלה הנחיה שנייה ושונה, ויש לה תשובה משלה מבוססת קובץ: אפשרות askpass קוראת את מילת הצופן מהשורה הראשונה של קובץ. במנהרות מבוססות SSH המקבילה היא תוכנית askpass שהלקוח מריץ, שפלט התקני שלה הופך לסוד.
אף אחת מהצורות לא שמה את הסוד ברשימת הארגומנטים, ושתיהן מותירות אותו קיים כקובץ או כתוכנית הרצה שמדפיסה אותו. ההגנה היא הרשאות קובץ ובעלות תהליך, לא עמימות. עוזר שמהדהד מחרוזת קשיחה הוא סוד עם צעדים נוספים.
המסלול השלישי: ה-CLI של לקוח הפורטל עצמו
לקוחות ארגוניים מספקים בדרך כלל נקודת כניסה בשורת הפקודה שמתחברת לפורטל בעל שם בלי שום חלון, וזה המסלול הנתמך. ב-Linux לקוח GlobalProtect חושף פעולות חיבור וייבוא תעודה דרך ה-CLI שלו, ופורטלים שמשתמשים באימות תעודה זקוקים לשלב הייבוא לפני שחיבור אוטומטי יכול לעבוד. העדיפו אותו על הקשות מקשים סינתטיות: מקבלים קוד יציאה אמיתי, בלי תלות במיקוד החלון, והוא שורד מסך נעול.
אם החיבור הראשון עדיין דורש אדם כדי לאשר תעודה, האוטומציה לא הושלמה. בצעו את הייבוא במהלך ההתקנה ותעדו אותו כדרישת סף.
כשהזרימה זקוקה לפסאודו-מסוף
לרצף שמבקש סיסמה ואחר כך קוד חד-פעמי אין קובץ אחד לקרוא. מנהל מסוף כמו Expect הוא הכלי הנכון כי הוא מחכה לכל תבנית בתורה, והוא זקוק לתהליך מופעל לפני שהוא יכול להתאים משהו בכלל.
שני כשלים שולטים. סקריפט שמחכה להנחיה בלי להפעיל את הלקוח מחכה לנצח, ו-Tcl אינה מעטפת, ולכן חשבון מעטפת שנכתב בתוך בלוק expect אינו מוערך כפי שהוא נקרא. השאירו את דגל הניפוי דלוק בזמן שאתם בונים את התבניות, ואז כבו אותו.
סודות שדולפים, והיכן הם מתחבאים
כל מה שמועבר כארגומנט גלוי ברשימת התהליכים, ולכן אישורים שייכים לקובץ או מאחורי עוזר, אף פעם לא בשורת הפקודה. קודים חד-פעמיים נצרכים לפי התכנון וחייבים להיות מיוצרים לכל ניסיון. יומני כשל נושאים לעיתים קרובות את שם המשתמש ולפעמים יותר, ולכן השחירו אותם לפני שליחה לכל מקום, והרחיקו את הסוד מהפרופיל עצמו, כי קובץ תצורה עם סיסמה מוטבעת מודבק לכרטיסים ומאגרים. החלפת החשבון אז פירושה ציד אחר כל עותק, וזה בדיוק המחיר שהסדר הזה נמנע ממנו.
בקרו את המסלולים שבחרתם, ואז חברו אותם לקובץ ה-unit או למתזמן שבאמת יריץ את הלקוח. המנהרה חיה בדיוק כל עוד התהליך הזה חי.