סודות דינמיים: מדוע מפתחות סטטיים אינם מגנים
מפתח סטטי בקונפיגורציה חי יותר מהמשימה שלשמה נוצר. הוא שוקע במאגר הקוד, במשתני הסביבה של תהליך הבנייה, במחשבים הניידים של המפתחים ובפלטי לוגים — ונשאר פעיל גם אם השירות נכתב מחדש מזמן. החלפת סיסמה במקום אחד אינה מספיקה: ההעתקים כבר נספרים בעשרות.
דליפת פרטי גישה לעתים רחוקות נראית כמו פריצה. לרוב זהו מפתח שנשאר בהיסטוריית מאגר הקוד, ייצוא של בסיס נתונים, לוג של אפליקציה עם פרמטרי חיבור, או קבלן משנה שאת הגישה שלו כך ולא שללו. קשה להבחין בכך, אך התוצאה אחת: לבסיס הנתונים או לאחסון יכול להתחבר מי שלא קיבל גישה.
הבעיה השנייה — פרטי גישה משותפים. מערכת סליקה, אנליטיקה פנימית ודוח לפי לוח זמנים משתמשים באותו סט מפתחות. לפי הלוגים אי אפשר להבין של מי הבקשה שהגיעה, ואי אפשר לשלול גישה למשתתף אחד בלי לשבור את האחרים.
שלילת הגישה הופכת לנוהל חירום: להנפיק מפתח חדש, לעדכן את הקונפיגורציה בכל הסביבות, להפעיל מחדש את השירותים. בזמן שזה נעשה, המפתח הישן ממשיך לעבוד — חלון הפגיעות נמדד ביממות.
סודות דינמיים ב-HashiCorp Vault מנתקים את הקשר הזה: פרטי הגישה נוצרים עבור בקשה מסוימת, בעלי תוחלת חיים קצרה, ומבוטלים אוטומטית. בהמשך נפרט איך זה עובד בפועל — מחיבור האחסון לשירותים ועד רוטציה מתוכננת ושלילת גישה ממוקדת.
רוטציה ללא השבתה ושלילת גישה בדקות
מפתחות קבועים חיים בקונפיגורציות ובמשתני סביבה חודשים. הם מועתקים בין סביבות, נמסרים לקבלן, נשכחים לביטול לאחר עזיבת עובד — ומפתח אחד כזה פותח גישה לכל הסביבה. כשהאירוע כבר קרה, השלילה הופכת למעבר ידני בעשרות שירותים, וחלקם ממשיכים לעבוד עם הסיסמה הישנה.
סודות דינמיים משנים את המודל: פרטי הגישה מונפקים עבור עומס עבודה ותפקיד מסוימים, ולא נשמרים בקובץ. תוחלת החיים של פרטי גישה קצרי-מועד היא דקות או שעות, ובסיומה הגישה נעלמת מעצמה, ללא מעורבות אדם.
הנפקת גישות אוטומטית נשענת על אימות של השירות עצמו, ולכן אין צורך להעביר, לאחסן או לסנכרן סיסמה בין צוותים — בפועל אצלנו זה HashiCorp Vault.
רוטציה של סודות מפסיקה להיות פעולה נפרדת עם חלון תחזוקה. השירות מבקש נתונים חדשים מראש, ממשיך לעבוד עם הפעילים, והקודמים מבוטלים לאחר המעבר — אין השבתה של שירותים.
בעת ההטמעה אנו בודקים שלכל תפקיד מוגדרת תוחלת חיים סבירה, שהאפליקציה מטפלת נכון בסירוב לפי סיסמה ישנה ויודעת להזדהות מחדש.
שלילת גישה הופכת לפעולה אחת: חוסמים את התפקיד — וכל פרטי הגישה שהונפקו על בסיסו מסומנים כבטלים. בלוג רואים איזה שירות קיבל מה ומתי, ולכן חקירת אירוע נשענת על עובדות ולא על השערות.
אנו מגדירים זאת בשילוב עם סביבת ההרצה של השירותים ועם אחסון הקונפיגורציות, כך שההנפקה והניתוק לא תלויים בצעדים ידניים.
דרכי הנפקת גישות: מסטטיקה ועד מפתחות קצרי-מועד
ההסתעפות פשוטה: היכן נמצאים פרטי הגישה וכמה זמן הם חיים. מפתחות סטטיים בקונפיגים ובמשתני סביבה מזרזים את ההפעלה, אך אין להם תוחלת חיים — דליפה דרך לוגים, דאמפ של זיכרון או מאגר קוד מעניקה גישה ללא הגבלת זמן שאיש לא יבחין בה.
העברת הסודות לאחסון מאובטח מסירה את השאלה "מי רואה את הקובץ", אך לא את שאלת הרוטציה: הערכים נשארים ארוכי-חיים. להלן לפי אילו קריטריונים לבחור מצב עבור סביבה מסוימת.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| מפתחות סטטיים בקונפיגורציה | דיבוג מקומי, מערכות חיצוניות ללא תמיכה ברוטציה | אין שלילה ותוחלת חיים; החלפת ערך — פעולה ידנית בכל הצמתים |
| סודות באחסון מאובטח מסוג מפתח-ערך | יש צורך להוציא מפתחות מהקוד ומהמאגרים, הספק אינו יודע להנפיק גישות זמניות | הערכים ארוכי-חיים, הרוטציה וההפצה נשארות על המהנדסים |
| פרטי גישה קצרי-מועד לפי בקשה | בסיסי נתונים, עננים, ממשקי API פנימיים עם תמיכה בהנפקה דינמית | השירות זקוק לזהות משל עצמו וליכולת לרענן גישה תוך כדי תנועה |
| פדרציה על בסיס זהות הצדדים | סביבות ללא מפתחות ארוכי-חיים, החלפה בין אשכולות ולספקים חיצוניים | דורשת אמון מוגדר מראש וסנכרון זמן |
| סכמה היברידית | סביבות עבודה: סטטיקה רק להפעלה ראשונית, השאר — דינמיקה | דיבוג מורכב יותר: צריך לראות איזה מסלול הנפקה פעל |
הסכמה ההיברידית היא שלמעשה מתבררת כתשובה מעשית. מפתח ארוך-חיים נשאר בדיוק במקום שבלעדיו אי אפשר לעלות: אימות ראשוני של השירות מול האחסון — Vault בתפקיד זה מנפיק בעצמו אסימון קצר-מועד — וגישה למערכת שאינה יודעת מפתחות זמניים. כל השאר מונפק לזמן, ולכן שלילת גישה מפסיקה להיות פעולה נפרדת ומתרחשת מעצמה כשפג תוקף.
כיצד אנו מטמיעים: ביקורת, סכמה, הגדרה, בדיקה, מסירה
הטמעת ניהול הסודות מתחילה לא בפריסת האחסון, אלא במלאי: היכן כיום נמצאים סיסמאות, מפתחות וטוקנים — בקונפיגורציות של אפליקציות, במשתני סביבה, בקבצים על השרתים, בהיסטוריית מאגרי הקוד. עד שהמפה הזו לא נאספת, רוטציה אוטומטית נותנת תחושת סדר כוזבת ומשאירה אזורים עיוורים. להלן השלבים, שאחרי כל אחד נשאר תוצאה ביניים עובדת.
- מלאי וביקורת גישות. אנו מתעדים כל סוד, את הבעלים שלו, תוחלת החיים שלו ואת מי שקורא אותו — שירות, אדם, מערכת חיצונית. בנפרד מסמנים את מה שאסור לשנות אוטומטית, כדי לא לעצור את הקשר עם קבלנים.
- סכמת הנפקת גישות. אנו מגדירים אילו שירותים מקבלים פרטי גישה קצרי-מועד לבסיס הנתונים, אילו — תעודות, ואילו — מפתחות סטטיים. כאן גם בוחרים את שיטות האימות של האפליקציות ואת תוחלת החיים של החכירה.
- הגדרת הסביבה. אנו מקימים אחסון עמיד בתקלות על בסיס Vault, מפעילים יומן ביקורת לכל קריאה, מגדירים גיבויים ופתיחה אוטומטית מחדש לאחר הפעלה. מחברים את מנגנוני ההנפקה הנדרשים — בסיסי נתונים, תעודות, הצפנה.
- פיילוט על שירות אחד. אנו מעבירים אפליקציה לקבלת הסוד מהאחסון: בודקים הארכת חכירה, שלילה נכונה והתנהגות בזמן אי-זמינות של האחסון.
- בדיקה בסביבת בדיקות. אנו מריצים תרחישי שלילה, הפעלה מחדש של האפליקציה תחת עומס ואובדן קשר עם האחסון. בודקים שכישלון של הנפקה אחת לא מפיל את כל הסביבה.
- מסירת הנהלים. אנו מוסרים לצוות שלכם את סכמת ההנפקה, הנחיות למפתחים, סדר הרוטציה והתורנויות, ואת ניתוח יומן הביקורת — בהמשך הליווי מתנהל בכוחות עצמכם או בתמיכתנו.
קונפיגורציות, מדיניות גישה ונהלי רוטציה
לאחר סיום העבודה התשתית צריכה להישאר ניתנת לניהול בלעדינו: הסודות מונפקים לפי בקשה, תוחלת החיים מוגדרת מראש, ואת הגישה שהונפקה אפשר לבדוק ולשלול בכל רגע. לכן אנו מוסרים לא רק אחסון מוגדר, אלא גם סט ארטיפקטים שלפיהם הצוות משחזר את קונפיגורציית Vault ומשנה אותה בלי לפענח קוד זר.
- מדיניות גישה — כללי קריאה וכתיבה לפי נתיבים, המשויכים לתפקידים ולא לאנשים: סביבת הפיתוח פתוחה יותר, וסודות הייצור רואה רק מי שהם נדרשים לו לפי המשימה.
- תפקידים לשירותים — תפקיד נפרד לכל אפליקציה עם סט נתיבים משל עצמו: פגיעה בשירות אחד אינה פותחת גישה לסודות של שכניו.
- נוהל רוטציה — טבלה "סוג הסוד / תוחלת חיים / מועד הנפקה מחדש / אחראי", ובנוסף סדר שלילה ידנית ובדיקת היסטוריית ההנפקות.
- סכמת אינטגרציות — כיצד אפליקציות, קווי בנייה וצמתי אשכול מקבלים סודות, היכן נשמרים הנתונים לאימות ראשוני ומה קורה בזמן אי-זמינות של האחסון.
- תיעוד הסודות — מפת נתיבים, תבניות הנפקה, שמות משתני סביבה והוראה לתורן: לשלול גישה, לראות מי קיבל אותה, לחבר שירות חדש.
- סט בדיקות — בדיקות המאשרות שהמדיניות מנפיקה סוד לתפקיד הנכון ומסרבת לכל השאר; מופעלות בכל שינוי בקונפיגורציה.
- תוכנית גישה לשעת חירום — פרטי גישה אטומים וסדר השימוש בהם אם האחסון אינו זמין.
מקרה בוחן: קיצור תוחלת החיים של גישות מחודשים לשעות
לפני ההטמעה גישות לבסיסי נתונים ולשירותים חיצוניים חיו בקונפיגורציות והונפקו ידנית: פרטי הגישה הוחלפו אחת לרבעון, ובעזיבת מהנדס היה צריך לעבור עשרות שירותים ולהיזכר היכן רשומה כל סיסמה סטטית.
שלילת גישה ארכה בממוצע 3-5 ימים, וכל אותו זמן העובד לשעבר נשאר רשמית במערכת. אי אפשר היה לבדוק למי יש כיום פרטי גישה פעילים — המלאי ארך שבועות ובכל זאת נשאר חלקי.
מה שינו
העברנו את השירותים לסודות דינמיים ב-HashiCorp Vault: פרטי הגישה נוצרים עבור משימה מסוימת, חיים מדקות ספורות ועד שעה ומבוטלים אוטומטית. הרוטציה אינה דורשת אדם — ההנפקה והשלילה מתועדות בלוג עם שיוך לתפקיד ולזמן.
מדדים לפני ואחרי
- תוחלת החיים של פרטי הגישה: מחודשים ספורים ל-15-60 דקות.
- זמן שלילה מלאה של גישה: מ-3-5 ימים ל-2-3 דקות — השבתת התפקיד מפסיקה מיד הנפקת סודות חדשים.
- שיעור הפעולות הידניות עם גישה: הצטמצם מכ-80% למקרים בודדים — ידנית נותר רק אישור של תפקיד חדש.
- סוג הכשל שהוסר: דליפה של סיסמה סטטית מקונפיגורציה או ממאגר הפסיקה להיות אירוע — עד لحשיפה הסוד כבר אינו בתוקף.
תופעת לוואי — כמעט ולא נותרו סיסמאות "נצחיות" בקונפיגורציות, במאגרים ובמשתני סביבה. המבקרים קיבלו תמונה מלאה: מי, מתי ולאילו מערכות קיבל גישה.
במה נבדלים סודות דינמיים ממפתחות סטטיים?
מפתח סטטי נוצר פעם אחת וחי עד רוטציה ידנית: מחרוזת בקונפיג של האפליקציה, משתנה סביבה בבנייה, רשומה באחסון סיסמאות. תוחלת החיים שלו אינה מוגבלת, וטווח הפעולה של הגישה בדרך כלל רחב ממה שדרוש לשירות מסוים — אותו שם משתמש לבסיס הנתונים ממוחזר לא פעם בכמה סביבות. כל עוד המפתח לא נשלל, הוא נשאר בתוקף גם עבור מי שקיבל אותו במקרה: מלוגים, מדאמפ או מענף ישן במאגר.
סודות דינמיים מונפקים לפי בקשה. HashiCorp Vault יוצר פרטי גישה עבור תפקיד מסוים ברגע הפנייה: השירות מציג את התפקיד שלו ומקבל זוג שם משתמש-סיסמה שקיים רק עבורו. תוחלת החיים נקבעת בחכירה — דקות או שעות; עם תומה הגישה נשללת אוטומטית, בלי תורן ורוטציה ידנית.
מכאן ההבדל בטווח הפעולה של הגישה ובמחיר הפגיעה במפתח. מפתח סטטי הוא משותף: השלילה נוגעת לכל מי שמשתמש בו, ולכן מחליפים אותו לעתים רחוקות ובחוסר רצון, ומפתח שדלף מחייב רוטציה בכל הנקודות ואיתור מקור הדליפה.
מפתח דינמי הונפק עבור תפקיד מסוים, שלילתו אינה פוגעת בשירותים שכנים, וחלון התקיפה מוגבל לתוחלת החכירה.
גם מודל האמון משתנה: במקום "סומכים על כל מי שיש לו קובץ עם המפתח" — "סומכים על המרכז המנפיק ועל היומן שלו", שבו רואים מי ומתי קיבל גישה.
מפתחות סטטיים לא נעלמים: עבור מערכות חיצוניות ללא תמיכה בהנפקה הם נשארים אפשרות מעשית, והמשימה היא לצמצם את מספר המקומות הללו למינימום.
ספקות נפוצים: תאימות, עמידות בתקלות, חזרה לאחור
ספקות בדרך כלל צפים לא בהתחלה, אלא כשהפיילוט כבר מנפיק סודות לשירות בייצור: מה יקרה בכשל של האחסון, האם זה יעבוד עם אפליקציה ישנה, איך לחזור אחורה. להלן תשובות קצרות למה ששואלים לרוב לפני ההפעלה בייצור.
מה יקרה אם האחסון לא יהיה זמין?
כל אפליקציה מקבלת סודות דרך סוכן מקומי שמחזיק מטמון של הערכים האחרונים שהונפקו. כל עוד תוחלת החיים של הסוד לא פגה, השירות עובד איתם כשורה, ואי-זמינות של האחסון אינה מובילה לקריסה.
הנפקות חדשות נכנסות לתור ומנוסות שוב בהשהיה הולכת וגדלה, ואם ההשהיה מתארכת — פועל מקור גיבוי שהוגדר בשלב ההטמעה. את האחסון עצמו פורסים כאשכול של כמה צמתים: בכשל של התפקיד הפעיל המעבר מתבצע אוטומטית, ותמונות מצב נשמרות מחוץ לצמתים.
האם זה יעבוד עם אפליקציות ישנות?
כן, גם אם האפליקציה אינה יודעת לפנות ישירות לאחסון. הסוכן מציב את הסודות בקובץ הקונפיגורציה או במשתני הסביבה וקורא אותם מחדש לפי אות — אין צורך לשנות קוד. לשירותים עם פורמט מפתחות נוקשה אנו מחזיקים שכבת ביניים שמחזירה את הערך בצורה המצופה.
איך בנויה תוכנית החזרה לאחור?
את המעבר ההפוך מתארים לפני ההפעלה: המסלול הסטטי עם המפתחות נשאר פעיל, והמעבר נעשה בדגל אחד בקונפיגורציה. לאחר החזרה כל הסודות שהונפקו נשללים בכפייה, כדי שלא יישארו במערכת עותקים חיים, וחשבונות הגישה עבור סודות דינמיים נסגרים.
נדון בסכמת הגישות שלכם ונחזור עם תוכנית
כדי שהערכת ההטמעה תישען על עובדות ולא על הנחות, אנו מציעים לדון במשימה עניינית: שלחו את סכמת סביבת התשתית ואת רשימת המערכות שמקבלות סודות. להלן מה בדיוק מסיר את אי-הוודאות בתוכנית העבודה.
- סכמת הסביבה: אילו סביבות קיימות (פיתוח, בדיקות, ייצור), היכן נמצאים השירותים ואיך הם רואים את אחסון הסודות.
- צרכני פרטי הגישה: אפליקציות, קווי בנייה ופריסה, מפעילים, בסיסי נתונים, אינטגרציות חיצוניות — בציון אילו גישות בדיוק נדרשות לכל אחד.
- מודל הגישות הנוכחי: היכן הסודות נמצאים כיום — משתני סביבה, קונפיגים, מאגרים, — מי מנפיק אותם ואיך הם מגיעים לסביבת ההרצה.
- דרישות לרוטציה: תוחלת החיים של פרטי הגישה, הבעלים, מה צריך לקרות בעת פגיעה או שלילת גישה.
- אילוצים: דרישות רגולטוריות, מערכות שאסור להשבית, חלונות לשינויים וסדרי אישור.
- היסטוריית כשלים: מה כבר נשבר בגלל דליפות או סיסמאות שפג תוקפן ואילו פעולות עדיין נעשות ביד.
הדיון מתקיים בשיחה אחת: עוברים על הסכמה, מסמנים היכן הסודות יישארו סטטיים והיכן אפשר באמת להעביר אותם לדינמיים, ומציינים את שלבי המיגרציה. בסיומו אתם מקבלים תוכנית עבודה עם סדר העברת המערכות, הערכת הטמעה לפי שלבים ורשימת נתוני מקור שחסרים כדי להתחיל.







