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

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

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

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

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

סקירה כללית

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

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

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

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

ידע מוקדם שנדרש לקורס

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

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

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

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

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

  2. לוחצים על Create credentials > חשבון שירות.

  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.

יצירת נקודת קצה (endpoint) של מקבל האירועים

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

  • token_identifier_alg: הערכים האפשריים מפורטים בטבלה הבאה.

  • token: פרטים נוספים מפורטים בטבלה שבהמשך.

token_identifier_alg אסימון
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. להפעיל את RISC Stream configuration API

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

קבלה ועדכון של הגדרת השידור הנוכחית

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

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

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

ממשק 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 Configuration Admin' (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.