הסבר על HashiCorp Vault
בסרטון זה, Armon Dadgar, מייסד חברת HashiCorp וה- CTO המשותף, מספק מבוא ל- Vault וכיצד המערכת פועלת.
ניתן לצפות עם כתוביות שהוספנו בצמוד לטקסט (יש ללחוץ על כפתור CC) וגם לקרוא את התרגום כאן בהמשך.
תרגום (Transcription)
היום אני רוצה להשקיע קצת זמן בשיחה על Vault של HashiCorp.
כשאנחנו מדברים על Vault, הבעיה שאנחנו מחפשים לה פתרון היא בעיית ניהול הסודות. כשאנחנו מתחילים לדבר על ניהול סודות, השאלה הראשונה שעולה באופן טבעי היא "מהו סוד?"
מהם הסודות שלכם?
כשאנחנו מדברים על ניהול סודות, מה שאנחנו באמת מדברים עליו זה מה שיעניק אותנטיקציה (authentication) או הרשאות (authorization). כוונתנו היא כל דבר שעשוי להעניק לך אימות למערכת או הרשאה למערכת. כמה דוגמאות לכך יכולות להיות שמות משתמש וסיסמאות (passwords). זה יכול להיות למשל אישורי כניסה ל- databases וזה יכול להיות דברים כמו API tokens, או שזה יכול להיות למשל תעודות TLS .
העניין הוא שנצטרך את הנ"ל כדי להכנס למערכת ולהזדהות (כמו username/password) , או שנשתמש בזה כדי לאמת זהות (כמו TLS certificate) – כך שאנחנו משתמשים בנ"ל כדי לאשר גישה למערכת.
כל הדברים הנ"ל הם סודות, ואלו דברים שאנחנו רוצים לנהל בזהירות. אנחנו רוצים להבין למי יש גישה אליהם, אנחנו רוצים להבין מי השתמש בדברים האלה, וברוב המקרים, אנחנו רוצים איזה תהליך שבאמצעותו נוכל לעדכן אותם מעת לעת.
כאשר אנו מסתכלים מסביב כיצד הדברים הללו מנוהלים כיום בפועל, אנו רואים התפשטות של סודות. הכוונה היא שהסודות מגיעים בסופו של דבר לכל מקום: הם נמצאים בטקסט רגיל (plain text) שנמצא בתוך קוד המקור שלנו, או פשוט נמצא בקובץ הגדרות/ header בצורה של "hard-coded". וזה גם בתוך קבצי קונפיגורציה (configuration management).
אז זה נמצא ב- cleartext, ב- Chef, Puppet, Ansible ודומיהם, כך שכל אחד יכול להיכנס ולראות מה האישורים האלה. ואז זה נכנס למערכת ניהול התצורה/גירסאות (version control) ומגיע אל מערכות כמו GitHub, או GitLab, או Bitbucket – כך שזה מתפזר בכל התשתית שלנו!
מהם האתגרים כאן?
ובכן, אנחנו לא יודעים למי יש גישה לכל הדברים האלה, ולכן אנחנו לא יודעים, למשל, האם למישהו בארגון שלנו יש גישה ל- GitHub, האם הוא יכול להיכנס ולראות את קוד המקור וכך לראות מה דרכי הגישה אל ה- database שלנו.
גם אם הם היו יכולים לעשות זאת, איננו יודעים אם כבר עשו זאת. אין לנו רישום וביקורת (audit trail) שאומר שרק בגלל שאני, ארמון, יכולתי לראות את הסוד הזה, האם הלכתי וניגשתי אליו? לכן, אין לנו שום יכולת לנהל למי יש גישה או אפילו לבדוק מי עשה מה איתה.
גרוע מכך, כיצד נחליף את הדברים הללו? אם אנו מבינים שעלינו לשנות את ה-credential של ה- database שלנו בגלל שהייתה פריצה, או שאנו מבצעים החלפה תקופתית, זה הופך להיות קשה מאוד אם credential זה מקודד ב-source code שלנו או שהוא זרוע בהמון מערכות שונות. במקרה כזה קשה לדעת כיצד לבצע את את ההחלפה בצורה יעילה.
מצב זה של העולם הוא מה שאנו מכנים התפשטות סודות. אחת המטרות הראשונות שלנו כשהתחלנו לעבוד על Vault הייתה להסתכל באמת על בעיה זו ולשאול, "איך נוכל לשפר את המצב?"
וכאן מגיע Vault
Vault התחיל באמת בכך שאנחנו הסתכלנו על בעיית התפשטות הסודות ואמרנו: "אנחנו יכולים לפתור אותה רק על ידי ריכוז". במקום שהסודות יאוחסנו בכל מקום אפשרי, אנו מעבירים אותם למיקום מרכזי, ו- Vault מבטיח כי אנו הולכים להצפין את כל הסודות גם כשהם נמצאים בתוך Vault, וגם במעבר בין Vault לכל אחד מהלקוחות שרוצים לגשת אליו.
זה נותן לנו כמה יתרונות:
הראשון: להבדיל מהמערכות שבהן אחסנו את הדברים בטקסט רגיל, לפחות עכשיו, אם היית יכול לראות היכן הסוד נשמר, היית מגלה שהוא מוצפן. אז אתה לא מקבל גישה מכך שאתה רואה את הסוד.
הדבר הבא ש- Vault מאפשר לנו הוא בקרה מדויקת של גישה לסודות. במקום להיות מישהו בארגון שלנו שיש לו גישה ל- GitHub ויכול לראות את ה-source code, עכשיו נוכל להיות מדויקים יותר טוב ולומר, "שרת האינטרנט זקוק לגישה למסד הנתונים, שרת ה- API צריך את ה-API tokens, אבל לאף אחד לא תהיה גישה לכל. "
ואז, נוסף על כך, יש לנו נתיב ביקורת (audit trail). כעת אנו יכולים לראות לאילו credentials ניגש שרת האינטרנט, לאילו credentials ניגש ארמון. יש לנו הרבה יותר ניראות ושליטה כיצד הדברים הללו מנוהלים.
זה האתגר הראשון עם Vault, מעבר מעולם של התפשטות הסודות, שבו הדברים נמצאים בכל מקום, לעולם של ריכוז, שבו יש לנו ערבויות חזקות כי הסודות מוצפנים, ערבויות חזקות לגבי למי יש גישה, וניראות חזקה לתוך זה.
זה הופך להיות הדבר הראשון שלנו. האתגר ברמה הבאה הוא להבין למי אנו נותנים את ה-credentials הללו. אז נהדר, שמרנו את כל ה-credentials האלה בבטחה ב-Vault, אבל עכשיו אנחנו הולכים למשוך אותם ולספק אותם ליישום.
הבעייה הוא שהיישומים עושים עבודה איומה בשמירת סודות. באופן בלתי נמנע היישום יתן את ה-credentials שלו למערכת logging כדי שזו תוכל לכתוב אותם ל-standard output, זה יישלח ל- Splunk, וכעת ה-credentials נמצאים ב-log המרכזי שכל אחד יכול לראות אותו.
זה מופיע בכל סוג של פלט דיאגנוסטי, אז אולי היישום שלנו נופל, והוא מראה את שם המשתמש והסיסמה בתוך traceback או בתוך דוח השגיאה. יתכן גם שהוא שולח אותם למערכות ניטור חיצוניות כאשר יש שגיאה.
באופן כללי, מה שאנו מוצאים הוא שיישומים עושים עבודה גרועה בשמירת הדברים בסוד. כך שגם אם אנו עושים עבודה נהדרת לרכז את הסודות, ולשלוט בהם בצורה חזקה ולהצפין אותם בדרך ליישום, על יישום לא ניתן לסמוך.
סודות דינאמיים (Dynamic Secrets)
אחת היכולות ברמה השנייה שמציגה Vault היא מה שאנו מכנים סודות דינמיים. הרעיון העומד מאחורי סודות דינמיים הוא, במקום לספק credentials ארוכי טווח ליישום שהוא בהכרח מדליף, אנו מספקים credentials ארעיים, קצרי טווח. הדברים האלה נוצרים באופן דינמי, אך הם ארעיים. למשל אנו יכולים לתת credentials ליישום שתקפים רק למשך 30 יום.
לדבר זה יש כמה יתרונות. כעת, גם אם היישום מדליף את credential זה, הוא תקף רק לתקופת מוגדרת. היישום אולי יכתוב אותו למערכת logging ואפשר יהיה לראות אותו, אבל אנחנו יוצרים יעד נע עבור התוקף על ידי ביטול מתמיד והנפקת credentials חדשים.
הדבר הנוסף בעל הערך הוא שכעת כל credentials ייחודיים לכל לקוח. בעבר, אם היו לי 50 שרתי אינטרנט, כולם היו נכנסים וקוראים אותו credential סטטי של גישה למסד הנתונים. פירוש הדבר שאם יש פריצה והcredential של מסד הנתונים נגנב, קשה מאוד לאתר היכן הייתה נקודת הכשל. חמישים שרתים חולקים כולם את אותו ה-credential. לעומת זאת בעולם של credentials דינמיים לכל אחד מאותם 50 שרתי האינטרנט היו credentials ייחודיים. אז אנחנו יודעים בדיוק בדיוק שמכונת האינטרנט 42 הייתה נקודת הכשל.
הדבר האחרון שזה מאפשר לנו לעשות הוא שתהיה לנו דרך ביטול הרשאות טובה בהרבה. כעת, אם אנו יודעים שמכונת האינטרנט 42 הייתה נקודת הכשל שלנו, נוכל לבטל את שם המשתמש והסיסמה עבור מכונת האינטרנט 42 בלבד ולבודד את הדליפה. אבל אם כל 50 המכונות היו חולקות את אותו שם המשתמש והסיסמה, ברגע שננסה לבטל אותם, היינו גורמים להפסקה בשירות כולו. לכן, רדיוס הפיצוץ של ביטול גדול בהרבה כשיש לך סוד משותף לעומת סוד דינמי.
האתגר השלישי שמצאנו היה שלעתים קרובות יישומים שומרים נתונים לאורך זמן. האתגר הופך להיות, איך היישומים מגינים על הנתונים שלהם? מכיוון שלא נוכל לאחסן את כל המידע בתוך Vault; הוא נועד רק לניהול סודות, ולא שום דבר נוסף שצריך להיות חסוי.
מה שאנחנו רואים לעיתים קרובות הוא ש- Vault משמש כמקום מרכזי לניהול סודות, אנשים מאחסנים בו מפתחות הצפנה. אנו עשויים לשים מפתח הצפנה בתוך Vault ואז להפיץ את המפתח בחזרה ליישום; היישום מבצע הצפנה כדי להגן על נתונים שהוא שומר.
אולם מה שאנו מגלים הוא כי יישומים בדרך כלל אינם מיישמים קריפטוגרפיה כהלכה. יש המון ניואנסים עדינים וקל לטעות. טעויות מסוג זה לעתים קרובות מכשילות את כל ההצפנה כאשר נעשות טעויות הללו.
אחד האתגרים שלעתים קרובות אנו מסתכלים עליו הוא כיצד אנו מתקדמים מהמצב ש-Vault הוא רק כספת לאחסון מפתחות הצפנה והוא סומך על האפליקציה שהיא תעשה את ההצפנה נכון?
זה התפתח ליכולת ש- Vault מכנה "הצפנה כשירות" (Encryption-as-a-service). הרעיון כאן הוא, במקום לצפות שאנחנו רק הולכים לספק מפתח למתכנת, והמתכנת יישם נכון קריפטוגרפיה, Vault יעשה כמה דברים. אחד מהם הוא ש-Vault יאפשר לך ליצור קבוצה של מפתחות עם שמות. אני יכול ליצור מפתח שאני מכנה "פרטי כרטיס אשראי", ושני שאני מכנה "מספר תעודת זהות", ואחד עבור "PII".
אלה הם רק שמות. אני רק נותן שם למפתח הזה, ואני לא אחשוף את הערך שלו. אבל אז מה שאנחנו חושפים זה קבוצה של ממשקי API high-level לעשות קריפטוגרפיה. ממשקי API אלה יהיו הפעולות הקלאסיות שאתה מצפה להן. דברים כמו להצפין, או לפענח, או לחתום או לאמת.
כעת, כמתכנת, מה שאני עושה הוא להתקשר אל Vault עם ממשק API ולומר: "אני רוצה לעשות HMAC באמצעות מפתח כרטיס האשראי שלי ואיזו פיסת נתונים." מה ש- Vault מגן עליו, הוא ש-Vault מספק את אימפלמנטציה, כך שאיננו צריכים לסמוך על המתכנתים שיישמו את הפעולות high-level כהלכה. וניהול המפתח מסופק גם על ידי Vault. המתכנת לעולם לא רואה את המפתח הבסיסי.
זה מאפשר לנו לעשות כמה דברים. קודם כל, הוא מבטיח שהקריפטוגרפיה מיושמת כראוי מכיוון שאנחנו משתמשים ביישום שנבדק על ידי Vault. יישום זה נבדק הן על ידינו, על ידי קהילת הקוד הפתוח, והן על ידי מבקרים חיצוניים בהם אנו משתמשים.
זה גם מאפשר לנו להאציל את ניהול המפתחות. אם אנו חושבים שהקריפטוגרפיה היא קשה, ניהול מפתחות קשה עוד יותר. בפועל, כשאתה שואל כמה יישומים מיישמים כראוי גרסאות מפתחות, החלפת מפתחות, ביטול מפתחות ואת מחזור החיים המלא של ניהול המפתחות, התשובה היא מעט מאוד מכיוון שזה קשה. אבל על ידי האצלה של משימות אלו ל-Vault אנו יכולים להשתמש בממשקי high-level API כדי לעשות את כל זה. אנו מקבלים גם את מחזור חיי המפתח המלא המסופק על ידי Vault .
כך שבפועל מדובר בסופו של דבר בשלושת האתגרים העיקריים שאנו מנסים לעזור למפתחים. כיצד אנו מעבירים את ה-credentials האלה מטקסט רגיל ומהמצב שהם מפוזרים על פני מערכות רבות ושונות לתרחיש שבו הם מנוהלים באופן מרכזי עם בקרת גישה הדוקה ונראות ברורה. ואז, איך נתקדם ונגן מפני יישומים שלא בהכרח אמונים על שמירת סודות?
אנו עושים זאת ע"י ארעיות. אנו יוצרים יעד נע שבו מה שאנחנו מנהלים הוא היכולת של שרת האינטרנט לגשת למסד הנתונים כך שה-credential המאפשר זאת הוא דינמי במקום סטטי. ואז, לבסוף, כיצד נמשיך ונעזור לאפליקציה להגן על הנתונים שהיא שומרת? זה נעשה באמצעות סדרה של כלי ניהול מפתח והעברת האחריות לקריפטוגרפיה. שלושת אלה הם עקרונות הליבה של Vault.
עכשיו אולי נסתכל במהירות מקרוב ונדבר קצת במבט על על הארכיטקטורה, איך זה מיושם? כשאנחנו מדברים על הארכיטקטורה של Vault, יש כמה דברים חשובים שיש להבין. האחת היא כי ל-Vault אפשר להוסיף תוספים (plugins). יש לו הרבה מנגנונים שונים להוספת תוספים.
כשאנחנו מדברים על Vault, יש לו את הליבה המרכזית, שיש לה תפקידים רבים, כולל ניהול מחזור החיים אשר מבטיח שבקשות מטופלות בצורה נכונה, ואז יש הרבה נקודות הרחבה (extension points) שונות המאפשרות לנו להתאים אותו לסביבה שלנו.
התפקיד הראשון שחשוב ביותר הוא ה-backends של אותנטיקציה. אלה מאפשרים ל-Vault לאפשר ללקוחות לבצע אותנטיקציה ממערכות שונות. לדוגמא, אם אנו מאתחלים EC2VM, EC2VM זה עשוי לאמת באמצעות תוסף האימות (authentication plugin) של AWS. תוסף זה מאפשר לנו להתחבר להגדרת ההזדהות של Amazon כדי להוכיח שהמתקשר הוא, למשל, שרת אינטרנט.
אבל אם יש לנו משתמשים אנושיים, ייתכן שהם נכנסים ומשתמשים במשהו כמו LDAP או Active Directory כדי להוכיח את זהותם. אם אנו משתמשים בפלטפורמה ברמה גבוהה, אולי משהו כמו Kubernetes, אנו עשויים להשתמש בספק אימות ה-Kubernetes שלנו.
מטרתם של ספקי האימות הללו היא לקחת מערכת כלשהי שאנו סומכים עליה, בין אם מדובר ב- Kubernetes, LDAP או AWS, ולהשתמש בה כדי לספק הזדהות של יישום או של משתמש אנושי. זה מה שיוצא לנו מזה: מושג על זהות המתקשר.
זה נהדר, ואז אנו משתמשים בזה כדי להתחבר ל-auditing backend, המאפשר לנו להתחבר ולהזרים auditing של בקשה/תגובה למערכת חיצונית שנותנת לנו מעקב על מי עשה מה. זה יכול להיות Splunk, כדוגמה, לשם אנו נשלח את כל ה-audit logs השונים שלנו. Vault יאפשר לנו לשמור audit logs שונים ומרובים. אנחנו יכולים גם לשלוח ל- Splunk, כמו גם למערכת כמו Syslog, כדוגמה.
האתגר ברמה הבאה הוא, היכן בעצם Vault מאחסנת נתונים משלה? אם אנחנו הולכים לקרוא ולכתוב סודות ל-Vault, הוא צריך להיות מסוגל לאחסן איפה שהוא את הדברים הללו. זה מה שאנו מכנים backends של אחסון.
Backends של אחסון אחראים לאחסון נתונים. זה יכול להיות כמה דברים שונים. זה יכול להיות RDBMS סטנדרטי ב-Postgres או mySQL, זו יכולה להיות מערכת כמו Consul, וזה יכול להיות בסיס נתונים מנוהל בענן כמו Google Spanner. אך המטרה של מערכות backend אלה היא לספק אחסון עמיד באופן זמין מאוד, כך שנוכל לסבול אובדן של אחת ממערכות ה- backend הללו.
החלק האחרון הוא, כיצד Vault מספק גישה לסודות שונים? אלה ה-backends הסודיים עצמם. הם מגיעים בכמה צורות שונות. השימוש הגדול ביותר בהם הוא לאפשר את יכולת הסודות הדינמית שעליה דיברנו קודם.
צורה אחת של backend סודי היא פשוטה. זה רק ערך של מפתח. אני יכול פשוט לאחסן שם משתמש וסיסמה סטטיים שם, ואני נותן לו שם משתמש וסיסמה, והדברים האלה הם סטטיים. זהו רק מחסן מוצפן של ערכי מפתחות. עם זאת, ככל שאנחנו מתוחכמים יותר, אולי נרצה להשתמש ביכולת הסודות הדינמיים שעליה דיברנו. זה המקום שבו התוספים השונים האלה מקבלים תפקיד.
יש לנו תוספי מסדי נתונים שונים; תוסף מסד נתונים יאפשר לנו לנהל באופן דינמי את credentials של mySQL, של Postgres, של Oracle, וכו '. יש לנו דברים כמו RabbitMQ, אז אולי אנחנו עושים credentials דינמיים לתורי ההודעות (message queues) שלנו.
וכך הלאה. אתה יכול אפילו להחיל את אותו העיקרון על משהו כמו AWS. יתכן ויש לנו יישומים שצריכים לקרוא ולכתוב מ- S3, אך איננו רוצים לתת להם גישה ארוכת טווח למסרים מיידיים (IM). במקום זאת, אנו מגדירים תפקיד במערך ה- AWS שלנו, ונלך ונאפשר באופן דינמי credentials קצרי מועד לפי הצורך. זה מרחיב את אותה פרדיגמה של credentials דינמיים.
זוהי נקודת הרחבה המאפשרת ל-Vault ליישם את אותו העיקרון על דברים רבים ושונים. שימוש נפוץ אחד בכך הוא PKI. בפועל, ניהול של סרטיפיקטים נוטה להיות סיוט, ומה שלעתים קרובות אנו רואים הוא סרטיפיקטים ארוכי-טווח; אולי סרטיפיקטים של חמש עד עשר שנים מכיוון שאנחנו לא רוצים לעבור את תהליך יצירתם. לעומת זאת ב-Vault, אנו יכולים לאתר אותם וליצור אותם בתוכנה. בפועל, אנשים ישתמשו בסרטיפיקטים קצרי מועד, עד כדי 72, 24 שעות. בדרך זו אתה כל הזמן זז ויוצר יעד נע.
רשימה זו נמשכת וכוללת דברים כמו SSH כדוגמה. אנו יכולים לתווך גם גישה ל- SSH, כך שאין לך PIN אחד ששולט בהרבה מכונות.
בבסיסו, זה מה שהופך את Vault לגמיש כל כך. זה מאפשר ל-Vault לנהל לקוחות שעושים אותנטיקציה מול קבוצה אחרת של ספקי זהות (identity providers). אנו יכולים לבצע ביקורת מול מגוון מקורות מהימנים שונים לניהול לוגים, אנו יכולים לאחסן נתונים כמעט בכל מערכת עמידה (durable system), ואז נוכל להרחיב את שטח הפנים של סוגי הסודות שניתן לנהל באופן סטטי או דינמי על ידי הוספת backends חדשים של סודות.
זהו מופע (instance) אחד של Vault. כשאנחנו מדברים על הפעלת מופע של Vault, כל מופע שלו הוא אחד מאלה. ואז, בפריסה רחבה יותר, איך זה ייראה כשאנחנו מריצים מספר מופעי Vault בכדי לספק זמינות גבוהה. ברמה הגבוהה ביותר, יהיה לנו backend משותף. לדוגמה, זה עשוי להיות Consul, שהוא מבפנים שלושה שרתים שונים, לדוגמה, המספקים לנו HA. ואז ב-frontend נוכל להריץ כמה Vaults.
מה ש-Vault עושה זה לתאם עם ה-backend המשותף לביצוע תפקיד "המנהיג". אחד מהמופעים ייבחר למנהיג הנוכחי שלנו, ואז כלקוחות, כשאנחנו מגישים בקשות, אנחנו מדברים עם המנהיג. גם כשאנחנו מדברים עם לא-מנהיג, הוא יעביר אותנו באופן שקוף למנהיג הפעיל.
בדרך זו, אם node מסוים מת, הפסקת חשמל, נפילה של פרוצסים, אולי קישוריות רשת היא בעיה, אנו נזהה זאת ונקדם מופע אחר להיות מנהיג באופן אוטומטי, ומופע זה ישתלט על הפעילות ושאר המופעים יעבירו אליו את הבקשות.
כך נראה Vault ברמה גבוהה. הוא פועל כשירות רשת משותפת, ואנחנו מדברים אליו פשוט כלקוח API ברשת. מה ש-Vault חושף בדרך כלל הוא ממשק API של JSON. כך שזה JSON דרך HTTP, מה שמקל יחסית על שילוב עם היישומים שלנו.
אני מקווה שזה היה שימושי כמבוא ל- Vault. תודה!