マネジメントコンソールでAWSリソースを構築して、terraformコードを作ってからインポートしたら想像以上に辛かった話

皆さんIaCしてますか？
私はAWSだとCloudFormationやterraform、AzureだとARM TemplateやBicepをよく使っています。また、かなり後発ですが最近CDKを触る機会があり、勉強し始めたところです。

そんなところで、今回はAWSをterraformで管理する際のお話をさせて頂きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236355/924d1506-f23a-4e85-8575-d3ec46035c36.png)

いきなりですがterraformにインポート機能がありますよね。
この機能ってterraform以外で構築したリソースをterraform管理のstateファイルに取り込めるということで、便利そうだなと気になっていました。
※terraformのインポート機能については[リンク先](https://dev.classmethod.jp/articles/terraform-import-command-and-import-block/)が参考になります

今回の記事は、そのインポート機能を使ったら、思っていた以上に大変で辛かった話をしたいと思います。

# 背景
私が参加したプロジェクトで、ステージング環境はマネジメントコンソールで、本番環境はterraformで構築するといったことがありました。
最初からterraformで作れよって突っ込みがありそうですが、意外にこういうプロジェクトってありませんか？

そんなこんなで、両環境を構築した後に、ステージング環境もterraform管理にしようとなりました。
そこ利用したのがterraformのインポート機能です。

インポートを実行するには、まず初めにインポートするリソース分resourceブロックを用意する必要があります。
resourceブロックの例は以下の通りです。
```terraform
resource "aws_instance" "sample1" {
}
```
このresourceブロックをリソース分用意するというのがまぁ大変で、リソースが多ければ多いほど用意する数が増えるので、とてつもない数用意する必要がありました。実際このresourceブロックの準備は別のメンバーがやってくれたので、お前が大変さを語るな！と怒られそうです。

resourceブロックの準備が終わり、いざインポート！ということで、terraform planを実行して結果を見たら、あらびっくり！
とてつもない数の``add``、``change``、``destroy``が出てきました。
スクショを取っておけば良かった。。。という後悔ですが、皆さんに見て頂きたい位、とんでもない数が出ました。

インポートするにあたり、この差分を解消するか、設定変更もしくは作り直しを受け入れるしかないので、この差分を1つずつチェックする必要があるのですが、これがまぁ大変。
ということで、この記事では私の環境で出た差分と、その原因についてご紹介しますので、見て頂いた方の差分調査にかける時間を少しでも減らすことが出来れば幸いです。

# いきなり結論
流行りのいきなり結論ということで、なんで私の環境でそんなに差分が出たのか？
結論は、同じ設定のリソースを作ろうとしてもマネジメントコンソールでの構築とterraformでの構築では一部の設定値が異なったり、片方にしかない設定が存在するからです。

勘違いが無いようにお伝えすると、明示的に指定している設定値については基本的に問題ありません。オプションとなっていて、特に設定する必要がないと思って記載しない設定であったり、デフォルト値で問題ないと思い明示的に記載しない設定で差異が発生していました。そもそもマネジメントコンソールでは設定出来ない項目もあったりするので、初見だと差分の調査に時間をかなり要しますが、一度経験してしまえば二回目以降は差分を調査する時間を削減できると思います。

なので、是非この記事を上手く活用して頂ければと思います！

# AWSリソースで発生した差分
今回私がインポートした主なAWSサービスは以下のサービスです。
- VPC
- VPC関連リソース(Subnet, RouteTable,SG,ManagedPrefixList,VPCEndpoint等)
- Route53
- API Gateway
- ALB
- Lambda
- ECS on Fargate
- Aurora for PostgreSQL
- DynamoDB
- OpenSearch
- S3
- ECR
- SSM ParameterStore
- SecretManage
- EventBridge
- CodeDeploy

これ以降で、上記のリソース群の中から差分が発生したリソースの差分内容について記述します。

# SG
## [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group)
### [revoke_rules_on_delete](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group#revoke_rules_on_delete-1)
この項目は、マネジメントコンソールでは存在しない設定項目で、terraform独自の設定項目となるため、差分が発生します。

terraform独自の設定項目ということで設定内容としては、依存関係があるSGを削除するときに依存関係を解消してからSGを削除してくれるといった設定になります。具体的には特定のAWSサービスでは必要なルールを自動的にSGに追加することがあると思いますが、この場合SGを削除しようとしても依存関係を削除しないとSGが削除できません。そこで、この設定を``true``にするとアタッチされたすべてのルールを先に削除してから、SG自体を削除するような挙動になるため、SGを削除出来るといった内容になります。また、この設定自体は対象となるSGにterraform側で自動的に付けられるため、一部のSGにのみに設定されていました。
```terraform
resource "aws_security_group" "example_sg" {
  name                   = "example"
  description            = "example"
  vpc_id                 = aws_vpc.main.id
  revoke_rules_on_delete = true
}
```

# ALB
## [aws_lb_listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener)
### [stickiness](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener#stickiness-1)
マネジメントコンソールにてListenerのデフォルトアクションで``転送``を選んだ場合、この設定をオフにしていても関連項目にデフォルト値(3600)で入ってしまいます。一方で、terraformで構築した場合、この設定自体はオフで関連項目(duration)は記載していないため、何も設定されていない状態になっているため、そこが差分として発生します。
```terraform
resource "aws_lb_listener" "example" {
  load_balancer_arn = aws_lb.example.id

  default_action {
    type         = "forward"
    forward {
      target_group {
        arn      = aws_lb_target_group.lb-tg.arn
        weight   = 1
      }

      stickiness {
        duration = 3600
        enabled  = false
      }
    }
  }
}
```

## [aws_lb_listener_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule)
### [stickiness](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_rule#stickiness-1)
マネジメントコンソールにてListener Ruleで``転送``を選んだ場合、この設定をオフにしていても関連項目にデフォルト値(3600)で入ってしまいます。一方で、terraformで構築した場合、この設定自体はオフで関連項目(duration)は記載していないため、何も設定されていない状態になっているため、そこが差分として発生します。
```terraform
resource "aws_lb_listener_rule" "host_based_routing" {
  listener_arn = aws_lb_listener.front_end.arn
  priority     = 99

  action {
    type = "forward"
    forward {
      target_group {
        arn    = aws_lb_target_group.main.arn
        weight = 1
      }

      stickiness {
        enabled  = false
        duration = 3600
      }
    }
  }

  condition {
    host_header {
      values = ["my-service.*.terraform.io"]
    }
  }
}
```

## [aws_lb_target_group](https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/lb_target_group)
### [lambda_multi_value_headers_enabled](https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/lb_target_group#lambda_multi_value_headers_enabled-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定しなければ何もはいりません。一方で、terraformで作成した場合は明示的に指定しなくても``false``で入るため、差分として表示されます。
```terraform
resource "aws_lb_target_group" "test" {
  name                               = "tf-example-lb-tg"
  port                               = 80
  protocol                           = "HTTP"
  vpc_id                             = aws_vpc.main.id
  lambda_multi_value_headers_enabled = false
}
```

### [proxy_protocol_v2](https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/lb_target_group#proxy_protocol_v2-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定しなければ何もはいりません。一方で、terraformで作成した場合は明示的に指定しなくても``false``で入るため、差分として表示されます。
```terraform
resource "aws_lb_target_group" "test" {
  name              = "tf-example-lb-tg"
  port              = 80
  protocol          = "HTTP"
  vpc_id            = aws_vpc.main.id
  proxy_protocol_v2 = false
}
```

### [healthy_threshold](https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/lb_target_group#healthy_threshold-1)
この項目はマネジメントコンソールでの作成とterraformでの作成のデフォルト値の違いがあります。マネジメントコンソールで作成した場合、設定内容を変更しなければデフォルトで``5``が入ります。一方で、terraformで作成した場合、明示的に指定しないとデフォルトで``3``が入るため、差分として表示されます。
```terraform
resource "aws_lb_target_group" "tcp-example" {
  name     = "tf-example-lb-nlb-tg"
  port     = 80
  protocol = "TCP"
  vpc_id   = aws_vpc.main.id

  health_check {
    path                = "/health"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}
```

### [unhealthy_threshold](https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/lb_target_group#unhealthy_threshold-1)
この項目はマネジメントコンソールでの作成とterraformでの作成のデフォルト値の違いがあります。マネジメントコンソールで作成した場合、設定内容を変更しなければデフォルトで``2``が入ります。一方で、terraformで作成した場合、明示的に指定しないとデフォルトで``3``が入るため、差分として表示されます。
```terraform
resource "aws_lb_target_group" "tcp-example" {
  name     = "tf-example-lb-nlb-tg"
  port     = 80
  protocol = "TCP"
  vpc_id   = aws_vpc.main.id

  health_check {
    path                = "/health"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}
```

# Lambda
## [aws_lambda_function](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function)
### [publish](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#publish-1)
この項目はマネジメントコンソールで作成した場合、何も設定されません(Versioningを設定していないから？)。一方で、terraformで作成した場合は明示的に指定しなくても``false``で入るため、差分として表示されます。
```terraform
resource "aws_lambda_function" "test_lambda" {
  # If the file is not in the current working directory you will need to include a
  filename      = "lambda_function_payload.zip"
  function_name = "lambda_function_name"
  role          = aws_iam_role.iam_for_lambda.arn
  handler       = "index.test"
  publish       = false

  source_code_hash = data.archive_file.lambda.output_base64sha256

  runtime = "nodejs18.x"

  environment {
    variables = {
      foo = "bar"
    }
  }
}
```

## [lambda_function_event_invoke_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function_event_invoke_config)
### [function_name](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function_event_invoke_config#function_name-1)
この項目はマネジメントコンソールで作成した場合、LambdaのARNが入ります。一方で、terraformで作成する場合はLambdaのARN、もしくはLambda関数の名前で指定可能です。今回我々はterraformでLambda関数の名前を記載していまっていたため、差分として表示されました。
```terraform
resource "aws_lambda_function_event_invoke_config" "example" {
  function_name                = aws_lambda_function.test_lambda.arn
  maximum_event_age_in_seconds = 900
  maximum_retry_attempts       = 0
}
```

# Aurora
## [aws_rds_cluste](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster)
### [enable_global_write_forwarding](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#enable_global_write_forwarding-1)と[enable_local_write_forwarding](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#enable_local_write_forwarding-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定しなければ何もはいりません。一方で、terraformで作成した場合は明示的に指定しなくても``false``で入るため、差分として表示されます。
```terraform
resource "aws_rds_cluster" "example" {
  cluster_identifier             = "example"
  engine                         = "aurora-postgresql"
  engine_mode                    = "provisioned"
  engine_version                 = "13.6"
  database_name                  = "test"
  master_username                = "test"
  master_password                = "must_be_eight_characters"
  storage_encrypted              = true
  enable_global_write_forwarding = false
  enable_local_write_forwarding  = false

  serverlessv2_scaling_configuration {
    max_capacity             = 1.0
    min_capacity             = 0.0
    seconds_until_auto_pause = 3600
  }
}
```

### [manage_master_user_password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#manage_master_user_password-1)
この項目は、マネジメントコンソールでは存在しない設定項目で、terraform独自の設定項目となるため、差分が発生します。

terraform独自の設定項目ということで設定内容としては、RDSでSecretManagerを使ったログインを設定する際に、それをterraform側で認識させるための設定になります。この設定を``true``するとterraform側でSecretManagerを使ったログインで設定していることを認識し、関連リソースの設定等を行います。
```terraform
resource "aws_rds_cluster" "example" {
  cluster_identifier             = "example"
  engine                         = "aurora-postgresql"
  engine_mode                    = "provisioned"
  engine_version                 = "13.6"
  database_name                  = "test"
  master_username                = "test"
  master_password                = "must_be_eight_characters"
  storage_encrypted              = true
  manage_master_user_password    = true

  serverlessv2_scaling_configuration {
    max_capacity             = 1.0
    min_capacity             = 0.0
    seconds_until_auto_pause = 3600
  }
}
```

## [aws_rds_cluster_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group)
### [description](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group#description-1)
この項目はマネジメントコンソールで作成した場合、``DB Cluster Parameter Group``と入ります。一方で、terraformで作成した場合は``Managed by Terraform``で入るため、差分として表示されました。
```terraform
resource "aws_rds_cluster_parameter_group" "default" {
  name        = "rds-cluster-pg"
  family      = "aurora5.6"
  description = "Managed by Terraform"

  parameter {
    name  = "character_set_server"
    value = "utf8"
  }
}
```

## [aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group)
### [description](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group#description-1)
この項目はマネジメントコンソールで作成した場合、``DB Instance Parameter Group``と入ります。一方で、terraformで作成した場合は``Managed by Terraform``で入るため、差分として表示されました。
```terraform
resource "aws_db_parameter_group" "default" {
  name   = "rds-pg"
  family = "mysql5.6"
  description = "Managed by Terraform"

  parameter {
    name  = "character_set_server"
    value = "utf8"
  }
}
```

## [aws_db_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group)
### [description](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group#description-1)
この項目はマネジメントコンソールで作成した場合、``aurora subnet group``と入ります。一方で、terraformで作成した場合は``Managed by Terraform``で入るため、差分として表示されました。
```terraform
resource "aws_db_subnet_group" "default" {
  name       = "main"
  subnet_ids = [aws_subnet.frontend.id, aws_subnet.backend.id]
  description = "Managed by Terraform"

  tags = {
    Name = "My DB subnet group"
  }
}
```

## [aws_rds_cluster_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance)
### [force_destroy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance#force_destroy-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定しなければ何もはいりません。一方で、terraformで作成した場合は明示的に指定しなくても``false``で入るため、差分として表示されます。
```terraform
resource "aws_rds_cluster_instance" "cluster_instances" {
  count              = 2
  identifier         = "aurora-cluster-demo-${count.index}"
  cluster_identifier = aws_rds_cluster.default.id
  instance_class     = "db.r4.large"
  engine             = aws_rds_cluster.default.engine
  engine_version     = aws_rds_cluster.default.engine_version
  force_destroy      = false
}
```

# ElastiCache for Redis
## [aws_elasticache_replication_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group)
### [auth_token_update_strategy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group#auth_token_update_strategy-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定しなければ何もはいりません。一方で、terraformで作成した場合は明示的に指定しなくても``ROTATE``で入るため、差分として表示されます。
```terraform
resource "aws_elasticache_replication_group" "example" {
  replication_group_id = "example"
  description          = "example with authentication"
  node_type            = "cache.t2.micro"
  num_cache_clusters   = 1
  port                 = 6379
  subnet_group_name    = aws_elasticache_subnet_group.example.name
  security_group_ids   = [aws_security_group.example.id]
  parameter_group_name = "default.redis5.0"
  engine_version       = "5.0.6"

  transit_encryption_enabled = false
  auth_token_update_strategy = "ROTATE"
}
```

# DynamoDB
## [aws_appautoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy)
### [name](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy#name-1)
この項目はマネジメントコンソールで作成した場合、明示的に設定出来ない項目となり、``$<テーブル名>-scaling-policy``で設定される。一方で、terraformでは明示的に設定出来る項目となり、名前を指定しまったため差分として表示されました。
```terraform
resource "aws_appautoscaling_policy" "dynamodb_table_read_policy" {
  name               = "$<Table Name>-scaling-policy"
  policy_type        = "TargetTrackingScaling"
  resource_id        = aws_appautoscaling_target.dynamodb_table_read_target.resource_id
  scalable_dimension = aws_appautoscaling_target.dynamodb_table_read_target.scalable_dimension
  service_namespace  = aws_appautoscaling_target.dynamodb_table_read_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "DynamoDBReadCapacityUtilization"
    }

    target_value = 70
  }
}
```

# OpenSearch
## [aws_cloudwatch_log_resource_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_resource_policy)
## 作成単位
OpenSearchでログ出力を行う場合、マネジメントコンソールではリソースポリシーが出力するログ毎に1つ自動で作成され、ログをCloudWatch Logsに出力することが出来る。一方で、terraformでは明示的にリソースを定義して作成する必要があるため、1つのリソースポリシーに出力するログ全ての設定を記載したため、差分として表示さました。
```terraform
# エラーログ用ポリシー準備
data "aws_iam_policy_document" "application_logs_iam_policy" {
  statement {
    actions = [
      "logs:CreateLogStream",
      "logs:PutLogEvents"
    ]

    resources = [
      "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/OpenSearchService/domains/<OpenSearch名>/application-logs:*"
    ]

    principals {
      identifiers = ["es.amazonaws.com"]
      type        = "Service"
    }
  }
}

# インデックススローログ用ポリシー準備
data "aws_iam_policy_document" "index_logs_iam_policy" {
  statement {
    actions = [
      "logs:CreateLogStream",
      "logs:PutLogEvents"
    ]

    resources = [
      "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/OpenSearchService/domains/<OpenSearch名>/index-logs:*"
    ]

    principals {
      identifiers = ["es.amazonaws.com"]
      type        = "Service"
    }
  }
}

# 検索スローログ用ポリシー準備
data "aws_iam_policy_document" "search_logs_iam_policy" {
  statement {
    actions = [
      "logs:CreateLogStream",
      "logs:PutLogEvents"
    ]

    resources = [
      "arn:aws:logs:ap-northeast-1:xxxxxxxxxxxx:log-group:/aws/OpenSearchService/domains/<OpenSearch名>/search-logs:*"
    ]

    principals {
      identifiers = ["es.amazonaws.com"]
      type        = "Service"
    }
  }
}

# エラーログ用リソースポリシー作成
resource "aws_cloudwatch_log_resource_policy" "application-logs" {
  policy_name     = "Application-logs"
  policy_document = data.aws_iam_policy_document.application_logs_iam_policy.json
}

# インデックススローログ用リソースポリシー作成
resource "aws_cloudwatch_log_resource_policy" "index-logs" {
  policy_name     = "Application-logs"
  policy_document = data.aws_iam_policy_document.index_logs_iam_policy.json
}

# 検索スローログ用リソースポリシー作成
resource "aws_cloudwatch_log_resource_policy" "search-logs" {
  policy_name     = "Application-logs"
  policy_document = data.aws_iam_policy_document.search_logs_iam_policy.json
}
```

# S3
## [aws_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket)
### [force_destroy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#force_destroy-1)
この項目は、マネジメントコンソールでは存在しない設定項目で、terraform独自の設定項目となるため、差分が発生します。

terraform独自の設定項目ということで設定内容としては、S3を削除するときにオブジェクトがあるとエラーになりますが、この設定を``true``にすることでオブジェクトも含めて削除することを有効化出来る設定です。この設定自体はterraformのドキュメントだとオプションになっているのですが、何も指定しなくてもデフォルトの設定値``false``で入るため、差分として表示されます。
```terraform
resource "aws_s3_bucket" "s3_buckets" {
  for_each      = local.s3_bucket_map
  bucket        = each.key
  force_destroy = true
}
```

## [aws_s3_bucket_versioning](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning)
### [expected_bucket_owner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning)
この項目はまだ調査中ですが、一部の画面から作成したS3にアカウントIDが入っていました。一部のリソースだけなので、何かしら作る時の手順で入ったのかなと思いますが、詳しい方いれば教えてください。

こちらterraformで作成した場合は明示的に指定しないとnullで入るため、差分として表示されます。
```terraform
resource "aws_s3_bucket_versioning" "bucket_versioning" {
  bucket                = aws_s3_bucket.s3_bucket.id
  expected_bucket_owner = "012345678912"

  versioning_configuration {
    status              = "Enabled"
  }
}
```

## [aws_s3_object](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object)
### オブジェクト
今回はオブジェクトもterraformで作成していたのですが、オブジェクトのインポートが上手くいきませんでした。


この理由としては、昔からよくある問題ですがフォルダオブジェクトがなかったためインポートが上手く機能していませんでした。具体的には、terraformには``test/``というオブジェクトを記載していました。
```terraform
resource "aws_s3_object" "s3_object" {
  bucket = aws_s3_bucket.s3_bucket.id
  key    = "test/"
}
```
一方で、マネジメントコンソールで構築した際は``test/index.html``といったようにファイルごとアップロードしていたため、フォルダオブジェクトが存在せず、terraformコードで記載しているオブジェクトが差分として表示されていました。

# まとめ
インポート機能については非常に便利な機能です。これは間違いなく言えることです。
今回多くの差分が発生しましたが、発生した差分は実際に設定値を間違って設定して差分が出ていたというよりは環境特有の問題が多く、どれも利用者が意図しないものでした。
インポートを実行するには、これらの差分を1つ1つ確認していく必要があるので、かなりの負荷がかかります。

私が今回実施したように、環境毎インポートするというのがレアなケースなのかもしれませんが、そういった用途で使う方も少なからずいると思っています。
そのため、今回の記事がそういった方々の助けに少しでもなれば幸いです。

また、今回の記事で記載したサービスと差分は、私が今回のプロジェクトで利用したサービスと設定値で発生したものになります。別のリソースを利用すれば同じようにそのリソースにも差分が発生する項目があるかもしれませんし、同じサービスでも設定が異なるとまた違った項目が発生することもあると思います。そのため、今回の記事はあくまでも一例で、差分が発生するリソース一覧や設定一覧ではないことをご認識頂ければ幸いです。

皆さんのIaC生活が実りあるものになりますように！

# We Are Hiring!

https://www.biprogy.com/recruit/recruiting/