Oracle Cloud Infrastructure の Object Storage を Terraform の Backend として設定する手順

# これはなに
Oracle Cloud Infrastructure (OCI) の Object Storage を Terraform の Backend として設定する手順について説明します。
若干のハマりどころがあったため、その備忘録も兼ねて記事にしました。

# 手順
基本的には公式のドキュメントどおりに設定を行います。

[Using Object Storage for State Files](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformUsingObjectStore.htm)

また、検証で使用したバージョンは以下のとおりです。

* Terraform: 1.1.2
* OCI Provider: 4.57.0

## Customer Secret Keys を作成する
公式のドキュメントに従い Customer Secret Keys を作成します。

https://docs.oracle.com/ja-jp/iaas/Content/Identity/Tasks/managingcredentials.htm#To4

> 「顧客秘密キー」は以前、「Amazon S3互換APIキー」と呼ばれていました。作成したすべてのキーは、コンソールに顧客秘密キーとしてリストされます。既存のキーを引き続き使用できます。
> Ref: [ユーザー資格証明の管理](https://docs.oracle.com/ja-jp/iaas/Content/Identity/Tasks/managingcredentials.htm#Working2)

## 認証情報を設定する
上記で作成したものはAWSのアクセスキーIDと互換性があるものとなります。
従って、[AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication)と同様の方法で認証情報を渡していきます。

環境変数経由でアクセスキーとシークレットアクセスキーを渡す場合は export します。

```
export AWS_ACCESS_KEY_ID=xxxx
export AWS_SECRET_ACCESS_KEY=yyyy
```

[公式のドキュメント](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformUsingObjectStore.htm#s3) にはAWSアクセスキーIDの例として `ocid1.credential.oc1..exampleuniqueID` のようなフォーマットが示されていました。しかしながら、現在実際に発行されるものは16進表記の文字列でしたので注意が必要です。
(これにより、公式のドキュメントが現在も信頼できるのかの判断が難しくなりました。)


## Backend を設定する
こちらも公式のドキュメントと同様の設定で問題ありません。
認証情報の渡し方によっては `region` や `access_key`, `secret_key` などのオプションも指定する必要があります。

```
terraform {
  backend "s3" {
    endpoint = "https://<Your namespace>.compat.objectstorage.<Your region>.oraclecloud.com"
    region   = "<Your region>"
    bucket   = "terraform"
    key      = "terraform.tfstate"

    # AWS 認証をスキップする
    skip_region_validation      = true
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    force_path_style            = true
  }
}
```

# ハマったポイント
## 認証に失敗する認証情報が発行される場合がある
実はここがこの記事で一番書いておきたかった点です。
以下の記事が無ければハマり続けていたでしょう。感謝します。

https://qiita.com/tettsu__/items/165afe4570f27468b90f

上記の記事で紹介されている通り、シークレットアクセスキーに特殊文字が含まれていると認証が通らない場合があるようです。
私の環境では以下のようなエラーが表示されました。

```console
$ terraform init
Initializing modules...

Initializing the backend...
╷
│ Error: Error loading state:
│     SignatureDoesNotMatch: The secret key required to complete authentication could not be found. The region must be specified if this is not the home region for the tenancy.


│       status code: 403, request id: kix-1:XXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, host id:
│
│ Terraform failed to load the default state from the "local" backend.
│ State migration cannot occur unless the state can be loaded. Backend
│ modification and state migration has been aborted. The state in both the
│ source and the destination remain unmodified. Please resolve the
│ above error and try again.
│
│
╵
```

認証情報ガチャを繰り返し、認証が通るものが発行されるまで頑張ることで無事動作させることができました。

## その他に試したこと
また、 `force_path_style = true` を Backend のオプションで指定しなかった場合は以下のようなエラーが表示されました。
結果としては、上記のオプションは指定する必要があることがわかりました。

```console
$ terraform init
Initializing modules...

Initializing the backend...
╷
│ Error: Error loading state:
│     RequestError: send request failed
│ caused by: Get "https://terraform.xxxxxxxxxxxx.compat.objectstorage.ap-osaka-1.oraclecloud.com/oci/terraform.tfstate": x509: certificate is valid for swiftobjectstorage.ap-osaka-1.oraclecloud.com, not terraform.xxxxxxxxxxxx.compat.objectstorage.ap-osaka-1.oraclecloud.com
│
│ Terraform failed to load the default state from the "s3" backend.


│ State migration cannot occur unless the state can be loaded. Backend
│ modification and state migration has been aborted. The state in both the
│ source and the destination remain unmodified. Please resolve the
│ above error and try again.
│
│
╵
```

# おわりに
OCI で Terraform を使用するための初期手順について説明しました。
OCI は最近では無料枠が充実していることで話題になっていますね。これを期に Terraform でリソースを管理してみては如何でしょうか。