14
11

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 5 years have passed since last update.

無呼吸になって死ぬ前にAWS Configでやっておきたいこと(terraformでAWS Config設定編)

Posted at

俺です。

今更ながら俺を守るAWS Configをまじめにはじめました。
昔と違いterraformでAWS Config Ruleは、ほぼinput_parameterにJSON食わす程度で設定できるようになっているのですごく簡単です。
地味にインターネッツに実装例が載って無いっぽい?とおもったのでサンプル載せておきますね...
module化できたら最高なんだけどめんどいからやってません。

AWS Configは自分が操作してないはず、定義していないはずのAWSリソースもチェックできるので
複数人で1つのAWSアカウントを管理している時は、お互いの作業ミスに気づいたり、サービスとして最低限あるべき姿を描くので、ガバナンス強化に役立てることができますね。

チームで仕事をしてるなら、事故ってからおめーこんなこともやっておかねーのかよ呼吸と同じだろってしょーーもないこと言い合う前に、
AWS Configを書いて共有して、殺らなかった結果死ぬ。から身を守りましょう。

参考

寺のdoc

俺の環境

Terraform v0.11.3
+ provider.aws v1.9.0

ファイル構成

  • aws_config.tf
  • aws_config_custom.tf
  • aws_sns.tf

aws_config.tf

  • AWS Configを使うためのIAM RoleとPolicyの作成
  • AWS Configの有効化
  • AWS Config Snapshotを保存するS3を有効化(AES-256)
  • AWS Config ruleで全体的に有効になってないといけないルールを記載(sshフルオープンとかS3バケットのpublic化とか)
resource "aws_config_configuration_recorder" "aws-config" {
  name     = "aws-config"
  role_arn = "${aws_iam_role.aws-config.arn}"
}

resource "aws_iam_role" "aws-config" {
  name = "aws-config"

  assume_role_policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "config.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy" "aws-config" {
  name = "aws-config"
  role = "${aws_iam_role.aws-config.id}"

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Action": "config:Put*",
        "Effect": "Allow",
        "Resource": "*"
    },
    {
        "Action": [ "s3:Put*" ],
        "Effect": "Allow",
        "Resource": [
            "${aws_s3_bucket.aws-config.arn}",
            "${aws_s3_bucket.aws-config.arn}/*"
      ]
    }
  ]
}
POLICY
}


resource "aws_s3_bucket" "aws-config" {
  bucket = "${var.project}-aws-config"
}

resource "aws_config_delivery_channel" "aws-config" {
  name           = "${var.project}-aws-config"
  s3_bucket_name = "${aws_s3_bucket.aws-config.bucket}"
  sns_topic_arn = "${aws_sns_topic.lambda_to_slack.arn}"
  snapshot_delivery_properties {
    delivery_frequency = "Three_Hours"
  }
}

resource "aws_config_configuration_recorder_status" "aws-config" {
  name       = "${aws_config_configuration_recorder.aws-config.name}"
  is_enabled = true
  depends_on = ["aws_config_delivery_channel.aws-config"]
}
# add your custom rule is aws_config_custom.tf
# see config rule list
# https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/managed-rules-by-aws-config.html
resource "aws_config_config_rule" "ssh" {
    name = "restricted-ssh"
    source {
        owner = "AWS"
        source_identifier = "INCOMING_SSH_DISABLED"
    }
    scope {
        compliance_resource_types = ["AWS::EC2::SecurityGroup"]
    }
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "r1" {
  name = "autoscaling-group-elb-healthcheck-required"
  source {
    owner             = "AWS"
    source_identifier = "AUTOSCALING_GROUP_ELB_HEALTHCHECK_REQUIRED"
  }
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "r2" {
  name = "db-instance-backup-enabled"
  source {
    owner             = "AWS"
    source_identifier = "DB_INSTANCE_BACKUP_ENABLED"
  }
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "r3" {
  name = "s3-bucket-logging-enabled"
  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_LOGGING_ENABLED"
  }
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "r4" {
  name = "s3-bucket-public-read-prohibited"
  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"

  }
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "r5" {
  name = "s3-bucket-public-write-prohibited"
  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_PUBLIC_WRITE_PROHIBITED"

  }
  depends_on = ["aws_config_configuration_recorder.aws-config"]

aws_config_custom.tf

  • システム/サービス特有のリソースのルールを書く
  • 特定のResourceIDがあるべき姿をルールにする(管理サーバのsshはフルオープンになってないよねとか、管理サーバで稼働する管理画面のIP制限は有効だよねとか)

例) 特定のSGを443または80ポートが0.0.0.0/0開放されていないルールにする

resource "aws_config_config_rule" "mng-cms" {
    name = "restricted-mng-cms"
    source {
        owner = "AWS"
        source_identifier = "RESTRICTED_INCOMING_TRAFFIC"
    }
    scope {
        compliance_resource_types = ["AWS::EC2::SecurityGroup"]
        compliance_resource_id = "${aws_security_group.mng-cms-elb.id}"
    }
    input_parameters = "{\"blockedPort1\":\"443\",\"blockedPort2\":\"80\"}"
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}
resource "aws_config_config_rule" "develop-cms" {
    name = "restricted-develop-cms"
    source {
        owner = "AWS"
        source_identifier = "RESTRICTED_INCOMING_TRAFFIC"
    }
    scope {
        compliance_resource_types = ["AWS::EC2::SecurityGroup"]
        compliance_resource_id = "${aws_security_group.develop-cms-elb.id}"
    }
    input_parameters = "{\"blockedPort1\":\"443\",\"blockedPort2\":\"80\"}"
  depends_on = ["aws_config_configuration_recorder.aws-config"]
}

aws_sns.tf

やられた、やらかしたこに気づくのが重要です。
カジュアルにslackへpostしています。
SNS Topic + Lambdaめんどくせーーってずーっと思ってたら神様がterraform moduleとして公開されてるのを見つけたので使ってます。最高。
id:builtinnyaさんに超絶感謝。
repoはコチラ

terraform get で幸せが待ってます。

# 神=> https://github.com/builtinnya/aws-sns-slack-terraform
module "sns_to_slack" {
  source = "github.com/builtinnya/aws-sns-slack-terraform/module"

  slack_webhook_url = "${var.oreno_slack_webhook_url}"
  slack_channel_map = "{ \"lambda_to_slack\": \"#notify-hoghoge\" }"
}

resource "aws_sns_topic" "lambda_to_slack" {
  name = "lambda_to_slack"
}

resource "aws_lambda_permission" "allow_lambda_sns_to_slack" {
  statement_id = "AllowSNSToSlackExecutionFromSNS"
  action = "lambda:invokeFunction"
  function_name = "${module.sns_to_slack.lambda_function_arn}"
  principal = "sns.amazonaws.com"
  source_arn = "${aws_sns_topic.lambda_to_slack.arn}"
}

resource "aws_sns_topic_subscription" "lambda_sns_to_slack" {
  topic_arn = "${aws_sns_topic.lambda_to_slack.arn}"
  protocol = "lambda"
  endpoint = "${module.sns_to_slack.lambda_function_arn}"
}

通知のスクショ

こんなかんじで通知がとんできます。
今回はLambdaを使わずAWSのマネージドルールだけ使ってRule設定しいます。
変更を検知して通知が飛んで来るので、ちょっとメッセージは修正せんとなというところ。

image.png

おわり。

14
11
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
14
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?