Rails 5 でSSLをLocalhostで使う。

# はじめに
Rails5のアプリ開発でSSLをLocalhostでも使いたい場合があるので、その環境構築手順のメモ

# SSL certificate generation setting
## 1. 証明書置き場作成
参考記事の通りで良い。

```ruby:RAILS_ROOTで実行
$ mkdir config/certs && touch config/certs/.keep
```

```ruby:.gitignore
/config/certs/*
!/config/certs/.keep
```

## 2. 環境変数読み込み設定
application.ymlは手作業で作成する。

```ruby:config/application.yml
defaults: &defaults

development:
  MY_LOCALHOST_NAME: 'MacBook-Pro.home'

  <<: *defaults

test:
  <<: *defaults

staging:
  <<: *defaults

production:
  <<: *defaults
```

`config/application.rb` に `application.yml` を読み込む設定をする。

```ruby:config/application.rb
module SSL
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
    ENV.update YAML.load_file('config/application.yml')[Rails.env] rescue {}　＜＝これを追加するだけ。

    # Don't generate system test files.
    config.generators.system_tests = nil
  end
end
```

## 3. 証明書作成・参照
ほぼ参考記事の通りだが、Localhostの時だけSSL設定を有効にしたいので最初の条件判断で `ENV['MY_LOCALHOST_NAME']` で判別している。 `settinglogic` Gemはインストールしなくても動く。

```ruby:config/puma.rb
# Rails server with SSL configuration
if Socket.gethostname == ENV['MY_LOCALHOST_NAME']
  key_file = Rails.root.join("config", "certs", "localhost.key")
  cert_file = Rails.root.join("config", "certs", "localhost.cert")

  unless key_file.exist?
    root_key = OpenSSL::PKey::RSA.new(2048)
    key_file.write(root_key)

    root_cert = OpenSSL::X509::Certificate.new.tap do |root_ca|
      root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
      root_ca.serial = 0x0
      root_ca.subject = OpenSSL::X509::Name.parse "/C=BE/O=A1/OU=A/CN=localhost"
      root_ca.issuer = root_ca.subject # root CA"s are "self-signed"
      root_ca.public_key = root_key.public_key
      root_ca.not_before = Time.now
      root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
      root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
    end
    cert_file.write(root_cert)
  end

  ssl_bind "0.0.0.0", "8443", {
    key: key_file.to_path,
    cert: cert_file.to_path
  }
```

## 4. Railサーバー起動
普通にTerminalから `rails s` するだけ。

```
$ rails s
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.5.3-p105), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
* Listening on ssl://0.0.0.0:8443?cert=/hogehoge/SSL/config/certs/localhost.cert&key=/hogehoge/SSL/config/certs/localhost.key&verify_mode=none
Use Ctrl-C to stop

```

![スクリーンショット 2019-09-29 午後4.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329289/e9a8d5d7-061a-7f83-c62f-ac30550746a3.png)


# Chrome setting
Chromeブラウザでオレオレ証明書が必要な場合は以下を参照。自分の環境では特に不便はないのでやってない。

[Chromeに怒られないオレオレ証明書の作り方](https://qiita.com/masahiro-aoike/items/dbf17fa03c5973ce9068)
[Chrome58以降でハネられないSHA-2でオレオレ認証局署名のあるオレオレ証明書](https://qiita.com/mkgask/items/8d66dcada58a485e3585)

# 今後の課題
RubyMineを使っているのでRailsサーバー起動をTerminalからではなくRubyMineでやる方法の調査。Terminalからは `/bin/bash -c "env RBENV_VERSION=2.5.3 /usr/local/Cellar/rbenv/1.1.1/libexec/rbenv exec ruby /Users/hoge/SSL/bin/rails server"` と入れたらSSLで動いたので試しにIP addressとPortをブランクにしてみたが、それだけだとIncorrect port valueエラーになった。

![スクリーンショット 2019-09-29 午後4.28.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329289/4cf50518-cee3-6830-e37c-9fa8bf7199ec.png)
![スクリーンショット 2019-09-29 午後4.30.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329289/e6025665-2ea3-a1dd-69fb-f93b52db88e5.png)

Terminalから `-b` と `-p` オプションを除外して起動すれば `ssl_bind "0.0.0.0", "8443"` が有効化されRubyMineと同じコマンドでもSSLでアクセスできた。

```
$ /bin/bash -c "env RBENV_VERSION=2.5.3 /usr/local/Cellar/rbenv/1.1.1/libexec/rbenv exec ruby /hogehoge/SSL/bin/rails server"
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.1 (ruby 2.5.3-p105), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
* Listening on ssl://0.0.0.0:8443?cert=/hogehoge/SSL/config/certs/localhost.cert&key=/hogehoge/SSL/config/certs/localhost.key&verify_mode=none
Use Ctrl-C to stop
Started GET "/" for 127.0.0.1 at 2019-09-29 16:42:36 -0400
   (0.3ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  ↳ /hogehoge/.rbenv/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by Rails::WelcomeController#index as HTML
  Rendering /hogehoge/.rbenv/gems/2.5.0/gems/railties-5.2.3/lib/rails/templates/rails/welcome/index.html.erb
  Rendered /hogehoge/.rbenv/gems/2.5.0/gems/railties-5.2.3/lib/rails/templates/rails/welcome/index.html.erb (2.5ms)
Completed 200 OK in 16ms (Views: 6.2ms | ActiveRecord: 0.0ms)
```

# 参考記事
[Railsの開発環境でhttpsを使う](https://qiita.com/itkrt2y/items/2837a45061b9a3b711b7)
[Ruby on Railsで定数の指定](https://qiita.com/srockstyle/items/daed31a78c343e607822)
[Rails5 + pumaのローカル環境でSSL/HTTPSを有効にする](https://qiita.com/zaru/items/ccf328e87c768168134d)