AWS Workload Credentials ProviderでACMエクスポート可能証明書のデプロイを自動化してみた
はじめに
2026年6月11日、AWS Workload Credentials Provider(以降「WCP」と略記)が発表されました。
ACMエクスポート可能パブリック証明書は有効期間198日で、期限の45日前にACMが自動更新します。しかし、更新された証明書をサーバーにデプロイするのは利用者の責任でした。CA/Bフォーラムの証明書有効期間短縮マンデートにより更新頻度が上がることを考えると、手動運用の負荷は大きくなります。
WCPのCertificate Management機能は、この課題に対応する仕組みを提供します。
| 項目 | 従来 | WCP 導入後 |
|---|---|---|
| 証明書エクスポート | 手動 or EventBridge + Lambda | WCP が自動実行 |
| ファイル配置 | カスタムスクリプト | WCP が書き出し |
| サーバーリロード | カスタムスクリプト | refresh_command で自動実行 |
| 更新チェック | EventBridge / cron等で自前設計 | 24 時間ごとに自動チェック |
| 冪等性 | 自前で実装 | 差分なしならスキップ |
今回はEC2上のApache (httpd) とNginxに対してWCPを設定し、証明書の自動配置とサーバーリロードが動作することを確認します。
公式ドキュメント:
検証環境
| 項目 | 値 |
|---|---|
| リージョン | ap-northeast-1 |
| EC2 インスタンス | t3a.small / AL2023 |
| ウェブサーバー | httpd (Apache 2.4) on :443 / Nginx on :8443 |
| WCP | v3.0.0 |
| ドメイン | wcp-demo.example.com |
IAM構成:
- IAMユーザー
wcp-demo-user:sts:AssumeRoleのみ(オンプレ想定のAccess Key認証) - IAMロール
wcp-demo-role:acm:ExportCertificate,acm:DescribeCertificate(証明書ARN限定。今回の検証ではDescribeCertificateも付与)
環境クレデンシャルにはAssumeRole権限のみを持たせ、ACM操作権限はロール側に分離しています。
事前準備: エクスポート可能な ACM 証明書
エクスポート可能なACMパブリック証明書の発行が前提です。発行操作上の主な違いは、リクエスト時に「エクスポート可能」を有効化する点です。なお、エクスポート可能証明書はFQDN証明書で7 USD、ワイルドカード証明書で79 USDが発行時および更新時に発生します(2026年6月時点)。


発行手順の詳細は以下の記事を参照してください。
CLIでの発行例(今回の検証と同じEC-prime256v1):
aws acm request-certificate \
--domain-name wcp-demo.example.com \
--validation-method DNS \
--key-algorithm EC_prime256v1 \
--options ExportOption=ENABLED \
--region ap-northeast-1
Before: 手動エクスポート+デプロイ
WCP導入前の手順を示します。
# パッケージインストール
sudo dnf install -y httpd mod_ssl nginx jq
# 証明書エクスポート(--passphrase は blob 型のため Base64 エンコード値を指定)
# temppass は検証用。本番では十分な強度のパスフレーズを使用する
aws acm export-certificate \
--certificate-arn arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
--passphrase $(echo -n 'temppass' | base64) \
--region ap-northeast-1 \
--output json > cert-export.json
# JSON から各ファイルを抽出
jq -r '.Certificate' cert-export.json > certificate.pem
jq -r '.CertificateChain' cert-export.json > chain.pem
jq -r '.PrivateKey' cert-export.json > encrypted_key.pem
# 秘密鍵のパスフレーズ解除
openssl pkey -in encrypted_key.pem -out private.key -passin pass:temppass
# fullchain 作成・配置
cat certificate.pem chain.pem > fullchain.pem
sudo mkdir -p /etc/ssl/acm
sudo cp fullchain.pem /etc/ssl/acm/
sudo cp private.key /etc/ssl/acm/
sudo chmod 600 /etc/ssl/acm/private.key
# httpd SSL 設定
sudo sed -i 's|^SSLCertificateFile.*|SSLCertificateFile /etc/ssl/acm/fullchain.pem|' /etc/httpd/conf.d/ssl.conf
sudo sed -i 's|^SSLCertificateKeyFile.*|SSLCertificateKeyFile /etc/ssl/acm/private.key|' /etc/httpd/conf.d/ssl.conf
sudo systemctl start httpd && sudo systemctl enable httpd
# Nginx デフォルトポートを変更(httpd の 80 番と競合回避)
sudo sed -i 's/listen 80;/listen 8080;/' /etc/nginx/nginx.conf
sudo sed -i 's/listen \[::]:80;/listen [::]:8080;/' /etc/nginx/nginx.conf
# Nginx SSL 設定(8443 ポート、httpd と共存)
sudo tee /etc/nginx/conf.d/ssl.conf > /dev/null << 'EOF'
server {
listen 8443 ssl;
server_name wcp-demo.example.com;
ssl_certificate /etc/ssl/acm/fullchain.pem;
ssl_certificate_key /etc/ssl/acm/private.key;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
EOF
sudo systemctl start nginx && sudo systemctl enable nginx
# 疎通確認
curl -sk https://localhost # httpd (443)
curl -sk https://localhost:8443 # Nginx (8443)
# 一時ファイル削除(秘密情報を含むため)
rm -f cert-export.json certificate.pem chain.pem fullchain.pem encrypted_key.pem private.key
数ヶ月ごとにこの手順を繰り返す運用は、対象が増えるほど負担が大きくなります。
After: WCP による自動化
ここからはEC2上でrootユーザーとして実行します。
IAM ユーザー・ロール作成
WCPの環境クレデンシャル用のIAMユーザーと、ACMエクスポート権限を持つIAMロールを作成します。
# ユーザー作成
aws iam create-user --user-name wcp-demo-user
# ロール作成(ユーザーからAssumeRole可能)
aws iam create-role \
--role-name wcp-demo-role \
--assume-role-policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Principal":{"AWS":"arn:aws:iam::123456789012:user/wcp-demo-user"},
"Action":"sts:AssumeRole"
}]
}'
# ロールにACMエクスポート権限を付与
aws iam put-role-policy \
--role-name wcp-demo-role \
--policy-name acm-export-policy \
--policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Action":["acm:ExportCertificate","acm:DescribeCertificate"],
"Resource":"arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}]
}'
# ユーザーにAssumeRole権限を付与
aws iam put-user-policy \
--user-name wcp-demo-user \
--policy-name assume-role-policy \
--policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Action":"sts:AssumeRole",
"Resource":"arn:aws:iam::123456789012:role/wcp-demo-role"
}]
}'
# Access Key発行(出力にSecretAccessKeyが含まれるため取り扱い注意)
aws iam create-access-key --user-name wcp-demo-user
acm:GetCertificate は今回の構成では付与せず正常に動作しました。acm:DescribeCertificate はREADMEのRequired permissionsには記載されていませんが、今回の検証では付与した状態で確認しています。
WCP のビルド
# スワップ追加
dd if=/dev/zero of=/swapfile bs=1M count=2048
chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
# 開発ツール・Rust インストール
dnf -y groupinstall "Development Tools"
dnf -y install git
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
export PATH=/root/.cargo/bin:$PATH
# ソース取得・ビルド
git clone --branch v3.0.0 https://github.com/aws/aws-workload-credentials-provider.git /opt/aws-wcp
cd /opt/aws-wcp
cargo build --release
ビルド所要時間は約10分、生成されるバイナリは27MBです。
WCPはRust製のため、ソースからビルドする場合はある程度のメモリが必要です。t3a.micro (2 vCPU / 1 GiB) ではメモリ不足で cargo build が失敗しました。今回はt3a.small (2 vCPU / 2 GiB) に2GBスワップを追加しています。実行環境にはビルドツールチェーンを持ち込まず、別環境でビルドしたバイナリをコピーして利用することを推奨します。
バイナリ配置・専用ユーザー作成
# バイナリ配置
mkdir -p /opt/aws/workload-credentials-provider/bin
cp /opt/aws-wcp/target/release/aws-workload-credentials-provider \
/opt/aws/workload-credentials-provider/bin/
chmod +x /opt/aws/workload-credentials-provider/bin/aws-workload-credentials-provider
mkdir -p /opt/aws/workload-credentials-provider/logs
# 専用ユーザー・グループ作成
useradd -r -s /sbin/nologin aws-wcp
groupadd -f awscreds
usermod -a -G awscreds aws-wcp
# ディレクトリ所有権
chown root:root /opt/aws/workload-credentials-provider
chmod 0755 /opt/aws/workload-credentials-provider
chown -R root:root /opt/aws/workload-credentials-provider/bin
chmod 0755 /opt/aws/workload-credentials-provider/bin/aws-workload-credentials-provider
chown -R aws-wcp:aws-wcp /opt/aws/workload-credentials-provider/logs
chmod 0750 /opt/aws/workload-credentials-provider/logs
# 証明書配置先ディレクトリ
mkdir -p /etc/ssl/acm
chown -R aws-wcp:aws-wcp /etc/ssl/acm
WCPは専用システムユーザー aws-wcp(ログインシェルなし)として動作します。
config.toml 作成
デフォルトパス /etc/aws-workload-credentials-provider/config.toml に配置します。
[logging]
log_level = "DEBUG"
log_to_file = true
[capabilities.secrets_manager]
enabled = false
[capabilities.acm]
enabled = true
[[capabilities.acm.certificates]]
certificate_arn = "arn:aws:acm:ap-northeast-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
certificate_path = "/etc/ssl/acm/fullchain.pem"
private_key_path = "/etc/ssl/acm/private.key"
role_arn = "arn:aws:iam::123456789012:role/wcp-demo-role"
refresh_command = "/usr/local/bin/reload-webservers.sh"
certificate_and_chain_permission = { mode = "0644" }
key_permission = { mode = "0600" }
mkdir -p /etc/aws-workload-credentials-provider
# (上記内容を config.toml として保存)
chown root:awscreds /etc/aws-workload-credentials-provider/config.toml
chmod 0640 /etc/aws-workload-credentials-provider/config.toml
主な設定項目:
| 項目 | 説明 |
|---|---|
certificate_arn |
ACM 証明書の ARN |
certificate_path |
証明書 PEM の書き出し先(chain_path 省略時は fullchain として結合) |
private_key_path |
秘密鍵の書き出し先 |
chain_path |
チェーン証明書(省略時は certificate_path に fullchain として結合) |
role_arn |
証明書エクスポートに使う IAM ロール |
refresh_command |
証明書ファイル書き出し後に実行するコマンド |
今回は chain_path を省略し、fullchainモードを使用しています。httpd / Nginxともに同じ fullchain.pem を参照する構成です。
検証では log_level = "DEBUG" としていますが、本番では INFO 等に変更し、ログローテーションも検討してください。ログ出力先は /opt/aws/workload-credentials-provider/logs です。
reload スクリプト
cat > /usr/local/bin/reload-webservers.sh << 'EOF'
#!/bin/bash
set -euo pipefail
/bin/systemctl reload httpd
/usr/sbin/nginx -s reload
EOF
chown root:root /usr/local/bin/reload-webservers.sh
chmod 755 /usr/local/bin/reload-webservers.sh
WCPは sudo -n <refresh_command> として実行するため、スクリプト内に sudo は不要です。スクリプトはroot所有・一般ユーザー書き換え不可とします。シェル構文(パイプ、&&、リダイレクト等)は解釈されないため、複数コマンドが必要ならラッパースクリプトを指定してください。
setup-config-based-permissions の実行
/opt/aws/workload-credentials-provider/bin/aws-workload-credentials-provider \
setup-config-based-permissions \
--config /etc/aws-workload-credentials-provider/config.toml
このコマンドにより以下が自動生成されます。
sudoers (/etc/sudoers.d/aws-workload-credentials-provider):
aws-wcp ALL=(ALL) NOPASSWD: /usr/local/bin/reload-webservers.sh
systemd drop-in (/etc/systemd/system/aws-workload-credentials-provider-acm.service.d/cert-paths.conf):
[Service]
ReadWriteDirectories=/etc/ssl/acm /opt/aws/workload-credentials-provider/logs
setup-config-based-permissions はconfig.tomlの内容からsudoersとsystemd drop-inを生成するため、生成時点での設定乖離を抑えられます。config.tomlを変更した場合は再実行が必要です。
なお、setup-config-based-permissions はv3.0.0のREADMEでは独立した手順として明示されていません。今回は --help と実機検証で挙動を確認し、手動構成に権限設定だけを取り込む目的で利用しています。公式の主導線は install スクリプトです。
systemd サービス・起動
cat > /etc/systemd/system/aws-workload-credentials-provider-acm.service << 'EOF'
[Unit]
Description=AWS Workload Credentials Provider - ACM
After=network-online.target
Wants=network-online.target
[Service]
User=aws-wcp
WorkingDirectory=/opt/aws/workload-credentials-provider
Type=simple
Restart=on-failure
RestartSec=5s
TimeoutSec=1min
ExecStart=/opt/aws/workload-credentials-provider/bin/aws-workload-credentials-provider acm start
[Install]
WantedBy=multi-user.target
EOF
# AWS 認証情報を drop-in で設定
mkdir -p /etc/systemd/system/aws-workload-credentials-provider-acm.service.d
cat > /etc/systemd/system/aws-workload-credentials-provider-acm.service.d/creds.conf << 'EOF'
[Service]
Environment="AWS_ACCESS_KEY_ID=<ACCESS_KEY>"
Environment="AWS_SECRET_ACCESS_KEY=<SECRET_KEY>"
Environment="AWS_REGION=ap-northeast-1"
EOF
chown root:root /etc/systemd/system/aws-workload-credentials-provider-acm.service.d/creds.conf
chmod 0600 /etc/systemd/system/aws-workload-credentials-provider-acm.service.d/creds.conf
# 起動
systemctl daemon-reload
systemctl enable --now aws-workload-credentials-provider-acm
--config オプションなしで起動します。WCPはデフォルトで /etc/aws-workload-credentials-provider/config.toml を読み込みます。
今回はオンプレ想定のためAccess Key認証を使用しましたが、EC2ならインスタンスプロファイル、オンプレならIAM Roles Anywhereも選択肢になります。
なお、今回のAL2023環境では、公式の install スクリプトで生成されたunitのハードニング設定(NoNewPrivileges 等)により refresh_command の sudo -n が失敗しました。そのため手動でunitを作成しています。setup-config-based-permissions でsudoersと ReadWriteDirectories の設定のみを取り込みました。
また、クリーンインストール時は証明書ファイルが存在しないとhttpd / Nginxが起動できません。一方、ウェブサーバー未起動時に refresh_command(reload)を実行すると失敗します。今回はBefore手順でhttpd / Nginxが起動済みの状態からWCPを導入したため問題は発生しませんでした。クリーン環境で構築する場合は、初回のみ手動で証明書を配置するか、未起動時も考慮したrefresh_command(reload-or-restart 等)を検討してください。
動作確認
起動後のログ(成功時):
INFO ACM Scheduler starting with 1 certificate(s)
INFO Certificate task started for arn:aws:acm:...
INFO Starting certificate refresh
INFO Certificate files written
INFO Running refresh command: first cycle after provider startup
INFO Refresh command succeeded
INFO Certificate refresh successful
WCPは以下の流れで動作しました:
- STS AssumeRoleで一時認証情報を取得
- ACM ExportCertificateで証明書をエクスポート
- 証明書ファイルを書き出し
refresh_commandを実行(httpd reload + Nginx reload)
サービス再起動後の初回サイクルでも、証明書に差分がない場合は「Certificate files written」「Running refresh command」が出力されず、スキップされることを確認しました(冪等動作)。
証明書内容の確認:
# WCP が書き出したファイル
openssl x509 -in /etc/ssl/acm/fullchain.pem -noout -subject -issuer -serial -dates
# httpd / Nginx が配信している証明書
openssl s_client -connect localhost:443 -servername wcp-demo.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -serial -dates
openssl s_client -connect localhost:8443 -servername wcp-demo.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -serial -dates
ファイル中のリーフ証明書と、サーバーが配信しているリーフ証明書のsubject / issuer / serial / datesが一致しており、WCPによる配置とreloadが動作していることを確認できました。秘密鍵は aws-wcp 所有・0600ですが、httpd / Nginxはroot権限のmaster processが秘密鍵を読み込むため、reload時にパーミッションの問題は発生しません。
refresh_commandの権限経路:
WCP (User=aws-wcp)
→ sudo -n /usr/local/bin/reload-webservers.sh
→ /etc/sudoers.d/aws-workload-credentials-provider で NOPASSWD 許可
→ root として reload スクリプト実行
→ httpd reload + nginx reload
まとめ
AWS Workload Credentials ProviderのCertificate Management機能を使い、ACMエクスポート可能証明書の初回取得、ファイル配置、Webサーバーのreload、差分なし時のスキップ動作を確認しました。
従来は、証明書エクスポート、秘密鍵のパスフレーズ解除、ファイル配置、Webサーバーのreloadを手動またはカスタムスクリプトで実装する必要がありました。WCPでは、必要なIAM・systemd・sudoers設定を行ったうえで、config.tomlに証明書ARN、出力先パス、refresh_commandを定義することで、これらの処理を自動化できます。
なお、今回はACM側の実更新日をまたいだ差し替えまでは検証していません。更新後の証明書差し替えについては、WCPの24時間ごとの定期チェック仕様に基づく整理です。
ACMエクスポート可能証明書をEC2やオンプレミス上のWebサーバーで利用する構成では、証明書更新時のデプロイ作業を減らす選択肢としてWCPを検討できそうです。
参考リンク






