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

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

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

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

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

סקירה כללית

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

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

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

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

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

מקבלים אסימונים של פעולות אבטחה רק למשתמשי Google שאישרו את הרשאה לשירות לגשת לפרטי הפרופיל או לכתובות האימייל שלהם. שלך כדי לקבל את ההרשאה הזו, צריך לשלוח בקשה להיקפי ההרשאות profile או email. הגרסה החדשה יותר כניסה באמצעות חשבון Google או מדור קודם כברירת מחדל, ערכות SDK עם כניסה באמצעות חשבון Google מבקשים את ההיקפים האלה, אבל אם לא משתמשים בהגדרות ברירת המחדל, או אם אתם ניגשים ל-OpenID של 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 ואז לוחצים על יצירה. כשהמפתח נוצר, תתבצע הורדה של קובץ JSON שמכיל את חשבון השירות שלך פרטי הכניסה. יש לשמור את הקובץ הזה במקום בטוח, אבל גם לגשת אליו נקודת הקצה של מקלט האירוע.

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

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

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

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

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

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

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

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

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

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