【AWS】S3を用いた画像のアップロード

# 目的
AWSのS3を使用し、画像をアップロードする。

# 開発環境
macOS: *Big Sur*
Rubyバージョン: *2.6.5*
Railsバージョン: *6.0.0*

# 前提

- S3のバケットが作成されている。
[【AWS】S3バケット作成](https://qiita.com/oak1331/items/b9b77200ad7c921f8961)
- アプリが作成されている。
[【Rails】簡単な投稿アプリの作成](https://qiita.com/oak1331/items/18a4f3a3386aab0fa354)
- 画像アップロード機能が実装されている。
[【Rails】画像アップロード機能の導入](https://qiita.com/oak1331/items/81c7d925e25d0e6fa629)

# 手順

1. [はじめに](#はじめに)
1. [Gemのインストール](#gemのインストール)
1. [development.rbの編集](#developmentrbの編集)
1. [storage.ymlの編集](#storageymlの編集)
1. [環境変数の設定](#環境変数の設定)
1. [環境変数の使用](#環境変数の使用)
1. [git-secretsの導入](#git-secretsの導入)
1. [git-secretsの条件設定](#git-secretsの条件設定)
1. [GitHub Desktopの利用設定](#github-desktopの利用設定)
1. [本番環境でのS3設定](#本番環境でのs3設定)
1. [Heroku上での環境変数設定](#heroku上での環境変数設定)

# はじめに

今回はAWSの`S3`を用いた画像アップロードを実装していきます。

# Gemのインストール

まずはローカル環境での実装を行います。
なお、以降のコードを編集する際はmasterブランチで作業していきます。

それでは早速始めていきます！
S3を使用するために必要な`aws-sdk-s3`というGemをインストールします!

```ruby:Gemfile
#中略
gem "aws-sdk-s3", require: false
```

```:ターミナル	
% bundle install
```

これでインストールできました!

# development.rbの編集

続いて、画像の保存先を`local`から`S3`に保存されるように設定を変更します！
まず、`development.rb`に記述している画像の保存先の設定を下記のように変更します。

```ruby:config/environments/development.rb
#省略
#config.active_storage.service = :local
config.active_storage.service = :amazon
#省略
```

これで画像の保存先が変更できました。

# storage.ymlの編集

次に、S3で使用する`バケット名`と`リージョン名`を記述します。
`storage.yml`に以下のコードを追記します。

```ruby: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」`は直接記載してはいけないため、それぞれの環境変数に入れてソースコードに記述します。
まずは、環境変数を設定するファイルを編集するために、`vimコマンド`を使用します。

```:ターミナル
$ vim ~/.bash_profile
```

続いて`「i」`を入力して、ファイルを編集モードにします。
ターミナル左下に`「INSERT」`という文字が表示されれば文字が入力できるようになっています。

環境変数に代入する`「Access key ID」`と`「Secret access key」`の値を調べるため、`「new_user_credentials.csv」`というcsvファイルを開き、以下のコードを追加します。

```:ターミナル
export AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
export AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```

値を貼りつけたら`「escキー」`→`「:wq」`の順で入力し、環境変数の設定ファイルを保存します。

次に`sourceコマンド`を入力し、先ほど設定した環境変数を使えるようにします。

```
$ source ~/.bash_profile
```

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

# 環境変数の使用

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

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

#省略
```

これで安全にソースコード内で安全に秘密情報を記述することができました！

# git-secretsの導入

ここまでの作業で、環境変数は設定できました。
しかし、うっかりミスで環境変数を使用し忘れてしまい、誤って秘密情報をGitHubにpushしてしまう可能性もあります。
そのため、誤操作で秘密情報をpushしないよう対策していきます！

AWSが公開している`「git-secrets」`というツールを使用して、誤ってGitHubにpushしないよう設定していきます。
`git-secrets`はcommitしようとしたコードをチェックし、パスワードだと推定されるような文字列が含まれている場合は、警告を出して処理が中断してくれる機能です。

まずは`git-secrets`のインストールです。

```:ターミナル（ホームディレクトリで実行すること）
% brew install git-secrets
```

`git-secrets`が導入できたら、設定を適用したいアプリケーションのディレクトリに移動して、`git-secrets`を有効化します。

```:ターミナル
% git secrets --install
```

これで、`git-secrets`を使用する準備ができました!

# git-secretsの条件設定

続いて、どのようなコードのcommitを防ぐのかを設定していきます。

下記のコマンドを実行し、`「Access key ID」`や`「Secret access key」`など、アップロードしたくないAWS関連の秘密情報を一括で設定します。

```:ターミナル
% git secrets --register-aws --global
```

これで条件が設定出来ました！

# GitHub Desktopの利用設定

commitなどソースコード管理を`GitHub Desktop`を使用して行なっている場合は、また追加で設定が必要になります。

以下のコマンドを実行して`GitHub Desktop`に`git-secrets`を適用させます！

```:ターミナル
% sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets
```

このコマンドの際にパスワードの入力が必要となる場合があります。このパスワードはPCにログインする際のパスワードです。

# git-secretsが適用範囲設定

ここまでの設定では、今後作成するリポジトリには`git-secrets`が適用されません。
そのため、以下のコマンドを実行して自動で適用されるようにします！

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

ここまでで、ローカル環境での設定とセキュリティ対策ができたので、実際に投稿した画像ファイルがS3に保存されるか確認してみましょう。問題がないようでしたら、成功です！

# 本番環境でのS3設定

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

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

```ruby:config/environments/production.rb
#省略

#config.active_storage.service = :local
config.active_storage.service = :amazon

#省略
```

# Heroku上での環境変数設定

Herokuで環境変数を扱うには、`heroku config:setコマンド`を打ちます。

```:ターミナル
% 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に反映させます。

```:ターミナル
% git push heroku master
```

その後、本番環境で挙動確認し問題がなければ完了です。

# 最後に

以上で、`S3`を用いた画像アップロード機能実装は完了です。
では。