証明書をユーザ権限によって振り分けて証明書ストアに登録するバッチ
要件
- 証明書をバッチでWindowsマシンにインストールしたい
- 証明書は2件あり、それぞれ「信頼されたルート証明機関」「中間証明機関」にインストールしたい
- バッチを実行したユーザの権限によって処理を分けたい
- 管理者権限を持つ場合
- コマンドプロンプトを管理者権限で実行した場合には、ローカルコンピュータの証明書ストアにインストール
- コマンドプロンプトを管理者権限なしに実行した場合には、管理者権限を持つコマンドプロンプトを起動して、ローカルコンピュータの証明書ストアにインストール
- 管理者権限を持たない場合
- 既にローカルコンピュータの証明書ストアに証明書がある場合には、インストール処理をスキップ
- ローカルコンピュータ、カレントユーザの証明書ストアの両方に証明書がない場合は、カレントユーザにインストール処理を実行する
- 管理者権限を持つ場合
- バッチを実行したログを残したい
実行環境
Windows7, 8.1, 10
(UACは有効無効どちらも対応)
難しかったところ
管理者権限ありユーザの挙動
- バッチを叩いて実行した場合、管理者権限として実行されるか、権限実行なしで実行されるか分からない(確実に管理者権限で実行する方法をご存知の方、ご教授ください…)
- 上記理由により、管理者ユーザが管理者権限なしコマンドプロンプトでバッチを実行してしまった場合に備えて、参考記事のコマンドプロンプトの昇格処理を追加した。
- ただし、管理者権限なしユーザで上記バッチをそのまま実行すると昇格無限ループに陥ってしまうため、管理者権限での実行タイミングで引数を設定し、その引数付でバッチが起動されたら、カレントユーザ用処理に移行するようにした。
参考)
バッチファイル(*.bat) を管理者として実行するための バッチファイル
http://qiita.com/jTakasuRyuji/items/e7bd576ed57969b2d06e
管理者権限なしユーザの挙動
- カレントユーザにCA証明書をインストールしようとすると、登録確認ダイアログが出てくる。
- 既に同じPCにおいて管理者権限ユーザでバッチを実行し、ローカルコンピュータに証明書が入っている場合、カレントユーザに証明書がなくても、状態としてはインストール不要
- カレントユーザからローカルコンピュータに指定証明書があるかのチェックを入れて、入ってたら、処理スキップ。なかったら仕方ないのでカレントユーザに証明書インストール
証明書インストール起動バッチ
(ユーザにはこちらのバッチを実行してもらう)
certexecute.bat
@echo off
rem -- カレントディレクトリを基準とする
cd /d %~dp0
rem -- バッチの実行結果をログとして出力する
cmd.exe /c certinstall.bat >> result.log 2>&1
証明書インストールバッチ
(これ単体でも起動可能)
certinstall.bat
@echo off
echo **** 証明書インストール処理: %date% %time%
SETLOCAL enabledelayedexpansion
rem -- SAMPLE1証明書のファイル名
set SAMPLE1_CERT_NAME=<sample1.cer>
rem -- SAMPLE2証明書のファイル名
set SAMPLE2_CERT_NAME=<sample2.cer>
rem -- SAMPLE1証明書のシリアル番号, サブジェクト
set SAMPLE1_CERT_SERIAL=<aaaaaaa>
set SAMPLE1_CERT_SERIAL_SUBJECT="OU=<aa>, OU=<aaa>, O=<aaaaa>"
rem -- SAMPLE2証明書のシリアル番号, サブジェクト
set SAMPLE2_CERT_SERIAL=<bbbbbbb>
set SAMPLE2_CERT_SUBJECT="CN=<bb>, OU=<bbb>, OU=<bbbb>, O=<bbbbb>"
rem -- カレントディレクトリを基準とする
cd /d %~dp0
:checkMandatoryLevel
rem --- ▼管理者として実行されているか確認 START
for /f "tokens=1 delims=," %%i in ('whoami /groups /FO CSV /NH') do (
if "%%~i"=="BUILTIN\Administrators" set ADMIN=yes
if "%%~i"=="Mandatory Label\High Mandatory Level" set ELEVATED=yes
)
echo ADMIN=%ADMIN%
echo ELEVATED=%ELEVATED%
if "%ADMIN%" neq "yes" (
rem -- Administratorsグループでない(ローカルユーザの場合)
echo カレントユーザにのみ証明書をインストールします。
rem --- 証明書コピーSAMPLE1確認処理
CALL :checkUserCertificationSAMPLE1
goto exit1
)
if "%ELEVATED%" neq "yes" (
rem -- (プロセスが昇格されていない) Admin権限ありユーザが通常実行した場合
echo このファイルは管理者権限での実行が必要です
echo 昇格を行いますので、しばらくお待ちください
goto runas
)
rem --- ▲管理者として実行されているか確認 END
:admins
rem --- ▼管理者として実行したいコマンド START
rem --- 証明書コピー処理
echo ローカルコンピュータに証明書をインストールします。
CALL :copyCertification
rem --- ▲管理者として実行したいコマンド END
goto exit1
:runas
if "%1" == "" (
rem --- 引数なしのため、★管理者として再実行
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "Start-Process %~f0 REPEATED -Verb runas"
) else (
rem --- 引数ありのため、すでに自身を再実行している。
rem --- カレントユーザにのみインストール
echo 管理者への昇格に失敗しました。カレントユーザにのみ証明書をインストールします。
rem --- 証明書コピーSAMPLE1確認処理
CALL :checkUserCertificationSAMPLE1
)
goto exit1
rem --- ローカルコンピュータ用コピー処理サブルーチン
:copyCertification
ECHO コピー処理実施: SAMPLE1証明書
rem -- SAMPLE1証明書を強制上書きインストールする
rem -- ローカル コンピューター:信頼されたルート証明機関
certutil -addstore -f ROOT %SAMPLE1_CERT_NAME%
ECHO コピー処理実施: SAMPLE2証明書
rem -- SAMPLE2証明書を強制上書きインストールする
rem -- ローカル コンピューター:中間証明機関
certutil -addstore -f CA %SAMPLE2_CERT_NAME%
exit /B
rem --- カレントユーザ用コピーSAMPLE1確認処理サブルーチン
:checkUserCertificationSAMPLE1
rem --- ローカルマシンに既にSAMPLE1証明書が入っているか
verify >nul
certutil -verifystore ROOT %SAMPLE1_CERT_SERIAL% | findstr %SAMPLE1_CERT_SERIAL_SUBJECT%
rem -- 見つからなかった(エラー)の場合、コピー
IF '%ERRORLEVEL%'=='1' goto copyUserCertificationSAMPLE1
rem -- 見つかった(正常)の場合、スキップ
IF '%ERRORLEVEL%'=='0' goto skipUserCertificationSAMPLE1
exit /B
rem --- カレントユーザ用SAMPLE1証明書スキップサブルーチン
:skipUserCertificationSAMPLE1
ECHO SAMPLE1証明書:ローカルコンピュータに証明書ありの為、処理スキップ
rem -- SAMPLE2証明書チェック
CALL :checkUserCertificationSAMPLE2
exit /B
rem --- カレントユーザ用SAMPLE1証明書コピーサブルーチン
:copyUserCertificationSAMPLE1
ECHO コピー処理実施: SAMPLE1証明書
rem -- SAMPLE1証明書をインストールする
rem -- カレントユーザ:信頼されたルート証明機関
certutil -user -addstore -f ROOT %SAMPLE1_CERT_NAME%
rem -- SAMPLE2証明書チェック
CALL :checkUserCertificationSAMPLE2
exit /B
rem --- カレントユーザ用コピーSAMPLE2証明書確認処理サブルーチン
:checkUserCertificationSAMPLE2
rem --- ローカルマシンに既にSAMPLE2明書が入っているか
verify >nul
certutil -verifystore CA %SAMPLE2_CERT_SERIAL% | findstr %SAMPLE2_CERT_SUBJECT%
rem -- 見つからなかった(エラー)の場合、コピー
IF '%ERRORLEVEL%'=='1' goto copyUserCertificationSAMPLE2
rem -- 見つかった(正常)の場合、スキップ
IF '%ERRORLEVEL%'=='0' goto skipUserCertificationSAMPLE2
exit /B
rem --- カレントユーザ用SAMPLE2証明書スキップサブルーチン
:skipUserCertificationSAMPLE2
ECHO SAMPLE2証明書:ローカルコンピュータに証明書ありの為、処理スキップ
exit /B
rem --- カレントユーザ用SAMPLE2証明書コピーサブルーチン
:copyUserCertificationSAMPLE2
ECHO コピー処理実施: SAMPLE2証明書
rem -- SAMPLE2証明書をインストールする
rem -- カレントユーザ:中間証明機関
certutil -user -addstore -f CA %SAMPLE2_CERT_NAME%
exit /B
:exit1
exit