ניהול סודות
Triggerfish לעולם אינו מאחסן אישורים בקובצי תצורה. כל הסודות -- מפתחות API, טוקני OAuth, אישורי אינטגרציה -- מאוחסנים באחסון מאובטח מקומי לפלטפורמה: ה-OS keychain לרמה האישית, או שירות כספת לרמה הארגונית. תוספים וסוכנים מתקשרים עם אישורים דרך ה-SDK, האוכף בקרות גישה מחמירות.
שכבות אחסון
| רמה | שכבת אחסון | פרטים |
|---|---|---|
| אישית | OS keychain | macOS Keychain, Linux Secret Service (דרך D-Bus), Windows Credential Manager |
| ארגונית | אינטגרציית כספת | HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, או שירותי כספת ארגוניים אחרים |
בשני המקרים, סודות מוצפנים בזמן מנוחה על ידי שכבת האחסון. Triggerfish אינו מיישם הצפנה משלו לסודות -- הוא מאציל לתוכנות ייעודיות ומבוקרות לאחסון סודות.
בפלטפורמות ללא keychain מקומי (Windows ללא Credential Manager, מכולות Docker), Triggerfish חוזר לקובץ JSON מוצפן ב- ~/.triggerfish/secrets.json. הרשומות מוצפנות עם AES-256-GCM באמצעות מפתח 256 סיביות הקשור למכונה המאוחסן ב-~/.triggerfish/secrets.key (הרשאות: 0600). כל רשומה משתמשת ב-IV אקראי חדש של 12 בתים בכל כתיבה. קובצי סודות ישנים בטקסט גלוי מועברים אוטומטית לפורמט המוצפן בטעינה הראשונה.
הרמה האישית אינה דורשת תצורה כלשהי לסודות. כאשר מחברים
אינטגרציה במהלך ההגדרה (triggerfish dive), אישורים מאוחסנים אוטומטית ב-OS keychain. אין צורך להתקין או להגדיר דבר מעבר למה שמערכת ההפעלה כבר מספקת. :::
הפניות סודות בתצורה
Triggerfish תומך בהפניות secret: ב-triggerfish.yaml. במקום לאחסן אישורים כטקסט גלוי, מפנים אליהם בשם והם מותרים מה-OS keychain בעת האתחול.
yaml
models:
providers:
anthropic:
apiKey: "secret:provider:anthropic:apiKey"
openai:
apiKey: "secret:provider:openai:apiKey"
channels:
telegram:
botToken: "secret:channel:telegram:botToken"המותר מבצע סריקה עומקית-ראשונה של קובץ התצורה. כל ערך מחרוזת המתחיל ב-secret: מוחלף ברשומת ה-keychain המתאימה. אם סוד שאליו מפנים לא נמצא, האתחול נכשל מיד עם הודעת שגיאה ברורה.
העברת סודות קיימים
אם יש לכם אישורים בטקסט גלוי בקובץ התצורה מגרסה קודמת, פקודת ההעברה מעבירה אותם ל-keychain אוטומטית:
bash
triggerfish config migrate-secretsפקודה זו:
- סורקת את
triggerfish.yamlלאיתור ערכי אישורים בטקסט גלוי - מאחסנת כל אחד ב-OS keychain
- מחליפה את ערך הטקסט הגלוי בהפניית
secret: - יוצרת גיבוי של הקובץ המקורי
לאחר ההעברה, וודאו שהסוכן מתחיל בהצלחה לפני מחיקת קובץ
הגיבוי. ההעברה אינה הפיכה ללא הגיבוי. :::
ארכיטקטורת אישורים מואצלים
עיקרון אבטחה מרכזי ב-Triggerfish הוא ששאילתות נתונים פועלות עם אישורי המשתמש, לא אישורי מערכת. זה מבטיח שהסוכן יורש את מודל ההרשאות של מערכת המקור -- משתמש יכול לגשת רק לנתונים שהיה יכול לגשת אליהם ישירות.
ארכיטקטורה זו מבטיחה:
- ללא הרשאות יתר -- הסוכן אינו יכול לגשת לנתונים שהמשתמש אינו יכול לגשת אליהם ישירות
- ללא חשבונות שירות מערכת -- אין אישור כל-יכול שעלול להיפרץ
- אכיפת מערכת מקור -- מערכת המקור (Salesforce, Jira, GitHub, וכו') אוכפת את ההרשאות שלה על כל שאילתה
אבטחה פלטפורמות סוכני AI מסורתיות משתמשות לעיתים קרובות
בחשבון שירות מערכת יחיד לגישה לאינטגרציות בשם כל המשתמשים. משמעות הדבר שלסוכן יש גישה לכל הנתונים באינטגרציה, והוא מסתמך על ה-LLM שיחליט מה להציג לכל משתמש. Triggerfish מבטל סיכון זה לחלוטין: שאילתות פועלות עם טוקן OAuth מואצל של המשתמש עצמו. :::
אכיפת SDK לתוספים
תוספים מתקשרים עם אישורים אך ורק דרך Triggerfish SDK. ה-SDK מספק שיטות מודעות-הרשאות וחוסם כל ניסיון לגשת לאישורי ברמת מערכת.
מותר: גישה לאישורי משתמש
python
def get_user_opportunities(sdk, params):
# ה-SDK מאחזר טוקן מואצל של המשתמש מאחסון מאובטח
# אם המשתמש לא חיבר Salesforce, מחזיר שגיאה מועילה
user_token = sdk.get_user_credential("salesforce")
# השאילתה פועלת עם הרשאות המשתמש
# מערכת המקור אוכפת בקרת גישה
return sdk.query_as_user(
integration="salesforce",
query="SELECT Id, Name, Amount FROM Opportunity",
user_id=sdk.current_user_id
)חסום: גישה לאישורי מערכת
python
def get_all_opportunities(sdk, params):
# זה יעלה PermissionError -- נחסם על ידי ה-SDK
token = sdk.get_system_credential("SALESFORCE_TOKEN")
return query_salesforce(token, "SELECT * FROM Opportunity")sdk.get_system_credential() חסום תמיד. אין תצורה לאפשר
אותו, אין דריסה ניהולית, ואין פתח מילוט. זהו כלל אבטחה קבוע, בדומה לכלל אין-כתיבה-למטה. :::
כלי סודות הניתנים לקריאה על ידי LLM
הסוכן יכול לעזור לכם לנהל סודות באמצעות שלושה כלים. באופן קריטי, ה-LLM לעולם אינו רואה את ערכי הסודות בפועל -- הקלט והאחסון מתרחשים מחוץ לפס.
secret_save
מבקש מכם להזין ערך סוד באופן מאובטח:
- CLI: הטרמינל עובר למצב קלט מוסתר (תווים לא מוצגים)
- Tidepool: חלון קלט מאובטח מופיע בממשק הרשת
ה-LLM מבקש ששוד ישמר, אך הערך בפועל מוזן על ידכם דרך הפרומפט המאובטח. הערך מאוחסן ישירות ב-keychain -- הוא לעולם לא עובר דרך הקשר ה-LLM.
secret_list
מציג את שמות כל הסודות השמורים. לעולם אינו חושף ערכים.
secret_delete
מוחק סוד לפי שם מה-keychain.
החלפת ארגומנטים בכלים
כאשר הסוכן משתמש בכלי שדורש סוד (למשל, הגדרת מפתח API במשתנה סביבה של שרת MCP), הוא משתמש בתחביר {{secret:name}} בארגומנטי הכלי:
tool_call: set_env_var
arguments: { "key": "API_TOKEN", "value": "{{secret:my-api-token}}" }סביבת הריצה מותרת הפניות {{secret:name}} מתחת לשכבת ה-LLM לפני שהכלי מבוצע. הערך המותר לעולם אינו מופיע בהיסטוריית השיחה או ביומנים.
אבטחה החלפת {{secret:name}} נאכפת על ידי
קוד, לא על ידי ה-LLM. גם אם ה-LLM ניסה לרשום או להחזיר את הערך המותר, שכבת המדיניות תתפוס את הניסיון בוו PRE_OUTPUT. :::
שיטות הרשאות SDK
| שיטה | התנהגות |
|---|---|
sdk.get_user_credential(integration) | מחזירה את טוקן ה-OAuth המואצל של המשתמש לאינטגרציה המצוינת. אם המשתמש לא חיבר את האינטגרציה, מחזירה שגיאה עם הוראות. |
sdk.query_as_user(integration, query) | מבצעת שאילתה מול האינטגרציה באמצעות אישורי המשתמש המואצלים. מערכת המקור אוכפת את ההרשאות שלה. |
sdk.get_system_credential(name) | חסום תמיד. מעלה PermissionError. נרשם כאירוע אבטחה. |
sdk.has_user_connection(integration) | מחזירה true אם המשתמש חיבר את האינטגרציה המצוינת, false אחרת. אינה חושפת נתוני אישורים כלל. |
גישה מודעת-הרשאות לנתונים
ארכיטקטורת האישורים המואצלים עובדת יד ביד עם מערכת הסיווג. גם אם למשתמש יש הרשאה לגשת לנתונים במערכת המקור, כללי הסיווג של Triggerfish שולטים לאן נתונים אלו יכולים לזרום לאחר שנאחזרו.
דוגמה:
משתמש: "סכם את עסקת Acme ושלח לאשתי"
שלב 1: בדיקת הרשאות
--> טוקן Salesforce של המשתמש בשימוש
--> Salesforce מחזירה הזדמנות Acme (למשתמש יש גישה)
שלב 2: סיווג
--> נתוני Salesforce מסווגים כ-CONFIDENTIAL
--> זיהום הסשן עולה ל-CONFIDENTIAL
שלב 3: בדיקת פלט
--> אשה = נמען EXTERNAL
--> CONFIDENTIAL --> EXTERNAL: חסום
תוצאה: נתונים אוחזרו (למשתמש יש הרשאה), אך לא ניתן לשלוח
(כללי סיווג מונעים דליפה)למשתמש יש גישה לגיטימית לעסקת Acme ב-Salesforce. Triggerfish מכבד זאת ומאחזר את הנתונים. אך מערכת הסיווג מונעת מנתונים אלו לזרום לנמען חיצוני. הרשאה לגשת לנתונים נפרדת מהרשאה לשתף אותם.
תיעוד גישה לסודות
כל גישה לאישורים מתועדת דרך וו האכיפה SECRET_ACCESS:
json
{
"timestamp": "2025-01-29T10:23:45Z",
"hook_type": "SECRET_ACCESS",
"session_id": "sess_456",
"decision": "ALLOW",
"details": {
"method": "get_user_credential",
"integration": "salesforce",
"user_id": "user_456",
"credential_type": "oauth_delegated"
}
}ניסיונות חסומים גם נרשמים:
json
{
"timestamp": "2025-01-29T10:23:46Z",
"hook_type": "SECRET_ACCESS",
"session_id": "sess_456",
"decision": "BLOCK",
"details": {
"method": "get_system_credential",
"requested_name": "SALESFORCE_TOKEN",
"reason": "System credential access is prohibited",
"plugin_id": "plugin_789"
}
}ניסיונות גישה חסומים לאישורים נרשמים ברמת התראה מוגברת.
בפריסות ארגוניות, אירועים אלו יכולים להפעיל התראות לצוות האבטחה. :::
אינטגרציית כספת ארגונית
פריסות ארגוניות יכולות לחבר את Triggerfish לשירות כספת מרכזי לניהול אישורים:
| שירות כספת | אינטגרציה |
|---|---|
| HashiCorp Vault | אינטגרציית API מקומית |
| AWS Secrets Manager | אינטגרציית AWS SDK |
| Azure Key Vault | אינטגרציית Azure SDK |
| כספת מותאמת אישית | ממשק SecretProvider הניתן לחיבור |
אינטגרציית כספת ארגונית מספקת:
- רוטציה מרכזית -- אישורים מתחלפים בכספת ונאספים אוטומטית על ידי Triggerfish
- מדיניות גישה -- מדיניות ברמת הכספת שולטת אילו סוכנים ומשתמשים יכולים לגשת לאילו אישורים
- איחוד ביקורת -- יומני גישה לאישורים מ-Triggerfish ומהכספת ניתנים לתיאום
מה לעולם לא מאוחסן בקובצי תצורה
הדברים הבאים לעולם אינם מופיעים כערכי טקסט גלוי ב-triggerfish.yaml או בכל קובץ תצורה אחר. הם מאוחסנים ב-OS keychain ומופנים דרך תחביר secret:, או מנוהלים דרך הכלי secret_save:
- מפתחות API לספקי LLM
- טוקני OAuth לאינטגרציות
- אישורי בסיס נתונים
- סודות webhook
- מפתחות הצפנה
- קודי צימוד (זמניים, בזיכרון בלבד)
אם מצאתם אישורים בטקסט גלוי בקובץ תצורה של Triggerfish
(ערכים שאינם הפניות secret:), משהו השתבש. הריצו triggerfish config migrate-secrets כדי להעביר אותם ל-keychain. אישורים שנמצאו כטקסט גלוי צריכים להתחלף מיד. :::
עמודים קשורים
- עיצוב מונחה-אבטחה -- סקירה כללית של ארכיטקטורת האבטחה
- כלל אין-כתיבה-למטה -- כיצד בקרות סיווג משלימות בידוד אישורים
- זהות ואימות -- כיצד זהות המשתמש מזינה גישה מואצלת לאישורים
- ביקורת ותאימות -- כיצד אירועי גישה לאישורים נרשמים
