ID 커넥터 만들기

기본적으로 Google Cloud Search는 Google Cloud Directory(사용자 및 그룹)에 저장된 Google ID만 인식합니다. ID 커넥터는 기업 ID를 Google Cloud Search에서 사용되는 Google ID와 동기화하는 데 사용됩니다.

Google에서는 다음과 같은 ID 커넥터 개발 옵션을 제공합니다.

  • ID 커넥터 SDK 이 옵션은 자바 프로그래밍 언어로 프로그래밍하는 개발자를 위한 것입니다. ID 커넥터 SDK는 REST API를 둘러싸는 래퍼로, 이를 사용하면 커넥터를 빠르게 만들 수 있습니다. SDK를 사용하여 ID 커넥터를 만들려면 ID 커넥터 SDK를 사용하여 ID 커넥터 만들기를 참조하세요.

  • 하위 수준 REST API 및 API 라이브러리: 이 옵션은 자바로 프로그래밍하지 않거나 코드베이스보다 REST API 또는 라이브러리가 더 익숙한 개발자용입니다. REST API를 사용하여 ID 커넥터를 만들려면 사용자 매핑에 대한 자세한 내용은 Directory API: 사용자 계정을 참조하고 그룹 매핑에 대한 자세한 내용은 Cloud ID 문서를 참조하세요.

ID 커넥터 SDK를 사용하여 ID 커넥터 만들기

일반적인 ID 커넥터는 다음 작업을 수행합니다.

  1. 커넥터를 구성합니다.
  2. 기업 ID 시스템에서 모든 사용자를 검색한 후 Google로 보내 Google ID와 동기화합니다.
  3. 기업 ID 시스템에서 모든 그룹을 검색한 후 Google로 보내 Google ID와 동기화합니다.

종속 항목 설정

SDK를 사용하려면 빌드 파일에 특정 종속 항목을 포함해야 합니다. 아래 탭을 클릭하여 빌드 환경의 종속 항목을 확인하세요.

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'

커넥터 구성 만들기

각 커넥터에는 커넥터에서 사용되는 매개변수(예: 저장소 ID)가 포함된 구성 파일이 있습니다. 매개변수는 키-값 쌍(예: api.sourceId=1234567890abcdef)으로 정의됩니다.

Google Cloud Search SDK에는 모든 커넥터에서 사용되는 Google 제공 구성 매개변수가 여러 개 포함되어 있습니다. 구성 파일에서 다음과 같은 Google 제공 매개변수를 선언해야 합니다.

  • 콘텐츠 커넥터의 경우 api.sourceIdapi.serviceAccountPrivateKeyFile을 선언해야 합니다. 이러한 매개변수가 저장소와 저장소에 액세스하는 데 필요한 비공개 키의 위치를 식별하기 때문입니다.
  • ID 커넥터의 경우 api.identitySourceId을 선언해야 합니다. 이 매개변수가 외부 ID 소스의 위치를 식별하기 때문입니다. 사용자를 동기화하는 경우 api.customerId도 기업의 Google Workspace 계정 고유 ID로 선언해야 합니다.

Google에서 제공하는 다른 매개변수의 기본 값을 재정의하려는 경우가 아니라면 구성 파일에서 매개변수를 선언하지 않아도 됩니다. Google에서 제공하는 구성 매개변수에 대한 자세한 내용(예: 특정 ID와 키 생성 방법)은 Google에서 제공하는 구성 매개변수를 참조하세요.

구성 파일에 사용할 고유한 저장소별 매개변수도 정의할 수 있습니다.

커넥터에 구성 파일 전달

시스템 속성 config를 설정하여 커넥터에 구성 파일을 전달합니다. 커넥터를 시작할 때 -D 인수를 사용하여 속성을 설정할 수 있습니다. 예를 들어 다음 명령어는 MyConfig.properties 구성 파일로 커넥터를 시작합니다.

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

이 인수가 없으면 SDK는 connector-config.properties이라는 기본 구성 파일에 액세스하려고 시도합니다.

템플릿 클래스를 사용하여 전체 동기화 ID 커넥터 만들기

ID 커넥터 SDK에는 ID 저장소의 모든 사용자 및 그룹을 Google ID와 동기화하는 데 사용할 수 있는 FullSyncIdentityConnector 템플릿 클래스가 포함되어 있습니다. 이 섹션에서는 FullSyncIdentityConnector 템플릿을 사용하여 Google 이외의 ID 저장소에서 사용자와 그룹의 전체 동기화를 수행하는 방법을 설명합니다.

이 섹션에서는 IdentityConnecorSample.java 샘플의 코드 스니펫을 참조합니다. 이 샘플은 사용자 및 그룹 ID를 두 CSV 파일에서 읽은 후 Google ID와 동기화합니다.

커넥터의 진입점 구현

커넥터의 진입점은 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는 커넥터의 main() 메서드가 Application.build를 호출한 후 initConfig() 메서드를 호출합니다. initConfig() 메서드는 다음 작업을 실행합니다.

  1. Configuation.isInitialized() 메서드를 호출하여 Configuration가 초기화되지 않았는지 확인합니다.
  2. Google에서 제공하는 키-값 쌍을 사용하여 Configuration 객체를 초기화합니다. 각 키-값 쌍은 Configuration 객체 내의 ConfigValue 객체에 저장됩니다.

Repository 인터페이스 구현

Repository 객체의 유일한 목적은 저장소 ID를 Google ID에 동기화하는 것입니다. 템플릿을 사용하는 경우 ID 커넥터를 만들려면 Repository 인터페이스 내에서 특정 메서드를 재정의하기만 하면 됩니다. FullTraversalConnector의 경우 다음 메서드를 재정의할 수 있습니다.

  • init() 메서드 ID 저장소 설정과 초기화를 수행하려면 `init() 메소드를 재정의합니다.

  • listUsers() 메서드 ID 저장소의 모든 사용자를 Google 사용자와 동기화하려면 listUsers() 메서드를 재정의합니다.

  • listGroups() 메서드 ID 저장소의 모든 그룹을 Google 그룹스와 동기화하려면 listGroups() 메서드를 재정의합니다.

  • (선택사항) close() 메서드. 저장소 정리를 수행해야 하면 close() 메서드를 재정의합니다. 이 메서드는 커넥터 종료 시 한 번 호출됩니다.

커스텀 구성 매개변수 가져오기

커넥터 구성을 처리하려면 Configuration 객체에서 커스텀 매개변수를 가져와야 합니다. 이 작업은 일반적으로 Repository 클래스의 init() 메서드에서 실행됩니다.

Configuration 클래스에는 구성에서 다양한 데이터 유형을 가져오기 위한 여러 메서드가 있습니다. 각 메서드는 ConfigValue 객체를 반환합니다. 그런 다음 ConfigValue 객체의 get() 메서드를 사용하여 실제 값을 검색합니다. 다음 스니펫은 Configuration 객체에서 userMappingCsvPathgroupMappingCsvPath 값을 검색하는 방법을 보여줍니다.

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);

모든 사용자의 매핑 가져오기

ID 저장소에서 모든 사용자의 매핑을 검색하려면 listUsers()를 재정의합니다. listUsers() 메서드는 동기화할 마지막 ID를 나타내는 체크포인트를 받아들입니다. 프로세스가 중단되면 체크포인트를 사용하여 동기화를 계속할 수 있습니다. 저장소의 각 사용자별로 listUsers() 메서드에서 다음 단계를 수행합니다.

  1. Google ID 및 연결된 외부 ID로 구성된 매핑을 가져옵니다.
  2. 이 쌍을 listUsers() 메서드에서 반환된 반복자에 패키징합니다.

사용자 매핑 가져오기

다음 코드 스니펫은 CSV 파일에 저장된 ID 매핑을 검색하는 방법을 보여줍니다.

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() 메서드는 IdentityUser 객체의 Iterator, 구체적으로 CheckpointCloseableIterable를 반환합니다. CheckpointClosableIterableImpl.Builder 클래스를 사용하여 반복자를 구성하고 반환할 수 있습니다. 다음 코드 스니펫은 각 매핑을 목록에 패키징하고 이러한 목록에서 반복자를 빌드하는 방법을 보여줍니다.

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

그룹 가져오기

ID 저장소에서 모든 그룹과 구성원을 검색하려면 listGroups()를 재정의합니다. listGroups() 메서드는 동기화할 마지막 ID를 나타내는 체크포인트를 받아들입니다. 프로세스가 중단되면 체크포인트를 사용하여 동기화를 계속할 수 있습니다. 저장소의 각 사용자별로 listGroups() 메서드에서 다음 단계를 수행합니다.

  1. 그룹 및 구성원을 가져옵니다.
  2. 각 그룹과 구성원을 listGroups() 메서드에서 반환된 반복자에 패키징합니다.

그룹 ID 가져오기

다음 코드 스니펫은 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() 메서드는 IdentityGroup 객체의 Iterator, 구체적으로 CheckpointCloseableIterable를 반환합니다. CheckpointClosableIterableImpl.Builder 클래스를 사용하여 반복자를 구성하고 반환할 수 있습니다. 다음 코드 스니펫은 각 그룹과 구성원을 목록에 패키징하고 이 목록에서 반복자를 빌드하는 방법을 보여줍니다.

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

다음 단계

그 다음으로는 아래와 같은 옵션도 고려해 볼 수 있습니다.