証明書のインポート(OS・環境別)
SAML 認証や LDAP(LDAPS)連携では、IdP やディレクトリサーバーの証明書をプリザンターの動作環境にインポートする必要があります。SAML の IdP 署名証明書は、プリザンター(.NET)が Authentication.json で指定された X509Store の中から探すので、.NET の X509Store から見えるストアに入れるのがポイントです。OS の CA トラストストアに追加しても、この検索には使われません。
- Windows は GUI・PowerShell・certutil のいずれかで個人ストア(
My)にインポートします。 - Linux は、プリザンターの実行ユーザーで PowerShell 7 から
X509Store.Addを呼び、.NET のCurrentUser\My(実行ユーザーのホームの~/.dotnet/corefx/cryptography/x509stores/my/)にインポートします。LocalMachineは使えません。update-ca-certificatesや NSS のcertutilではCurrentUser\Myに入りません。 - Docker は、ストアが実行ユーザーのホームにできるため、PowerShell 入りの .NET SDK イメージで作ったストアをイメージに焼き込むか、ボリュームで渡します。
- Azure App Service は、Windows プランなら
WEBSITE_LOAD_CERTIFICATESの設定でCurrentUser\Myから読めます。Linux プランは証明書がファイルとして置かれるだけなので、カスタムコンテナーで Docker と同じ手順にします。AWS / Google Cloud はコンテナなら Docker、VM なら Linux と同じ手順です。
INFO
プリザンター 1.4 系以降が対象です。SAML 認証の設定手順そのものは 認証(Google Workspace の SAML SSO / SMTP の OAuth) を参照してください。以下の URL・拇印・ファイルパス・ユーザー名はすべてダミー値です。
証明書が参照される仕組み
SAML 認証では、Authentication.json の IdentityProviders の SigningCertificate で証明書の検索条件を指定します。FindValue などは IdentityProviders の直下ではなく SigningCertificate の中に書きます(既定の Authentication.json)。
"IdentityProviders": [
{
"EntityId": "https://idp.example.com/...",
"SignOnUrl": "https://idp.example.com/sso",
"SigningCertificate": {
"StoreName": "My",
"StoreLocation": "CurrentUser",
"X509FindType": "FindByThumbprint",
"FindValue": "A1B2C3D4E5F6..."
}
}
]項目(SigningCertificate の中) | 説明 |
|---|---|
FindValue | 証明書の拇印(Thumbprint / Fingerprint) |
X509FindType | 検索方法。拇印で探すなら FindByThumbprint(既定) |
StoreLocation | CurrentUser または LocalMachine(既定は CurrentUser)。Linux では CurrentUser だけが使える(後述) |
StoreName | 証明書ストア名(通常は My。既定も My) |
プリザンターは StoreName と StoreLocation で X509Store を開き(OpenFlags.OpenExistingOnly)、X509FindType と FindValue で検索して、見つかった最初の証明書を IdP の署名検証用の鍵として登録します(Saml.cs)。ソースから読み取れるのは次の点です。
- 証明書ファイルのパスを指定する項目はなく、
X509Storeの中しか探しません。 - 検索は
Find(..., validOnly: false)なので、見つけるときに証明書チェーンや信頼の検証はしません。IdP の自己署名証明書でもそのまま見つかります。 OpenExistingOnlyで開くため、指定したストアが存在しないと例外になります。SigningCertificateを書かない場合(IdP のメタデータを読み込む構成など)は、ストアを参照しません(if (paramIdp.SigningCertificate != null))。
図を読み込み中…
拇印の確認方法
FindValue に設定する拇印は、環境を問わず次のコマンドで確認できます。
# SHA-1 拇印を確認
openssl x509 -in certificate.pem -fingerprint -sha1 -noout
# 出力例: SHA1 Fingerprint=A1:B2:C3:D4:E5:F6:...コロンを除いて FindValue にそのまま使える形で取り出すには次のようにします。
openssl x509 -in certificate.pem -fingerprint -sha1 -noout | sed 's/SHA1 Fingerprint=//;s/://g'Windows では PowerShell でも確認できます。
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("certificate.pem")
$cert.ThumbprintWindows
GUI(証明書のインポートウィザード)
.pemまたは.cerファイルをダブルクリックし、「証明書のインポートウィザード」を開きます。- 保存場所を選択します。
CurrentUser:「現在のユーザー」LocalMachine:「ローカル コンピューター」(IIS でホストする場合はこちらを推奨)
- 証明書ストアは「個人」(
My)を選択します。 - インポート後、証明書の管理画面を開いて拇印をコピーします。
CurrentUserの場合:certmgr.mscLocalMachineの場合:certlm.msc
PowerShell
# LocalMachine の個人ストアにインポート
Import-Certificate -FilePath "C:\certs\idp-certificate.pem" -CertStoreLocation Cert:\LocalMachine\My
# CurrentUser の個人ストアにインポート
Import-Certificate -FilePath "C:\certs\idp-certificate.pem" -CertStoreLocation Cert:\CurrentUser\Myインポート後の拇印は次のように確認します。
# LocalMachine の個人ストアの証明書一覧を表示
Get-ChildItem Cert:\LocalMachine\My | Format-Table Subject, Thumbprintcertutil
:: LocalMachine の個人ストアにインポート
certutil -addstore My "C:\certs\idp-certificate.pem"
:: CurrentUser の個人ストアにインポート
certutil -user -addstore My "C:\certs\idp-certificate.pem"INFO
certutil -addstore / -user -addstore は Windows の certutil の書式です。Linux の certutil(NSS のツール)は別物で、この書式は使えません。
Authentication.json の設定例(IIS)
"IdentityProviders": [
{
"EntityId": "https://idp.example.com/...",
"SignOnUrl": "https://idp.example.com/sso",
"SigningCertificate": {
"StoreName": "My",
"StoreLocation": "LocalMachine",
"X509FindType": "FindByThumbprint",
"FindValue": "A1B2C3D4E5F6..."
}
}
]INFO
IIS でホストしている場合は、StoreLocation に LocalMachine を指定し、IIS のアプリケーションプール ID に証明書の読み取り権限を付与してください。
Linux
Linux では、プリザンターの実行ユーザーで、.NET の CurrentUser\My ストアに証明書を追加するのが唯一の手順です。Authentication.json は StoreLocation を CurrentUser、StoreName を My にします。OS の CA トラストストアへの追加は、SigningCertificate の検索には関係しません(必要になる場面は後述)。
.NET の X509Store は Linux でどこを見るか
Microsoft Learn の「.NET でのクロスプラットフォーム暗号化」によると、Windows 以外の X509Store は「システムの信頼の決定(読み取り専用)、ユーザー信頼の決定(読み取り/書き込み)、ユーザー キー ストレージ(読み取り/書き込み)のプロジェクション」で、Windows の証明書ストアとは仕組みが違います。プリザンターに関係するストアは次のとおりです。
| ストア | Linux での実体と挙動 | 出典 |
|---|---|---|
CurrentUser\My | 実行ユーザーのホームの ~/.dotnet/corefx/cryptography/x509stores/my/ に、SHA-1 拇印をファイル名にして保存される。読み書きできる。既定では存在せず、最初の書き込みで作られるため、それまでは ExistingOnly で開くと失敗する | クロスプラットフォーム暗号化、ASP.NET Core で HTTPS を適用する |
LocalMachine\My | 開けない(CryptographicException がスローされる) | クロスプラットフォーム暗号化 |
LocalMachine\Root | OpenSSL の既定のパスにある CA バンドルを解釈したもの(読み取り専用)。update-ca-certificates などで更新されるのはこちら | クロスプラットフォーム暗号化 |
NSS のデータベース(~/.pki/nssdb)は、X509Store の投影先として挙げられていません。NSS の certutil(libnss3-tools などのパッケージ)は、Microsoft Learn でも「ブラウザーの証明書ストアを管理する」ツールとして扱われています(ASP.NET Core で HTTPS を適用する)。
これとプリザンターのソース(Saml.cs)を合わせると、Linux では次のようになります。
StoreLocationにLocalMachineを指定すると、ストアを開く時点で例外になります。CurrentUser以外は使えません。- 証明書を 1 件も追加していないユーザーでは
CurrentUser\Myがまだ存在しないので、OpenExistingOnlyで開けずに例外になります。 CurrentUserはプリザンターのプロセスを動かしているユーザーです。root でインポートしても、別ユーザーで動くプリザンターからは見えません。update-ca-certificates/update-ca-trustで更新されるのはLocalMachine\Root側で、NSS のcertutilは NSS のデータベースに書き込むだけなので、どちらもCurrentUser\Myには入りません。
手順
PowerShell 7(
pwsh)をインストールします。ディストリビューションごとの入手方法は対応表を参照してください。pwshは .NET 上で動くので、pwshからX509Store.Addを呼ぶと、プリザンターと同じ .NET のストアに書き込めます。証明書ファイルを、プリザンターの実行ユーザーが読める場所に置きます。
bashsudo install -d -m 755 /etc/pleasanter/certs sudo install -m 644 idp-certificate.pem /etc/pleasanter/certs/idp-certificate.pemプリザンターの実行ユーザーを確認します。systemd で動かしている場合は、ユニットの
User=を見ます(空なら root)。bashsystemctl show -p User pleasanter.service # 出力例: User=pleasanter次のスクリプトを置き、プリザンターの実行ユーザーで実行します。
sudo -Hでホームディレクトリを実行ユーザーのものに切り替えるのが大事です(ストアは$HOMEの下に作られます)。powershellparam( [string]$Path = '/etc/pleasanter/certs/idp-certificate.pem' ) $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($Path) $store = [System.Security.Cryptography.X509Certificates.X509Store]::new( [System.Security.Cryptography.X509Certificates.StoreName]::My, [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser) # ReadWrite で開くと、ストアが無ければここで作られる $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite) try { $store.Add($cert) } finally { $store.Close() } # FindValue に設定する拇印を表示 $cert.Thumbprintbashsudo -u pleasanter -H pwsh -NoProfile -File /etc/pleasanter/certs/import-idp-cert.ps1 \ -Path /etc/pleasanter/certs/idp-certificate.pem実行ユーザーから見えることを確認します。
bash# ストアのファイル(拇印.pfx)ができていること sudo -u pleasanter -H sh -c 'ls -la "$HOME/.dotnet/corefx/cryptography/x509stores/my/"' # .NET から見える証明書の一覧 sudo -u pleasanter -H pwsh -NoProfile -Command '$s = [System.Security.Cryptography.X509Certificates.X509Store]::new("My", "CurrentUser"); $s.Open("ReadOnly"); $s.Certificates | Format-Table Subject, Thumbprint; $s.Close()'Authentication.jsonのSigningCertificateを次のように設定し、プリザンターを再起動します。
"IdentityProviders": [
{
"EntityId": "https://idp.example.com/...",
"SignOnUrl": "https://idp.example.com/sso",
"SigningCertificate": {
"StoreName": "My",
"StoreLocation": "CurrentUser",
"X509FindType": "FindByThumbprint",
"FindValue": "A1B2C3D4E5F6..."
}
}
]WARNING
systemd のユニットで ProtectHome= を有効にしていたり、実行ユーザーのホームディレクトリが存在しなかったりすると、プリザンターから ~/.dotnet/corefx/cryptography/x509stores/ を読めません。インポートしたのに見つからないときは、ユニットの設定と実行ユーザーのホームを確認してください。
TIP
サーバーに PowerShell を入れたくない場合は、Docker と同じく、PowerShell 入りの .NET SDK コンテナで作ったストアのディレクトリ(x509stores)を、実行ユーザーのホームの ~/.dotnet/corefx/cryptography/x509stores/ にコピーする方法もあります。ディレクトリの所有者は実行ユーザーにしてください。
ディストリビューション別の対応表
CurrentUser\My へのインポートに必要なのは PowerShell 7 だけです。CA トラストストアの配置先と更新コマンドは、CA トラストストアに追加する必要がある場合だけ使います。
| 項目 | Debian / Ubuntu | RHEL / CentOS / AlmaLinux / Rocky Linux | SUSE / openSUSE | Alpine |
|---|---|---|---|---|
| PowerShell 7 の入手 | Microsoft のパッケージリポジトリから apt(Ubuntu / Debian) | Microsoft のパッケージリポジトリから dnf(RHEL) | Microsoft のサポート対象外。Snap や tar.gz で導入(コミュニティ サポート) | tar.gz から導入(Alpine) |
| CA 証明書の配置先 | /usr/local/share/ca-certificates/ | /etc/pki/ca-trust/source/anchors/ | /usr/share/pki/trust/anchors/ | /usr/local/share/ca-certificates/ |
| CA 証明書の推奨拡張子 | .crt | .pem | .pem | .crt |
| CA トラストストアの更新コマンド | update-ca-certificates | update-ca-trust | update-ca-certificates | update-ca-certificates |
| パッケージマネージャ | apt | dnf / yum | zypper | apk |
各ディストリビューションの対応状況は「Linux 用の PowerShell のサポート」を参照してください。.NET SDK が入っている環境なら dotnet tool install --global PowerShell でも入ります(PowerShell をインストールする別の方法)。
OS の CA トラストストアに追加する場合
OS の CA トラストストアに追加すると、.NET からは LocalMachine\Root として見えます(クロスプラットフォーム暗号化)。前述のとおり、SigningCertificate は CurrentUser\My で探し、見つけるときに信頼の検証もしないので、IdP の署名証明書をここに追加する必要はありません。
追加が必要なのは、プリザンターから HTTPS や LDAPS で接続する相手(IdP のメタデータの URL、LDAP サーバーなど)のサーバー証明書をプライベート CA が発行していて、その CA を OS に信頼させたい場合です。そのときは、対応表の配置先に CA の証明書を置いて更新コマンドを実行します。
# Debian / Ubuntu / Alpine(拡張子は .crt)
sudo cp private-ca.pem /usr/local/share/ca-certificates/private-ca.crt
sudo update-ca-certificates
# RHEL / CentOS / AlmaLinux / Rocky Linux
sudo cp private-ca.pem /etc/pki/ca-trust/source/anchors/private-ca.pem
sudo update-ca-trust
# SUSE / openSUSE
sudo cp private-ca.pem /usr/share/pki/trust/anchors/private-ca.pem
sudo update-ca-certificatesDocker
CurrentUser\My はコンテナの実行ユーザーのホームの下(root なら /root/.dotnet/corefx/cryptography/x509stores/)にできます。本体リポジトリの Dockerfile は USER を指定していないので、そのイメージのプリザンターは root で動きます(Dockerfile)。
起動中のコンテナの中でインポートしても、コンテナを作り直すと消えます。また、実行用の mcr.microsoft.com/dotnet/aspnet イメージには PowerShell が入っていません(PowerShell が入っているのは .NET SDK のイメージだけです。Docker での PowerShell の使用)。そのため、次のどちらかにします。
- SDK イメージでストアを作り、プリザンターのイメージにコピーする(マルチステージビルド)
- SDK コンテナでホスト側にストアを作り、ボリュームでマウントする
どちらも、Linux の手順の import-idp-cert.ps1 を使います。
マルチステージビルドでイメージに焼き込む
# 1. PowerShell が入っている .NET SDK イメージで、.NET の証明書ストアを作る
# (プリザンターと同じ .NET のメジャーバージョンのイメージを使う)
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS certstore
COPY import-idp-cert.ps1 idp-certificate.pem /tmp/
RUN pwsh -NoProfile -File /tmp/import-idp-cert.ps1 -Path /tmp/idp-certificate.pem
# 2. プリザンターのイメージに、ストアのディレクトリだけをコピーする
# (pleasanter-base は、本体リポジトリの Dockerfile でビルドしたイメージなどに置き換える)
FROM pleasanter-base:latest
COPY --from=certstore /root/.dotnet/corefx/cryptography/x509stores/ /root/.dotnet/corefx/cryptography/x509stores/USER で root 以外のユーザーに切り替えているイメージでは、そのユーザーのホームへ所有者を付けてコピーします。
COPY --from=certstore --chown=app:app /root/.dotnet/corefx/cryptography/x509stores/ /home/app/.dotnet/corefx/cryptography/x509stores/
USER appビルド後に、コンテナからストアが見えることを確認します。
docker exec pleasanter sh -c 'ls -la "$HOME/.dotnet/corefx/cryptography/x509stores/my/"'docker-compose でボリュームをマウントする
証明書を差し替えるたびにイメージを作り直したくない場合は、SDK コンテナでホスト側にストアを作り、プリザンターのコンテナにマウントします。ストアをボリュームに置くので、コンテナを作り直しても残ります。
# ./certs に idp-certificate.pem と import-idp-cert.ps1 を置いてから実行する
docker run --rm \
-v "$PWD/certs:/certs:ro" \
-v "$PWD/x509stores:/root/.dotnet/corefx/cryptography/x509stores" \
mcr.microsoft.com/dotnet/sdk:10.0 \
pwsh -NoProfile -File /certs/import-idp-cert.ps1 -Path /certs/idp-certificate.pemservices:
pleasanter:
image: pleasanter-base:latest
volumes:
# コンテナの実行ユーザー(ここでは root)のホームの下にマウントする
- ./x509stores:/root/.dotnet/corefx/cryptography/x509storesWARNING
証明書ファイル(.pem)をコンテナにマウントするだけでは、プリザンターは読みません。プリザンターが探すのは X509Store の中だけです(Saml.cs)。また、Dockerfile やエントリポイントで update-ca-certificates や NSS の certutil を実行しても、CurrentUser\My には入りません。
Azure App Service
- Azure ポータルで対象の App Service を開きます。
- 「証明書」メニューを開き、「公開キー証明書 (.cer) の追加」をクリックします。
- 名前に任意の識別名(例:
idp-certificate)を入力し、証明書ファイルをアップロードします。 - 一覧に表示された拇印(Thumbprint)をコピーします。
- 「構成」→「アプリケーション設定」で
WEBSITE_LOAD_CERTIFICATESに拇印を設定します(すべての証明書を読み込む場合は*)。 - 設定を保存し、App Service を再起動します。
WEBSITE_LOAD_CERTIFICATES で証明書がどこに読み込まれるかは、プランによって違います(アプリケーション コードで TLS/SSL 証明書を使用する)。
| プラン | 読み込み先 | プリザンターの設定 |
|---|---|---|
| Windows | Windows の証明書ストアの Current User\My | StoreLocation を CurrentUser、StoreName を My |
| Windows コンテナー(Server Core) | ファイルに加えて LocalMachine\My にも自動で読み込まれる | StoreLocation を LocalMachine、StoreName を My |
| Linux(組み込み・カスタムコンテナー) | ファイルとして /var/ssl/certs/<拇印>.der に置かれるだけ | X509Store からは見えないので、下記の方法にする |
"IdentityProviders": [
{
"EntityId": "https://idp.example.com/...",
"SignOnUrl": "https://idp.example.com/sso",
"SigningCertificate": {
"StoreName": "My",
"StoreLocation": "CurrentUser",
"X509FindType": "FindByThumbprint",
"FindValue": "A1B2C3D4E5F6..."
}
}
]WARNING
Windows プランでは、WEBSITE_LOAD_CERTIFICATES を設定しないと、アップロードした証明書がアプリのプロセスから参照できません。
Linux プランの場合
Linux の App Service では、WEBSITE_LOAD_CERTIFICATES の証明書は /var/ssl/certs にファイルとして置かれるだけで、Microsoft Learn でもファイルから読み込むコード例が示されています。プリザンターは証明書ファイルのパスを指定できず X509Store しか探さないため、この方法では SigningCertificate の証明書は見つかりません。Linux プランでは、Docker の手順で CurrentUser\My のストアを焼き込んだカスタムコンテナーを使ってください。
AWS
EC2
通常の Linux サーバーと同じ手順です。OS に合わせて Linux の手順を参照してください。
- Amazon Linux 2023:RHEL 系の手順
- Ubuntu on EC2:Debian / Ubuntu 系の手順
Elastic Beanstalk
Docker プラットフォームを使う場合は、Docker の手順でストアを焼き込んだイメージをデプロイするのがいちばん確実です。
.NET の Linux プラットフォームで動かす場合は、.ebextensions で証明書とスクリプトを配置し、アプリの実行ユーザーで import-idp-cert.ps1 を実行します。インスタンスに PowerShell 7 が入っている必要があります。実行ユーザー名(下の例の pleasanter)は環境に合わせて置き換えてください(ps -o user= -C dotnet などで確認できます)。
files:
"/etc/pleasanter/certs/idp-certificate.pem":
mode: "000644"
owner: root
group: root
content: |
-----BEGIN CERTIFICATE-----
MIIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(証明書の内容)
-----END CERTIFICATE-----
"/etc/pleasanter/certs/import-idp-cert.ps1":
mode: "000644"
owner: root
group: root
content: |
# Linux の手順の import-idp-cert.ps1 と同じ内容
commands:
01_import_idp_cert:
command: "sudo -u pleasanter -H pwsh -NoProfile -File /etc/pleasanter/certs/import-idp-cert.ps1 -Path /etc/pleasanter/certs/idp-certificate.pem"WARNING
IdP の署名証明書は公開鍵の証明書なので秘密情報ではありませんが、差し替えられると偽の IdP の署名を受け入れてしまいます。.ebextensions に証明書の内容を直接書く場合は、リポジトリの書き込み権限を十分に管理してください。
ECS(Fargate / EC2)
コンテナイメージに証明書ストアを焼き込むのが基本です。Docker の Dockerfile でカスタムイメージをビルドしてください。
証明書を差し替えるたびにイメージを作り直したくない場合は、Docker のボリュームの例と同じく、SDK コンテナで作ったストアのディレクトリ(x509stores)を EFS などのボリュームに置き、コンテナの /root/.dotnet/corefx/cryptography/x509stores にマウントします。証明書の PEM を Secrets Manager から環境変数やファイルで渡すだけでは、X509Store には入らないので読まれません。
Google Cloud
Cloud Run
コンテナベースのサービスなので、Docker の Dockerfile でストアを焼き込んだカスタムイメージをビルドし、Artifact Registry にプッシュしてデプロイします。
WARNING
Secret Manager のシークレットを .pem ファイルとしてマウントするだけでは、プリザンターは読みません(X509Store しか探さないため)。ストアはイメージに含めてください。
Compute Engine
通常の Linux サーバーと同じ手順です。OS に合わせて Linux の手順を参照してください。
環境別の設定サマリ
| 環境 | StoreLocation | StoreName | 備考 |
|---|---|---|---|
| Windows(IIS) | LocalMachine | My | アプリケーションプール ID に読み取り権限が必要 |
| Windows(Kestrel) | CurrentUser | My | 実行ユーザーの個人ストア |
| Linux 全般 | CurrentUser | My | 実行ユーザーで PowerShell 7 の X509Store.Add を実行し、~/.dotnet/corefx/cryptography/x509stores/my/ に入れる。LocalMachine は使えない |
| Docker | CurrentUser | My | SDK イメージで作ったストアをイメージにコピーするか、ボリュームでマウントする |
| Azure App Service(Windows) | CurrentUser | My | WEBSITE_LOAD_CERTIFICATES の設定が必須 |
| Azure App Service(Linux) | CurrentUser | My | ストアを焼き込んだカスタムコンテナーを使う(WEBSITE_LOAD_CERTIFICATES はファイルを置くだけ) |
| AWS ECS / Fargate | CurrentUser | My | コンテナイメージに焼き込むか、ボリュームでマウントする |
| Google Cloud Run | CurrentUser | My | コンテナイメージに焼き込む |
トラブルシューティング
よくあるエラーと対処
| 症状 | 原因 | 対処 |
|---|---|---|
| SAML ログインで例外になる(証明書が見つからない) | StoreLocation / StoreName / FindValue の不一致、ストアが存在しない | SigningCertificate の設定値とインポート先が一致しているか確認する。ストアが無いと OpenExistingOnly で開けずに例外になる |
| 拇印が一致しない | 拇印のコピーミス、大文字小文字の違い | openssl x509 -fingerprint で再確認し、コロンを除いた値を設定する |
Linux で StoreLocation を LocalMachine にすると例外になる | Linux の .NET は LocalMachine\My を開けない | CurrentUser にし、実行ユーザーの CurrentUser\My にインポートする |
| Linux / Docker でインポートしたのに見つからない | 別のユーザー(root など)のホームにインポートした、update-ca-certificates や NSS の certutil だけで済ませた | プリザンターの実行ユーザーで ls -la "$HOME/.dotnet/corefx/cryptography/x509stores/my/" を確認し、Linux の手順でインポートし直す |
Linux で certutil -user -addstore がエラーになる | Windows の certutil の書式で、Linux の NSS の certutil とは別物 | PowerShell 7 の X509Store.Add でインポートする(Linux の手順) |
| Azure App Service で証明書が読めない | Windows プランは WEBSITE_LOAD_CERTIFICATES 未設定。Linux プランはファイルが置かれるだけで X509Store から見えない | Windows プランはアプリケーション設定で拇印または * を設定する。Linux プランはストアを焼き込んだカスタムコンテナーにする |
| IIS で「アクセス拒否」エラー | アプリプールの権限不足 | certlm.msc で証明書を右クリック →「すべてのタスク」→「秘密キーの管理」からアプリプール ID に読み取り権限を付与する |
SysLogs テーブルで調べる
本体の SAML 認証処理(Saml.cs)は、SAML-MultiTenant で使うテナントごとのメタデータの読み込みに関するイベントを SysLogs テーブルに記録します(SetIdpConfiguration と SetIdpCache。Saml.cs)。Authentication.json の IdentityProviders に書いた IdP の証明書(SigningCertificate)は、後述の SetSPOptions の中で読み込まれるため、SysLogs には記録されません。
| 場面 | SysLogType | 値 | ErrMessage に含まれるキーワード |
|---|---|---|---|
| IdP キャッシュ登録成功 | Info | 10 | (正常時のログ) |
| SAML 設定が不完全(必須パラメータ不足) | Warning | 50 | Saml settings is incomplete |
| メタデータが見つからない | SystemError | 80 | Metadata not found |
| メタデータの形式が不正(証明書パース失敗を含む) | SystemError | 80 | Invalid metadata format |
メタデータ読み込み時の例外(X509Certificate2 関連など) | Exception | 90 | 例外メッセージ(e.Message)がそのまま記録される |
Info・Warning・SystemError の行は Method 列に SetIdpConfiguration が記録されます。Exception の行は例外用の SysLogModel で記録されるため、Method 列は SetIdpConfiguration ではなく、そのときのリクエストのアクション名になります(SysLogModel.cs)。下の 1 つ目の SQL は Exception の行を拾わないので、2 つ目の SQL と組み合わせて使います。
SAML 関連のエラーを抽出する SQL:
-- SAML 証明書関連のエラーを抽出(SystemError 以上)
SELECT
[SysLogId],
[CreatedTime],
[SysLogType],
[Method],
[ErrMessage],
[ErrStackTrace]
FROM [SysLogs]
WHERE [Method] LIKE '%SetIdpConfiguration%'
AND [SysLogType] >= 80
ORDER BY [CreatedTime] DESC;-- SAML 証明書関連のエラーを抽出(SystemError 以上)
SELECT
"SysLogId",
"CreatedTime",
"SysLogType",
"Method",
"ErrMessage",
"ErrStackTrace"
FROM "SysLogs"
WHERE "Method" LIKE '%SetIdpConfiguration%'
AND "SysLogType" >= 80
ORDER BY "CreatedTime" DESC;-- SAML 証明書関連のエラーを抽出(SystemError 以上)
SELECT
`SysLogId`,
`CreatedTime`,
`SysLogType`,
`Method`,
`ErrMessage`,
`ErrStackTrace`
FROM `SysLogs`
WHERE `Method` LIKE '%SetIdpConfiguration%'
AND `SysLogType` >= 80
ORDER BY `CreatedTime` DESC;例外メッセージから証明書関連のエラーを横断的に探す SQL:
-- 証明書関連の例外を横断検索
SELECT
[SysLogId],
[CreatedTime],
[SysLogType],
[ErrMessage]
FROM [SysLogs]
WHERE [ErrMessage] LIKE '%certificate%'
OR [ErrMessage] LIKE '%X509%'
OR [ErrMessage] LIKE '%PEM%'
ORDER BY [CreatedTime] DESC;-- 証明書関連の例外を横断検索
SELECT
"SysLogId",
"CreatedTime",
"SysLogType",
"ErrMessage"
FROM "SysLogs"
WHERE "ErrMessage" LIKE '%certificate%'
OR "ErrMessage" LIKE '%X509%'
OR "ErrMessage" LIKE '%PEM%'
ORDER BY "CreatedTime" DESC;-- 証明書関連の例外を横断検索
SELECT
`SysLogId`,
`CreatedTime`,
`SysLogType`,
`ErrMessage`
FROM `SysLogs`
WHERE `ErrMessage` LIKE '%certificate%'
OR `ErrMessage` LIKE '%X509%'
OR `ErrMessage` LIKE '%PEM%'
ORDER BY `CreatedTime` DESC;INFO
SysLogs へのデータベース記録は Parameters/SysLog.json の EnableLoggingToDatabase が true(既定値)のときに有効です。無効にしている場合は EnableLoggingToFile を true にし、NLog 経由のファイルログを確認してください。
WARNING
SetSPOptions 内では SysLogs への書き込みが行われません。SetSPOptions では SP 側の証明書(ServiceCertificates)に加えて、Authentication.json の IdentityProviders の署名証明書(SigningCertificate)も読み込みます(Saml.cs)。シングルテナントの SAML で証明書が読めないときは、ここで例外になるため、アプリケーションログ(stdout / stderr)を確認してください。
- Windows(IIS):
web.configでstdoutLogEnabledをtrueにし、stdoutLogFileに指定されたパス(既定は.\logs\stdout)のログファイルを確認する - Windows(Kestrel 直接実行): コンソールウィンドウの出力を確認する。サービス登録している場合は Windows イベントビューアーも確認する
- Linux(systemd):
journalctl -u pleasanter.service -eで直近のログを確認する - Docker:
docker logs <コンテナ名>でコンテナの標準出力・標準エラーを確認する - Azure App Service: Azure ポータルの「ログストリーム」または Kudu(
https://<app>.scm.azurewebsites.net)で確認する
証明書の有効期限
期限切れの証明書ではログインに失敗するため、定期的に確認します。
# 有効期限を確認
openssl x509 -in certificate.pem -noout -dates
# 出力例:
# notBefore=Jan 1 00:00:00 2026 GMT
# notAfter=Dec 31 23:59:59 2027 GMT# PowerShell で有効期限を確認
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("certificate.pem")
$cert.NotAfterWARNING
IdP 側で証明書が更新された場合は、プリザンター側でも新しい証明書をインポートし直し、Authentication.json の FindValue を新しい拇印に更新する必要があります。Linux / Docker では、新しい証明書も同じ実行ユーザーの CurrentUser\My に入れてください(Docker で焼き込んでいる場合はイメージの再ビルドが必要です)。