S3に保存する処理

#S3に保存する処理を実装する
Heroku上で投稿した画像をS3に保存する方法を理解すること
コード内で秘密情報を扱う際のセキュリティー対策を理解すること

#条件
ローカル環境でDBに画像が保存できることを前提する。

#S3に画像を保存する
まずは、S3を使用するために必要なGemfileを導入します。

```
gem "aws-sdk-s3", require: false
```
bundle installしましょう。

続いて、画像の保存先を指定します。

現状では画像の保存先が「local」に設定されており、これはアプリケーション内に画像を保存することを意味しています。そこで、S3に保存されるように設定を変更しましょう。

```config/environments/development.rb
# ~省略~

config.active_storage.service = :local

# ~省略~
```
を下記に↓

```config/environments/development.rb
# ~省略~

config.active_storage.service = :amazon

# ~省略~
```
次に、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: ご自身の「バケット名」を入力
↑ここまでを記載
```

#アクセスキーの記述方法
最後に、S3にアクセスするための認証情報を設定します。

しかし、秘密情報である「Access key ID」「Secret access key」を直接storage.ymlに記載してはいけません。

なぜなら、GitHubでソースコードを管理しているため、もしリモートリポジトリで秘密情報を公開してしまった場合、誰でも見れる状態になってしまうためです。

悪意あるユーザーがGItHub内を探して見つけた「Access key ID」「Secret access key」を使って、AWSのサービスを不正利用する危険性があります。

そこで、秘密情報が漏洩しないようにするために、環境変数を用いてセキュリティー対策をします。
まずは、環境変数に代入する「Access key ID」「Secret access key」の値を調べます。
ダウンロードした「new_user_credentials.csv」というcsvファイルを開いておき、後ほどcsvファイルを使用します。
環境変数を設定するファイルを編集するために、vimコマンドを使用します。

ターミナル（開発中のアプリで実行）

```
% vim ~/.zshrc
```
vimとは、サーバー上で使用できるテキストエディタです。vimコマンドを用いることで、指定したファイルの編集をターミナルから行うことが可能。zshはシェルの1つです。

```
vim ~/.bash_profile
```
環境変数を設定
「i」を押してインサイトモードにし

```
export AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
export AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```
注意：ダブルクォーテーションは消さない
値を貼りつけたら「escキー」→「:wq」の順で入力し、環境変数の設定ファイルを保存しましょう。
```環境変数の設定ファイルを読み込み直し、追加した環境変数を使えるようにしましょう```

```
 % source ~/.zshrc
```
sourceコマンドとは現在開いているターミナルのタブで環境変数の設定ファイルを読み込み直してくれるものです。

ここまでで、環境変数を設定することができました。
実際にソースコード内で環境変数を使用して、S3への認証情報を記述しましょう

```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'] %>

# ~省略~
```
これで安全にソースコード内で安全に秘密情報を記述することができました。

しかし、うっかりミスで環境変数を使用し忘れてしまい、誤って秘密情報をGitHubにpushしてしまう可能性もあります。
誤操作で秘密情報をpushしないよう対策しましょう。
###git-secrets
git-secretsとは、AWSが公開しているツールです。
commitしようとしたコードをチェックし、パスワードだと推定されるような文字列が含まれている場合は、警告を出して処理が中断してくれる機能です。

ターミナルから、Homebrewを経由してgit-secretsを導入します。

```
% cd ~/
% brew install git-secrets
```
Homebrewを使うことにより、依存関係のあるパッケージが正しく動作するよう、複数のパッケージのバージョンをコントロールしてインストールすることが可能です。

```
% cd アプリケーション名 #開発中のアプリに移動
% git secrets --install
```
これで、有効化を行なったリポジトリでgit-secretsを使用する準備ができました

続いて、どのようなコードのcomiitを防ぐのかを設定していきましょう。
「Access key ID」「Secret access key」など、アップロードしたくないAWS関連の秘密情報を一括で設定します。

```
% git secrets --register-aws --global
```
実際にどのような設定がされているか確認しましょう。

```
git secrets --list
```
これで、「git secrets --install」を行なったリポジトリでは「git commit」コマンドを実行した際にAWSの秘密情報を含んでいないかチェックされるようになりました。

###GitHub Desktopからgit-secretsを利用できるようにしましょう
GitHub Desktopを使用してcommitなどソースコード管理を行なっている場合は、また追加で設定が必要になります。
まず、GitHub Desktopがアプリケーションのディレクトリに存在しているか確認しましょう。
アプリケーションに内に存在していることを前提で設定を進めていくためです。
もし他の場所に存在している場合はアプリケーション内に移動しましょう。

```
% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets
```
###今後作成する全てのリポジトリに、git-secretsが適用されるようにしましょう
ここまでの設定では、今後作成するリポジトリにはgit-secretsが適用されません。
特段の理由がなければ、以下のコマンドを実行して自動で適用されるようにしましょう。

```
% git secrets --install ~/.git-templates/git-secrets
% git config --global init.templatedir '~/.git-templates/git-secrets'
```
これで、今後作成する他のアプリケーションにも、git-secretsが適用されるようになりました。

#ローカル環境で画像は保存できているか確認する。
ローカル環境で画像を投稿し、AWSのIAMユーザーでログインしよう。

S3のバケットにファイルが保存されているか確認します。
まず、以下の手順でバケットのページに遷移しましょう。

・AWSのサイト画面上部のメニューバーから「サービス」をクリック
・サービス一覧から「S3」を選択
・「バケット名」をクリック

次に、以下の手順で投稿した画像が保存されているか確かめます。

・一度リロードして情報を最新の状態にする
・バケットの詳細ページで画面を下にスクロールする
・「オブジェクト」という項目の中に投稿した画像があるか確認する
【確認方法①】 最終更新日時が投稿した時間と一致しているか
【確認方法②】 オブジェクトをクリックし詳細ページを開く。「オブジェクトアクション」から「開く」をクリックし、同じ画像が表示されるかどうか

#本番環境からS3に画像を保存
ローカル環境での設定と同様に、画像の保存先を指定します。
現状では画像の保存先がローカルに設定されているため、S3に保存されるように設定を変更しましょう。

まずproduction.rbに記述していある画像の保存先の設定を「:local」→「:amazon」に変更します。

```config/environments/production.rb
# ~省略~

config.active_storage.service = :local

# ~省略~
```
を下記に

```config/environments/production.rb
# ~省略~

config.active_storage.service = :amazon

# ~省略~
```
ローカル環境での設定と同様に本番環境でも、「Access key ID」「Secret access key」を環境変数に代入して使用します。
Herokuで環境変数を扱うには、「heroku config:setコマンド」を打つ必要があります。
開発中のアプリケーションのディレクトリで、以下2つのコマンドを実行しましょう。
右辺にはcsvファイルの「Access key ID」「Secret access key」の値をコピーして貼り付けてください。

```
heroku config:set AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
```

```
% heroku config:set AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```
環境変数が正しく設定できているかを確認するために、下記のコマンドを入力してください。

```
% heroku config
```
ここまで編集出来たらコミットをしましょう。

herokuにpushし反映しよう

```
% git push heroku master
```

また本番環境で画像を投稿し、IAMユーザでログインしバゲットを確認し保存ができていたら完了です。