🚀

AWS学びなおし(+TF)_ACM

2025/03/03に公開

AWS Certificate Manager (ACM) は、AWS クラウドでセキュアなウェブサイトやアプリケーションを構築・運用するために不可欠な SSL/TLS 証明書を、簡単にプロビジョニング、管理、デプロイできるサービスです。

ACM の役割とメリット:

従来の SSL/TLS 証明書管理は、煩雑で手間のかかる作業でした。証明書の購入、インストール、更新作業を手動で行う必要があり、設定ミスや更新忘れによるセキュリティリスクも存在しました。ACM はこれらの課題を解決し、以下のメリットを提供します。

  • 無料のパブリック証明書: ACM は、AWS のサービス (Elastic Load Balancing (ELB)、Amazon CloudFront、Amazon API Gateway など) で使用するパブリック SSL/TLS 証明書を無料でプロビジョニングします。証明書費用を削減し、HTTPS 化を容易にします。
  • 簡単な証明書管理: 証明書の生成、検証、インストール、更新といった煩雑な作業を自動化します。AWS マネジメントコンソール、CLI、API、Terraform などの Infrastructure as Code (IaC) ツールから簡単に操作できます。
  • 自動更新: ACM が証明書の有効期限を自動的に監視し、期限切れ前に自動更新を行います。証明書の更新忘れによるサービス停止やセキュリティリスクを回避できます。
  • AWS サービスとの統合: ELB、CloudFront、API Gateway など、多くの AWS サービスと緊密に統合されており、数クリックで証明書をデプロイできます。
  • セキュリティ強化: 証明書の有効期限切れ、設定ミス、脆弱な鍵管理といった一般的な SSL/TLS 運用における人的ミスを削減し、セキュリティを向上させます。
  • プライベート証明書のサポート: パブリック証明書だけでなく、企業内システムや内部向けサービスで使用するプライベート証明書の発行・管理も可能です。AWS Private CA と連携することで、プライベート CA 基盤を構築・運用できます。

ACM で扱える証明書の種類:

  • パブリック証明書: DigiCert などのパブリック認証局 (CA) によって発行される証明書です。インターネット上のクライアント (ブラウザなど) から信頼されます。ウェブサイトの HTTPS 化、API Gateway のカスタムドメイン、CloudFront の HTTPS ディストリビューションなどで使用されます。ACM で無料でプロビジョニング可能です。
  • プライベート証明書: AWS Private CA によって発行される証明書です。パブリック CA からは信頼されませんが、組織内で信頼された認証局 (ルート CA) を構築することで、内部システムやサービス間の通信を暗号化できます。マイクロサービス間の通信、社内システムへのアクセス制御などで使用されます。プライベート証明書の発行には料金が発生します。
  • インポート証明書: 外部の認証局から購入した証明書や、既存の証明書を ACM にインポートして管理できます。ACM の自動更新機能や AWS サービスとの統合を利用できます。

ACM の主な機能:

  • 証明書のプロビジョニング: パブリック証明書、プライベート証明書を数クリックでリクエストできます。ドメイン認証 (DNS 検証、メール検証) を行うことで証明書が発行されます。
  • 証明書の自動更新: ACM が証明書の有効期限を監視し、自動的に更新を行います。ユーザーによる手動更新は不要です。
  • 証明書の一元管理: AWS アカウント内のすべての証明書を ACM コンソールで一元的に管理できます。証明書の有効期限、ドメイン名、ステータスなどを確認できます。
  • 証明書のデプロイ: ACM でプロビジョニングした証明書を、ELB、CloudFront、API Gateway などの AWS サービスに簡単にデプロイできます。
  • 証明書のインポート: 外部の証明書を ACM にインポートし、ACM の管理下で利用できます。
  • 証明書のエクスポート (プライベート証明書): AWS Private CA で発行したプライベート証明書をエクスポートし、ACM と統合されていないシステムで使用できます。

【実務レベルの内容と重要事項】

実務における ACM の重要事項:

  • ドメイン検証 (DNS 検証 vs メール検証): パブリック証明書の発行にはドメインの所有権を証明するドメイン検証が必要です。
    • DNS 検証: DNS レコード (CNAME レコード) をドメインの DNS 設定に追加することで検証します。自動検証が可能で、Route 53 と連携すると更に容易になります。推奨される検証方法です。
    • メール検証: ドメインの WHOIS 情報に登録されているメールアドレス宛に検証メールが送信されます。手動での操作が必要で、自動化が難しいため、DNS 検証が推奨されます。
  • ワイルドカード証明書: *.example.com のように、サブドメインを包括的にカバーするワイルドカード証明書を発行できます。複数のサブドメインで HTTPS を有効にする場合に便利です。
  • Subject Alternative Names (SANs): 1 つの証明書で複数のドメイン名 (例: example.comwww.example.com) をカバーできます。ワイルドカード証明書と組み合わせることで、柔軟なドメイン構成に対応できます。
  • リージョン: ACM 証明書はリージョンリソースです。証明書を使用する AWS サービス (ELB など) と同じリージョンに証明書を作成する必要があります。ただし、CloudFront で使用する証明書は、us-east-1 (バージニア北部) リージョンに作成する必要があります (グローバルサービスである CloudFront の制約)。
  • IAM ポリシー: ACM へのアクセス制御は IAM ポリシーで行います。証明書の発行、削除、インポートなどの操作権限を IAM ユーザーやロールに付与することで、セキュリティを確保します。
  • 証明書のライフサイクル管理: ACM の自動更新機能は非常に強力ですが、以下のような点に注意が必要です。
    • DNS 検証の場合: DNS レコードが削除されたり、CNAME レコードのターゲットが変わると自動更新が失敗する可能性があります。DNS 設定を適切に管理する必要があります。
    • メール検証の場合: メール検証は自動化が難しいため、自動更新には DNS 検証への移行が推奨されます。
    • 証明書のローテーション: セキュリティ上の理由から、定期的に証明書をローテーション (再発行) することが推奨される場合があります。ACM を利用することで、ローテーション作業を比較的容易に行えます。
  • プライベート CA との連携: AWS Private CA を利用することで、組織独自のプライベート認証局を構築し、プライベート証明書を発行・管理できます。内部システムやマイクロサービス間の通信暗号化に活用できます。
  • 証明書のインポート: 外部の認証局から購入した証明書を ACM にインポートする場合、プライベートキーも一緒にインポートする必要があります。プライベートキーの管理には十分注意が必要です。

実務で遭遇しやすい問題点と解決策:

  • 証明書のリクエスト失敗: ドメイン検証の失敗、AWS のサービス制限、IAM ポリシーの問題などが原因として考えられます。エラーメッセージを確認し、原因を特定する必要があります。
  • ドメイン検証のトラブルシューティング: DNS レコードの設定ミス、DNS 伝播の遅延などが原因で検証に失敗することがあります。DNS レコードが正しく設定されているか、DNS 伝播が完了しているかを確認する必要があります。DNS 検証がうまくいかない場合は、メール検証を試すこともできます。
  • 証明書の有効期限切れ: ACM の自動更新機能が正常に機能していれば、通常は有効期限切れは発生しません。ただし、DNS 設定の変更やネットワーク障害などにより自動更新が失敗する可能性もあります。ACM コンソールや CloudWatch Events で証明書のステータスを監視し、異常があれば対応する必要があります。

【実務でどの程度使用されるのか】

ACM は、現代のクラウド環境において非常に広く、そして不可欠なサービスとして利用されています。HTTPS はウェブサイトの標準となり、セキュリティと信頼性のために必須です。ACM は、その HTTPS 化を容易かつ低コストで実現するため、多くの企業や組織で採用されています。

実務での利用シーン:

  • ウェブサイトの HTTPS 化: ELB (ALB, NLB) と連携してウェブサイトを HTTPS 化し、ユーザーとウェブサーバー間の通信を暗号化します。
  • API Gateway のカスタムドメイン: API Gateway のカスタムドメインに ACM 証明書を適用し、HTTPS で API を公開します。
  • CloudFront の HTTPS ディストリビューション: CloudFront ディストリビューションに ACM 証明書を適用し、コンテンツ配信を HTTPS でセキュアに行います。
  • マイクロサービス間の通信暗号化: AWS Private CA と連携してプライベート証明書を発行し、マイクロサービス間の通信を暗号化します。
  • 社内システムの HTTPS 化: 社内向けウェブアプリケーションや API を HTTPS 化し、セキュリティを向上させます。
  • DevOps/Infrastructure as Code (IaC) 環境: Terraform や AWS CloudFormation などの IaC ツールで ACM 証明書をプロビジョニングし、インフラ構築を自動化します。

利用頻度と重要性:

ほぼ全てのウェブアプリケーション、API、コンテンツ配信基盤において HTTPS 化は必須要件となっています。そのため、ACM はこれらのシステムを構築・運用する上でほぼ必ず使用されると言っても過言ではありません。

  • 新規プロジェクト: 新規にウェブアプリケーションや API を構築する場合、最初から HTTPS を前提として設計・構築するのが一般的です。ACM はその HTTPS 化を容易にするため、初期段階から利用が検討されます。
  • 既存システムの移行: HTTP で運用されている既存システムを HTTPS 化する場合、ACM を導入することで、証明書管理の煩雑さを解消し、移行作業をスムーズに進めることができます。
  • 大規模システム/高可用性システム: 大規模システムや高可用性システムでは、多数の証明書を効率的に管理する必要があります。ACM の自動更新機能や AWS サービスとの統合は、これらのシステム運用において大きなメリットとなります。

コンプライアンス要件:

PCI DSS、HIPAA などのコンプライアンス要件を満たすためには、HTTPS による通信暗号化が必須となる場合があります。ACM は、これらのコンプライアンス要件を満たすための基盤として重要な役割を果たします。

【terraformのコードで記述する場合の基本的内容と実務レベルの内容】

基本的な Terraform コード (パブリック証明書、DNS 検証):

resource "aws_acm_certificate" "example" "example" {
  domain_name               = "example.com"
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "example_validation" {
  for_each = {
    for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => dvo
  }

  allow_overwrite = true
  name            = each.value.resource_record_name
  records         = [each.value.resource_record_value]
  ttl             = 60
  type            = each.value.resource_record_type
  zone_id         = data.aws_route53_zone.primary.zone_id # example.com の Route 53 ホストゾーン ID
}

resource "aws_acm_certificate_validation" "example_validation" {
  certificate_arn         = aws_acm_certificate.example.arn
  validation_record_fqdns = [for record in aws_route53_record.example_validation : record.fqdn]
}

コード解説:

  1. aws_acm_certificate リソース:

    • domain_name: 証明書をリクエストするドメイン名 (例: "example.com")
    • validation_method = "DNS": DNS 検証を使用することを指定
    • lifecycle { create_before_destroy = true }: 証明書のリプレース時にダウンタイムを避けるための設定 (重要)
  2. aws_route53_record リソース:

    • ACM から提供される DNS 検証レコード (CNAME レコード) を Route 53 に自動的に作成します。
    • for_each: 複数のドメイン検証オプション (SANs など) に対応するためのループ処理
    • zone_id: ドメインの Route 53 ホストゾーン ID を指定 (事前に data.aws_route53_zone データソースなどで取得しておく必要があります)
  3. aws_acm_certificate_validation リソース:

    • DNS 検証が完了したことを ACM に通知し、証明書の発行を完了させます。
    • validation_record_fqdns: 検証レコードの FQDN (Fully Qualified Domain Name) をリスト形式で指定

実務レベルの Terraform コード (モジュール化、変数化、CloudFront デプロイ):

# modules/acm-certificate/main.tf
resource "aws_acm_certificate" "certificate" {
  domain_name               = var.domain_name
  validation_method         = "DNS"
  subject_alternative_names = var.subject_alternative_names

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "certificate_validation" {
  for_each = {
    for dvo in aws_acm_certificate.certificate.domain_validation_options : dvo.domain_name => dvo
  }

  allow_overwrite = true
  name            = each.value.resource_record_name
  records         = [each.value.resource_record_value]
  ttl             = 60
  type            = each.value.resource_record_type
  zone_id         = var.zone_id
}

resource "aws_acm_certificate_validation" "certificate_validation" {
  certificate_arn         = aws_acm_certificate.certificate.arn
  validation_record_fqdns = [for record in aws_route53_record.certificate_validation : record.fqdn]
}


# modules/acm-certificate/variables.tf
variable "domain_name" {
  type        = string
  description = "メインのドメイン名"
}

variable "subject_alternative_names" {
  type        = list(string)
  default     = []
  description = "SANs (Subject Alternative Names) のリスト"
}

variable "zone_id" {
  type        = string
  description = "Route 53 ホストゾーン ID"
}


# main.tf (ルートモジュール)
module "acm_certificate" {
  source = "./modules/acm-certificate"

  domain_name               = "example.com"
  subject_alternative_names = ["www.example.com", "api.example.com"]
  zone_id                   = data.aws_route53_zone.primary.zone_id
}

resource "aws_cloudfront_distribution" "example_cdn" {
  # ... (CloudFront ディストリビューションの設定) ...

  viewer_certificate {
    acm_certificate_arn = module.acm_certificate.aws_acm_certificate.certificate.arn # モジュールから証明書 ARN を参照
    ssl_support_method  = "sni-only"
    minimum_protocol_version = "TLSv1.2_2021"
  }
}

data "aws_route53_zone" "primary" {
  name = "example.com." # 末尾にドットが必要
}

実務レベルのポイント:

  • モジュール化: aws_acm_certificate リソースと関連リソースをモジュール化することで、コードの再利用性と可読性を向上させます。
  • 変数化: ドメイン名、SANs、ゾーン ID などを変数で定義することで、柔軟性と設定の変更容易性を高めます。
  • SANs のサポート: subject_alternative_names 変数で SANs を指定できるようにすることで、複数のドメインをカバーする証明書を簡単に作成できます。
  • CloudFront デプロイ例: aws_cloudfront_distribution リソースの viewer_certificate ブロックで、ACM 証明書を CloudFront にデプロイする例を示しています。モジュールから証明書 ARN を参照しています。
  • lifecycle { create_before_destroy = true }: 証明書のリプレース時のダウンタイムを最小限にするために、lifecycle ブロックで create_before_destroy = true を設定することが重要です。
  • Terraform State Management: Terraform state ファイルの管理 (リモートバックエンド、ステートロック) を適切に行うことが、チームでの IaC 運用において重要です。ACM 証明書を含むインフラ全体の状態を安全かつ整合性のある状態で管理する必要があります。
  • エラーハンドリングとロギング: 実務環境では、証明書発行の失敗、検証エラーなどを検知し、適切なエラーハンドリングとロギングを行うことが重要です。CloudWatch Events や CloudWatch Logs と連携して、証明書のステータスを監視し、異常発生時にアラートを通知する仕組みを構築することが望ましいです。

上記はあくまで基本的な例であり、実際のシステム構成や要件に応じて Terraform コードは複雑になる場合があります。しかし、上記のポイントを押さえることで、ACM 証明書を Terraform で効率的かつ安全に管理することができます。

Discussion