(備忘録)AWSのS3を使い、画像をアップロードする方法


# データの保管とは？
* Webアプリケーションでは、毎日たくさんのユーザーより写真や動画がアップロードされてる。
* そのデータはユーザーがいつでも見返すことができるように蓄積しないといけない。
* その時、使うサービスを「ストレージサービス」という。

# ストレージサービスとは？
* インターネット上でデータを保存する場所を提供するサービス
* AmazonのS3はその体表的なサービス提供者

# Heroku、Renderなど、デプロイサイト利用(経由)し、リリースしたサイトに関して、ストレージサービスが必要となる理由
* Userがアップロードした画像などデータは、アプリがデプロイまたは再起動（自動更新）される度に、消えてしまう仕様になっている為
* 但し、有料バージョンはその限りではない。

# AWS、S３の無料使用期間
* 12ヶ月間、一定の使用量までは無料で利用できる
→S3の場合、以下が無料で使える
①5GBの容量
②20,000 件のGetリクエスト
③2,000 件のPutリクエスト
※今後変わる可能性はあり

* 無料枠でS3を利用する際は以下に注意
①不要となったらS3の利用を解除
②費用はこまめに確認

# S3導入の流れ

## ①S3で画像の保存先を作成
##### 1)AWSのトップページに遷移、「コンソールにサインイン」をクリック
##### 2)「ルートユーザーのEメールを使用したサインイン」を選択、ログイン
##### 3)二段階認証のトークン入力が求められた場合、Authyアプリを起動、表示されたトークン（数字6桁）を入力
##### 4)ログインできたら、画面上部の検索フォームに「S3」と入力、検索結果からS3のページにアクセスする
##### 5)S3バケットのページに遷移し、「バケットを作成」を選択
##### 6)「バケット名」を入力し、リージョンが「アジアパシフィック（東京）」になっていることを確認
##### 7)アクセス許可の設定
* 「パブリックアクセスをすべてブロック」のチェックを外す
* 画像のように3つのチェックボックスにチェックを入れる。
* 注意！この設定が誤っているとファイルのアップロードができなくなるので要注意！
![スクリーンショット 2022-12-29 4.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843483/44f84338-8734-8b7a-5034-7f70af4feb11.png)

##### 8)オプション設定が表示されるが、何も入力せず、「バケットを作成」をクリックし終了

## ②バケットポリシーを設定して、セキュリティ対策する
* バケットポリシーとはバケットに対し、どのようなユーザーが、どのような処理をできるか取り決めをするもの
* 処理には、データの保存やデータの読み取りなどがある
##### 1）画面上部の検索フォームに「IAM」と入力し、検索結果からIAMのページにアクセス
##### 2）左のサイドバーから「ユーザー」をクリック、IAMユーザーのページへ遷移し、「IAMユーザー名」をクリック
##### 3）「ユーザーのARN」をコピーするため、コピーするボタンをクリック
![スクリーンショット 2022-12-29 4.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843483/d0d494a0-ec1a-82c1-2709-5fdd4fdd4080.png)

##### 4）後の作業で「ユーザーのARN」を使用するため、メモアプリなどに保存
##### 5）画面上部の検索フォームに「S3」と入力し、検索結果からS3のページ
##### 6）作成した「バケット名」をクリック
##### 7）画面中央の「アクセス許可」をクリック
##### 8）「編集する」をクリック

```ruby
{
    "Version": "2012-10-17",
    "Id": "Policy1544152951996",
    "Statement": [
        {
            "Sid": "Stmt1544152948221",
            "Effect": "Allow",
            "Principal": {
                "AWS": "①"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::②"
        }
    ]
}
```

 「①」の箇所に、先ほどコピーした「ユーザーのARN」を入力
 「②」の箇所に、作成したバケット名を入力

##### 9）エラーが出なかったら異常なし

## ③<ローカル環境>S3に保存する処理を記述する

##### 1）S3を使用するために必要なGemfile導入の為、Gemfileの一番下に以下を追記
* Gemfile
```gem "aws-sdk-s3", require: false```
* ターミナル（開発中のアプリで実行）
```% bundle install```

##### 2）画像の保存先指定の為、development.rbを編集

config/environments/development.rb
(変更前)
```ruby
~省略~
config.active_storage.service = :local
~省略~
```
(変更後)
```ruby
~省略~
config.active_storage.service = :amazon
~省略~
```

##### 3）S3で使用するバケット名とリージョン名を記述

config/storage.yml
```ruby
test:
 service: Disk
 root: <%= Rails.root.join("tmp/storage") %>

local:
 service: Disk
 root: <%= Rails.root.join("storage") %>

```

>amazon:
 service: S3
 region: ap-northeast-1
>bucket: 「バケット名」を入力

```
~省略~
```


## ④<本番環境>S3に保存する処理を記述する
##### 1)セキュリティ対策の為、環境変数の設定の必要があり、ダウンロードしたcsvファイルを開いてアクセスキーの値を確認

##### 2)macOSのバージョンを確認
* macOSのバージョンによって、環境変数の設定をするファイルが異なるため
* Mojave以前の場合は「.bash_profile」、MacOSがCatalina以降の場合は「.zshrc」というファイルを使用
* 以下、MacOSがCatalina以降の場合を想定して進めます。

##### 3)環境変数を設定するファイルを開く
* ターミナル（開発中のアプリで実行）
```
% vim ~/.zshrc
```

##### 4)環境変数にアクセスキーを代入
![スクリーンショット 2022-12-29 6.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843483/aeca34d1-f62e-f81e-7b3a-72c42fc87c9a.png)

##### 1)「i」を入力して、ファイルを編集モードへ
##### 2)ターミナル左下に「INSERT」という文字が表示された後、入力
##### 3)以下のコードを追加
 
```
export AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
export AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```
##### 4)値を貼りつけたら「escキー」→「:wq」の順で入力し、環境変数の設定ファイルを保存
##### 5)環境変数の設定ファイルを読み込み直し、追加した環境変数を使えるようにする為、以下コマンド実行
* ターミナル（開発中のアプリで実行）
```
% source ~/.zshrc
```
##### 6)実際にソースコード内で環境変数を使用して、S3への認証情報を記述の為、storage.ymlに以下のコードを追記
config/storage.yml
```
test:
 service: Disk
 root: <%= Rails.root.join("tmp/storage") %>

local:
 service: Disk
 root: <%= Rails.root.join("storage") %>

amazon:
 service: S3
 region: ap-northeast-1
 bucket:  （自身のバケット名が記載されている状態です）
```
 >access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
 >secret_access_key:  <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
```
~省略~
```
##### 7)git-secretsを設定して、セキュリティ対策(推奨)
* 誤操作で秘密情報をpushしないように対策
* git-secretsとは、AWSが公開しているツール
* commitしようとしたコードをチェック、パスワードだと推定されるような文字列が含まれている場合、警告を出し処理が中断される機能

①git-secretsをインストール
##### ターミナル（ホームディレクトリで実行）
```
% cd ~/ #ホームディレクトリに移動
% brew install git-secrets
```

②git-secretsの条件を設定
* 「Access key ID」「Secret access key」など、アップロードしたくないAWS関連の秘密情報を一括で設定
##### ターミナル（開発中のアプリで実行）
```
% git secrets --register-aws --global
```
③現在のgit-secretsの設定を表示してみる
##### ターミナル（開発中のアプリで実行）
```
% git secrets --list
```
* 様々な正規表現を用いて、AWSで作成される秘密情報のパターンが条件に設定されていることを確認
* これで、「git secrets --install」を行なったリポジトリでは「git commit」コマンドを実行した際にAWSの秘密情報を含んでいないかチェックされるようになる。

④　GitHub Desktopからgit-secretsを利用できるようにしましょう
* 先にGitHub Desktopがアプリケーションのディレクトリに存在しているか確認
* 次に以下のコマンドを実行してGitHub Desktopにgit-secretsを適用
##### ターミナル
```
% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets
```
⑤今後作成する全てのリポジトリに、git-secretsが適用されるようにする
##### ターミナル
```
% git secrets --install ~/.git-templates/git-secrets
% git config --global init.templatedir '~/.git-templates/git-secrets'
```

## ⑤ローカル環境で画像を保存できるか確認
##### 1)ローカル環境で画像を投稿
##### 2)IAMユーザーでログイン
##### 3)S3のバケットのページを開く
##### 4)画像が保存されているか確認

## ⑥本番環境からS3に画像を保存
##### 1)ローカル環境での設定と同様に、画像の保存先を指定
config/environments/production.rb
(変更前)
```ruby
~省略~
config.active_storage.service = :local
~省略~
```
(変更後)
```ruby
~省略~
config.active_storage.service = :amazon
~省略~
```
##### 2)HerokuやRenderなど、環境変数を設定するコマンド

## ⑦本番環境で画像を保存できるか確認

##### 1)本番環境で画像を投稿
##### 2)IAMユーザーでログイン
##### 3)S3のバケットのページを開く
##### 4)画像が保存されているか確認