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

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

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

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

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

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

מחבר זהויות רגיל מבצע את הפעולות הבאות:

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

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

כדי להשתמש ב-SDK, צריך לכלול יחסי תלות מסוימים בקובץ ה-build. לוחצים על אחת מהכרטיסיות הבאות כדי להציג את יחסי התלות של סביבת ה-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.

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

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

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

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

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

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

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

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

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

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

הקטע הזה במסמכי העזרה מתייחס לקטעי קוד מהדוגמה IdentityConnecorSample.java. הדוגמה הזו קוראת זהויות של משתמשים וקבוצות משני קובצי CSV ומסנכרנת אותן עם הזהויות ב-Google.

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

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

לפני שמפעילים את application.start(), משתמשים בכיתה IdentityApplication.Builder כדי ליצור מופע של התבנית FullSyncIdentityConnector. הפרמטר FullSyncIdentityConnector מקבל אובייקט Repository, שבו תטמיעו את השיטות. קטע הקוד הבא מראה איך מטמיעים את השיטה main():

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 קורא ל-method‏ initConfig() אחרי ש-method‏ main() של המחבר קורא ל-Application.build. השיטה initConfig() מבצעת את המשימות הבאות:

  1. קריאה לשיטה Configuation.isInitialized() כדי לוודא ש-Configuration לא הותחל.
  2. הפונקציה מפעילה אובייקט Configuration עם זוגות המפתח-ערך ש-Google מספקת. כל צמד מפתח/ערך מאוחסן באובייקט ConfigValue בתוך האובייקט Configuration.

הטמעת הממשק Repository

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

  • השיטה init(). כדי לבצע הגדרה ואתחול של מאגר הזהויות, צריך לשנות את השיטה init().

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

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

  • (אופציונלי) השיטה close(). אם צריך לבצע ניקוי של המאגר, צריך לשנות את השיטה close(). השיטה הזו נקראת פעם אחת במהלך כיבוי המחבר.

אחזור של פרמטרים מותאמים אישית של תצורה

כחלק מהטיפול בהגדרות המחבר, תצטרכו לקבל את כל הפרמטרים המותאמים אישית מהאובייקט Configuration. בדרך כלל, המשימה הזו מתבצעת ב-method‏ init() של הכיתה Repository.

לכיתה Configuration יש כמה שיטות לאחזור סוגי נתונים שונים מהגדרה. כל method מחזיר אובייקט ConfigValue. לאחר מכן משתמשים בשיטה get() של האובייקט ConfigValue כדי לאחזר את הערך בפועל. קטע הקוד הבא מראה איך לאחזר את הערכים של userMappingCsvPath ו-groupMappingCsvPath מאובייקט Configuration:

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 כדי לנתח את הנתונים למקטעים נפרדים. קטע הקוד הבא, מהמחבר במדריך, משתמש ב-method‏ getMultiValue כדי לקבל רשימה של שמות המאגרים ב-GitHub:

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

הצגת המיפוי לכל המשתמשים

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

  1. מקבלים מיפוי שמכיל את הזהות ב-Google ואת הזהות החיצונית המשויכת.
  2. מארזים את הצמד ב-iterator שמוחזר על ידי השיטה 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);
    }
  }
  // ...
}

אריזה של מיפוי משתמשים בתוך מעבד (iterator)

השיטה listUsers() מחזירה Iterator, ובפרט CheckpointCloseableIterable, של אובייקטים מסוג IdentityUser. אפשר להשתמש בכיתה CheckpointClosableIterableImpl.Builder כדי ליצור מעבד וחזרה אליו. קטע הקוד הבא מראה איך לארוז כל מיפוי ברשימה וליצור את האינטראטור מהרשימה הזו:

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

אחזור קבוצה

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

  1. אחזור הקבוצה והחברים בה.
  2. צריך לארוז כל קבוצה ומשתתפים ב-iterator שמוחזר על ידי השיטה 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);
    }
  }
  // ...

}

אריזה של הקבוצה והחברים ב-iterator

השיטה listGroups() מחזירה Iterator, ובפרט CheckpointCloseableIterable, של אובייקטים מסוג IdentityGroup. אפשר להשתמש בכיתה CheckpointClosableIterableImpl.Builder כדי ליצור מעבד וחזרה אליו. קטע הקוד הבא מראה איך לארוז כל קבוצה ואת החברים שלה ברשימה וליצור את האינטראטור מהרשימה הזו:

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

השלבים הבאים

הנה כמה שלבים אפשריים:

  • (אופציונלי) מטמיעים את השיטה close()‎ כדי לשחרר משאבים לפני סגירה.
  • (אופציונלי) יוצרים מחבר תוכן באמצעות ה-SDK של Content Connector.