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

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

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

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

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

יצירת מחבר זהויות באמצעות 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.

ה-SDK של Google Cloud Search מכיל כמה פרמטרים של הגדרות שסופקו על ידי 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 קורא לשיטה initConfig() אחרי שהשיטה 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. המשימה הזו מתבצעת בדרך כלל בשיטה של מחלקה Repositoryinit().

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

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

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

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

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

קבלת קבוצה

‫Override listGroups() כדי לאחזר את כל הקבוצות והחברים שלהן ממאגר הזהויות. השיטה listGroups() מקבלת נקודת ביקורת שמייצגת את הזהות האחרונה שסונכרנה. אפשר להשתמש בנקודת הבדיקה כדי להמשיך את הסנכרון אם התהליך מופסק. לכל משתמש במאגר, תבצעו את השלבים האלה בשיטה 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() מחזירה Iterator, במיוחד CheckpointCloseableIterable, של אובייקטים מסוג IdentityGroup. אפשר להשתמש במחלקה CheckpointClosableIterableImpl.Builder כדי ליצור איטרטור ולהחזיר אותו. בקטע הקוד הבא מוצג אופן האריזה של כל קבוצה והחברים בה לרשימה, ויצירת האיטרטור מהרשימה הזו:

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

השלבים הבאים

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

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