標準機能では、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);
}
}
