Encrypted Credentials②
マスターキーの管理
Railsではアプリ作成時に、Gitの管理から外すように設定されています。
.gitignore
# Ignore master key for decrypting credentials and more. /config/master.key
上記のようにプッシュしてしまわないように設定されています。
ただ、チーム開発の時はマスターキーを共有しないとcredentials.yml.encの中身を見れないので、どのように共有するのかを書いていきます。
ローカル開発環境でのマスターキーの共有方法を確認
まずは、Slack等でconfig/master.keyの内容を共有します。
そして他のメンバーはクローンしたアプリケーションのconfigフォルダに新規で「master.key」ファイルを作成し、Slack等で共有した内容をコピーします。
本番環境でのマスターキーの扱い方を確認
作成したアプリケーションをCapistranoを使ってデプロイしても、本番環境のアプリケーションはcredentialsを読み込むことができません。
なぜならGit Hubへマスターキーがプッシュされないので、EC2にもプルされません。
本番環境でcredentialsを使うための手順
本番環境でcredentialsを使えるようにするため、環境変数にマスターキーを設定する必要があります。
etc/environmentsファイルに記述を行う事で、環境変数を設定することができます。
ターミナル
$ ssh -i ~/.ssh/(pemファイル名) ec2-user@(EC2のElastic IP) [ec2-user]$ sudo vim /etc/environment
iキーを押して編集していきます。
/etc/environment
RAILS_MASTER_KEY='master.keyの値' # config/master.key」の値をコピーして貼り付けます
これで設定はできたので、ログインし直します。
[ec2-user]$ exit $ ssh -i ~/.ssh/(pemファイル名) ec2-user@(EC2のElastic IP) [ec2-user]$ env | grep RAILS_MASTER_KEY
マスターキーの内容が表示されればうまくいっています。
Encrypted Credentials①
Encrypted Credentialsとは
Rails5.2から導入され、秘密情報を管理する機能です。外部に公開されたくない値はcredentials.yml.encというファイルでまとめて管理し、暗号化・復号にはmaster keyが必要になります。
credentialsの使い方
credentials.yml.encは普通に編集することができません。まずは編集するための準備を行います。
VSCodeでcredentialsを編集できるようにしていきます。
VSCodeで、「Command + Shift + P」を同時に押してコマンドパレットを開きます。
続いて、「shell」と入力します。そして「PATH内に'code'コマンドをインストールします」という項目が表示されるので、それをクリックします。
credentialsを編集
ターミナル
# アプリのディレクトリにいることを確認して $ EDITOR='code --wait' rails credentials:edit
そうすると下記のように表示されます。
# aws: # access_key_id: 123 # secret_access_key: 345 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: dcb9317dcd2d42d9e045a2cd00c20df0b8109・・・
コメントアウトになってる部分を外して保存します。
※yamlファイルの記述方法 yamlファイルではインデントが意味を持っています。ネストをさせる場合は、上のコードの2,3行目のようにスペース2つのインデントを入れるようにします。
credentialsの内容を確認
ターミナル
$ rails c $ Rails.application.credentials[:secret_key_base] $ Rails.application.credentials[:aws][:access_key_id]
carrierwave.rb
CarrierWave.configure do |config| config.fog_credentials = { provider: 'AWS', aws_access_key_id: Rails.application.credentials[:aws][:access_key_id], aws_secret_access_key: Rails.application.credentials[:aws][:secret_access_key], region: 'ap-northeast-1' } end
master.keyとは
config/master.keyに記載されいる値のことです。記載されていればcredentials.yml.encファイル を先ほどみたいなに編集することができます。
そのほかに、「環境変数」にキーを設定することでも同様の操作ができます。
マスターキーを環境変数にセット
config/master.key
b0705c15e27c0dd14e34fda・・・
コンソール
$ export RAILS_MASTER_KEY=(上の英数字)
※マスターキーとして使用する環境変数名は必ず「RAILS_MASTER_KEY」にする必要があります。
※「=」の前後にスペースが入らないよう注意です。
S3を使ってアップロード⑥
本番環境からS3にアップロード
本番環境の環境変数を設定
環境変数の設定ファイルを変更
# 本番環境 ターミナル $ ssh -i [pem鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP] (ダウンロードした鍵を用いて、ec2-userとしてログイン) $ sudo vim /etc/environment # iを押してインサートモードに移行し、下記を追記する。既存の記述は消去しない。 AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー' AWS_SECRET_ACCESS_KEY='ここにCSVファイルのにSecret access keyの値をコピー' # 編集が終わったらescapeキーを押してから:wqと入力して保存して終了
環境変数の設定を反映
ターミナル
# 本番環境 # 編集した環境変数を適用するために一旦ログアウトします。 $ exit $ ssh -i [pem鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP] # 環境変数が適用されているか確認しましょう。 $ env | grep AWS_SECRET_ACCESS_KEY $ env | grep AWS_ACCESS_KEY_ID
デプロイにCapistranoを利用しているため、environmentというファイルに書き込んで環境変数の設定を行いました。
本番環境での環境変数読み込みの設定
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"] %>
このままではCapstranoで自動デプロイを行っても本番環境には送られないので、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
変更内容をデプロイ
GitHubにアップロードします。コミットしてGithubにプッシュ(publish)します。
自動デプロイを実行
ターミナル(ローカル)
$ bundle exec cap production deploy
S3を使ってアップロード⑤
画像のアップロード先をS3に変更
CarrierWaveによる画像のアップロード先がアプリ内のpublicフォルダでした。これをS3に変更します。
fog-awsをインストール
fog-awsをインストールします。
fogとは
画像をアップロードする際、外部のストレージを選択しアップロードするのを補助してくれるGemです。
Gemfile
gem 'fog-aws'
ターミナル
$bundle install
fogを使用するための設定
app/uploaders/image_uploader.rb
storage :file ↓ 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', 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
「ap-northeast-1」は、アジアパシフィック(東京)です。
安全にAWSのキーを扱えるよう設定
AWSのidやパスワードそのものは「環境変数」だけに設定します。
IAMユーザー設定時にダウンロードしたCSVファイル(2つ目のダウンロードファイル)を開きましょう。その中に、Access_key_IDとSecret_access_keyというカラムがあるので、こちらに書かれた値を設定していきます。
MacOSがCatalina以降の場合
ターミナル
# ローカル環境 $ vim ~/.zshrc # iを押してインサートモードに移行し、下記を追記する。既存の記述は消去しない。 export AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー' export AWS_SECRET_ACCESS_KEY='ここにCSVファイルのにSecret access keyの値をコピー' # 編集が終わったらescapeキーを押してから:wqと入力して保存して終了
※ファイル編集時の注意
上記の設定は、現在の設定に「追加」してください。
ターミナル
# ローカル環境 # 編集した.zshrcを読み込み直して、追加した環境変数を使えるようにする $ source ~/.zshrc
MacOSがMojave以前の方のローカル環境変数の設定
ターミナル
# ローカル環境 $ vim ~/.bash_profile # iを押してインサートモードに移行し、下記を追記する。既存の記述は消去しない。 export AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー' export AWS_SECRET_ACCESS_KEY='ここにCSVファイルのにSecret access keyの値をコピー' # 編集が終わったらescapeキーを押してから:wqと入力して保存して終了
ターミナル
# ローカル環境 # 編集した.bash_profileを読み込み直して、追加した環境変数を使えるようにする $ source ~/.bash_profile
secrets.ymlの設定
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"] %>
この2行を追記します。
.gitignoreを編集
「.gitignore」というファイルに設定を行うことで、Gitの管理下から除外することができます。
.gitignore
# ファイルの最下部に下記を追記 config/secrets.yml
ターミナル
$ git rm --cached config/secrets.yml # アプリのあるディレクトリで行います
S3を使ってアップロード④
S3で保存先を用意
S3でファイルがアップロードされる領域を準備します。
S3を利用してバケットを作成
S3のページの左上の「バケットの作成」をクリックします。
バケットは、名前とリージョンを決めるだけで作成できます。
バケット名は任意の名前で、リージョンは「アジアパシフィック(東京)」を選択します。
次の画面では変更は必要ないので、そのまま「次へ」をクリックします。
続いてセキュリティの設定を行います。今回はバケットポリシーを使用してセキュリティ設定を行いますので下の2つにチェックを入れて、「次へ」をクリックし(上3つはチェックしない)、そして次の画面で「バケットを作成」をクリックします。
バケットポリシーの設定を行っていきます。IAMのページの「ユーザー」→「さっき作成したユーザー名」をクリックします。IAMユーザーの情報が表示されるので、「ユーザーのARN」をコピーしておきます。
次に、バケットポリシーの設定を行います。S3のページの「さっき作成したバケット」→「アクセス権限」→「バケットポリシー」をクリックします。
バケットポリシー
{ "Version": "2012-10-17", "Id": "Policy1544152951996", "Statement": [ { "Sid": "Stmt1544152948221", "Effect": "Allow", "Principal": { "AWS": "************①****************" }, "Action": "s3:*", "Resource": "arn:aws:s3:::************②**********" } ] }
①に「ユーザーのARN」、②に「バケット名」を記述します。
最後に保存して終了です。
S3を使ってアップロード③
セキュリティ対策③
git-secretsをインストール
ターミナルから、Homebrewを経由してgit-secretsを導入します。
git-secretsとは
誤操作でパスワードをGitHubにpushしてしまうような誤操作を防いでくれるツールです。 パスワードだと推定されるような文字列が含まれている場合は、そこで処理が中断される仕組みです。
ターミナル
$ cd ~/ $ brew install git-secrets
ターミナル
$ git secrets --install # 設定を適用したいリポジトリに移動して、git-secretsを有効化します
git-secretsの条件を設定
ターミナル
$ git secrets --register-aws --global # アップロードしたくないAWS関連の秘密情報を一括で設定することができます
ターミナル
$ git secrets --list # git-secretsの設定を確認することができます
今後作成する全てのリポジトリにgit-secretsが適用
ターミナル
$ git secrets --install ~/.git-templates/git-secrets $ git config --global init.templatedir '~/.git-templates/git-secrets'
GitHub Desktopから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を使ってアップロード②
セキュリティ対策②
IAMユーザーの利用
IAMユーザーでログインできるようにしていきます。
IAMユーザーとは
IAMユーザーは、AWSのサービスの1つです。
AWSで作ったアカウントの使用できる機能を制限したユーザーのことです。
IAMユーザーを作成します
IAMのページの「個々のIAMユーザーの作成」→「ユーザーの管理」→左上の「ユーザーを追加」をクリックします。
そしてユーザー名を入力し、「プログラムによるアクセス」にチェックを入れ、「次のステップ:アクセス権限」をクリックします。
「既存のポリシーを直接アタッチ」から「AmazonS3FullAccess」にチェックを入れ、「次のステップ タグ」をクリックします。
次は何もせずに、「次のステップ: 確認」を押し、最後に確認して、「ユーザーの作成」をクリックします。
※この時「アクセス権限の境界:アクセス権限の境界が設定されていません」という表示が追加でされていることもありますが、設定に問題はありません。
ユーザーの作成が完了しました。
※忘れずに認証情報をダウンロードしておきます。(.csvのダウンロードってやつ)
IAMユーザーのパスワードを設定
IAMのメニューから作成したIAMユーザーをクリックします。「認証情報」のタブをクリックし「コンソールのパスワード」欄の管理 をクリックします。
「コンソールのアクセス」の欄は「有効化」、「パスワードの設定」の欄は「自動生成パスワード」にチェックを入れ「適用」をクリックします。
※ここでも忘れずに認証情報をダウンロードしておきます。(.csvのダウンロードってやつ)
これでIAMユーザーでログインができるようになります。
IAMユーザーも二段階認証
ルートユーザーでログインしなおします。
IAMのユーザー選択画面から先ほど作成したユーザー名を選択し遷移したページ先で、「MFAデバイスの割当」の欄の「管理」をクリックします。
あとは、ルートユーザーの時と同じように二段階認証の設定をします。