SAMLユーザマッピングのジョブを作成する

公開日: 2024-09-30 / カテゴリ: CookBook

標準機能では、IdPユーザとintra-martユーザを紐付けるには以下の方法があります。

・SAMLユーザマッピング画面からユーザ毎に登録する。
・SAMLユーザマッピング画面からCSVファイルを利用して、一括登録する

上記いずれの場合も、画面での操作が必要になります。

これを半自動化するために、SAMLユーザマッピングのCSVファイルを取り込み一括登録するジョブを作成します。
定期的にSAMLユーザマッピングのCSVファイルを作成し、ジョブスケジューラを利用してデータを取り込むことが可能です。

サンプルはシンプルなものとなっています。
必要であれば目的によってサンプルを改変して利用してください。

【サンプルの仕様】

ジョブパラメータ
path:CSVファイルパス(パブリックストレージからの相対パス)
prov_id:IdP登録時のID(IdP一覧画面から確認できます)

【サンプルの注意点】

・基本的に新規追加と変更を想定したシンプルなサンプルです。
・既存のデータ間のユーザの入れ替えには対応してません。(別途処理が必要です)
・トランザクション処理は行っていません。一件づつコミットが行われます。

package com.example.saml;

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;

import jp.co.intra_mart.common.platform.log.Logger; import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.job_scheduler.Job; import jp.co.intra_mart.foundation.job_scheduler.JobResult; import jp.co.intra_mart.foundation.job_scheduler.JobSchedulerContext; import jp.co.intra_mart.foundation.job_scheduler.annotation.Parameter; import jp.co.intra_mart.foundation.job_scheduler.annotation.Parameters; import jp.co.intra_mart.foundation.job_scheduler.exception.JobExecuteException; import jp.co.intra_mart.foundation.saml.mapping.SAMLMappingManager; import jp.co.intra_mart.foundation.saml.mapping.entity.ImsamlUserMapping; import jp.co.intra_mart.foundation.saml.mapping.exception.IdpNotExistException; import jp.co.intra_mart.foundation.service.client.file.PublicStorage;

public final class SamlMappingImporterJob implements Job {

private static String PATH\_KEY = "path";
private static String PROV\_ID = "prov\_id";

public SamlMappingImporterJob() {
}

@Override
@Parameters({@Parameter(key = "prov\_id", value = ""),@Parameter(key = "path", value = "saml\_mapping.csv")})
public JobResult execute() throws JobExecuteException {

    final Logger logger = Logger.getLogger();

    // ジョブスケジューラコンテキスト取得
    final JobSchedulerContext jobSchedulerContext = Contexts.get(JobSchedulerContext.class);

    // パラメータの取得(prov\_id)
    String provId = jobSchedulerContext.getParameter(PROV\_ID);
    if (null == provId) {
        // 処理結果:異常
        return JobResult.error("prov\_id not found.");
    }
    provId = provId.trim();
    if (provId.isEmpty()) {
        // 処理結果:異常
        return JobResult.error("prov\_id id Empty.");
    }

    // パラメータの取得(path)
    String path = jobSchedulerContext.getParameter(PATH\_KEY);
    if (null == path) {
        // 処理結果:異常
        return JobResult.error("path is not found.");
    }
    path = path.trim();
    if (path.isEmpty()) {
        // 処理結果:異常
        return JobResult.error("path is empty.");
    }

    // ファイルを取得とチェック
    final PublicStorage storage = new PublicStorage(path);
    try {
        if (!storage.exists()) {
            // 処理結果:異常
            return JobResult.error(String.format("File not found.(%s)", path));
        }
    } catch (IOException e) {
        final String errorMessage = String.format("Can not read the file.(%s)", path);
        logger.error(errorMessage, e);
        return JobResult.error(errorMessage);
    }

    // インポート処理
    BufferedReader reader = null;
    int totalCount = 0;
    int insertCount = 0;
    int updateCount = 0;
    int skipCount = 0;

    final SAMLMappingManager manager = new SAMLMappingManager();

    try {
        reader = new BufferedReader(new InputStreamReader(storage.open()));
        String line;
        while ((line = reader.readLine()) != null) {
            try {
                String\[\] record = line.split(",", 2);
                if (record.length == 2) {
                    record\[0\] = record\[0\].trim();
                    record\[1\] = record\[1\].trim();
                    final ImsamlUserMapping mapping = manager.find(provId, record\[0\]);
                    if (mapping != null) {
                        // 更新
                        manager.update(provId, record\[0\], record\[1\], mapping.getProvUserCd(), mapping.getUserCd());
                        updateCount++;

                    } else {
                        // 新規追加
                        manager.insert(provId, record\[0\], record\[1\]);
                        insertCount++;
                    }
                } else {
                    logger.warn(String.format("Skip for invalid format.(%s)", line));
                    skipCount++;
                }
            } catch (IdpNotExistException e) {
                String errorMessage = String.format("prov\_id not found.(%s)", provId);
                logger.error(errorMessage, e);
                return JobResult.error(errorMessage);
            } catch (Exception e) {
                String errorMessage = String.format("Skip for import error.(%s)", line);
                logger.warn(errorMessage, e);
                skipCount++;
            }

            totalCount++;
        }
    } catch (IOException e) {
        final String errorMessage = String.format("Can not read the file.(%s)", path);
        logger.error(errorMessage, e);
        return JobResult.error(errorMessage);
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                final String errorMessage = String.format("Can not close the file.(%s)", path);
                logger.error(errorMessage, e);
                return JobResult.error(String.format("Can not close the file.(%s)", path));
            }
        }
    }
    final String message = String.format("Success import.( total:%d / insert:%d / update:%d / skip:%d )",
            totalCount, insertCount, updateCount, skipCount);
    return JobResult.success(message);
}

}