אם האפליקציה שלכם מאפשרת למשתמשים להיכנס לחשבונות שלהם באמצעות Google, אתם יכולים לשפר את האבטחה של החשבונות המשותפים האלה על ידי האזנה להתראות על אירועי אבטחה שסופקו על ידי שירות ההגנה על כל החשבונות, ותגובה אליהן.
ההתראות האלה מודיעות לכם על שינויים משמעותיים בחשבונות Google של המשתמשים שלכם, שלעיתים קרובות יכולות להיות להם גם השלכות אבטחה על החשבונות שלהם באפליקציה שלכם. לדוגמה, אם חשבון Google של משתמש נפרץ, זה עלול להוביל לפריצה לחשבון של המשתמש באפליקציה שלכם באמצעות שחזור חשבון אימייל או שימוש בכניסה יחידה (SSO).
כדי לעזור לכם לצמצם את הסיכון הפוטנציאלי של אירועים כאלה, Google שולחת לשירות שלכם אובייקטים שנקראים אסימונים של אירועי אבטחה. האסימונים האלה חושפים מעט מאוד מידע – רק את סוג אירוע האבטחה, מתי הוא התרחש ואת המזהה של המשתמש שהושפע – אבל אתם יכולים להשתמש בהם כדי לבצע את הפעולה המתאימה בתגובה. לדוגמה, אם חשבון Google של משתמש נפרץ, אתם יכולים להשבית זמנית את הכניסה באמצעות חשבון Google לאותו משתמש, ולמנוע שליחה של הודעות אימייל לשחזור החשבון לכתובת Gmail של המשתמש.
ההגנה על כל החשבונות מבוססת על תקן RISC, שפותח ב-OpenID Foundation.
סקירה כללית
כדי להשתמש בהגנה על כל החשבונות באפליקציה או בשירות, צריך לבצע את הפעולות הבאות:
מגדירים את הפרויקט בקונסולה לממשקי API.
יוצרים נקודת קצה לקבלת אירועים, שאליה Google תשלח אסימונים של אירועי אבטחה. נקודת הקצה הזו אחראית לאמת את האסימונים שהיא מקבלת, ואז להגיב לאירועי אבטחה בכל דרך שתבחרו.
רושמים את נקודת הקצה ב-Google כדי להתחיל לקבל אסימוני אירועי אבטחה.
דרישות מוקדמות
אתם מקבלים אסימונים של אירועי אבטחה רק עבור משתמשי Google שנתנו לשירות שלכם הרשאה לגשת לפרטי הפרופיל או לכתובות האימייל שלהם. כדי לקבל את ההרשאה הזו, צריך לבקש את ההיקפים profile או email. ערכות ה-SDK החדשות יותר של כניסה באמצעות חשבון Google או ערכות ה-SDK הקודמות של כניסה באמצעות חשבון Google מבקשות את היקפי ההרשאות האלה כברירת מחדל. עם זאת, אם אתם לא משתמשים בהגדרות ברירת המחדל או אם אתם ניגשים ישירות לנקודת הקצה של OpenID Connect של Google, ודאו שאתם מבקשים לפחות אחד מהיקפי ההרשאות האלה.
הגדרת פרויקט בקונסולה לממשקי API
כדי להתחיל לקבל אסימוני אירועי אבטחה, צריך ליצור חשבון שירות ולהפעיל את RISC API בפרויקט בקונסולה לממשקי API. אתם צריכים להשתמש באותו פרויקט ב-קונסולה לממשקי API שבו אתם משתמשים כדי לגשת לשירותי Google, כמו כניסה באמצעות חשבון Google, באפליקציה שלכם.
כדי ליצור את חשבון השירות:
פותחים את הדף Credentials במסוף ה-API. כשמוצגת בקשה, בוחרים את הפרויקט ב-קונסולה לממשקי API שמשמש לגישה לשירותי Google באפליקציה.
לוחצים על Create credentials > Service account.
יוצרים חשבון שירות חדש עם התפקיד "אדמין של הגדרות RISC" (
roles/riscconfigs.admin) לפי ההוראות האלה.(אופציונלי) אם בארגון שלכם ב-Google Cloud אפשר ליצור מפתחות לחשבונות שירות, ואתם מתכננים לחתום על אסימוני JWT באופן מקומי, צרו מפתח לחשבון השירות החדש שיצרתם. בוחרים את סוג המפתח JSON ולוחצים על Create. כשיוצרים את המפתח, מורידים קובץ JSON שמכיל את פרטי הכניסה לחשבון השירות. שומרים את הקובץ הזה במקום בטוח, אבל גם נגיש לנקודת הקצה של מקלט האירועים.
בדף Credentials של הפרויקט, שימו לב גם למזהי הלקוח שבהם אתם משתמשים לכניסה באמצעות חשבון Google או לכניסה באמצעות חשבון Google (גרסה קודמת). בדרך כלל יש מזהה לקוח לכל פלטפורמה שבה אתם תומכים. תצטרכו את מזהי הלקוחות האלה כדי לאמת אסימונים של אירועי אבטחה, כמו שמתואר בקטע הבא.
כדי להפעיל את RISC API:
פותחים את דף RISC API בקונסולה לממשקי API. מוודאים שהפרויקט שדרכו ניגשים לשירותי Google עדיין נבחר.
קוראים את התנאים של RISC ומוודאים שהדרישות מובנות.
אם אתם מפעילים את ה-API בפרויקט שבבעלות ארגון, ודאו שיש לכם הרשאה לחייב את הארגון לתנאים של RISC.
לוחצים על הפעלה רק אם מסכימים לתנאים של RISC.
יצירת נקודת קצה של מקבל אירועים
כדי לקבל מ-Google התראות לגבי אירועי אבטחה, צריך ליצור נקודת קצה מסוג HTTPS שמטפלת בבקשות HTTPS POST. אחרי שתרשמו את נקודת הקצה הזו (ראו בהמשך), Google תתחיל לפרסם בנקודת הקצה מחרוזות חתומות באופן קריפטוגרפי שנקראות אסימוני אירועי אבטחה. אסימונים של אירועי אבטחה הם אסימוני JWT חתומים שמכילים מידע על אירוע יחיד שקשור לאבטחה.
לכל אסימון של אירוע אבטחה שמתקבל בנקודת הקצה, קודם צריך לאמת ולפענח את האסימון, ואז לטפל באירוע האבטחה בהתאם לשירות שלכם. חשוב לאמת את אסימון האירוע לפני הפענוח כדי למנוע התקפות זדוניות מצד גורמים זדוניים. ��קטעים הבאים מוסבר איך לבצע את המשימות האלה:
1. פענוח ואימות של אסימון אירוע האבטחה
מכיוון שאסימוני אירועי אבטחה הם סוג ספציפי של JWT, אתם ��כולים לה��תמש ב��ל ��פ��י��ת JWT, ��מו ��לה ��מופיעות ב-jwt.io, כדי לפענח ולאמת אותם. לא משנה באיזו ספרייה אתם משתמשים, קוד אימות האסימון צריך לבצע את הפעולות הבאות:
- משיגים את מזהה המנפיק של ההגנה על כל החשבונות (
issuer) ואת ה-URI של אישור מפתח החתימה (jwks_uri) ממסמך ההגדרות של RISC ב-Google, שנמצא בכתובתhttps://accounts.google.com/.well-known/risc-configuration. - משתמשים בספריית ה-JWT לבחירתכם כדי לקבל את מזהה מפתח החתימה מהכותרת של אסימון אירוע האבטחה.
- ממסמך האישור של מפתח החתימה של Google, מקבלים את המפתח הציבורי עם מזהה המפתח שקיבלתם בשלב הקודם. אם המסמך לא מכיל מפתח עם המזהה שאתם מחפשים, סביר להניח שהאסימון של אירוע האבטחה לא תקין, ונקודת הקצה אמורה להחזיר שגיאת HTTP 400.
- באמצעות ספריית JWT לבחירתכם, מאמתים את הפרטים הבאים:
- האסימון של אירוע האבטחה נחתם באמצעות המפתח הציבורי שקיבלתם בשלב הקודם.
- הטענה
audשל האסימון היא אחד ממזהי הלקוח של האפליקציות שלכם. - הטענה
issשל האסימון תואמת למזהה המנפיק שקיבלתם ממסמך Discovery של RISC. שימו לב שאין צורך לאמת את תפוגת האסימון (exp) כי אסימוני אירועי אבטחה מייצגים אירועים היסטוריים, ולכן אין להם תפוגה.
לדוגמה:
Java
באמצעות java-jwt ו-jwks-rsa-java:
public DecodedJWT validateSecurityEventToken(String token) {
DecodedJWT jwt = null;
try {
// In a real implementation, get these values from
// https://accounts.google.com/.well-known/risc-configuration
String issuer = "accounts.google.com";
String jwksUri = "https://www.googleapis.com/oauth2/v3/certs";
// Get the ID of the key used to sign the token.
DecodedJWT unverifiedJwt = JWT.decode(token);
String keyId = unverifiedJwt.getKeyId();
// Get the public key from Google.
JwkProvider googleCerts = new UrlJwkProvider(new URL(jwksUri), null, null);
PublicKey publicKey = googleCerts.get(keyId).getPublicKey();
// Verify and decode the token.
Algorithm rsa = Algorithm.RSA256((RSAPublicKey) publicKey, null);
JWTVerifier verifier = JWT.require(rsa)
.withIssuer(issuer)
// Get your apps' client IDs from the API console:
// https://console.developers.google.com/apis/credentials?project=_
.withAudience("123456789-abcedfgh.apps.googleusercontent.com",
"123456789-ijklmnop.apps.googleusercontent.com",
"123456789-qrstuvwx.apps.googleusercontent.com")
.acceptLeeway(Long.MAX_VALUE) // Don't check for expiration.
.build();
jwt = verifier.verify(token);
} catch (JwkException e) {
// Key not found. Return HTTP 400.
} catch (InvalidClaimException e) {
} catch (JWTDecodeException exception) {
// Malformed token. Return HTTP 400.
} catch (MalformedURLException e) {
// Invalid JWKS URI.
}
return jwt;
}
Python
import json
import jwt # pip install pyjwt
import requests # pip install requests
def validate_security_token(token, client_ids):
# Get Google's RISC configuration.
risc_config_uri = 'https://accounts.google.com/.well-known/risc-configuration'
risc_config = requests.get(risc_config_uri).json()
# Get the public key used to sign the token.
google_certs = requests.get(risc_config['jwks_uri']).json()
jwt_header = jwt.get_unverified_header(token)
key_id = jwt_header['kid']
public_key = None
for key in google_certs['keys']:
if key['kid'] == key_id:
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(key))
if not public_key:
raise Exception('Public key certificate not found.')
# In this situation, return HTTP 400
# Decode the token, validating its signature, audience, and issuer.
try:
token_data = jwt.decode(token, public_key, algorithms='RS256',
options={'verify_exp': False},
audience=client_ids, issuer=risc_config['issuer'])
except:
raise
# Validation failed. Return HTTP 400.
return token_data
# Get your apps' client IDs from the API console:
# https://console.developers.google.com/apis/credentials?project=_
client_ids = ['123456789-abcedfgh.apps.googleusercontent.com',
'123456789-ijklmnop.apps.googleusercontent.com',
'123456789-qrstuvwx.apps.googleusercontent.com']
token_data = validate_security_token(token, client_ids)
אם האסימון תקין והפענוח שלו הצליח, מחזירים את סטטוס ה-HTTP 202. לאחר מכן, מטפלים באירוע האבטחה שצוין באסימון.
2. טיפול באירועי אבטחה
אחרי הפענוח, אסימון אירוע אבטחה נראה כמו בדוגמה הבאה:
{
"iss": "https://accounts.google.com/",
"aud": "123456789-abcedfgh.apps.googleusercontent.com",
"iat": 1508184845,
"jti": "756E69717565206964656E746966696572",
"events": {
"https://schemas.openid.net/secevent/risc/event-type/account-disabled": {
"subject": {
"subject_type": "iss-sub",
"iss": "https://accounts.google.com/",
"sub": "7375626A656374"
},
"reason": "hijacking"
}
}
}
ההצהרות iss ו-aud מציינות את מנפיק האסימון (Google) ואת הנמען המיועד של האסימון (השירות שלכם). אימתת את הטענות האלה בשלב הקודם.
הטענה jti היא מחרוזת שמזהה אירוע אבטחה יחיד, והיא ייחודית לסטרימינג. אתם יכולים להשתמש במזהה הזה כדי לעקוב אחרי אירועי האבטחה שקיבלתם.
התביעה events מכילה מידע על אירוע האבטחה שהאסימון מייצג. ההצהרה הזו היא מיפוי ממזהה של סוג אירוע להצהרה subject, שמציינת את המשתמש שהאירוע הזה קשור אליו, ולפרטים נוספים על האירוע שעשויים להיות זמינים.
ההצהרה subject מזהה משתמש מסוים באמצעות מזהה חשבון Google הייחודי של המשתמש (sub). מזהה חשבון Google הזה הוא אותו מזהה (sub) שכלול בטוקנים של מזהה JWT שהונפקו על ידי הספרייה החדשה יותר של 'כניסה באמצעות חשבון Google' (JavaScript, HTML), הספרייה הקודמת של כניסה באמצעות חשבון Google או OpenID Connect. כשהערך של subject_type בתביעה הוא id_token_claims, יכול להיות שהיא תכלול גם שדה email עם כתובת האימייל של המשתמש.
משתמשים במידע שבתביעה events כדי לבצע את הפעולה המתאימה לסוג האירוע בחשבון של המשתמש שצוין.
מזהי טוקן OAuth
באירועי OAuth שקשורים לטוקנים ספציפיים, סוג המזהה נושא הטוקן מכיל את השדות הבאים:
token_type: יש תמיכה רק ב-refresh_token.
token_identifier_alg: בטבלה שבהמשך מפורטים הערכים האפשריים.
token: ראו את הטבלה שבהמשך.
| token_identifier_alg | token |
|---|---|
prefix |
16 התווים הראשונים של הטוקן. |
hash_base64_sha512_sha512 |
הגיבוב הכפול של האסימון באמצעות SHA-512. |
אם אתם משלבים את האירועים האלה, מומלץ להוסיף את הטוקנים לאינדקס על סמך הערכים האפשריים האלה כדי להבטיח התאמה מהירה כשהאירוע מתקבל.
סוגי האירועים הנתמכים
ההגנה על כל החשבונות תומכת בסוגים הבאים של אירועי אבטחה:
| סוג האירוע | מאפיינים | איך להגיב |
|---|---|---|
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked |
חובה: כדי לאבטח מחדש את החשבון של המשתמש, צריך לסיים את הסשנים הפתוחים שלו. | |
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked |
חובה: אם האסימון מיועד לכניסה באמצעות חשבון Google, צריך לסיים את הסשנים הפתוחים כרגע. בנוסף, כדאי להציע למשתמש להגדיר שיטת כניסה לחשבון חלופית. הצעה: אם הטוקן מיועד לגישה לממשקי Google API אחרים, מחקו את כל טוקני ה-OAuth של המשתמש ששמרתם. |
|
https://schemas.openid.net/secevent/oauth/event-type/token-revoked |
בקטע מזהי אסימוני OAuth מפורטים מזהי האסימונים. |
חובה: אם אתם שומר��ם את טוקן הרענון התואם, מחקו אותו ובקשו מהמשתמש להביע הסכמה מחדש בפעם הבאה שיהיה צורך בטוקן גישה. |
https://schemas.openid.net/secevent/risc/event-type/account-disabled |
reason=hijacking,reason=bulk-account |
חובה: אם החשבון הושבת בגלל הצעה: אם החשבון הושבת בגלל הצעה: אם לא צוינה סיבה, משביתים את הכניסה באמצעות חשבון Google של המשתמש ומשביתים את שחזור החשבון באמצעות כתובת האימייל שמשויכת לחשבון Google של המשתמש (בדרך כלל, אבל לא בהכרח, חשבון Gmail). להציע למשתמש שיטת כניסה לחשבון חלופית. |
https://schemas.openid.net/secevent/risc/event-type/account-enabled |
הצעה: מפעילים מחדש את הכניסה באמצעות חשבון Google למשתמש, ומפעילים מחדש את שחזור החשבון באמצעות כתובת האימייל בחשבון Google של המשתמש. | |
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required |
הצעה: חפשו פעילות חשודה בשירות ונקטו פעולה מתאימה. | |
https://schemas.openid.net/secevent/risc/event-type/verification |
state=state | הצעה: רישום ביומן של קבלת טוקן לבדיקה. |
אירועים כפולים ואירועים שהוחמצו
התכונה "הגנה על כל החשבונות" תנסה לשלוח מחדש אירועים שלדעתה לא נשלחו. לכן, לפעמים יכול להיות שתקבלו את אותו אירוע כמה פעמים. אם זה עלול לגרום לפעולות חוזרות ונשנות שגורמות לאי נוחות למשתמשים, כדאי להשתמש בטענת הנכוֹנוּת (claim) של jti (שהיא מזהה ייחודי לאירוע) כדי לבטל את הכפילויות של האירועים. יש כלים חיצוניים כמו Google Cloud Dataflow שיכולים לעזור לכם להריץ את תהליך הסרת הכפילויות.
חשוב לזכור שהאירועים נשלחים עם מספר מוגבל של ניסיונות חוזרים, כך שאם המקלט מושבת לפרק זמן ממושך, יכול להיות שתפספסו חלק מהאירועים באופן סופי.
רישום המקלט
כדי להתחיל לקבל אירועי אבטחה, צריך לרשום את נקודת הקצה של המקבל באמצעות RISC API. קריאות ל-RISC API חייבות לכלול אסימון הרשאה.
תקבלו אירועי אבטחה רק למשתמשים באפליקציה שלכם, לכן אתם צריכים להגדיר מסך הסכמה של OAuth בפרויקט שלכם ב-GCP כתנאי מוקדם לשלבים שמתוארים בהמשך.
1. יצירת אסימון הרשאה
כדי ליצור אסימון הרשאה ל-RISC API, אתם יכולים להשתמש ב-Google Cloud CLI (gcloud) עם התחזות לחשבון שירות (מומלץ כשנאכפת המדיניות iam.disableServiceAccountKeyCreation או להגדרה חד-פעמית של CLI), או לחתום על JWT באופן מקומי באמצעות מפתח פרטי של חשבון שירות.
אפשרות א': יצירת אסימון גישה לטווח קצר באמצעות gcloud (לא נדרש מפתח JSON)
אם לחשבון המשתמש שלכם יש את התפקיד "יצירת אסימונים בחשבון שירות" (roles/iam.serviceAccountTokenCreator) בחשבון השירות, אתם יכולים להנפיק אסימון גישה לטווח קצר מסוג OAuth 2.0 עם היקף ההרשאות הנדרש להגדרת RISC ישירות מהמסוף:
AUTH_TOKEN=$(gcloud auth print-access-token \
--impersonate-service-account=SERVICE_ACCOUNT_EMAIL \
--scopes=https://www.googleapis.com/auth/risc.configuration.readwrite,https://www.googleapis.com/auth/risc.verify,https://www.googleapis.com/auth/risc.status.readwrite)
בקטע היקפי ההרשאות של טוקני גישה מפורטים היקפי ההרשאות של OAuth 2.0 שזמינים ל-RISC API.
אפשרות ב': יצירת JWT בחתימה עצמית באמצעות מפתח של חשבון שירות
לחלופין, כדי ליצור אסימון הרשאה באופן מקומי בלי הלוך ושוב ברשת, צריך ליצור JWT עם ההצהרות הבאות:
{
"iss": SERVICE_ACCOUNT_EMAIL,
"sub": SERVICE_ACCOUNT_EMAIL,
"aud": "https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService",
"iat": CURRENT_TIME,
"exp": CURRENT_TIME + 3600
}חותמים על ה-JWT באמצעות המפתח הפרטי של חשבון השירות, שנמצא בקובץ ה-JSON שהורדתם כשיצרתם את המפתח של חשבון השירות.
לדוגמה:
Java
שימוש ב-java-jwt ובספריית האימות של Google:
public static String makeBearerToken() {
String token = null;
try {
// Get signing key and client email address.
FileInputStream is = new FileInputStream("your-service-account-credentials.json");
ServiceAccountCredentials credentials =
(ServiceAccountCredentials) GoogleCredentials.fromStream(is);
PrivateKey privateKey = credentials.getPrivateKey();
String keyId = credentials.getPrivateKeyId();
String clientEmail = credentials.getClientEmail();
// Token must expire in exactly one hour.
Date issuedAt = new Date();
Date expiresAt = new Date(issuedAt.getTime() + 3600000);
// Create signed token.
Algorithm rsaKey = Algorithm.RSA256(null, (RSAPrivateKey) privateKey);
token = JWT.create()
.withIssuer(clientEmail)
.withSubject(clientEmail)
.withAudience("https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService")
.withIssuedAt(issuedAt)
.withExpiresAt(expiresAt)
.withKeyId(keyId)
.sign(rsaKey);
} catch (ClassCastException e) {
// Credentials file doesn't contain a service account key.
} catch (IOException e) {
// Credentials file couldn't be loaded.
}
return token;
}
Python
import json
import time
import jwt # pip install pyjwt
def make_bearer_token(credentials_file):
with open(credentials_file) as service_json:
service_account = json.load(service_json)
issuer = service_account['client_email']
subject = service_account['client_email']
private_key_id = service_account['private_key_id']
private_key = service_account['private_key']
issued_at = int(time.time())
expires_at = issued_at + 3600
payload = {'iss': issuer,
'sub': subject,
'aud': 'https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService',
'iat': issued_at,
'exp': expires_at}
encoded = jwt.encode(payload, private_key, algorithm='RS256',
headers={'kid': private_key_id})
return encoded
auth_token = make_bearer_token('your-service-account-credentials.json')
אפשר להשתמש באסימון ההרשאה הזה כדי לבצע קריאות ל-RISC API במשך שעה. כשתוקף האסימון יפוג, תצטרכו ליצור אסימון חדש כדי להמשיך לבצע קריאות ל-RISC API.
2. שליחת קריאה ל-API להגדרת הסטרימינג של RISC
עכשיו, כשיש לכם אסימון הרשאה, אתם יכולים להשתמש ב-RISC API כדי להגדיר את זרם אירועי האבטחה של הפרויקט, כולל רישום נקודת הקצה (endpoint) של המקבל.
כדי לעשות את זה, שולחים בקשת HTTPS POST אל https://risc.googleapis.com/v1beta/stream:update, ומציינים את נקודת הקצה של המקבל ואת סוגי אירועי האבטחה שמעניינים אתכם:
POST /v1beta/stream:update HTTP/1.1
Host: risc.googleapis.com
Authorization: Bearer AUTH_TOKEN
{
"delivery": {
"delivery_method":
"https://schemas.openid.net/secevent/risc/delivery-method/push",
"url": RECEIVER_ENDPOINT
},
"events_requested": [
SECURITY_EVENT_TYPES
]
}
לדוגמה:
Java
public static void configureEventStream(final String receiverEndpoint,
final List<String> eventsRequested,
String authToken) throws IOException {
ObjectMapper jsonMapper = new ObjectMapper();
String streamConfig = jsonMapper.writeValueAsString(new Object() {
public Object delivery = new Object() {
public String delivery_method =
"https://schemas.openid.net/secevent/risc/delivery-method/push";
public String url = receiverEndpoint;
};
public List<String> events_requested = eventsRequested;
});
HttpPost updateRequest = new HttpPost("https://risc.googleapis.com/v1beta/stream:update");
updateRequest.addHeader("Content-Type", "application/json");
updateRequest.addHeader("Authorization", "Bearer " + authToken);
updateRequest.setEntity(new StringEntity(streamConfig));
HttpResponse updateResponse = new DefaultHttpClient().execute(updateRequest);
Header[] responseContentTypeHeaders = updateResponse.getHeaders("Content-Type");
StatusLine responseStatus = updateResponse.getStatusLine();
int statusCode = responseStatus.getStatusCode();
HttpEntity entity = updateResponse.getEntity();
// Now handle response
}
// ...
configureEventStream(
"https://your-service.example.com/security-event-receiver",
Arrays.asList(
"https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required",
"https://schemas.openid.net/secevent/risc/event-type/account-disabled"),
authToken);
Python
import requests
def configure_event_stream(auth_token, receiver_endpoint, events_requested):
stream_update_endpoint = 'https://risc.googleapis.com/v1beta/stream:update'
headers = {'Authorization': 'Bearer {}'.format(auth_token)}
stream_cfg = {'delivery': {'delivery_method': 'https://schemas.openid.net/secevent/risc/delivery-method/push',
'url': receiver_endpoint},
'events_requested': events_requested}
response = requests.post(stream_update_endpoint, json=stream_cfg, headers=headers)
response.raise_for_status() # Raise exception for unsuccessful requests
configure_event_stream(auth_token, 'https://your-service.example.com/security-event-receiver',
['https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required',
'https://schemas.openid.net/secevent/risc/event-type/account-disabled'])
אם הבקשה מחזירה את קוד הסטטוס HTTP 200, זרם האירועים הוגדר בהצלחה ונקודת הקצה של המקבל אמורה להתחיל לקבל א��ימונים של אירועי אבטחה. בקטע הבא מוסבר איך לבדוק את הגדרת הסטרימינג ונקודת הקצה כדי לוודא שהכול פועל כמו שצריך.
קבלת הגדרות השידור הנוכחיות ועדכון שלהן
אם בעתיד תרצו לשנות את הגדרות הסטרימינג, תוכלו לשלוח בקשת GET מורשית אל https://risc.googleapis.com/v1beta/stream כדי לקבל את הגדרות הסטרימינג הנוכחיות, לשנות את גוף התגובה ואז לשלוח בקשת POST עם ההגדרות ששונו בחזרה אל https://risc.googleapis.com/v1beta/stream:update, כמו שמתואר למעלה.
עצירה והמשך של זרם האירועים
אם תצטרכו להפסיק את זרם האירועים מ-Google, שלחו בקשת POST מורשית אל https://risc.googleapis.com/v1beta/stream/status:update עם { "status": "disabled" } בגוף הבקשה. כשהסטרימינג מושבת, Google לא שולחת אירועים לנקודת הקצה ולא שומרת אירועי אבטחה במאגר נתונים זמני כשהם מתרחשים. כדי להפעיל מחדש את זרם האירועים, שולחים בקשת POST { "status": "enabled" } לאותה נקודת קצה.
3. אופציונלי: בדיקת הגדרות השידור
כדי לוודא שהגדרת הסטרימינג ונקודת הקצה של המקבל פועלות יחד בצורה תקינה, אתם יכולים לשלוח אסימון אימות דרך סטרימינג האירועים. האסימון הזה יכול להכיל מחרוזת ייחודית שבאמצעותה אפשר לוודא שהאסימון התקבל בנקודת הקצה. כדי להשתמש בתהליך הזה, הקפידו להירשם לסוג האירוע https://schemas.openid.net/secevent/risc/event-type/verification כשאתם רושמים את המקבל.
כדי לבקש אסימון אימות, שולחים בקשת HTTPS POST מורשית אל https://risc.googleapis.com/v1beta/stream:verify. בגוף הבקשה, מציינים מחרוזת מזהה כלשהי:
{
"state": "ANYTHING"
}
לדוגמה:
Java
public static void testEventStream(final String stateString,
String authToken) throws IOException {
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(new Object() {
public String state = stateString;
});
HttpPost updateRequest = new HttpPost("https://risc.googleapis.com/v1beta/stream:verify");
updateRequest.addHeader("Content-Type", "application/json");
updateRequest.addHeader("Authorization", "Bearer " + authToken);
updateRequest.setEntity(new StringEntity(json));
HttpResponse updateResponse = new DefaultHttpClient().execute(updateRequest);
Header[] responseContentTypeHeaders = updateResponse.getHeaders("Content-Type");
StatusLine responseStatus = updateResponse.getStatusLine();
int statusCode = responseStatus.getStatusCode();
HttpEntity entity = updateResponse.getEntity();
// Now handle response
}
// ...
testEventStream("Test token requested at " + new Date().toString(), authToken);
Python
import requests
import time
def test_event_stream(auth_token, nonce):
stream_verify_endpoint = 'https://risc.googleapis.com/v1beta/stream:verify'
headers = {'Authorization': 'Bearer {}'.format(auth_token)}
state = {'state': nonce}
response = requests.post(stream_verify_endpoint, json=state, headers=headers)
response.raise_for_status() # Raise exception for unsuccessful requests
test_event_stream(auth_token, 'Test token requested at {}'.format(time.ctime()))
אם הבקשה תצליח, טוקן האימות יישלח לנקודת הקצה (endpoint) שרשמתם. לאחר מכן, לדוגמה, אם נקודת הקצה מטפלת באסימוני אימות על ידי רישום שלהם ביומן, תוכלו לבדוק את היומנים כדי לוודא שהאסימון התקבל.
הפניה לקוד השגיאה
אלה השגיאות ש-RISC API יכול להחזיר:
| קוד שגיאה | הודעת שגיאה | הצעות לפעולות |
|---|---|---|
| 400 | הגדרת הסטרימינג חייבת להכיל את השדה $fieldname. | הבקשה שלכם לנקודת הקצה https://risc.googleapis.com/v1beta/stream:update לא תקינה או שלא ניתן לנתח אותה. צריך לכלול את $fieldname בבקשה. |
| 401 | לא מורשה. | ההרשאה נכשלה. חשוב לוודא שצירפתם לבקשה אסימון הרשאה, ושהאסימון תקין ובתוקף. |
| 403 | נקודת הקצה למסירה חייבת להיות כתובת URL מסוג HTTPS. | נקודת הקצה (endpoint) למסירה (כלומר נקודת הקצה שאליה אתם מצפים שאירועי RISC יימסרו) חייבת להיות מסוג HTTPS. אנחנו לא שולחים אירועי RISC לכתובות URL מסוג HTTP. |
| 403 | בהגדרת הסטרימינג הקיימת אין שיטת העברה שתואמת למפרט של RISC. | בפרויקט בענן של Google Cloud כבר צריכה להיות הגדרת RISC. אם אתם משתמשים ב-Firebase והפעלתם את כניסה באמצעות חשבון Google, Firebase תנהל את RISC בפרויקט שלכם ולא תוכלו ליצור הגדרה מותאמת אישית. אם לא משתמשים בכניסה באמצעות חשבון Google בפרויקט Firebase, צריך להשבית אותה ולנסות לעדכן שוב אחרי שעה. |
| 403 | הפרויקט לא נמצא. | חשוב לוודא שאתם משתמשים בחשבון השירות הנכון לפרויקט הנכון. יכול להיות שאתם משתמשים בחשבון שירות שמשויך לפרויקט שנמחק. איך רואים את כל חשבונות השירות שמשויכים לפרויקט |
| 403 | לחשבון השירות נדרשת הרשאה כדי לגשת להגדרות ה-RISC שלך | נכנסים ל-API Console של הפרויקט ומקצים את התפקיד "אדמין של הגדרות RISC" (roles/riscconfigs.admin) לחשבון השירות שמבצע את הקריאות לפרויקט, לפי ההוראות האלה.
|
| 403 | רק חשבון שירות יכול לקרוא לממשקי API לניהול סטרימינג. | איך שולחים קריאות ל-Google APIs באמצעות חשבון שירות |
| 403 | נקודת הקצה למסירה לא שייכת לאף אחד מהדומיינים של הפרויקט. | לכל פרויקט יש קבוצה של דומיינים מורשים. אם נקודת הקצה למסירה (כלומר, נקודת הקצה שאליה אתם מצפים שאירועי RISC יימסרו) לא מתארחת באחד מהם, אתם צריכים להוסיף את הדומיין של נקודת הקצה לקבוצה הזו. |
| 403 | כדי להשתמש ב-API הזה, צריך להגדיר בפרויקט לפחות לקוח OAuth אחד. | RISC פועל רק אם מפתחים אפליקציה שתומכת בכניסה באמצעות חשבון Google. כדי להשתמש בחיבור הזה, צריך לקוח OAuth. אם בפרויקט אין לקוחות OAuth, סביר להניח ש-RISC לא יועיל לכם. מידע נוסף על השימוש של Google ב-OAuth בממשקי ה-API שלנו |
| 403 |
סטטוס לא נתמך. סטטוס לא חוקי. |
בשלב הזה אנחנו תומכים רק בסטטוסים "enabled" ו-"disabled" של שידורים. |
| 404 |
לפרויקט אין הגדרת RISC. בפרויקט אין הגדרת RISC קיימת, אי אפשר לעדכן את הסטטוס. |
קוראים לנקודת הקצה https://risc.googleapis.com/v1beta/stream:update כדי ליצור הגדרת סטרימינג חדשה. |
| 4XX/5XX | לא ניתן לעדכן את הסטטוס. | כדי לקבל מידע נוסף, אפשר לעיין בהודעת השגיאה המפורטת. |
היקפי ההרשאות של טוקן הגישה
אם אתם מחליטים להשתמש בטוקני גישה לאימות ב-RISC API, אלה היקפי ההרשאות שהאפליקציה שלכם צריכה לבקש:
| נקודת קצה (endpoint) | היקף |
|---|---|
https://risc.googleapis.com/v1beta/stream/status |
https://www.googleapis.com/auth/risc.status.readonly
או https://www.googleapis.com/auth/risc.status.readwrite |
https://risc.googleapis.com/v1beta/stream/status:update |
https://www.googleapis.com/auth/risc.status.readwrite |
https://risc.googleapis.com/v1beta/stream |
https://www.googleapis.com/auth/risc.configuration.readonly
או https://www.googleapis.com/auth/risc.configuration.readwrite
|
https://risc.googleapis.com/v1beta/stream:update |
https://www.googleapis.com/auth/risc.configuration.readwrite |
https://risc.googleapis.com/v1beta/stream:verify |
https://www.googleapis.com/auth/risc.verify |
דרושה לך עזרה?
קודם כל, כדאי לעיין בקטע הפניה לקוד השגיאה. אם עדיין יש לכם שאלות, אתם יכולים לפרסם אותן ב-Stack Overflow עם התג #SecEvents.