1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エクスポートしたACMの証明書で自動更新のアップデートがあったので試してみた

1
Posted at

ご挨拶

こんにちは、白"雪姫"です。
皆様、セキュリティ対策、効率よくは進んでますか?

前回の記事でACM証明書をエクスポートしてオンプレミスのnginxに設置するをやりましたが、あの記事の最後に書いた「自動更新されないため、有効期限の管理が必要」という課題。

これを解決するツールが AWS Workload Credentials Provider(WCP) です。
v3.0.0で安定してきたので実際に導入してみました。

前回のおさらい

前回の記事では、ACMからエクスポートした証明書をnginxに手動で配置しました。

ACMからエクスポートした証明書は、ACMの自動更新の恩恵を受けられません。有効期限前に手動でエクスポート→再配置が必要です。

この「手動でエクスポート→再配置」をどうにか自動化したい。そこで出てくるのがWCPです。

AWS Workload Credentials Provider とは

ACM証明書のエクスポートとローカルへの配置を自動化する軽量クライアントです。

項目 内容
機能 ACM証明書の定期エクスポート+ファイル配置の自動化
対応OS Linux (RPM/Deb), Windows, コンテナ
対応Web Apache / NGINX
対象ホスト EC2 および オンプレミス
最新版 v3.0.0
動作形態 systemdサービスとして常駐

証明書の有効期限が近づくとACMが自動更新 → WCPが検知して再エクスポート → ファイルを差し替え → Webサーバをリロード、という流れを全自動でやってくれます。

今回の環境

項目
対象サーバ AlmaLinux 9.7 (オンプレミス)
Webサーバ nginx 1.20.1
証明書 *.lovelive-presents.com (ACM発行, us-east-1)
有効期限 2026-12-15
AWS CLI 2.16.4

導入手順

1. IAMの準備(最小権限・構成タイプ③)

WCP用に最小権限のIAM構成を組みます。ルートキーの利用は絶対にやめましょう。

リソース 役割 権限
IAMユーザ wcp-cert-export-base 土台ユーザ sts:AssumeRole のみ
IAMロール wcp-cert-export-role 実行ロール acm:ExportCertificate, acm:DescribeCertificate (対象ARN限定)

信頼関係はロールが土台ユーザのみを信頼する形にします。

前回の記事から引き続きIAM Roles Anywhereを利用されている方は、そちらの認証基盤を流用するのもありです。

2. 対象証明書の確認

エクスポート可能な証明書である必要があります。

aws acm describe-certificate \
  --region us-east-1 \
  --certificate-arn "arn:aws:acm:us-east-1:<ACCOUNT_ID>:certificate/<CERT_ID>" \
  --query 'Certificate.Options.CertificateTransparencyLoggingPreference'

list-certificatesKeyTypesにエクスポート可能と表示されない場合は、describe-certificateで確認してください。エクスポート不可の場合は再発行が必要です。

3. WCPのビルドとインストール

v3.0.0はビルド済みバイナリが配布されていなかったため、サーバ上でRustビルドしました。

# Rustのインストール(sudo不要)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# ビルド(gcc, openssl-develは既存)
cargo build --release

インストールはconfig.tomlを作成してから実行します。

sudo ./install --config ~/wcp-config.toml --no-start

これにより以下が生成されます:

  • aws-wcp ユーザ
  • systemd ユニット(acm, sm, token の3つ)
  • sudoers 設定
  • 証明書パスのdrop-in設定

今回はACM証明書の管理のみなので、sm(Secrets Manager)とtoken は disable にしました。

4. config.toml の設定

[acm]
certificate_arn = "arn:aws:acm:us-east-1:<ACCOUNT_ID>:certificate/<CERT_ID>"
role_arn = "arn:aws:iam::<ACCOUNT_ID>:role/wcp-cert-export-role"
region = "us-east-1"
certificate_path = "/etc/nginx/ssl/acm/fullchain.pem"
private_key_path = "/etc/nginx/ssl/acm/privkey.pem"

認証情報は ProtectHome=true 対策のため、/opt/aws/workload-credentials-provider/.aws/ に配置し、aws-wcp所有・パーミッション600としています。

5. 遭遇した問題:nginx reloadが失敗する

ここが今回一番ハマったポイントです。

問題

config.tomlの refresh_commandnginx -s reload を設定したところ、exit 1 で失敗。

原因

WCPの acm.servicePrivateDevices=yes でハードニングされています。
これにより実効的に NoNewPrivileges が強制ONとなり、setuidな sudo -n が動作しません。

no new privileges flag is set

systemctl showでは NoNewPrivileges=no と表示されるのですが、PrivateDevices=yes が暗黙的にONにしてしまう罠です。

解決策:権限分離アーキテクチャ

acm.serviceのサンドボックスを一切弱めず、reloadを別の特権ユニットに分離しました。

acm.service (aws-wcp, 完全サンドボックス)
  └ 定期的に ACM から証明書をエクスポート
     内容に変更があれば atomic rename で
     /etc/nginx/ssl/acm/{fullchain.pem, privkey.pem} を更新
        │ (ファイル変更を inotify 検知)
        ▼
wcp-nginx-reload.path → wcp-nginx-reload.service (root)
     └ nginx -t && nginx -s reload

wcp-nginx-reload.path

[Unit]
Description=Watch ACM certificate for changes

[Path]
PathChanged=/etc/nginx/ssl/acm/fullchain.pem

[Install]
WantedBy=multi-user.target

wcp-nginx-reload.service

[Unit]
Description=Reload nginx after ACM certificate update

[Service]
Type=oneshot
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx -s reload

これにより:

  • acm.serviceのハードニング(ProtectSystem/ProtectHome/PrivateTmp/PrivateDevices/最小cap)は維持
  • nginx reloadはroot権限で安全に実行
  • config.tomlからはrefresh_commandを削除(デーモンは証明書をファイルに書くだけ)

acm.serviceで PrivateDevices=no / NoNewPrivileges=no に緩和する方法もありますが、セキュリティ後退のため不採用としました。

6. 動作確認

最終的な構成図

┌─────────────────────────────────────────────────┐
│  ACM (us-east-1)                                │
│  *.lovelive-presents.com / Export=ENABLED        │
└──────────────────────┬──────────────────────────┘
                       │ (定期エクスポート)
                       ▼
┌─────────────────────────────────────────────────┐
│  acm.service (aws-wcp, サンドボックス)            │
│  AssumeRole → ExportCertificate                  │
│  → atomic rename で証明書ファイル更新             │
└──────────────────────┬──────────────────────────┘
                       │ (inotify: PathChanged)
                       ▼
┌─────────────────────────────────────────────────┐
│  wcp-nginx-reload.path → .service (root)         │
│  nginx -t && nginx -s reload                     │
└──────────────────────┬──────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────┐
│  nginx (TLS稼働)                                 │
│  /etc/nginx/ssl/acm/{fullchain,privkey}.pem      │
└─────────────────────────────────────────────────┘

確認コマンド

# acm.serviceの状態確認
sudo systemctl status acm.service
# → active / "Certificate refresh successful"

# path監視の状態確認
sudo systemctl status wcp-nginx-reload.path
# → active (fullchain.pem 監視中)

# reloadの手動テスト
sudo systemctl start wcp-nginx-reload.service
# → Result=success

# TLS証明書の確認
echo | openssl s_client -connect mail.lovelive-presents.com:443 \
  -servername mail.lovelive-presents.com 2>/dev/null | \
  openssl x509 -noout -issuer -dates

セキュリティ上の考慮

項目 対応
認証情報 専用IAMユーザ、最小権限、AssumeRoleで分離
デーモンの権限 aws-wcpユーザ、ProtectHome/PrivateDevices等で完全サンドボックス化
秘密鍵 /opt配下、600、aws-wcp所有。ステージング用コピーはshredで削除済み
nginx reload 権限分離ユニット(root)で実行。デーモン側のセキュリティ緩和なし
SSRF対策 /var/run/awssmatoken + X-Aws-...-Token ヘッダ必須

まとめ

前回の記事で課題として残していた「ACMエクスポート証明書の手動更新問題」を、WCP v3.0.0で自動化できました。

ポイントは:

  • WCPが証明書のエクスポートとファイル配置を自動でやってくれる
  • PrivateDevices=yes 環境では sudo が使えない罠がある → pathユニットで権限分離が正解
  • セキュリティを緩めない設計が大事

これで証明書の有効期限を気にせず運用できるようになりました。
半年に一回の手動作業から解放されるのは大きいです。

では。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?