見出し画像

S3に画像をアップロード

開発環境で問題がないことを確認します。

セキュリティ対策

AWSは従量制のサービスのため他人がなりすましでログインして膨大な処理を行うと被害が発生します。今回は3つ対策します。

・二段階認証

・AWSログイン後、ヘッダー部分のアカウント名をクリック。
・マイセキュリティ資格情報 をクリック。
・Continue to Security Credentialsをクリック。
・多要素認証(MFA) をクリックし、 MFAの有効化 をクリック。
・仮想MFAデバイス の選択を確認して、続行をクリック。
・QRコードの表示 をクリック。
・表示されたQRコードを二段階認証アプリで読み込む。
・アプリ側のワンタイムパスワードをAWSに入力。
・MFAの割り当て をクリックで完了。

・IAMユーザー
AWSのサービスの1つ。最初に作ったアカウントはルートユーザーと呼ぶ。ルートユーザーでログインすると全ての機能を使えるので、ルートユーザーのID・パスワードが悪用されると、第三者が全ての機能を使えてしまう。
IAMは使用機能を制限したユーザーを作成できる。

IAMユーザー作成
・ログイン後、検索のフォームにIAMと打ち込み、IAMのページに遷移。
・個々の IAM ユーザーの作成 をクリック。
・ユーザーの管理をクリック。
・ユーザーを追加をクリック。
・ユーザ名を入力、プログラムによるアクセスをチェックで次のステップへ
・既存のポリシーを直接アタッチ から AmazonS3FullAccess をチェック。
・次のステップをクリックし、次のステップ: 確認 をクリック。
・成功したら .csvのダウンロード をクリック。

パスワードを設定
・作成したIAMユーザーをクリック。
・認証情報のタブをクリックし、コンソールのパスワードの管理をクリック
・有効化 、自動生成パスワード にチェック。
・.csvファイル をダウンロード。
・サインアウト後、上記ダウンロードファイル内のURLにアクセス。
・ダウンロードファイル内のnameとpasswordでログイン。
・二段階認証設定の為、ルートユーザーで再度ログイン。
・IAMのユーザー選択画面から作成したユーザー名を選択し遷移。
・MFAデバイスの割当 の 管理 をクリック。
・ルートユーザーの時と同じように二段階認証設定で完了。

・git-secrets
誤操作でパスワードをGitHubにpushしてしまうと、誰でも見られる
状態になる。そのような誤操作を防ぐツール。

ターミナル

# git-secretsをインストール
$ cd ~/
$ brew install git-secrets

# 適用したいリポジトリに移動し、git-secretsを有効化
$ cd リポジトリ
$ git secrets --install

# アップロードしたくないAWS関連の秘密情報を一括で設定
$ git secrets --register-aws --global

# git-secretsの設定を確認
$ git secrets --list

# git-secretsを自動で適用するコマンド
$ git secrets --install ~/.git-templates/git-secrets
$ git config --global init.templatedir '~/.git-templates/git-secrets'

# GitHub Desktopからgit secretsを利用。
# Github Desktopがapplicationフォルダに移す。
$ sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets

# No such file or directoryのエラーがでる場合
$ sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/git/bin/git-secrets

S3 (Amazon Simple Storage Service)設定

バケット
S3で、実際にデータが格納される場所。

バケットを作成
・AWSログイン後メニューバーのサービスをクリック。
・ストレージ下のS3をクリック。
・右上の バケットを作成 をクリック。
・好きなバケット名を入れて、リージョンを 東京 に変更。
・パブパブリックアクセスをすべてブロック のチェックを外す。
・下二つにチェックをいれる。
・!の項目にもチェック。

画像1

バケットポリシー
どのアクセスに対しS3への読み書きを許可するか決める。
作成したIAMユーザーからのアクセスのみを許可するよう設定。

バケットポリシーの設定
・一覧から IAM をクリック。
・作成したユーザーをクリック。
・ユーザーのARN をコピー。
・作成したS3に戻り作成したバケットをクリック。
・アクセス権限 をクリックして バケットポリシー をクリック。
・下記を入力 ① にIAMの ユーザーのARN を貼り付け。
・② に作成したバケット名を入力。
・右上の 保存 をクリック。
バケットポリシー を編集

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

ローカルからS3にアップロード

①必要なGemのインストール

Gemfile を編集

# 画像アップロードの際、外部のストレージを選択し補助してくれる。AWSに最適化されたfog-awsをインストール。
# group ~ end で囲まれていない部分に追記
gem 'fog-aws'

ターミナルで bundle install を実行。

②アップロードにfogを使用するための設定

app/uploaders/image_uploader.rb を編集

# storageを :file から :fog に変更
storage :fog

③fogのアップロード先の設定

# config/initializers 下に carrierwave.rb を作成
config/initializers/carrierwave.rb を編集

require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
 config.storage = :fog
 config.fog_provider = 'fog/aws'
 config.fog_credentials = {
   provider: 'AWS',
# 下記でsecrets.ymlの設定内容を呼び出す。
   aws_access_key_id: Rails.application.secrets.aws_access_key_id,
   aws_secret_access_key: Rails.application.secrets.aws_secret_access_key,
   region: 'ap-northeast-1'
 }

 config.fog_directory  = '作成したバケット名'
# ap-northeast-1 は、アジアパシフィック(東京)の意味
 config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/作成したバケット名'
end 

④AWSのキーを設定

3箇所で設定を行うことで安全性を確保します。S3で使用するキーの
設定。万が一漏洩すると巨額の被害を被る恐れがあるので注意。
AWSのidやパスワードそのものは 環境変数 だけに設定する。
環境変数の値を secrets.yml から読み込み、その内容を
carrierwave.rb が読み込むという構造。

⑤環境変数を設定
S3の接続に必要な認証情報を、環境変数として設定
IAMユーザー設定時にダウンロードしたCSVファイル内の
Access_key_ID と Secret_access_key をコピー。

・MacOSがCatalina以降の場合

ターミナル

$ vim ~/.zshrc

# i でインサートモードに移行、下記を追記。既存の記述は消去しない。
# 既存の設定を削除するとパソコンが正常に動作しなくなる危険性がある。
export AWS_ACCESS_KEY_ID='上記コピーした Access key ID を貼り付け'
export AWS_SECRET_ACCESS_KEY='上記コピーした Secret access key を貼り付け'

# 編集が終わったらescapeキーを押してから:wqと入力して保存して終了
ターミナル

# 編集した.zshrcを再読込、追加した環境変数を使えるようにする。
$ source ~/.zshrc

・MacOSがMojave以前場合

ターミナル

$ vim ~/.bash_profile

# i でインサートモードに移行、下記を追記。既存の記述は消去しない。
export AWS_ACCESS_KEY_ID='上記コピーした Access key ID を貼り付け'
export AWS_SECRET_ACCESS_KEY='上記コピーした Secret access key を貼り付け'

# 編集が終わったらescapeキーを押してから:wqと入力して保存して終了


# 編集した.bash_profileを読み込み直して、追加した環境変数を使えるようにする
$ source ~/.bash_profile

⑥secrets.ymlの設定

YAMLファイル
YAMLと呼ばれるファイルは拡張子がymlです。設定ファイルとして
よく使われ、Rubyのハッシュのように「:(コロン)」で区切って
「キー」「バリュー」が設定できる。

config/secrets.yml を編集

# Be sure to restart your server when you modify this file.

# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!

# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rails secret` to generate a secure secret key.

# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.

development:
 secret_key_base: ce9b8afbaf9a74ab612b9754f98・・・・・
 aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
 aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

test:
 secret_key_base: e9d17e7e960adf75f110e17bb4cd1f2d4edc3d・・・・・

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
 secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

⑦.gitignoreを編集
他人に知られてはいけない内容を、Gitの管理から外してアップロード
されないようにする。

.gitignore を編集

# ファイル最下部に追記
config/secrets.yml

.gitignoreの変更は、一度gitの監視下に置かれたファイルには適用されない。アプリ名のディレクトリでコマンドを実行し、config/secrets.yml を
gitの監視から外す。

ターミナル

$ cd ~/projects/アプリ名
$ git rm --cached config/secrets.yml

⑧メッセージの投稿を行う
ローカル開発環境から、画像つきの投稿をする。
S3のバケット内に uploads というディレクトリができていれば成功。

本番環境からS3にアップロード

①本番環境の環境変数を設定

# 本番環境(ダウンロードした鍵で、ログイン)
$ ssh -i 〇〇.pem ec2-user@Elastic IP

$ sudo vim /etc/environment

# i でインサートモードに移行、下記を追記。既存の記述は消去しない。
AWS_ACCESS_KEY_ID='ローカル環境と同じ'
AWS_SECRET_ACCESS_KEY='ローカル環境と同じ'

# 編集が終わったらescapeキーを押してから:wqと入力して保存して終了

②環境変数の設定を反映

# 本番環境 編集内容を適用するために一旦ログアウト。
$ exit

# 再ログイン
$ ssh -i 〇〇.pem ec2-user@Elastic IP

# 環境変数が適用されているか確認。
$ env | grep AWS_SECRET_ACCESS_KEY
$ env | grep AWS_ACCESS_KEY_ID

ローカルでは .bash_profile に記述して、環境変数を設定した。
本番環境にも .bash_profile はあるが、デプロイにCapistranoを利用
しているため環境変数の設定ができない。
通常ユーザーがログインを行うと .bash_profile が読み込まれ、
内容が実行されるが、Capstranoを使用した場合は読み込まれない。
/etc/environments に記述することで環境変数を設定できる。

config/secrets.yml を編集

# Be sure to restart your server when you modify this file.

# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!

# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rails secret` to generate a secure secret key.

# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.

development:
 secret_key_base: cb2965bfebd75267542611a74ab612b9754f98・・・・・
 aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
 aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

test:
 secret_key_base: 7362cb8e960adf75f110e17bb4cd1f2d4edc3d・・・・・

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
 secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
 aws_access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %>
 aws_secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %>

③Capistranoの設定を変更
secrets.ymlの設定を変更したが、このファイルはGitで管理されないように設定したので、自動デプロイを行っても本番環境には送られない。
Capistranoの設定を変更することで可能にする。

config/deploy.rb を編集

# secrets.yml用のシンボリックリンクを追加
set :linked_files, %w{ config/secrets.yml }

# after 「'deploy:publishing', 'deploy:restart'」以下を削除して、書き換え。

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
 task :restart do
   invoke 'unicorn:restart'
 end

 desc 'upload secrets.yml'
 task :upload do
   on roles(:app) do |host|
     if test "[ ! -d #{shared_path}/config ]"
       execute "mkdir -p #{shared_path}/config"
     end
     upload!('config/secrets.yml', "#{shared_path}/config/secrets.yml")
   end
 end
 before :starting, 'deploy:upload'
 after :finishing, 'deploy:cleanup'
end

set :linked_files で指定されたファイルは、config/secrets.yml を参照する
代わりに、shared/config/secrets.yml を参照するようになる。
desc upload secrets.yml 以下は、ローカル環境にある config/secrets.ymlを本番環境の shared/config/secrets.yml に反映するための設定を
行なっている。これでGithubを経由せずにデプロイできる。

デプロイ

・GitHubにアップロード(コミット、プッシュ)

ローカル環境

# 自動デプロイを実行
$ bundle exec cap production deploy

エラーなくS3に画像が保存されていれば 完了!!


↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓エラーは下記↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

ローカル開発環境からのアップロードができない

①環境変数およびsecrets.ymlの設定を確認
・アプリのディレクトリで rails c を実行。

コンソール

# 以下のコマンドを実行.
Rails.application.secrets.aws_access_key_id
Rails.application.secrets.aws_secret_access_key

上記コマンドの実行でsecrets.ymlの設定を呼び出す。正しくAWSのキーと
パスワードが表示されれば、ここまでの設定は正しい。

・うまくいかなかった場合
 OSがMojaveより前の場合は下記。

ターミナル

# bash_profileの内容を確認
cat ~/.bash_profile
~/.bash_profile 

export AWS_SECRET_ACCESS_KEY='AWSのシークレットキー'
export AWS_ACCESS_KEY_ID='AWSのアクセスキー'
ターミナル

# bash_profileの内容を反映
source ~/.bash_profile

OSがCatalina以降の場合

cat ~/.zshrc

# zshrc内、下記を確認。なければ設定する。
export AWS_SECRET_ACCESS_KEY='AWSのシークレットキー'
export AWS_ACCESS_KEY_ID='AWSのアクセスキー'

# 内容を反映。
source ~/.zshrc
config/initializers/carrierwave.rb を確認

require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
 config.storage = :fog
 config.fog_provider = 'fog/aws'
 config.fog_credentials = {
   provider: 'AWS',
   aws_access_key_id: Rails.application.secrets.aws_access_key_id,
   aws_secret_access_key: Rails.application.secrets.aws_secret_access_key,
   region: 'ap-northeast-1'
 }

 config.fog_directory  = 'バケット名'
 config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/バケット名'
end

②バケットの指定が正しいか確認
・AWSのサービスからS3を選択し、バケットを表示。
・バケット名が正しく設定できているか。
・S3のリージョンが「アジアパシフィック(東京)」になっているか

本番環境からのアップロードができない

①Capistranoが動く

config/environments/production.rb を編集

# 下記設定で本番環境でもローカル開発環境と同じように、ブラウザにエラーメッセージが表示される。
# false になっているので、 true に変更
config.consider_all_requests_local = true

・GitHubへのプッシュ
・bundle exec cap production deploy の実行

②Capistranoがエラー

ターミナル

# Unicornのエラーログ確認
$ cat /var/www/(アプリ名)/current/log/unicorn.stderr.log 
$ cat /var/www/(アプリ名)/current/log/production.log

エラーログ確認方法
・ファイルの下に行くほど新しいログ。
・いつのログなのかを必ず確認。
・いつ起きたエラーに対するログなのかを確認する。
・ログの中にタイムスタンプがあったら、そこに9時間を足す。
(標準時での出力になるため、時差が9時間ある)。その時刻と、
今の時刻を見比べて今起きたエラーなのかをチェック。

③環境変数が正しく設定できているか確認

ローカル環境
$ ssh -i ~/.ssh/〇〇.pem ec2-user@<IP>

リモートのターミナル
$ env | grep AWS

出力結果が、AWSのキー、パスワードと一致するか確認。「|」は複数の処理を行うために必要。「A | B」と書くことで、Aの処理が終わったらBの処理をする。envは、現在設定されている環境変数を確認するためのコマンド。grepは文字の検索をして絞込みを行ってくれるコマンド。
AWS と付ける事で、AWS の文字列を含んだ行を表示。
env | grep AWS のコマンドで、環境変数の中に AWS という文字を含んだものだけを出力してとの命令になる。

④変更後のコードが本番に反映しているか確認
・GitHubを確認(プッシュできているか)

ローカルターミナル

# リモートファイルを確認
ssh -i ~/.ssh/〇〇.pem ec2-user@<IP>
 
# 最後の変更が反映しているか確認
/var/www/(アプリ名)/current/app

⑤サーバーを再起動

リモートターミナル

# Nginxの再起動
$ sudo service nginx restart 

# Unicornの再起動
$ ps aux |grep unicorn

# Unicornのプロセスidを確認する
$ kill -9 (unicornのプロセスid)
ローカルターミナル

$ bundle exec cap production deploy

エラー解決参考記事はこちら


この記事が気に入ったらサポートをしてみませんか?