SAMLユーザマッピングのジョブを作成する
標準機能では、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);
}
}