LoginSignup
3
1

More than 1 year has passed since last update.

【AWS】Terraformでアクセスを分散、WebサーバーをHTTPS化する その3(ACM)

Last updated at Posted at 2021-09-05

概要

TerraformでAWSサービスを使用して、

  • 負荷分散
  • 独自ドメインの設定
  • SSL証明書を作成してHTTPS化

上記の3つを含めた構成を作成する手順をまとめました。

目次

本記事は「3. AWS Certificate Manager(ACM)でSSL証明書の作成」について記述。
「1. アプリケーションロードバランサー(ALB)の作成」はこちら →【AWS】Terraformでアクセスを分散、WebサーバーをHTTPS化する その1(ALB)
「2. Route53でDNS設定」はこちら → 【AWS】Terraformでアクセスを分散、WebサーバーをHTTPS化する その2(Route53)

  1. アプリケーションロードバランサー(ALB)の作成
    • ALBの作成
    • ターゲットグループの作成 / ターゲットの登録
    • リスナーを設定
    • ALBのDNS名からHTTPアクセス確認
  2. Route53でDNS設定
    • ドメインの取得(例はfreenomの無料ドメイン)
    • ホストゾーンの作成
    • DNSレコードの定義
    • ネームサーバーの設定を加える
    • 取得したドメインへHTTPアクセス確認
  3. AWS Certificate Manager(ACM)でSSL証明書の作成 ←本記事はここから
    • SSL証明書の作成
    • SSL証明書の検証
    • HTTPSリスナーの定義
    • HTTPSアクセス確認

ここまでの前提条件として
DNS設定済みで設定したドメインにhttpでアクセスできる状態であること。

構成図

目標構成図はこちら。
ALB_Route53_ACM.png

3. AWS Certificate Manager(ACM)でSSL証明書の作成

SSL証明書の作成

HTTPS化に必要なSSL証明書をACMで作成する。
ACMでSSL証明書を作成すれば証明書の有効期限日をむかえても自動更新されるため、期限切れによる失効や稼働停止の防止に役立つ。

ACMを使ってパブリックなSSL/TLS証明書を発行できるのは下記のサービス。

  • ELB
  • CloudFront
  • Elastic Beanstalk
  • API Gateway
  • CloudFormation

acm.tfを作成。
下記にてSSL証明書を定義。

acm.tf
#SSL証明書の定義
resource "aws_acm_certificate" "cert" {
  domain_name               = aws_route53_record.dns_record.name
  subject_alternative_names = []
  validation_method         = "DNS"
  lifecycle {
    create_before_destroy = true
  }
}
  • subject_alternative_names
    ドメイン名を追加したい場合、subject_alternative_names = [リスト]を設定。
    ["blahblahblah.example.com"]と設定した場合、「example.com」と「blahblahblah.example.com」のSSL証明書を作成する。
    追加しない場合は[ ](空リスト)を渡す。

  • validation_method = "DNS"
    ドメインの検証方法を設定。DNSかEMAILかを設定できる。
    SSL証明書を自動更新したい場合は、DNS検証を選択。

  • lifecycle { create_before_destroy = true }
    create_before_destroyを設定することで、「リソースの作成→リソースの削除」という順序でリソースの再生成を実行できる。(通常は逆の削除→作成の順で実施される)
    これにより、リソースの依存関係によって発生しうる不要なリソースの再生成を避けることができる。
    注意点として、一時的に2つのリソースが作成されるため、ネーミングにユニーク制約があるリソースは作成に失敗する恐れがある。

SSL証明書の検証

続いてDNS検証用のDNSレコードを追加する。
またaws_acm_certification_validationリソースを定義することで、apply時にSSL証明書の検証が完了するまで待機する設定を加える。

acm.tf
# 検証用のレコード定義
resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }
  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = aws_route53_zone.hostzone.zone_id
}

# 検証完了までの待機
resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

HTTPSリスナーの定義

続いてALBへHTTPSアクセスできるよう、HTTPSリスナーを作成する。
また、HTTPSのインバウンドルールを既存のセキュリティグループに追加する。

acm.tf
# HTTPSリスナーを追記
resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.alb.arn
  port              = "443"
  protocol          = "HTTPS"
  certificate_arn   = aws_acm_certificate.cert.arn
  ssl_policy        = "ELBSecurityPolicy-2016-08"

  default_action {
    type             = "forward" # リクエストをターゲットグループに転送
    target_group_arn = aws_lb_target_group.alb_target_group.id
  }

  depends_on = [
    aws_acm_certificate_validation.cert
  ]
}
acm.tf
# HTTPSインバウンドルールを追記
resource "aws_security_group_rule" "ingress_https" {
  security_group_id = aws_security_group.sg_for_ec2.id
  type              = "ingress"
  from_port         = 443
  to_port           = 443
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
}
  • certificate_arn
    SSL証明書発行リソースを指定。
  • ssl_policy
    ELBはプロトコルと暗号の組み合わせであるセキュリティポリシーを使用して、クライアントとSSL接続を確立している。
    ALBはELBSecurityPolicy-2016-08をデフォルトのセキュリティポリシーとしている。
  • depends_on
    ここではSSL証明書の検証完了してから、HTTPSリスナーを作成するように明示的に依存関係を記している。

HTTPSアクセス確認

ここまででHTTPSアクセス確認の準備は整ったが、まだHTTPでもアクセスできる状態なので、HTTPでアクセスした際にHTTPSへリダイレクトする設定を加える。

alb.tfのHTTPリスナーのdefault_actionを編集しておく。

alb.tf
#HTTPリスナー
resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.alb.arn
  port              = "80"
  protocol          = "HTTP"

  # default_action {
  #   type             = "forward"
  #   target_group_arn = aws_lb_target_group.alb_target_group.id
  # }

  # ↑ 上記内容を
  # ↓ 下記に書き換え  

  default_action {
    type = "redirect"

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}
  • default_action
    type = "redirect"を設定し、後はリダイレクト先プロトコルの情報を加えるだけ。

ここまででterraform applyを実行する。

HTTPSにアクセス確認
https://取得したドメインにアクセスし、問題なくページが表示されたら、HTTPS化が成功!

HTTPでアクセスしてHTTPSへリダイレクトされるか確認
http://取得したドメインにアクセスし、HTTPSへリダイレクトされたら、リダイレクトも成功!

終わりに

今回まででALBでの負荷分散、Route53でDNS設定、ACMでSSL証明書作成をまとめました。
1つテンプレを持っておくと、色々カスタマイズして使えそうです。

ここまでのコードを全て合わせてまとめて実行しようとすると、SSL証明書の検証完了待ちあたりで処理が終わらないという壁にぶち当たりました。 ※ 今回は全て同ディレクトリでalb.tf、route53.tf、acm.tfと順々に追加したので、問題なくデプロイできました。 ファイルの分割、実施順序やリソースデプロイのタイミングなど細かく詰めていく必要がありそうです。

↓↓↓
並行してディレクトリ構造整理をまとめました。
【AWS】Terraformディレクトリ構造の整理(tfファイル配置方式の見直し)

3
1
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
3
1