לפני שחותמים על עסקה באמצעות חישוב רב-משתתפים, המערכת בודקת את העסקה בהתאם למדיניות העסקאות במכונה שלכם. במאמר הזה נסביר אילו כללי מדיניות נבדקים, איך כלל מדיניות עובר במחזור החיים שלו, מה אפשר לבדוק באמצעות כלל מדיניות ולמה טרנזקציה נדחית.
איך מתבצעת הערכה של עסקה
מדיניות עסקה היא הצהרה אחת של Cedar מסוג permit או forbid. כשחותם קורא ל-CreateTransaction, המכונה מפענחת את העסקה הלא חתומה ב-Transaction.payload באמצעות המנתח של Transaction.schema, ובודקת כל מדיניות שנאכפת מול העסקה לפני שנעשה שימוש בחלק כלשהו של המפתח. המדיניות נאכפת כשהסטטוס שלה הוא ACTIVE או PENDING_DISABLED. מידע נוסף על מחזור החיים של המדיניות
ההחלטה מבוססת על שלושה כללים:
- דחייה כברירת מחדל. טרנזקציה מותרת רק אם לפחות מדיניות אחת של
permitתואמת לה. אם אין כללי מדיניות לאכיפה, כל עסקה נדחית. - האיסור מנצח. אם יש התאמה למדיניות
forbidכלשהי, הטרנזקציה נדחית, גם אם יש התאמה גם למדיניותpermit. - אם המערכת לא מצליחה להעריך מדיניות, היא לא תואמת. לדוגמה, מדיניות שקוראת מאפיין הקשר אופציונלי שלא קיים בטרנזקציה תיכשל בהערכה. המכונה מתעדת את השגיאה, מדלגת על המדיניות הזו ומקבלת החלטה על סמך שאר כללי המדיניות שנאכפים. זה חל גם על כללי מדיניות של
forbid, אז צריך לכתוב כללי מדיניות שלforbidשלא יכולים להיכשל בגלל מאפיין חסר. לדוגמה, ראו תרחיש 8 ותרחיש 9.
עסקה שמכילה כמה העברות, כמו עסקת Solana עם כמה הוראות העברה, נבדקת פעם אחת לכל העברה. העסקה מותרת רק אם כל העברה מותרת. אם אחת מההעברות נדחית או שלא ניתן לפענח אותה, כל העסקה נדחית.
כל הערכה, אישור או דחייה, יוצרת רשומת הערכה שמוחזרת בעסקה ב-Transaction.policyEvaluationRecord.
ההחלטה קובעת אם המכונה יכולה לחתום על העסקה בלי לחכות לחתימות נוספות:
-
PERMIT: אם בקשת ה-CreateTransactionכבר כוללת מספיק הרשאות חתימה כדי לעמוד בדרישות של מדיניות המפתחות של KeyRing, הטרנזקציה עוברת מיד לסטטוסSIGNING. אחרת, הוא נוצר ב-PENDING_AUTHORIZATIONוממתין לחתימות נוספות. -
DENY: המכונה לא חותמת על העסקה באופן אוטומטי. הטרנזקציה נוצרת ב-PENDING_AUTHORIZATION, והערך שלpolicyEvaluationRecord.decisionמוגדר כ-DENY. החותמים יכולים לבדוק את רשומת ההערכה ולדחות את העסקה (RecordSignerDecisionעםDENY) או לאשר אותה בכל מקרה (AUTHORIZE). העסקה נחתמת רק אם מספיק חותמים מאשרים אותה כדי לעמוד במדיניות המפתח.
מדיניות העסקאות היא אמצעי הגנה על חתימה אוטומטית, ולא חסימה של החותמים: החותמים יכולים לאשר עסקה שהמדיניות דוחה. הקובץ המקורי של PolicyEvaluationRecord נשאר מצורף לעסקה לצורכי ביקורת.
מחזור החיים של הפוליסה
אי אפשר לשנות את מדיניות העסקאות. ל-TransactionPolicy אין שיטת עדכון, וה-rule שלו לא ניתן לשינוי. כדי לשנות כלל, משביתים את המדיניות באמצעות DisableTransactionPolicy ויוצרים מדיניות חדשה באמצעות CreateTransactionPolicy.
כדי להפעיל או להשבית מדיניות, צריך לקבל אישורים מקוורום של כותבי מדיניות (משתמשים עם תפקיד POLICY_AUTHOR פעיל ב-User.roleStatuses). כל כותב מדיניות חותם על TransactionPolicySigningPayload שמציין את המדיניות (או את המכונה, במקרה של CreateTransactionPolicy), את הפעולה (ACTIVATE או DISABLE) ואת rule.cedarDocument. הבקשה שכוללת הצעה לשינוי נחשבת לאישור הראשון. מחברי מדיניות אחרים מאשרים באמצעות
ApproveTransactionPolicy. מספר האישורים הנדרש הוא בין activationInfo.requiredApprovals ל-deactivationInfo.requiredApprovals. אם המכונה צריכה רק אישור אחד, השינוי נכנס לתוקף באופן מיידי.
בטבלה הבאה מתוארים כל מצבי המדיניות, ומצוין אם המדיניות נאכפת במצב הזה:
| מדינה | משמעות | האם המדיניות נאכפת? |
|---|---|---|
PENDING_ACTIVE |
המדיניות הוצעה והיא ממתינה לאישורים של כותבי המדיניות. | לא |
ACTIVE |
למדיניות יש activationInfo.requiredApprovals אישורים. |
כן |
PENDING_DISABLED |
מחבר המדיניות ביקש להשבית את המדיניות, והבקשה ממתינה לאישורים. | כן, עד שהבקשה תקבל deactivationInfo.requiredApprovals אישורים |
DISABLED |
המדיניות הושבתה או בוטלה לפני שהופעלה. כללי מדיניות מושבתים נשמרים לצורכי ביקורת. | לא |
המדיניות עוברת בין הסטטוסים האלה בכיוון אחד:
-
PENDING_ACTIVEעדACTIVE: ההפעלה קיבלה מספיק אישורים. -
PENDING_ACTIVEעדDISABLED: כותב המדיניות מבטל את המדיניות באמצעותDisableTransactionPolicyלפני שהיא הופכת לפעילה. -
ACTIVEעדPENDING_DISABLED: כותב המדיניות קורא ל-DisableTransactionPolicy. -
PENDING_DISABLEDעדDISABLED: לבקשת ההשבתה יש מספיק אישורים.
מדיניות יכולה להיכנס לכל מצב המתנה פעם אחת לכל היותר. אי אפשר להפעיל מחדש מדיניות שהושבתה. במקום זאת, צריך ליצור מדיניות חדשה.
בקטע תפקידי משתמשים מוסבר מי יכול להפעיל את השיטות האלה.
גרסת קבוצת המדיניות
קבוצת כללי המדיניות היא קבוצת כללי המדיניות שנאכפים (ACTIVE או PENDING_DISABLED) בנקודת זמן מסוימת. בכל פעם שמסתיימת הפעלה או השבתה, המכונה נותנת למעבר הזה את המספר הבא במונה של המכונה, ומתעדת אותו ב-activationInfo.transitionSequence או ב-deactivationInfo.transitionSequence. המספר הזה הוא גרסת קבוצת המדיניות שנוצרה במעבר.
בטבלה הבאה אפשר לראות איך הגרסה של קבוצת כללי המדיניות משתנה ברצף של אירועים:
| אירוע | רצף המעבר | כללי מדיניות שנאכפים |
|---|---|---|
| מדיניות א' מופעלת. | תשובה: activationInfo.transitionSequence = 1 |
A |
| מדיניות ב' מופעלת. | B: activationInfo.transitionSequence = 2 |
א', ב' |
מדיניות ג' מוצעת (PENDING_ACTIVE) ואז מבוטלת. |
ללא | א', ב' |
| בקשה להשבתת מדיניות א' אושרה. | תשובה: deactivationInfo.transitionSequence = 3 |
B |
ביטול של מדיניות PENDING_ACTIVE אף פעם לא משנה את קבוצת כללי המדיניות שנאכפים, ולכן לא מתבצע רצף מעבר וגרסת קבוצת כללי המדיניות לא משתנה. בזמן שההעברה ממתינה לאישורים, הערך של transitionSequence לא מוגדר.
בכל הערכה, המערכת קוראת את כללי המדיניות, את ה-KeyLists ואת המפתחות נכון ל-createTime של העסקה, ומתעדת את רצף המעברים הגבוה ביותר שהושלם באותו זמן ב-policyEvaluationRecord.policySetVersion. אם לשתי הערכות יש את אותה גרסה של קבוצת כללי מדיניות, הן השתמשו באותם כללי מדיניות.
הבקשה של Cedar
בקשה ב-Cedar כוללת את הגורם, הפעולה, המשאב וההקשר. לדוגמה:
permit (
principal == User::"alice@example.com",
action == Action::"buy_transaction",
resource == Resource::"transaction_management"
)
when {
context.principal_keyring == "institutional-treasury" &&
context has fiat_amount && context.fiat_amount <= 10000
};
איך משתמש ממופה ל-principal של Cedar
ה-principal הוא יוזם הטרנזקציה: המשתמש שה-principal שלו תואם לזהות המאומתת של מי שקורא ל-CreateTransaction. למשתמש צריך להיות תפקיד פעיל של SIGNER. ב-Cedar, הישות הראשית היא ישות User שהמזהה שלה הוא השדה principal של המשתמש, לדוגמה User::"alice@example.com".
המופע לא מעביר נתוני ישויות ל-Cedar. לישות User אין מאפיינים ואין הורים, לכן:
principal == User::"alice@example.com"תואם לעסקאות שאליס יוזמת.- התנאי
principal in Team::"treasury"אף פעם לא מתקיים. כדי להגביל את המשתמשים שיכולים לחתום באמצעות מפתח, משתמשים במדיניות המפתח של KeyRing. כדי להחיל כלל על קבוצת מפתחות, מסמנים את התיבהcontext.principal_keyring. - כלל שקורא מאפיין של
principal, כמוprincipal.team, נכשל בהערכה.
אי אפשר לשנות את ה-principal של המשתמש, ולכן כלל שכולל שם של חשבון משתמש ממשיך להתייחס לאותה זהות.
פעולה ומשאב
action: הערך שלTransaction.actionבבקשהCreateTransaction, בפורמט של ישות CedarAction. אפשר לבצע את הפעולות הבאות ב-CreateTransaction:פעולה משמש ל: Action::"buy_transaction"עסקה שבה רוכשים נכס. Action::"sell_transaction"עסקה שבה נפטרים מנכס. Action::"internal_transfer_transaction"העברה של נכס, כמו תשלום או העברה בין מפתחות. מגיש הבקשה בוחר את הפעולה. החישוב הרב-משתתפים לא מסיק אותה מהמטען הייעודי (payload). כלל יכול להתאים לפעולה אחת (
action == Action::"buy_transaction"), לרשימת פעולות (action in [Action::"buy_transaction", Action::"sell_transaction"]), או להשאיר אתactionללא הגבלה כדי להתאים לכל פעולה.
resource: תמידResource::"transaction_management"להערכות של טרנזקציות. כלל יכול לבדוק אתresource == Resource::"transaction_management"או להשאיר אתresourceללא הגבלה.
מאפייני הקשר
ההקשר מכיל את המאפיינים שכללי המדיניות בודקים. הם מגיעים משני מקומות:
- מטען הייעודי (payload) של העסקה ומפתח החתימה. המכונה מפענחת את
Transaction.payloadומוסיפה את המזהים של מפתח החתימה ושל אוסף המפתחות שלו. המאפיינים האלה הםprincipal_keyring,principal_key,blockchain,schema,secondary_key,amount_token_scaled,token_symbol,contract_address,chain_id,max_fee_atomic,payloadו-time_stamp. במאמר כתיבת כללים למדיניות של טרנזקציות מופיעה הטבלה המלאה וההתנהגות של כל בלוקצ'יין. - השדה
metadataשל העסקה,שמוגדר על ידי יוזם הפעילות ב-CreateTransaction.
בטבלה הבאה מתוארים מאפייני המטא-נתונים:
השדה Transaction.metadata |
מאפיין Cedar | סוג הארז | ערך |
|---|---|---|---|
fiatAmount |
context.fiat_amount |
Long |
ערך העסקה בדולר ארה"ב (google.type.Money). הערך של currencyCode חייב להיות USD, הערך של units חייב להיות אפס או יותר, והערך של nanos חייב להיות 0. |
validity |
context.validity |
Long |
משך הזמן שהעסקה תקפה (google.protobuf.Duration), בשניות שלמות. הערך חייב להיות גדול מ-0 שניות, ללא חלקי שניות. |
principalValue1 |
context.principal_value1 |
String |
כל ערך שתגדירו, עד 256 תווים, למשל דסק מסחר או מרכז עלויות. |
principalValue2 |
context.principal_value2 |
String |
כל ערך שתגדירו, עד 256 תווים, למשל מזהה פנימי של כרטיס או של צד נגדי. |
הכללים הבאים חלים על מטא-נתונים:
- שדות שלא הוגדרו לא נמצאים בהקשר. אם לעסקה אין
fiatAmount, אזcontext.fiat_amountלא קיים, והמדיניות שקוראת אותו נכשלת בהערכה. קודם בודקים אם המאפיין קיים באמצעותhas, כמו ב-context has fiat_amount && context.fiat_amount <= 10000. - מטא-נתונים לא תקינים גורמים לבקשה להיכשל. אם שדה מפר את הכללים בטבלה שלמעלה, למשל
fiatAmountב-EURאו עםnanosשאינו אפס,validityשל 0 שניות אוprincipalValue1באורך של יותר מ-256 תווים, הפעולהCreateTransactionנכשלת עםINVALID_ARGUMENTואף מדיניות לא נבדקת. - המופע לא בודק את המטא-נתונים מול העסקה.
הערך
fiatAmountהוא הערך של העסקה לפי מה שהיוזם אומר. חותמים אחרים רואים את המטא-נתונים ב-Transaction.metadataוב-policyEvaluationRecord.evaluationContextלפני שהם מאשרים אותם. כדי להגביל את הסכומים בשרשרת ללא קשר למטא-נתונים, צריך לבדוק אתcontext.amount_token_scaledו-context.contract_address. - אי אפשר לשנות את המטא-נתונים אחרי שהעסקה נוצרת.
KeyRings
KeyRing מקבץ מפתחות. לכל הקשר של טרנזקציה יש principal_keyring ו-principal_key, כך שכלל יכול לחול על כל מפתח ב-KeyRing, כולל מפתחות שנוצרו מאוחר יותר, ו-KeyRing יכול להיות רשומה ב-KeyList. למידע נוסף ולכלל לדוגמה, ראו KeyRings.
KeyLists
KeyList היא רשימה עם שם של כתובות בלוקצ'יין שאפשר להפנות אליהן כללי מדיניות, למשל כרשימת היתרים של יעדים. כל רשומה היא אחת מהאפשרויות הבאות:
- רשומה ידנית (
manualEntry): כתובת שהמכונה לא מנהלת, עם שדות אופציונליים שלsourceו-reason. - מפתח במכונה (
key): תואם לכתובות של המפתח. - אוסף מפתחות במכונה (
keyRing): תואם לכתובות של כל מפתח פעיל באוסף המפתחות, כולל מפתחות שנוצרו אחרי שהרשומה נוספה.
רשימות KeyLists יכולות להשתנות אחרי שהמדיניות מאושרת. כשמוסיפים או מסירים רשומה באמצעות AddKeyListEntries או RemoveKeyListEntries, כל כללי המדיניות שמתייחסים ל-KeyList משתמשים ברשומות החדשות מההערכה הבאה, בלי אישורים חדשים של כותבי המדיניות. אי אפשר למחוק KeyList באמצעות DeleteKeyList אם כללי המדיניות PENDING_ACTIVE, ACTIVE או PENDING_DISABLED מתייחסים אליו.
KeyLists בהקשר של Cedar
בזמן ההערכה, המכונה מרחיבה כל KeyList ל-Set שטוח של כתובות בלוקצ'יין ב-String: הרשומות הידניות, וגם הכתובות שנגזרות מכל רשומה של מפתח ו-KeyRing. כל קבוצה מועברת ל-Cedar בתור context.key_lists["<var>KEY_LIST_ID</var>"], כאשר KEY_LIST_ID הוא המזהה של {keyList} בשם המשאב של KeyList, לדוגמה trusted-destinations עבור projects/my-project/locations/us-central1/instances/my-instance/keyLists/trusted-destinations.
כלל בודק את החברות באמצעות האופרטור contains של Cedar מול כתובת היעד המפוענחת, context.secondary_key. לדוגמה, כדי לאפשר העברות רק לכתובות ב-KeyList של trusted-destinations:
// Assuming you created a KeyList with ID "trusted-destinations":
permit (principal, action, resource)
when { context.key_lists["trusted-destinations"].contains(context.secondary_key) };
כדי לדחות העברות לכל כתובת ב-KeyList של blocked-addresses:
// Assuming you created a KeyList with ID "blocked-addresses":
forbid (principal, action, resource)
when { context.key_lists["blocked-addresses"].contains(context.secondary_key) };
חשוב לזכור:
- צריך להשתמש בתחביר של סוגריים מרובעים, ולא בתחביר של נקודה, עבור מזהה KeyList. תחביר הנקודה של Cedar (
context.key_lists.trusted-destinations) נכשל בניתוח כשהמזהה מכיל מקף, ש-Cedar קורא כחיסור, או כשהוא מתחיל בספרה, כמו UUID שנוצר על ידי שרת. תחביר הסוגריים המרובעים,context.key_lists["<var>KEY_LIST_ID</var>"], פועל עם כל מזהה. -
key_listsתמיד קיים, וכלל יכול לקרוא KeyList ישירות בתוכו. CreateTransactionPolicyמוודא שכל KeyList שהכלל מתייחס אליו קיים, ו-DeleteKeyListמסרב למחוק KeyList אם מדיניות מתייחסת אליו. השתמשו ב-context.key_lists has "<var>KEY_LIST_ID</var>"רק כשכלל מתייחס ל-KeyList שאולי עדיין לא קיים. - הכתובות מושוות כמחרוזות. השדה
secondary_keyמשתמש בפורמט שמתואר בקטע כתיבת כללי מדיניות לעסקאות לכל בלוקצ'יין, למשל פורמט סיכום ביקורת (checksum) של EIP-55 עם אותיות רישיות וקטנות ל-Ethereum. מוסיפים רשומות ידניות באותו פורמט. - השדה
secondary_keyבהעברת טוקן של Solana הוא חשבון הטוקן של היעד, ולא הארנק של הבעלים. כדי לאשר ארנק, צריך להוסיף את חשבון האסימון שלו לכל מטבע שמאשרים.
כל הערכה פותרת את החברות ב-KeyList נכון ל-createTime של העסקה, באותו זמן כמו המדיניות, ומתעדת את התוצאה ב-policyEvaluationRecord.keyListMemberships: ה-KeyList, הכתובת שנבדקה, אם היא הייתה חברה, והרשומה שהתאימה.
מכיוון ש-KeyList משנה את מה שהמדיניות מתירה, צריך להגביל את מי שיכול לשנות אותה.
השיטות של KeyList צריכות את roles/mpc.admin. מידע נוסף זמין במאמר הרשאות IAM.
הסיבות לדחייה
כשהערך של policyEvaluationRecord.decision הוא DENY,
הסיבה מופיעה בשדה policyEvaluationRecord.denyReason. בטבלה הבאה מפורטות הסיבות לדחייה:
| הסיבה לדחייה | מתי | קביעת כללי מדיניות |
|---|---|---|
FORBID_RULE_MATCHED |
לפחות מדיניות forbid אחת שנאכפה תאמה. |
forbid כללי המדיניות שתואמים. |
NO_PERMIT_RULE_MATCHED |
המטען הייעודי (payload) פוענח, לא נמצאה התאמה למדיניות forbid, לא נכשלה הערכה של מדיניות ולא נמצאה התאמה למדיניות permit. |
ללא |
EVALUATION_ERROR |
אין התאמה למדיניות permit או forbid, ולפחות מדיניות אחת נכשלה בהערכה, למשל כי היא קוראת מאפיין אופציונלי שלא נמצא בהקשר. |
אין. evaluationErrors מפרט את השגיאות. |
UNRECOGNIZED_PAYLOAD |
המכונה לא הצליחה לפענח את Transaction.payload או להקרין אותו להקשר, למשל בגלל בייטים פגומים, הוראה או פעולת חוזה לא נתמכות, או עסקה בביטקוין עם כמה נמענים. לא מתבצעת הערכה של המדיניות. |
אין. השגיאה בניתוח מופיעה ב-evaluationErrors. |
הסיבות נקבעות לפי הסדר הבא:
- אם אי אפשר לפענח את המטען הייעודי (payload) או להקרין אותו להקשר, ההחלטה היא
DENYעםUNRECOGNIZED_PAYLOAD. - אחרת, כל מדיניות שנאכפת נבדקת. אם יש התאמה למדיניות
forbidכלשהי, ההחלטה היאDENYעםFORBID_RULE_MATCHED, גם אם יש התאמה גם לכללי מדיניותpermitאו אם כללי מדיניות אחרים לא נבדקו. - אחרת, אם יש התאמה לפחות למדיניות אחת של
permit, ההחלטה היאPERMIT. שגיאות ממדיניות אחרת עדיין מתועדות ב-evaluationErrors. - אחרת, ההחלטה היא
DENYעםEVALUATION_ERRORאם הערכת מדיניות כלשהי נכשלה, אוNO_PERMIT_RULE_MATCHEDאם כל כללי המדיניות הוערכו ללא התאמה.
השגיאות מתועדות גם כשההחלטה היא PERMIT, לכן כדאי לבדוק את רשומת ההערכה כדי לראות אם יש כללי מדיניות שאף פעם לא תואמים כי הם תמיד נכשלים.
תרחישים
בתרחישים 1 עד 9, אליס (User::"alice@example.com") יוצרת העברת Ethereum תקינה, שבה action מוגדר ל-Action::"internal_transfer_transaction", עם המטא-נתונים הבאים, אלא אם צוין אחרת בתרחיש:
"metadata": {
"fiatAmount": {"currencyCode": "USD", "units": "5000"},
"principalValue1": "treasury-desk"
}
בעסקה אין validity ואין principalValue2.
בטבלה הבאה מפורטים התרחישים השונים:
| תרחיש | כללי מדיניות שנאכפים או מטען ייעודי (payload) | החלטה | הסיבה לדחייה |
|---|---|---|---|
| 1 | ללא | DENY |
NO_PERMIT_RULE_MATCHED |
| 2 | permit אחד שתואם |
PERMIT |
|
| 3 | permit אחד שלא תואם |
DENY |
NO_PERMIT_RULE_MATCHED |
| 4 | שני permit, אחד תואם |
PERMIT |
|
| 5 | permit ו-forbid ששניהם תואמים |
DENY |
FORBID_RULE_MATCHED |
| 6 | permit שקורא מאפיין חסר |
DENY |
EVALUATION_ERROR |
| 7 | אותו permit, עם has |
DENY |
NO_PERMIT_RULE_MATCHED |
| 8 | forbid שקורא מאפיין חסר, וpermit תואם |
PERMIT |
|
| 9 | forbid שנדרש לו מאפיין |
DENY |
FORBID_RULE_MATCHED |
| 10 | מטען ייעודי (payload) שלא ניתן לפענח | DENY |
UNRECOGNIZED_PAYLOAD |
תרחיש 1: אין כללי מדיניות שנאכפים
במכונה אין כללי מדיניות של ACTIVE או PENDING_DISABLED.
החלטה: DENY, NO_PERMIT_RULE_MATCHED. בלי מדיניות permit תואמת, כל טרנזקציה נדחית. במכונה חדשה, אף טרנזקציה לא נחתמת באופן אוטומטי עד שכותבי המדיניות מפעילים מדיניות permit. החותמים חייבים לאשר כל טרנזקציה.
תרחיש 2: היתר אחד שתואם
permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };
ההחלטה: PERMIT. הסכום, 5,000, הוא לכל היותר 10,000.
המדיניות הזו מופיעה ב-determiningPolicyIds.
תרחיש 3: היתר אחד שלא תואם
permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 1000 };
החלטה: DENY, NO_PERMIT_RULE_MATCHED. הסכום, 5,000, גבוה מ-1,000, ואין מדיניות אחרת שמאפשרת את העסקה.
תרחיש 4: שני היתרים, אחד תואם
מדיניות א':
permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 1000 };
מדיניות ב':
permit (
principal == User::"alice@example.com",
action == Action::"internal_transfer_transaction",
resource == Resource::"transaction_management"
)
when {
context has fiat_amount && context.fiat_amount <= 25000 &&
context has principal_value1 && context.principal_value1 == "treasury-desk"
};
ההחלטה: PERMIT. מדיניות א' לא תואמת, אבל מדיניות ב' כן. מספיקה מדיניות permit תואמת אחת. determiningPolicyIds מציג רק את מדיניות ב'.
תרחיש 5: איסור מבטל היתר
מדיניות א':
permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };
מדיניות ב':
forbid (principal, action, resource)
when { context has principal_value1 && context.principal_value1 == "treasury-desk" };
החלטה: DENY, FORBID_RULE_MATCHED. שתי כללי המדיניות תואמים, והמדיניות forbid
מנצחת. determiningPolicyIds מציג רק את מדיניות ב'.
תרחיש 6: היתר קורא מאפיין חסר
permit (principal, action, resource)
when { context.validity <= 3600 };
החלטה: DENY, EVALUATION_ERROR. בעסקה אין validity, ולכן context.validity לא קיים והמדיניות לא נבדקת. אין מדיניות אחרת שמאפשרת את העסקה. השגיאה מופיעה בעמודה evaluationErrors.
תרחיש 7: אותו היתר, עם
permit (principal, action, resource)
when { context has validity && context.validity <= 3600 };
החלטה: DENY, NO_PERMIT_RULE_MATCHED. context has validity הוא false, ולכן המדיניות מקבלת את הערך false במקום להיכשל. העסקה עדיין נדחית, אבל הסיבה מראה שהמדיניות נבדקה ולא נמצאה התאמה.
תרחיש 8: כלל איסור קורא מאפיין חסר
מדיניות א':
permit (principal, action, resource)
when { context has fiat_amount && context.fiat_amount <= 10000 };
מדיניות ב':
forbid (principal, action, resource)
when { context.principal_value2 == "sanctioned-counterparty" };
ההחלטה: PERMIT. בעסקה אין principalValue2, ולכן מדיניות ב' לא נבדקת והמערכת מדלגת עליה. מדיניות א' תואמת. determiningPolicyIds
מציג את מדיניות א', ו-evaluationErrors מציג את השגיאה ממדיניות ב'.
תרחיש 9: איסור שדורש מאפיין
מדיניות א' היא המדיניות permit מתרחיש 8. מדיניות ב':
forbid (principal, action, resource)
unless { context has fiat_amount };
החלטה: PERMIT על העסקה בתרחישים האלה, שבהם יש fiatAmount. אם אליס לא כוללת את fiatAmount, ההחלטה היא DENY,
FORBID_RULE_MATCHED: context has fiat_amount הוא false, ולכן המדיניות forbid תואמת. המדיניות הזו לא יכולה להיכשל בהערכה, כי היא משתמשת רק ב-has.
כדי לשלב מאפיין חובה עם בדיקה של הערך שלו במדיניות forbid אחת, קודם בודקים את המאפיין:
forbid (principal, action, resource)
unless { context has fiat_amount && context.fiat_amount <= 10000 };
תרחיש 10: מטען ייעודי (payload) שלא ניתן לפענח
אליס יוצרת עסקה שהמנתח של Transaction.schema לא יכול לפענח את ה-payload שלה, למשל בייטים של RLP קטועים, PSBT של ביטקוין עם כמה נמענים או עסקת סולאנה עם הוראה שלא נתמכת.
החלטה: DENY, UNRECOGNIZED_PAYLOAD. לא מתבצעת הערכה של המדיניות.
השדה evaluationErrors מפרט את שגיאת הניתוח, והשדה determiningPolicyIds ריק.
רשומת הערכה
כל הערכה מפיקה PolicyEvaluationRecord שאי אפשר לשנות. הוא מוחזר ב-Transaction.policyEvaluationRecord וכולל את השדות הבאים:
| שדה | ערך |
|---|---|
decision |
PERMIT או DENY. |
denyReason |
אחת מהסיבות לדחייה. לא מוגדר כשההחלטה היא PERMIT. |
determiningPolicyIds |
ב-PERMIT, המזהים של כללי המדיניות של permit שתאמו. ב-FORBID_RULE_MATCHED, המזהים של כללי המדיניות של forbid שתאמו. אחרת, השדה ריק. |
evaluationErrors |
השגיאות ממדיניות שההערכה שלה נכשלה, או שגיאת המנתח כש-denyReason הוא UNRECOGNIZED_PAYLOAD. |
evaluationContext |
ההקשר של Cedar שכללי המדיניות הוערכו לפיו, בתור google.protobuf.Struct. מספרים שלמים של 64 ביט מאוחסנים כמחרוזות עשרוניות כדי לשמור על הדיוק שלהם. |
policySetVersion |
גרסת קבוצת כללי המדיניות ששימשה להערכה. |
keyListMemberships |
החברויות ב-KeyList שזוהו במהלך ההערכה. |
intentDigest |
תקציר מקודד הקסדצימלי באותיות קטנות של המטען הייעודי (payload) של העסקה שנבדקה. הגיבוב תלוי בסכימה של המטען הייעודי (payload): Keccak-256 של העסקה עבור ETHEREUM_TX_V2, ה-sighash של הקלט הראשון עבור BITCOIN_TX_V2, SHA-256 של ההודעה הלא חתומה עבור SOLANA_TX_V1, ותקציר החתימה של EIP-712, keccak256(0x1901 ++ domainSeparator ++ hashStruct(message)), עבור EIP712_TYPED_DATA_V1. |
evaluationTime |
מתי הבדיקה בוצעה. |