TerraformでS3リソースをインポートしてみた：①Terraform import編

# やりたいこと
・手動で作成したS3リソースをterraformで管理したい 👈今回はここ

・AWSで事前に書いた3バケットポリシーをtfファイルに丸ごと取り込みたい
　👇👇👇次回やる

https://qiita.com/curlneko/items/9faf4e016a03af19d412


# 前提
・AWSアカウント作成済み
・AWS IAMユーザーを作成し、access_keyとsecret_keyを発行済み
・Terraformインストール済み
・AWS CLIインストール済み
・VSCODEインストール済み
　（お好みのエディターで大丈夫）

・AWSのほうで、手動でS3バケットとそのポリシーを作成済み
　（バケットポリシー以外の設定は、全部デポジットで大丈夫）

　バケット名を「terraform-test-import-20230828」にして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/0eb9acf4-b5a9-9a8c-8dd2-073f6d49ed29.png)
　「IPアドレスのアクセス許可権限」に関するバケットポリシーを手動で設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/9f2780d8-b9b1-bdee-6bcb-df8a0493303e.png)

```ruby:バケットポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::terraform-test-import-20230828/*"
            ],
            "Condition": {
              "IpAddress": {"aws:SourceIp": "設定したいIP"},
              "NotIpAddress": {"aws:SourceIp": "設定したいIP"}
            }
        }
    ]
}
POLICY
}
```

:::note info
※補足
・バケットポリシーは今回の主役じゃないので、どうでもいい内容で大丈夫だけど、場合によって「ブロックパブリックアクセス (バケット設定)」が引っかかってうまく設定できないのがある

・特に「s3:GetObject」のallow権限は、ブロックパブリックアクセスが関連してるので避けたほうが無難かな。。。

・今回はブロックパブリックアクセス (バケット設定)が関わらない「IPアドレスのアクセス」ポリシーを選定
:::

# 環境
```
$ terraform -v 
Terraform v1.5.5
on windows_amd64
+ provider registry.terraform.io/hashicorp/aws v5.13.1
```
# ディレクトリ構成
```
root  　　   
  ┣━ main.tf
  ┣━ variables.tf
  ┣━ terraform.tfstate（Terraform実行により作成されたやつ）
  ┣━ terraform.tfstate.backup（Terraform実行により作成されたやつ）
  ┗━ import.tf (importのお試し)
```

# ソースの中身

### main.tf
・main.tfには基本、全体共通で重要な設定、例えば「AWS プロバイダの設定」を書く
```ruby:main.tf
# AWS プロバイダの設定
provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region     = var.region
}
```

### variables.tf
・variables.tfに全ソース共通の変数を書く
・リージョンは東京にしたが、適宜変更して大丈夫
・access_keyとsecret_keyは事前に発行したやつを使用
```ruby:variables.tf
variable "region" {
  default = "ap-northeast-1"
}

variable "access_key" {
  default = "自分のaccess_key"
}

variable "secret_key" {
  default = "自分のsecret_key"
}
```

### import.tf
・Terraform importのお試しファイル
・Terraform import実行後、中身の編集をやりたいので、最初はリソース**aws_s3_bucket**と**aws_s3_bucket_policy**の枠だけ用意すればいい
　（いったんリソース名だけ書いて、中身を完全に空にしても大丈夫）
```ruby:import.tf
resource "aws_s3_bucket" "s3" {
  bucket = "terraform-test-import-20230828"
}

resource "aws_s3_bucket_policy" "s3" {
  bucket = aws_s3_bucket.s3.id
#   policy = <<POLICY
# {
# }
# POLICY
}
```
:::note info
※補足
通常、この状態でterraform planを実行するとpolicyがないよ！！って怒られるが、今回は**terraform plan**からではなく、**terraform import**をやりたいので、policyのコメントアウトは大丈夫（空にするのは必須である）
:::



# Terraformのimportを試してみる
AWSのほうですでにリソースがあるだけど、手動で作成したやつらをIaaS風で管理したい場合はどうしたらいいか？

**Terraform import** の出番だ！！！

まず、ローカルでimport.tfを用意したうえ、terraform importのコマンドを実行しよう

```
terraform import aws_s3_bucket.s3 terraform-test-import-20230828
```
これが出たら成功かな
```ruby:実行結果
Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

すると、terraform.tfstateのほうに何か自動で書き込まれたはず
```ruby:terraform.tfstate
{
  "version": 4,
  "terraform_version": "1.5.5",
  "serial": 1482,
  "lineage": "ccde992e-debb-97f0-c5bd-458b5945bd4e",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "s3",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "acceleration_status": "",
            "acl": null,
            "arn": "arn:aws:s3:::terraform-test-import-20230828",
            "bucket": "terraform-test-import-20230828",
            "bucket_domain_name": "terraform-test-import-20230828.s3.amazonaws.com",
            "bucket_prefix": "",
            "bucket_regional_domain_name": "terraform-test-import-20230828.s3.ap-northeast-1.amazonaws.com",
            "cors_rule": [],
            "force_destroy": null,
            "grant": [
              {
                "id": "2078aa226b78698297fd9aaff292740e1c8f3ce3d6ee33fcc33cd14e0ddea4aa",
                "permissions": [
                  "FULL_CONTROL"
                ],
                "type": "CanonicalUser",
                "uri": ""
              }
            ],
            "hosted_zone_id": "Z2M4EHUR26P7ZW",
            "id": "terraform-test-import-20230828",
            "lifecycle_rule": [],
            "logging": [],
            "object_lock_configuration": [],
            "object_lock_enabled": false,
            "policy": "{\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"設定したいIP"},\"NotIpAddress\":{\"aws:SourceIp\":\"設定したいIP"}},\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::terraform-test-import-20230828/*\",\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}",
            "region": "ap-northeast-1",
            "replication_configuration": [],
            "request_payer": "BucketOwner",
            "server_side_encryption_configuration": [
              {
                "rule": [
                  {
                    "apply_server_side_encryption_by_default": [
                      {
                        "kms_master_key_id": "",
                        "sse_algorithm": "AES256"
                      }
                    ],
                    "bucket_key_enabled": true
                  }
                ]
              }
            ],
            "tags": {},
            "tags_all": {},
            "timeouts": null,
            "versioning": [
              {
                "enabled": false,
                "mfa_delete": false
              }
            ],
            "website": [],
            "website_domain": null,
            "website_endpoint": null
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH0sInNjaGVtYV92ZXJzaW9uIjoiMCJ9"
        }
      ]
    }
  ],
  "check_results": null
}

```


terraform import実行前、terraform.tfstateの中身はほぼ空だけど

コマンド実行すると、S3がimportされ、Terraformで管理されるようになった！

よく見ると↓↓↓、バケット名とかpolicyとか（今回はこの二つしか設定してないからね）、S3の状態やmetaデータはterraform.tfstateに書き込まれた！

```ruby:terraform.tfstateから抜粋
"bucket": "terraform-test-import-20230828"

"policy": "{\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"設定したいIP"},\"NotIpAddress\":{\"aws:SourceIp\":\"設定したいIP"}},\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::terraform-test-import-20230828/*\",\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}"
```

:::note info
※補足
terraform.tfstateはTerraformが管理しているリソースの現在の状態（terraformの実行計画）を記載するファイル

初めてterraform planを実行したら、terraform.tfstateはローカルに作られ、リソースのstate（状態）が自動で書き込まれる

その後terraform destroyすると、terraform.tfstateは空になるけど、ファイル自体は消えない

一回もterraform planかterraform importを実行したことないのであれば、terraform.tfstateファイルはローカルに存在しないはず
:::


でも、本当にこれでTerraformの管理下になったのか不安なので、最初に作ったほぼ空のimport.tfに、手動で中身を入れ替えて、S3の設定をいじってみよう

```ruby:import.tf
resource "aws_s3_bucket" "s3" {
  bucket = "terraform-test-import-20230828"

　#タグをいれてみる
  tags = {
    Name = "test"
  }
}

resource "aws_s3_bucket_policy" "s3" {
  bucket = aws_s3_bucket.s3.id
　#バケットポリシを手動で張り付け、AllowをDenyへ変更
　policy = <<POLICY
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::terraform-test-import-20230828/*"
            ],
            "Condition": {
              "IpAddress": {"aws:SourceIp": "設定したいIP"},
              "NotIpAddress": {"aws:SourceIp": "設定したいIP"}
            }
        }
    ]
}
POLICY
}
```
こんな感じで、タグを一個追加し、バケットポリシをAllowからDenyにしてみた～

terraformの実行計画を変えるため、今度はterraform planを実行しよう

```
terraform plan
```
こんな感じで、結果が出たら成功
1 to add：「新規tfファイルの内容を実行計画にいれたよ」って言ってる
1 to change：「tfファイルに書いたS3リソースは、さっきのimportですでにterraform管理下になったけど、修正分があるよ」って言ってる

```ruby:実行結果
Plan: 1 to add, 1 to change, 0 to destroy.
```
次に、変更分をAWS側へデプロイ
```
terraform apply
```
ちゃんと成功したっぽい
```ruby:実行結果
Apply complete! Resources: 1 added, 1 changed, 0 destroyed.
```

もう一度terraform.tfstateを確認すると、変更分はちゃんと管理ファイルに書かれてるね！
```ruby:terraform.tfstateから抜粋
"policy": "{\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"54.240.143.0/24\"},\"NotIpAddress\":{\"aws:SourceIp\":\"54.240.143.188/32\"}},\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::terraform-test-import-20230828/*\",\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}",
"tags": {
              "Name": "test"
            },
```
そして、AWS側を見てみると、バケットポリシは確かに修正されて、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/baf23058-5fac-9fb7-4a89-d1035cc070be.png)
testのタグもできてます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/e002a901-ba8b-462f-8fe9-7f2f986e0287.png)

最後、リソースはterraformにより削除できるか確認しよう

```
terraform destroy
```
リソースが削除されたよって言ってます！
```ruby:実行結果
Destroy complete! Resources: 2 destroyed.
```
AWSを確認すると、ちゃんと削除してくれたね！Good！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/fd664d10-21b7-7cae-f16e-35e63debe5e3.png)


# 終わりに

お疲れ様です！今回のやりたいことが無事終わった！
・手動で作成したS3リソースをterraformで管理したい
 　⇒🎉terraform importすればできるよ！
・AWSで事前に書いたS3バケットポリシーをtfファイルに丸ごと取り込みたい
 　⇒🐱次回書く

https://qiita.com/curlneko/items/9faf4e016a03af19d412


# 参考サイト

以下のサイトのおかげで、大変勉強になりました！ありがとうございます！

https://qiita.com/empty948/items/f5707be8077dba995978

https://developer.hashicorp.com/terraform/cli/import