הדרכה בנושא אימות משתמשי קצה ב-Cloud Run

במדריך הזה מוסבר איך ליצור שירות הצבעה שכולל את הרכיבים הבאים:

  • לקוח מבוסס-דפדפן שמבצע את הפעולות הבאות:

    1. משתמש ב-Identity Platform כדי לאחזר אסימון מזהה.
    2. המשתמשים יכולים להצביע לחיית המחמד המועדפת עליהם.
    3. האסימון המזהה הזה מתווסף לבקשה לשרת Cloud Run שמטפל בהצבעה.
  • שרת Cloud Run שמבצע את הפעולות הבאות:

    1. הבדיקה מוודאת שהמשתמש הקצה עבר אימות בצורה תקינה על ידי אספקת אסימון מזהה תקף.
    2. מעבד את ההצבעה של משתמש הקצה.
    3. האפליקציה שולחת את ההצבעה ל-Cloud SQL כדי לאחסן אותה, באמצעות פרטי הכניסה שלה.
  • מסד נתונים של PostgreSQL שבו נשמרים הקולות.

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

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

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

השירות הזה מצמצם את הסיכונים לאבטחה באמצעות Secret Manager כדי להגן על מידע אישי רגיש שמשמש לחיבור למופע Cloud SQL. הוא גם משתמש בזהות שירות עם הרשאות מינימליות כדי לאבטח את הגישה למסד הנתונים.

מטרות

כתיבה, בנייה ופריסה של שירות ב-Cloud Run שמראה איך:

  • משתמשים ב-Identity Platform כדי לאמת משתמש קצה ב-backend של שירות Cloud Run.

  • יוצרים זהות עם הרשאות מינימליות לשירות כדי להעניק גישה מינימלית למשאבים. Google Cloud

  • משתמשים ב-Secret Manager כדי לטפל בנתונים רגישים כשמחברים את שירות Cloud Run למסד נתונים של PostgreSQL.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

לפני שמתחילים

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. מפעילים את ממשקי ה-API של Cloud Run,‏ Secret Manager,‏ Cloud SQL,‏ Artifact Registry ו-Cloud Build.

    תפקידים שנדרשים להפעלת ממשקי API

    כדי להפעיל ממשקי API, צריך את תפקיד ה-IAM 'אדמין של Service Usage' (roles/serviceusage.serviceUsageAdmin), שכולל את ההרשאה serviceusage.services.enable. איך מקצים תפקידים

    הפעלת ממשקי ה-API

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות להשלמת המדריך, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט:

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

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

הגדרת ברירות מחדל ב-CLI של gcloud

כדי להגדיר את Google Cloud CLI עם ערכי ברירת מחדל לשירות Cloud Run:

  1. מגדירים את פרויקט ברירת המחדל:

    gcloud config set project PROJECT_ID

    מחליפים את PROJECT_ID בשם הפרויקט שיצרתם לצורך המדריך הזה.

  2. מגדירים את Google Cloud CLI לאזור שבחרתם:

    gcloud config set run/region REGION

    מחליפים את REGION באזור נתמך ב-Cloud Run לבחירתכם.

מיקומים של Cloud Run

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

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

‫Cloud Run זמין באזורים הבאים:

בכפוף לתמחור ברמה 1

בכפוף לתמחור ברמה 2

  • africa-south1 (יוהנסבורג)
  • asia-east2 (הונג קונג)
  • asia-northeast3 (סיאול, קוריאה הדרומית)
  • asia-southeast1 (סינגפור)
  • asia-southeast2 (ג'אקארטה)
  • asia-south2 (דלהי, הודו)
  • australia-southeast1 (סידני)
  • australia-southeast2 (מלבורן)
  • europe-central2 (ורשה, פולין)
  • europe-west10 (Berlin)
  • europe-west12 (טורינו)
  • europe-west2 (לונדון, בריטניה) סמל של עלה רמה נמוכה של CO2
  • europe-west3 (פרנקפורט, גרמניה)
  • europe-west6 (ציריך, שווייץ) סמל של עלה רמה נמוכה של CO2
  • me-central1 (דוחה)
  • me-central2 (דמאם)
  • northamerica-northeast1 (מונטריאול) סמל של עלה רמה נמוכה של CO2
  • northamerica-northeast2 (טורונטו) סמל של עלה רמה נמוכה של CO2
  • southamerica-east1 (סאו פאולו, ברזיל) סמל של עלה רמה נמוכה של CO2
  • southamerica-west1 (סנטיאגו, צ'ילה) סמל של עלה רמה נמוכה של CO2
  • us-west2 (לוס אנג'לס)
  • us-west3 (סולט לייק סיטי)
  • us-west4 (לאס וגאס)

אם כבר יצרתם שירות Cloud Run, תוכלו לראות את האזור בלוח הבקרה של Cloud Run בGoogle Cloud מסוף.

אחזור של דוגמת הקוד

כדי לאחזר את דוגמת קוד לשימוש:

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

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    אפשרות נוספת היא להוריד את הדוגמה כקובץ ZIP ולחלץ אותה.

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    אפשרות נוספת היא להוריד את הדוגמה כקובץ ZIP ולחלץ אותה.

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    אפשרות נוספת היא להוריד את הדוגמה כקובץ ZIP ולחלץ אותה.

  2. עוברים לספרייה שמכילה את הקוד לדוגמה של Cloud Run:

    Node.js

    cd nodejs-docs-samples/run/idp-sql/

    Python

    cd python-docs-samples/run/idp-sql/

    Java

    cd java-docs-samples/run/idp-sql/

הדמיה של הארכיטקטורה

תהליך הכניסה של משתמש הקצה.
הדיאגרמה מציגה משתמש קצה שנכנס דרך תיבת דו-שיח לכניסה באמצעות חשבון Google שסופקה על ידי Identity Platform, ואז מופנה חזרה אל Cloud Run עם הזהות של המשתמש.
  1. משתמש קצה שולח את הבקשה הראשונה לשרת Cloud Run.

  2. הלקוח נטען בדפדפן.

  3. המשתמש מספק פרטי כניסה דרך תיבת הדו-שיח של הכניסה לחשבון Google מ-Identity Platform. המשתמש שמחובר לחשבון מקבל התראה.

  4. השליטה מועברת חזרה לשרת. משתמש הקצה מצביע באמצעות הלקוח, ששולף אסימון מזהה מ-Identity Platform ומוסיף אותו לכותרת של בקשת ההצבעה.

  5. כשהשרת מקבל את הבקשה, הוא מאמת את טוקן ה-ID של Identity Platform כדי לוודא שמשתמש הקצה אומת בצורה מתאימה. לאחר מכן השרת שולח את ההצבעה ל-Cloud SQL באמצעות פרטי הכניסה שלו.

הסבר על קוד הליבה

הדוגמה מיושמת כלקוח ולשרת, כפי שמתואר בהמשך.

שילוב עם Identity Platform: קוד בצד הלקוח

בדוגמה הזו נעשה שימוש ב-Firebase SDKs כדי לבצע שילוב עם Identity Platform לצורך כניסה וניהול של משתמשים. כדי להתחבר אל Identity Platform, קובץ ה-JavaScript בצד הלקוח מכיל את ההפניה לפרטי הכניסה של הפרויקט כאובייקט הגדרה ומייבא את ערכות Firebase JavaScript SDK הנדרשות:

const config = {
  apiKey: 'API_KEY',
  authDomain: 'PROJECT_ID.firebaseapp.com',
};
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-app.js"></script>
<!-- Add Firebase Auth service-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-auth.js"></script>

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

function signIn() {
  const provider = new firebase.auth.GoogleAuthProvider();
  provider.addScope('https://www.googleapis.com/auth/userinfo.email');
  firebase
    .auth()
    .signInWithPopup(provider)
    .then(result => {
      // Returns the signed in user along with the provider's credential
      console.log(`${result.user.displayName} logged in.`);
      window.alert(`Welcome ${result.user.displayName}!`);
    })
    .catch(err => {
      console.log(`Error during sign in: ${err.message}`);
      window.alert('Sign in failed. Retry or check your browser logs.');
    });
}

כשמשתמש נכנס בהצלחה, הלקוח משתמש בשיטות של Firebase כדי ליצור טוקן מזהה. הלקוח מוסיף את האסימון המזהה לכותרת Authorization של הבקשה שלו לשרת.

async function vote(team) {
  if (firebase.auth().currentUser) {
    // Retrieve JWT to identify the user to the Identity Platform service.
    // Returns the current token if it has not expired. Otherwise, this will
    // refresh the token and return a new one.
    try {
      const token = await firebase.auth().currentUser.getIdToken();
      const response = await fetch('/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          Authorization: `Bearer ${token}`,
        },
        body: 'team=' + team, // send application data (vote)
      });
      if (response.ok) {
        const text = await response.text();
        window.alert(text);
        window.location.reload();
      }
    } catch (err) {
      console.log(`Error when submitting vote: ${err}`);
      window.alert('Something went wrong... Please try again!');
    }
  } else {
    window.alert('User not signed in.');
  }
}

שילוב עם Identity Platform: קוד בצד השרת

השרת משתמש ב-SDK של Firebase לאדמינים כדי לאמת את אסימון מזהה המשתמש שנשלח מהלקוח. אם אסימון המזהה שסופק הוא בפורמט הנכון, לא פג תוקפו והוא חתום בצורה תקינה, השיטה מחזירה את אסימון המזהה המפוענח. השרת מחלץ את מזהה uid של המשתמש מ-Identity Platform.

Node.js

const firebase = require('firebase-admin');
// Initialize Firebase Admin SDK
firebase.initializeApp();

// Extract and verify Id Token from header
const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (authHeader) {
    const token = authHeader.split(' ')[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    firebase
      .auth()
      .verifyIdToken(token)
      .then(decodedToken => {
        const uid = decodedToken.uid;
        req.uid = uid;
        next();
      })
      .catch(err => {
        req.logger.error(`Error with authentication: ${err}`);
        return res.sendStatus(403);
      });
  } else {
    return res.sendStatus(401);
  }
};

Python

def jwt_authenticated(func: Callable[..., int]) -> Callable[..., int]:
    """Use the Firebase Admin SDK to parse Authorization header to verify the
    user ID token.

    The server extracts the Identity Platform uid for that user.
    """

    @wraps(func)
    def decorated_function(*args: a, **kwargs: a) -> a:
        header = request.headers.get("Authorization", None)
        if header:
            token = header.split(" ")[1]
            try:
                decoded_token = firebase_admin.auth.verify_id_token(token)
            except Exception as e:
                logger.exception(e)
                return Response(status=403, response=f"Error with authentication: {e}")
        else:
            return Response(status=401)

        request.uid = decoded_token["uid"]
        return func(*args, **kwargs)

    return decorated_function

Java

/** Extract and verify Id Token from header */
private String authenticateJwt(Map<String, String> headers) {
  String authHeader =
      (headers.get("authorization") != null)
          ? headers.get("authorization")
          : headers.get("Authorization");
  if (authHeader != null) {
    String idToken = authHeader.split(" ")[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      return uid;
    } catch (FirebaseAuthException e) {
      logger.error("Error with authentication: " + e.toString());
      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "", e);
    }
  } else {
    logger.error("Error no authorization header");
    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
  }
}

חיבור השרת ל-Cloud SQL

השרת מתחבר לשקע של דומיין Unix של מופע Cloud SQL באמצעות הפורמט: /cloudsql/CLOUD_SQL_CONNECTION_NAME.

Node.js

/**
 * Connect to the Cloud SQL instance through UNIX Sockets
 *
 * @param {object} credConfig The Cloud SQL connection configuration from Secret Manager
 * @returns {object} Knex's PostgreSQL client
 */
const connectWithUnixSockets = async credConfig => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';
  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: credConfig.DB_USER, // e.g. 'my-user'
      password: credConfig.DB_PASSWORD, // e.g. 'my-user-password'
      database: credConfig.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${credConfig.CLOUD_SQL_CONNECTION_NAME}`,
    },
    ...config,
  });
};

Python

def init_unix_connection_engine(
    db_config: dict[str, int]
) -> sqlalchemy.engine.base.Engine:
    """Initializes a Unix socket connection pool for a Cloud SQL instance of PostgreSQL.

    Args:
        db_config: a dictionary with connection pool config

    Returns:
        A SQLAlchemy Engine instance.
    """
    creds = credentials.get_cred_config()
    db_user = creds["DB_USER"]
    db_pass = creds["DB_PASSWORD"]
    db_name = creds["DB_NAME"]
    db_socket_dir = creds.get("DB_SOCKET_DIR", "/cloudsql")
    cloud_sql_connection_name = creds["CLOUD_SQL_CONNECTION_NAME"]

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # postgres+pg8000://<db_user>:<db_pass>@/<db_name>
        #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
        sqlalchemy.engine.url.URL.create(
            drivername="postgresql+pg8000",
            username=db_user,  # e.g. "my-database-user"
            password=db_pass,  # e.g. "my-database-password"
            database=db_name,  # e.g. "my-database-name"
            query={
                "unix_sock": f"{db_socket_dir}/{cloud_sql_connection_name}/.s.PGSQL.5432"
                # e.g. "/cloudsql", "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialized from unix connection")

    return pool

Java

אפשר להשתמש בשילוב Spring Cloud Google Cloud PostgreSQL starter כדי ליצור אינטראקציה עם מסדי נתונים של PostgreSQL ב-Cloud SQL באמצעות ספריות Spring JDBC. מגדירים את התצורה של Cloud SQL ל-MySQL כך שתגדיר אוטומטית רכיב DataSource bean, שביחד עם Spring JDBC מספק רכיב JdbcTemplate object bean שמאפשר פעולות כמו שליחת שאילתות ושינוי מסד נתונים.

# Uncomment and add env vars for local development
# spring.datasource.username=${DB_USER}
# spring.datasource.password=${DB_PASSWORD}
# spring.cloud.gcp.sql.database-name=${DB_NAME}
# spring.cloud.gcp.sql.instance-connection-name=${CLOUD_SQL_CONNECTION_NAME}  
private final JdbcTemplate jdbcTemplate;

public VoteController(JdbcTemplate jdbcTemplate) {
  this.jdbcTemplate = jdbcTemplate;
}

טיפול בהגדרות רגישות באמצעות Secret Manager

‫Secret Manager מספק אחסון מרכזי ומאובטח של נתונים רגישים, כמו הגדרות של Cloud SQL. השרת מזריק את פרטי הכניסה ל-Cloud SQL מ-Secret Manager בזמן הריצה באמצעות משתנה סביבה. מידע נוסף על שימוש בסודות ב-Cloud Run

Node.js

// CLOUD_SQL_CREDENTIALS_SECRET is the resource ID of the secret, passed in by environment variable.
// Format: projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION
const {CLOUD_SQL_CREDENTIALS_SECRET} = process.env;
if (CLOUD_SQL_CREDENTIALS_SECRET) {
  try {
    // Parse the secret that has been added as a JSON string
    // to retrieve database credentials
    return JSON.parse(CLOUD_SQL_CREDENTIALS_SECRET.toString('utf8'));
  } catch (err) {
    throw Error(
      `Unable to parse secret from Secret Manager. Make sure that the secret is JSON formatted: ${err}`
    );
  }
}

Python

def get_cred_config() -> dict[str, str]:
    """Retrieve Cloud SQL credentials stored in Secret Manager
    or default to environment variables.

    Returns:
        A dictionary with Cloud SQL credential values
    """
    secret = os.environ.get("CLOUD_SQL_CREDENTIALS_SECRET")
    if secret:
        return json.loads(secret)

Java

/** Retrieve config from Secret Manager */
public static HashMap<String, Object> getConfig() {
  String secret = System.getenv("CLOUD_SQL_CREDENTIALS_SECRET");
  if (secret == null) {
    throw new IllegalStateException("\"CLOUD_SQL_CREDENTIALS_SECRET\" is required.");
  }
  try {
    HashMap<String, Object> config = new Gson().fromJson(secret, HashMap.class);
    return config;
  } catch (JsonSyntaxException e) {
    logger.error(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted: "
            + e);
    throw new RuntimeException(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted.");
  }
}

הגדרה של Identity Platform

צריך להגדיר את Identity Platform באופן ידני במסוף Google Cloud .

  1. במסוף Google Cloud , מפעילים את Identity Platform API:

    הפעלה של ה-API

  2. מגדירים את הפרויקט:

    1. בחלון חדש, עוברים אל הדף 'סקירה כללית' בפלטפורמת האימות של Google.

      לסקירה הכללית

    2. לוחצים על Get Started (מתחילים) ופועלים לפי ההוראות להגדרת הפרויקט.

    3. בתיבת הדו-שיח פרטי האפליקציה:

      1. מזינים את שם האפליקציה.
      2. בוחרים אחת מכתובות האימייל של תמיכת המשתמשים שמוצגות.
    4. בתיבת הדו-שיח קהל, בוחרים באפשרות חיצוני.

    5. בתיבת הדו-שיח פרטים ליצירת קשר, מזינים כתובת אימייל של איש קשר.

    6. מאשרים את המדיניות בנושא נתוני משתמשים ולוחצים על יצירה.

  3. יוצרים ומקבלים את מזהה הלקוח והסוד ב-OAuth:

    1. במסוף Google Cloud , נכנסים לדף APIs & Services > Credentials.

      כניסה לדף Credentials

    2. בחלק העליון של הדף, לוחצים על יצירת פרטי כניסה ובוחרים באפשרות OAuth client ID.

    3. בקטע Application Type (סוג האפליקציה), בוחרים באפשרות Web Application (אפליקציית אינטרנט) ומזינים את השם.

    4. לוחצים על יצירה.

    5. הערכים client_id ו-client_secret ישמשו בשלב הבא.

  4. מגדירים את Google כספק:

    1. נכנסים לדף Identity Providers במסוף Google Cloud .

      כניסה לדף 'ספקי זהויות'

    2. לוחצים על הוספת ספק.

    3. בוחרים באפשרות Google מהרשימה.

    4. בהגדרות של Web SDK Configuration, מזינים את הערכים client_id ו-client_secret מהשלב הקודם.

    5. בקטע הגדרת האפליקציה, לוחצים על פרטי ההגדרה.

  5. מעתיקים את ההגדרות לאפליקציה:

    • מעתיקים את הערכים apiKey ו-authDomain אל static/config.js בדוגמה כדי לאתחל את Identity Platform Client SDK.

פריסת השירות

פועלים לפי השלבים כדי להשלים את הקצאת התשתית והפריסה:

  1. יוצרים מכונת Cloud SQL עם מסד נתונים של PostgreSQL באמצעות המסוף או CLI:

    gcloud sql instances create CLOUD_SQL_INSTANCE_NAME \
        --database-version=POSTGRES_16 \
        --region=CLOUD_SQL_REGION \
        --cpu=2 \
        --memory=7680MB \
        --root-password=DB_PASSWORD
  2. מוסיפים את ערכי פרטי הכניסה של Cloud SQL אל postgres-secrets.json:

    Node.js

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Python

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Java

    {
      "spring.cloud.gcp.sql.instance-connection-name": "PROJECT_ID:REGION:INSTANCE",
      "spring.cloud.gcp.sql.database-name": "postgres",
      "spring.datasource.username": "postgres",
      "spring.datasource.password": "PASSWORD_SECRET"
    }

  3. יוצרים סוד עם ניהול גרסאות באמצעות המסוף או ה-CLI:

    gcloud secrets create idp-sql-secrets \
        --replication-policy="automatic" \
        --data-file=postgres-secrets.json
  4. יוצרים חשבון שירות לשרת באמצעות המסוף או ה-CLI:

    gcloud iam service-accounts create idp-sql-identity
  5. הקצאת תפקידים לגישה ל-Secret Manager ול-Cloud SQL באמצעות המסוף או ה-CLI:

    1. מתן אפשרות לחשבון השירות שמשויך לשרת לגשת לסוד שנוצר:

      gcloud secrets add-iam-policy-binding idp-sql-secrets \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    2. מתן אפשרות לחשבון השירות שמשויך לשרת לגשת ל-Cloud SQL:

      gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudsql.client
  6. יוצרים Artifact Registry:

    gcloud artifacts repositories create REPOSITORY \
        --repository-format docker \
        --location REGION
    • REPOSITORY הוא שם המאגר. שמות המאגרים צריכים להיות ייחודיים לכל מיקום מאגר בפרויקט.
  7. יוצרים את קובץ האימג' של הקונטיינר באמצעות Cloud Build:

    Node.js

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

    Python

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

    Java

    בדוגמה הזו נעשה שימוש ב-Jib כדי ליצור תמונות Docker באמצעות כלים נפוצים של Java. ‫Jib מבצע אופטימיזציה של בניית קונטיינרים בלי צורך בקובץ Dockerfile או בהתקנה של Docker. מידע נוסף על יצירת מאגרי Java באמצעות Jib

    1. משתמשים בכלי העזר לפרטי כניסה של gcloud כדי לתת ל-Docker הרשאה להעביר בדחיפה אל Artifact Registry.

      gcloud auth configure-docker

    2. משתמשים בתוסף Jib Maven כדי ליצור את הקונטיינר ולהעביר אותו בדחיפה ל-Artifact Registry.

      mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

  8. פורסים את קובץ האימג' של הקונטיינר ב-Cloud Run באמצעות המסוף או CLI. שימו לב: השרת נפרס כדי לאפשר גישה ללא אימות. כך המשתמש יוכל לטעון את הלקוח ולהתחיל את התהליך. השרת מאמת באופן ידני את האסימון המזהה שנוסף לבקשת ההצבעה, וכך מאמת את משתמש הקצה.

    gcloud run deploy idp-sql \
        --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql \
        --allow-unauthenticated \
        --service-account idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --add-cloudsql-instances PROJECT_ID:REGION:CLOUD_SQL_INSTANCE_NAME \
        --update-secrets CLOUD_SQL_CREDENTIALS_SECRET=idp-sql-secrets:latest

    שימו לב גם לדגלים --service-account, --add-cloudsql-instances ו---update-secrets, שמציינים את זהות השירות, את החיבור למופע Cloud SQL ואת שם הסוד עם הגרסה כמשתנה סביבתי, בהתאמה.

ליטושים אחרונים

ב-Identity Platform, אחרי שהמשתמש נכנס לחשבון, צריך לאשר את כתובת ה-URL של שירות Cloud Run כהפניה אוטומטית מותרת:

  1. בדף ספקי זהויות, לוחצים על סמל העיפרון כדי לערוך את ספק Google.

  2. בחלונית השמאלית, בקטע 'דומיינים מורשים', לוחצים על הוספת דומיין ומזינים את כתובת ה-URL של שירות Cloud Run.

    אפשר לאתר את כתובת ה-URL של השירות ביומנים אחרי הבנייה או הפריסה, או למצוא אותה בכל שלב באמצעות:

    gcloud run services describe idp-sql --format 'value(status.url)'
  3. עוברים לדף APIs & Services > Credentials

    1. לוחצים על סמל העיפרון לצד מזהה הלקוח ב-OAuth כדי לערוך אותו, ומתחת ללחצן Authorized redirect URIs click the הוספת URI.

    2. מעתיקים ומדביקים את כתובת ה-URL הבאה בשדה ולוחצים על הלחצן שמירה בתחתית הדף.

    https://PROJECT_ID.firebaseapp.com/__/auth/handler

רוצה לנסות?

כדי לנסות את השירות המלא:

  1. בדפדפן, עוברים לכתובת ה-URL שסופקה בשלב הקודם של הפריסה.

  2. לוחצים על הלחצן כניסה באמצעות חשבון Google ומשלימים את תהליך האימות.

  3. הצבעה

    הוא אמור להיראות כך:

    בממשק המשתמש מוצג מספר ההצבעות לכל קבוצה ורשימת ההצבעות.

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

הסרת המשאבים

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

מחיקת הפרויקט

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

הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.

כדי למחוק את הפרויקט:

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

מחיקת משאבי הדרכה

  1. מוחקים את שירות Cloud Run שפרסתם במדריך הזה. שירותי Cloud Run לא צוברים עלויות עד שהם מקבלים בקשות.

    כדי למחוק את שירות Cloud Run, מריצים את הפקודה הבאה:

    gcloud run services delete SERVICE-NAME

    מחליפים את SERVICE-NAME בשם השירות.

    אפשר גם למחוק שירותים של Cloud Run מGoogle Cloud המסוף.

  2. מסירים את הגדרת ברירת המחדל של האזור gcloud שהוספתם במהלך ההגדרה של המדריך:

     gcloud config unset run/region
    
  3. מסירים את הגדרות הפרויקט:

     gcloud config unset project
    
  4. מחיקת משאבים אחרים Google Cloud שנוצרו במדריך הזה:

המאמרים הבאים