יצירת מחבר זהות

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

‫Google מספקת את האפשרויות הבאות לפיתוח מחברי זהויות:

  • ‫Identity Connector SDK: הכי מתאים למתכנתי Java. ה-SDK הוא wrapper סביב ה-REST API שמאפשר ליצור מחברים במהירות. כדי להשתמש ב-SDK, אפשר לעיין במאמר יצירת מחבר זהויות באמצעות Identity Connector SDK.

  • ‫REST API וספריות API ברמה נמוכה: מתאים במיוחד למתכנתים שלא משתמשים ב-Java. כדי ליצור מחבר זהויות באמצעות REST API, אפשר לעיין במאמר Directory API: User Accounts (Directory API: חשבונות משתמשים) למיפוי משתמשים ובמאמר Google Cloud Identity documentation (תיעוד של Google Cloud Identity) למיפוי קבוצות.

יצירת מחבר זהויות באמצעות Identity Connector SDK

מחבר זהויות טיפוסי מבצע את המשימות הבאות:

  1. הגדרת המחבר.
  2. מאחזר משתמשים ממערכת הזהויות שלכם ושולח אותם אל Google.
  3. הכלי מאחזר קבוצות ממערכת הזהויות שלכם ושולח אותן ל-Google.

הגדרת יחסי תלות

כוללים את התלויות האלה בקובץ ה-build.

Maven

<dependency>
  <groupId>com.google.enterprise.cloudsearch</groupId>
  <artifactId>google-cloudsearch-identity-connector-sdk</artifactId>
  <version>v1-0.0.3</version>
</dependency>

Gradle

compile group: 'com.google.enterprise.cloudsearch',
        name: 'google-cloudsearch-identity-connector-sdk',
        version: 'v1-0.0.3'

יצירת הגדרות של מחבר

כל מחבר משתמש בקובץ הגדרה לפרמטרים כמו מזהה המאגר. מגדירים פרמטרים כצמדים של מפתח-ערך, כמו api.sourceId=1234567890abcdef.

ערכת ה-SDK של Google Cloud Search כוללת פרמטרים שסופקו על ידי Google לכל המחברים. צריך להצהיר על הפרטים הבאים בקובץ ההגדרות:

  • מחבר תוכן: צריך להצהיר על api.sourceId ועל api.serviceAccountPrivateKeyFile. הם מזהים את המאגר ואת המפתח הפרטי שנדרש לגישה.
  • מחבר זהויות: צריך להצהיר על api.identitySourceId כדי לזהות את מקור הזהויות החיצוני. לסנכרון משתמשים, צריך גם להצהיר על api.customerId (המזהה הייחודי של חשבון Google Workspace).

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

אפשר גם להגדיר פרמטרים ספציפיים למאגר בקובץ ההגדרות.

העברת קובץ התצורה למחבר

מגדירים את מאפיין המערכת config כדי להעביר את קובץ התצורה. משתמשים בארגומנט -D כשמפעילים את המחבר. לדוגמה:

java -classpath myconnector.jar -Dconfig=MyConfig.properties MyConnector

אם לא מציינים את הארגומנט הזה, ערכת ה-SDK מנסה להשתמש בקובץ בשם connector-config.properties בספרייה המקומית.

יצירת מחבר זהויות לביצוע סנכרון מלא באמצעות מחלקת תבנית

חבילת ה-SDK כוללת תבנית FullSyncIdentityConnector לסנכרון כל המשתמשים והקבוצות מהמאגר. בקטע הזה מוסבר איך משתמשים בו.

בקטע הזה יש התייחסות לקוד מIdentityConnectorSample.javaהדוגמה, שקורא זהויות מקובצי CSV.

הטמעה של נקודת הכניסה למחבר

נקודת הכניסה היא השיטה main(). הוא יוצר מופע של Application וקורא ל-start() כדי להפעיל את המחבר.

לפני ששולחים קריאה ל-application.start(), משתמשים ב-IdentityApplication.Builder כדי ליצור מופע של התבנית FullSyncIdentityConnector.

IdentityConnectorSample.java
/**
 * This sample connector uses the Cloud Search SDK template class for a full
 * sync connector. In the full sync case, the repository is responsible
 * for providing a snapshot of the complete identity mappings and
 * group rosters. This is then reconciled against the current set
 * of mappings and groups in Cloud Directory.
 *
 * @param args program command line arguments
 * @throws InterruptedException thrown if an abort is issued during initialization
 */
public static void main(String[] args) throws InterruptedException {
  Repository repository = new CsvRepository();
  IdentityConnector connector = new FullSyncIdentityConnector(repository);
  IdentityApplication application = new IdentityApplication.Builder(connector, args).build();
  application.start();
}

ערכת ה-SDK שולחת קריאה ל-initConfig() אחרי שמתבצעות קריאות ל-method main() שלכם Application.build(). השיטה initConfig():

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

הטמעה של ממשק המאגר

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

  • init(): להגדרה ולאתחול.
  • listUsers(): כדי לסנכרן את כל המשתמשים.
  • listGroups(): כדי לסנכרן את כל הקבוצות.
  • (אופציונלי) close(): לניקוי במהלך כיבוי.

אחזור פרמטרים של הגדרה בהתאמה אישית

שליפת פרמטרים מותאמים אישית מהאובייקט Configuration, בדרך כלל בשיטה init(). בקטע הקוד הבא אפשר לראות איך מאחזרים נתיבי CSV:

IdentityConnectorSample.java
/**
 * Initializes the repository once the SDK is initialized.
 *
 * @param context Injected context, contains convenienve methods
 *                for building users & groups
 * @throws IOException if unable to initialize.
 */
@Override
public void init(RepositoryContext context) throws IOException {
  log.info("Initializing repository");
  this.context = context;
  userMappingCsvPath = Configuration.getString(
      "sample.usersFile", "users.csv").get().trim();
  groupMappingCsvPath = Configuration.getString(
      "sample.groupsFile", "groups.csv").get().trim();
}

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

GithubRepository.java
ConfigValue<List<String>> repos = Configuration.getMultiValue(
    "github.repos",
    Collections.emptyList(),
    Configuration.STRING_PARSER);

קבלת המיפוי לכל המשתמשים

מחליפים את listUsers() כדי לאחזר מיפויי משתמשים. השיטה הזו מקבלת נקודת ביקורת כדי להמשיך את הסנכרון אם הוא מופסק. לכל משתמש:

  1. מקבלים את המיפוי בין הזהות ב-Google לבין הזהות החיצונית.
  2. אורזים את הצמד לתוך האיטרטור שמוחזר על ידי listUsers().

קבלת מיפוי משתמשים

בקטע הקוד הזה מוצג איך לאחזר מיפויים של זהויות מקובץ CSV:

IdentityConnectorSample.java
/**
 * Retrieves all user identity mappings for the identity source. For the
 * full sync connector, the repository must provide a complete snapshot
 * of the mappings. This is reconciled against the current mappings
 * in Cloud Directory. All identity mappings returned here are
 * set in Cloud Directory. Any previously mapped users that are omitted
 * are unmapped.
 *
 * The connector does not create new users. All users are assumed to
 * exist in Cloud Directory.
 *
 * @param checkpoint Saved state if paging over large result sets. Not used
 *                   for this sample.
 * @return Iterator of user identity mappings
 * @throws IOException if unable to read user identity mappings
 */
@Override
public CheckpointCloseableIterable<IdentityUser> listUsers(byte[] checkpoint)
    throws IOException {
  List<IdentityUser> users = new ArrayList<>();
  try (Reader in = new FileReader(userMappingCsvPath)) {
    // Read user mappings from CSV file
    CSVParser parser = CSVFormat.RFC4180
        .withIgnoreSurroundingSpaces()
        .withIgnoreEmptyLines()
        .withCommentMarker('#')
        .parse(in);
    for (CSVRecord record : parser.getRecords()) {
      // Each record is in form: "primary_email", "external_id"
      String primaryEmailAddress = record.get(0);
      String externalId = record.get(1);
      if (primaryEmailAddress.isEmpty() || externalId.isEmpty()) {
        // Skip any malformed mappings
        continue;
      }
      log.info(() -> String.format("Adding user %s/%s",
          primaryEmailAddress, externalId));

      // Add the identity mapping
      IdentityUser user = context.buildIdentityUser(
          primaryEmailAddress, externalId);
      users.add(user);
    }
  }
  // ...
}

אריזת מיפוי משתמשים באיטרטור

השיטה listUsers() מחזירה CheckpointCloseableIterable של אובייקטים מסוג IdentityUser.

IdentityConnectorSample.java
CheckpointCloseableIterable<IdentityUser> iterator =
  new CheckpointCloseableIterableImpl.Builder<IdentityUser>(users)
      .setHasMore(false)
      .setCheckpoint((byte[])null)
      .build();

קבלת קבוצה

החלפת ברירת המחדל listGroups() כדי לאחזר קבוצות ואת החברים שלהן. השיטה הזו מקבלת נקודת ביקורת. לכל קבוצה:

  1. קבלת הקבוצה והחברים בה.
  2. אורזים אותם באיטרטור שמוחזר על ידי listGroups().

קבלת הזהות של הקבוצה

בקטע הקוד הבא מוצגות קבוצות וחברים מקובץ CSV:

IdentityConnectorSample.java
/**
 * Retrieves all group rosters for the identity source. For the
 * full sync connector, the repository must provide a complete snapshot
 * of the rosters. This is reconciled against the current rosters
 * in Cloud Directory. All groups and members  returned here are
 * set in Cloud Directory. Any previously created groups or members
 * that are omitted are removed.
 *
 * @param checkpoint Saved state if paging over large result sets. Not used
 *                   for this sample.
 * @return Iterator of group rosters
 * @throws IOException if unable to read groups
 */    @Override
public CheckpointCloseableIterable<IdentityGroup> listGroups(byte[] checkpoint)
    throws IOException {
  List<IdentityGroup> groups = new ArrayList<>();
  try (Reader in = new FileReader(groupMappingCsvPath)) {
    // Read group rosters from CSV
    CSVParser parser = CSVFormat.RFC4180
        .withIgnoreSurroundingSpaces()
        .withIgnoreEmptyLines()
        .withCommentMarker('#')
        .parse(in);
    for (CSVRecord record : parser.getRecords()) {
      // Each record is in form: "group_id", "member"[, ..., "memberN"]
      String groupName = record.get(0);
      log.info(() -> String.format("Adding group %s", groupName));
      // Parse the remaining columns as group memberships
      Supplier<Set<Membership>> members = new MembershipsSupplier(record);
      IdentityGroup group = context.buildIdentityGroup(groupName, members);
      groups.add(group);
    }
  }
  // ...

}

אריזת הקבוצה והחברים שלה באיטרטור

השיטה listGroups() מחזירה CheckpointCloseableIterable של אובייקטים מסוג IdentityGroup.

IdentityConnectorSample.java
CheckpointCloseableIterable<IdentityGroup> iterator =
   new CheckpointCloseableIterableImpl.Builder<IdentityGroup>(groups)
      .setHasMore(false)
      .setCheckpoint((byte[])null)
      .build();

השלבים הבאים