8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

1.はじめに

こんにちは。
今回はAWS SecurityHubをTerraformを利用して展開する方法について記事にしていきたいと思います。

SecurityHubとは、AWS Configと連携して、セキュリティ業界標準およびベストプラクティスに照らしたAWS環境評価を行うのに有効なサービスです。
参考:AWS Security Hubとは?

SecurityHubの使用を開始すると、ベストプラクティスに沿ったConfigルールが自動的に作成されますが、不要なルールがあった場合は一つずつルールを無効化させる必要があり、かなり手間になってしまいます。
そこでSecurityHubの使用の開始、不要ルールの無効化などを一度に展開できるTerraformコードを作成しましたので共有します。

2.構成

前回の記事でConfigルールをデプロイする構成について紹介しましたので、
今回はSecurityHubを加えた構成で実装していきたいと思います。
構成.png

3.実装

3.1 フォルダ構成

以下のようなフォルダ構成で実装していきます。
リソース名などは変数管理としたいため、Local Valuesを利用します。
参考:Local Values

Terraform/
└─ dev
    ├─ s3.tf
    ├─ locals.tf
    ├─ security.tf
    └─ terraform.tf

3.2 terraform.tf

以下の内容でterraform.tfを設定します。
アカウントIDとリージョンをコード内で取得できるようにしたいので、aws_caller_identityaws_regionのdata source設定を記載しておきます。

terraform.tf
# providerの定義
provider "aws" {
  region = "ap-northeast-1"
}

terraform {
  required_version = ">=1.0"
  required_providers {
    awscc = {
      source  = "hashicorp/awscc"
      version = "0.45.0"
    }
  }
}

# 実行するAWSアカウント情報取得用
data "aws_caller_identity" "self" {}

# 実行するリージョン情報取得用
data "aws_region" "self" {}

3.3 s3.tf

S3のバケット名は後述するlocals.tfに記載するため、以下のコード内ではlocalsを参照するようにしています。
ConfigとS3の連携にはS3バケットポリシーの設定が必要となるため、それも記載します。

s3.tf
# S3 Bucket
resource "aws_s3_bucket" "this" {
  for_each      = toset(local.s3_bucket)
  force_destroy = true

  bucket = "${local.env}-${each.value}"

  tags = {
    Name = "${local.env}-${each.value}"
  }
}

resource "aws_s3_bucket_policy" "config-service" {
  bucket = aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].bucket
  policy = data.aws_iam_policy_document.config-service.json
}

data "aws_iam_policy_document" "config-service" {
  version = "2012-10-17"
  statement {
    sid    = "AWSConfigBucketPermissionsCheck"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
    actions = [
      "s3:GetBucketAcl"
    ]
    resources = [
      "${aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].arn}"
    ]
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values   = ["${data.aws_caller_identity.self.account_id}"]
    }
  }
  statement {
    sid    = "AWSConfigBucketExistenceCheck"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
    actions = [
      "s3:ListBucket"
    ]
    resources = [
      "${aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].arn}"
    ]
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values   = ["${data.aws_caller_identity.self.account_id}"]
    }
  }
  statement {
    sid    = "AWSConfigBucketDelivery"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["config.amazonaws.com"]
    }
    actions = [
      "s3:PutObject"
    ]
    resources = [
      "${aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].arn}/AWSLogs/${data.aws_caller_identity.self.account_id}/Config/*"
    ]
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceAccount"
      values   = ["${data.aws_caller_identity.self.account_id}"]
    }
  }
}

resource "aws_s3_bucket_public_access_block" "config-service" {
  bucket = aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

3.4 security.tf

Configに関連するリソースの説明については前回の記事をご参考ください。

SecurityHubのデプロイのために、以下のリソースを利用します。

security.tf
# IAM
# AWSConfigサービスロールの作成
resource "aws_iam_service_linked_role" "config-service" {
  aws_service_name = "config.amazonaws.com"
}

# Config
# Configレコーダーの有効化
resource "aws_config_configuration_recorder_status" "config-service" {
  name       = aws_config_configuration_recorder.config-service.name
  is_enabled = true
  depends_on = [aws_config_delivery_channel.config-service]
}

# Configレコーダーの作成
resource "aws_config_configuration_recorder" "config-service" {
  name     = "${local.env}-awsconfig"
  role_arn = aws_iam_service_linked_role.config-service.arn
  recording_group {
    all_supported                 = "true"
    include_global_resource_types = "true"
  }
}

# Config配信チャネルの作成
resource "aws_config_delivery_channel" "config-service" {
  name           = "${local.env}-awsconfig"
  s3_bucket_name = aws_s3_bucket.this["awsconfig-${data.aws_caller_identity.self.account_id}"].id
  depends_on     = [aws_config_configuration_recorder.config-service]
}

# SecurityHub
resource "aws_securityhub_account" "securityhub" {
  depends_on = [
    aws_config_configuration_recorder.config-service,
    aws_config_configuration_recorder_status.config-service,
    aws_config_delivery_channel.config-service
  ]
}

# セキュリティ基準の有効化
resource "aws_securityhub_standards_subscription" "securityhub_standards" {
  depends_on    = [aws_securityhub_account.securityhub]
  for_each      = local.securityhub_standards
  standards_arn = each.value.standards_arn
}

# 不要なコントロールを無効化
resource "aws_securityhub_standards_control" "securityhub_disabled_controls" {
  for_each              = local.securityhub_disabled_controls
  standards_control_arn = each.value.standards_control_arn
  control_status        = "DISABLED"
  disabled_reason       = each.value.disabled_reason
  depends_on            = [aws_securityhub_standards_subscription.securityhub_standards]
}

3.5 locals.tf

locals.tfでは以下の設定が行えるようにコードに記載します。

  • 環境名:dev
  • S3バケット名:awsconfig-{AWSアカウントID}
  • 有効化するセキュリティ基準:
    • AWS 基礎セキュリティのベストプラクティス v1.0.0
    • CIS AWS Foundations Benchmark v1.2.0
  • 無効化するルール:
    • ACM.1:インポートされ ACM によって発行された証明書は、一定期間後に更新する必要があります
    • ELB.4:Application Load Balancer は、http ヘッダーを削除するように設定する必要があります
    • CIS 1.4:IAM ユーザーのアクセスキーは 90 日以内にローテーションする必要があります
locals.tf
# ##########
# Environment Parameters
# ##########

locals {
  env = "dev"
}

# ##########
# S3
# ##########

locals {
  s3_bucket = [
    "awsconfig-${data.aws_caller_identity.self.account_id}"
  ]
}

# ##########
# SecurityHub
# ##########
# SecurityHubセキュリティ標準の有効化
locals {
  securityhub_standards = {
    aws-best-practices = {
      standards_arn = "arn:aws:securityhub:${data.aws_region.self.name}::standards/aws-foundational-security-best-practices/v/1.0.0"
    }
    cis = {
      standards_arn = "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0"
    }
  }
}

# SecuritHub個別のコントロールの無効化
locals {
  securityhub_disabled_controls = {
    access-keys-rotated-cis-1-4 = {
      standards_control_arn = "arn:aws:securityhub:${data.aws_region.self.name}:${data.aws_caller_identity.self.account_id}:control/cis-aws-foundations-benchmark/v/1.2.0/1.4"
      disabled_reason       = "No access key rotation required."
    }
    acm-certificate-expiration-check-acm-1 = {
      standards_control_arn = "arn:aws:securityhub:${data.aws_region.self.name}:${data.aws_caller_identity.self.account_id}:control/aws-foundational-security-best-practices/v/1.0.0/ACM.1"
      disabled_reason       = "ACM is automatically updated."
    }
    alb-http-drop-invalid-header-enabled-elb-4 = {
      standards_control_arn = "arn:aws:securityhub:${data.aws_region.self.name}:${data.aws_caller_identity.self.account_id}:control/aws-foundational-security-best-practices/v/1.0.0/ELB.4"
      disabled_reason       = "No setting required."
    }
  }
}

4.デプロイ

まずterraform planを実行してエラーがないことを確認してからterraform applyを実行して、AWS環境にデプロイします。

ログにApply complete!と出力されたらデプロイ完了です。

5.実機確認

AWSマネジメントコンソールにアクセスし、実際にリソースが作成されているか確認します。
前回の記事でConfig、S3バケット、IAMロールの作成ができることは確認済みのため、今回はSecurityHubに関連するリソースのみ見ていきます。

  • SecuritHub セキュリティ基準の有効化
    キャプチャ03.JPG

  • SecurityHub ルールの無効化

    • ACM.1キャプチャ08.JPG
    • ELB.4キャプチャ09.JPG
    • CIS 1.4キャプチャ07.JPG

Terraformコードで記載した通りの設定が反映されていることが確認できました。

6.おわりに

今回はSecurityHubの有効化の設定と、周辺環境の構築をTerraformを利用して展開する方法について記事にしてみました。
SecurityHubのルールを無効化にする作業は、手作業でやろうとするとかなり手間のかかるものなので、デプロイが容易にできるようにこちらの記事が参考になれば幸いです。

7.参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?