הגנה על חשבונות משתמשים באמצעות הגנה על כל החשבונות

אם האפליקציה מאפשרת למשתמשים להיכנס לחשבונות שלהם באמצעות Google, אתם יכולים לשפר את האבטחה של החשבונות המשותפים האלה על ידי מעקב אחרי התראות על אירועי אבטחה שמתקבלות משירות ההגנה על כל החשבונות, ופעולה בהתאם.

ההתראות האלה מודיעות לכם על שינויים משמעותיים בחשבונות Google של המשתמשים שלכם, שיכולים להיות להם השלכות על האבטחה של החשבונות שלהם באפליקציה שלכם. לדוגמה, אם חשבון Google של משתמש נפרץ, זה עלול להוביל לפריצה של החשבון של המשתמש באפליקציה שלכם באמצעות שחזור חשבון אימייל או שימוש בכניסה יחידה.

כדי לעזור לכם לצמצם את הסיכון הפוטנציאלי של אירועים כאלה, Google שולחת אובייקטים של שירות שנקראים טוקנים של אירועי אבטחה. האסימונים האלה חושפים מעט מאוד מידע – רק את סוג אירוע האבטחה, מתי הוא התרחש ומזהה המשתמש שהושפע – אבל אפשר להשתמש בהם כדי לבצע פעולה מתאימה בתגובה. לדוגמה, אם חשבון Google של משתמש נפרץ, תוכלו להשבית באופן זמני את האפשרות'כניסה באמצעות חשבון Google' עבור המשתמש הזה ולמנוע שליחה של אימיילים לשחזור החשבון לכתובת Gmail של המשתמש.

ההגנה על כל החשבונות מבוססת על תקן RISC, שפותח ב-OpenID Foundation.

סקירה כללית

כדי להשתמש ב'הגנה על כל החשבונות' באפליקציה או בשירות, צריך להשלים את המשימות הבאות:

  1. מגדירים את הפרויקט ב API Console.

  2. יוצרים נקודת קצה לקבלת אירועים, שאליה Google תשלח טוקנים של אירועי אבטחה. נקודת הקצה הזו אחראית לאימות האסימונים שהיא מקבלת, ואז למענה לאירועי אבטחה בכל דרך שתבחרו.

  3. כדי להתחיל לקבל טוקנים של אירועי אבטחה, צריך לרשום את נקודת הקצה ב-Google.

דרישות מוקדמות

אתם מקבלים אסימוני אירועי אבטחה רק עבור משתמשי Google שהעניקו לשירות שלכם הרשאה לגשת לפרטי הפרופיל או לכתובות האימייל שלהם. כדי לקבל את ההרשאה הזו, צריך לבקש את היקפי ההרשאות profile או email. ערכות ה-SDK החדשות יותר של Sign In With Google או ערכות ה-SDK מדור קודם של Google Sign-in מבקשות את ההיקפים האלה כברירת מחדל, אבל אם אתם לא משתמשים בהגדרות ברירת המחדל, או אם אתם ניגשים ישירות לנקודת הקצה של Google OpenID Connect, אתם צריכים לוודא שאתם מבקשים לפחות אחד מההיקפים האלה.

הגדרת פרויקט ב- API Console

כדי להתחיל לקבל אסימונים של אירועי אבטחה, צריך ליצור חשבון שירות ולהפעיל את RISC API בAPI Console פרויקט. אתם צריכים להשתמש באותוAPI Console פרויקט שבו אתם משתמשים כדי לגשת לשירותי Google, כמו כניסה לחשבון Google, באפליקציה שלכם.

כדי ליצור את חשבון השירות:

  1. פותחים את API Console Credentials page. כשמוצגת בקשה, בוחרים את הפרויקט שמשמש לגישה לשירותי Google באפליקציה.API Console

  2. לוחצים על Create credentials > Service account (יצירת פרטי כניסה > חשבון שירות).

  3. יוצרים חשבון שירות חדש עם התפקיד 'אדמין של הגדרות RISC' (roles/riscconfigs.admin) לפי ההוראות האלה.

  4. יוצרים מפתח לחשבון השירות החדש. בוחרים את סוג מפתח ה-JSON ולוחצים על Create. כשיוצרים את המפתח, מורידים קובץ JSON שמכיל את פרטי הכניסה של חשבון השירות. חשוב לשמור את הקובץ הזה במקום בטוח, אבל גם במקום שנקודת הקצה של מקבל האירועים תוכל לגשת אליו.

בזמן שאתם בדף Credentials (פרטי כניסה) של הפרויקט, כדאי גם לשים לב למזהי הלקוח שבהם אתם משתמשים לכניסה באמצעות חשבון Google או לכניסה לחשבון Google (גרסה קודמת). בדרך כלל, יש לכם מזהה לקוח לכל פלטפורמה שאתם תומכים בה. תצטרכו את מזהי הלקוח האלה כדי לאמת אסימונים של אירועי אבטחה, כפי שמתואר בקטע הבא.

כדי להפעיל את RISC API:

  1. פותחים את הדף של RISC API ב-API Console. מוודאים שהפרויקט שדרכו אתם ניגשים לשירותי Google עדיין מסומן.

  2. קוראים את התנאים של RISC ומוודאים שאתם מבינים את הדרישות.

    אם אתם מפעילים את ה-API בפרויקט שבבעלות ארגון, אתם צריכים לוודא שיש לכם הרשאה לקשר את הארגון לתנאים של RISC.

  3. לוחצים על הפעלה רק אם מסכימים לתנאי השימוש של RISC.

יצירה של נקודת קצה לקבלת אירועים

כדי לקבל מ-Google התראות על אירועי אבטחה, צריך ליצור נקודת קצה (endpoint) של HTTPS שמטפלת בבקשות HTTPS POST. אחרי שתרשמו את נקודת הקצה הזו (כפי שמתואר בהמשך), Google תתחיל לפרסם בנקודת הקצה מחרוזות חתומות קריפטוגרפית שנקראות טוקנים של אירועי אבטחה. אסימוני אירועי אבטחה הם JWT חתומים שמכילים מידע על אירוע יחיד שקשור לאבטחה.

לכל אסימון של אירוע אבטחה שמתקבל בנקודת הקצה, צריך קודם לאמת ולפענח את האסימון, ואז לטפל באירוע האבטחה בהתאם לשירות. חשוב מאוד לאמת את טוקן האירוע לפני שמפענחים אותו, כדי למנוע מתקפות זדוניות מצד גורמים עם כוונות רעות. בקטעים הבאים מפורטות הפעולות האלה:

1. פענוח של אסימון אירוע האבטחה ואימות שלו

אסימוני אירועי אבטחה הם סוג ספציפי של JWT, ולכן אפשר להשתמש בכל ספריית JWT, כמו אחת מהספריות שמופיעות ב-jwt.io, כדי לפענח ולאמת אותם. לא משנה באיזו ספריה משתמשים, קוד אימות האסימון צריך לבצע את הפעולות הבאות:

  1. מקבלים את מזהה מנפיק ההגנה על חשבונות (issuer) ואת ה-URI של אישור מפתח החתימה (jwks_uri) ממסמך ההגדרה של RISC של Google, שאפשר למצוא בכתובת https://accounts.google.com/.well-known/risc-configuration.
  2. באמצעות ספריית ה-JWT שתבחרו, מקבלים את מזהה מפתח החתימה מהכותרת של אסימון אירוע האבטחה.
  3. ממסמך האישור של מפתח החתימה של Google, מקבלים את המפתח הציבורי עם מזהה המפתח שקיבלתם בשלב הקודם. אם המסמך לא מכיל מפתח עם המזהה שאתם מחפשים, סביר להניח שאסימון אירוע האבטחה לא תקין, ונקודת הקצה (endpoint) צריכה להחזיר שגיאת HTTP 400.
  4. באמצעות ספריית JWT לבחירתכם, מאמתים את הפרטים הבאים:
    • אסימון אירוע האבטחה חתום באמצעות המפתח הציבורי שקיבלתם בשלב הקודם.
    • התלונה aud על האסימון היא אחד ממזהי הלקוח של האפליקציות שלכם.
    • ההצהרה iss של האסימון תואמת למזהה המנפיק שקיבלתם ממסמך הגילוי של 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 subject מכיל את השדות הבאים:

  • 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

חובה: אם החשבון הושבת בגלל hijacking, צריך לאבטח מחדש את החשבון של המשתמש על ידי סגירת הסשנים הפתוחים שלו.

הצעה: אם החשבון הושבת בגלל 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 הצעה: רישום בקובץ היומן של קבלת טוקן לבדיקה.

אירועים משוכפלים ואירועים שהוחמצו

ההגנה על כל החשבונות תנסה לשלוח מחדש אירועים שלדעתה לא נשלחו. לכן, יכול להיות שלפעמים תקבלו את אותו אירוע כמה פעמים. אם זה עלול לגרום לפעולות חוזרות שיוצרות אי נוחות למשתמשים, כדאי להשתמש בטענה jti (שהיא מזהה ייחודי לאירוע) כדי לבטל את הכפילות של האירועים. יש כלים חיצוניים כמו Google Cloud Dataflow שיכולים לעזור לכם להריץ את תהליך העבודה של ביטול הכפילויות.

שימו לב: המערכת מנסה לשלוח אירועים מספר מוגבל של פעמים, ולכן אם השרת שלכם מושבת לתקופה ארוכה, יכול להיות שתפספסו חלק מהאירועים באופן סופי.

רישום המקלט

כדי להתחיל לקבל אירועי אבטחה, צריך לרשום את נקודת הקצה של המקלט באמצעות RISC API. לקריאות ל-RISC API צריך לצרף אסימון הרשאה.

תקבלו אירועי אבטחה רק לגבי המשתמשים באפליקציה שלכם, ולכן צריך להגדיר מסך הסכמה של OAuth בפרויקט שלכם ב-GCP כתנאי מוקדם לביצוע השלבים שמתוארים בהמשך.

1. יצירת טוקן הרשאה

כדי ליצור אסימון הרשאה ל-RISC API, צריך ליצור 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 כדי להגדיר את זרם אירועי האבטחה של הפרויקט, כולל רישום נקודת הקצה של המקלט.

כדי לעשות זאת, שולחים בקשת 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 כדי לקבל את הגדרות הסטרימינג הנוכחיות, שינוי גוף התגובה ואז שליחת ההגדרות ששונו בחזרה אל https://risc.googleapis.com/v1beta/stream:update באמצעות בקשת POST, כמו שמתואר למעלה.

עצירה והפעלה מחדש של הסטרימינג של האירוע

אם תצטרכו להפסיק את זרם האירועים מ-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()))

אם הבקשה תצליח, אסימון האימות יישלח לנקודת הקצה שרשמתם. לדוגמה, אם נקודת הקצה מטפלת באסימוני אימות על ידי רישום שלהם ביומן, אפשר לבדוק את היומנים כדי לוודא שהאסימון התקבל.

הפניה לקוד השגיאה

השגיאות הבאות יכולות להיות מוחזרות על ידי RISC API:

קוד שגיאה הודעת השגיאה הצעות לפעולות
400 הגדרת הזרם חייבת להכיל את השדה $fieldname. הבקשה שלך לנקודת הקצה https://risc.googleapis.com/v1beta/stream:update לא תקינה או שלא ניתן לנתח אותה. עליך לכלול את $fieldname בבקשה.
401 לא מורשה. ההרשאה נכשלה. חשוב לוודא שצירפתם טוקן הרשאה לבקשה, שהטוקן תקף ושלא פג התוקף שלו.
403 נקודת הקצה של המסירה חייבת להיות כתובת URL מסוג HTTPS. נקודת המסירה (כלומר, נקודת הקצה שאליה אתם מצפים שאירועי 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 לניהול הזרם רק באמצעות חשבון שירות. מידע נוסף על קריאה לממשקי API של Google באמצעות חשבון שירות
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.