[日本語訳] SECURITY - DEVELOPER GUIDE | SPREE COMMERCE

Spreeのドキュメントを日本語に訳しました。意訳や怪しい部分もあるのでおかしなところがあればご指摘ください。

[SECURITY - DEVELOPER GUIDE | SPREE COMMERCE](https://guides.spreecommerce.com/developer/security.html)

## 概要

適切なアプリケーションデザイン、聡明なプログラミング、そして安全なインフラストラクチャーはあらゆる安全なEコマースサイトを作るうえで欠かせないものとなっています。Spreeチームは安全で有益なウェブプレゼンスをあなたに与えられるよう最大限の努力をしていますが、それらのツールを適切に使い、配置できるかは貴方次第です。[Rails Security Guide](http://guides.rubyonrails.org/security.html)を読み、理解することを強くおすすめします。

## セキュリティ上の問題を報告する場合

セキュリティ面の脆弱性は、公にアナウンスしないでください。専用のメールアドレスがあります。我々は素早くそれらの問題の重要度を決定し、適切なバージョンにて修正します。我々はあなたの発見を評価し、ブログ記事に記名させていただきます。

もし修正パッチをあなた自身で提供いただける場合、__セキュリティ面の問題はプルリクエストを作らないでください。__代わりにあなたのフォークにコミットし、下記のコマンドを実行してください。

    $ git format-patch HEAD~1..HEAD --stdout > patch.txt

このコマンドは`patch.txt`というファイルを生成します。その後にパッチを説明とともに我々の専用メールアドレスへ送信してください。

## 認証

もし`spree_auth_devise`をアプリケーションのセットアップとともにインストールしたならば、サードパーティー製の認証用ライブラリでよく知られているDeviseを使用することとなります。このライブラリは便利な機能を提供しており、Spree内で以下のような機能を提供します。

* 認証
* 強固なパスワード暗号化（暗号化アルゴリズムの指定も可）
* "Remember Me"機能(クッキーによるオートログイン)
* "Forget my password"機能（メールアドレスによるパスワード再設定）
* トークンベースアクセス（REST API機能）

### Deviseの設定

```
Spreeをインストールするとspree_auth_deviseも一緒に含まれており、DeviseによるSpreeの認証機能が提供されています。当ガイドのこのセクションではデフォルトのセットアップについて説明します。もし独自の認証を使うならその認証エンジンのマニュアルを参考にしてください。
```

私達はSpreeサイトの認証に必要な機能だけを扱えるよう変更したDeviseを使っています。下記がデフォルトで使用できる設定です。

* パスワードをソルトとともに暗号化してデータベースに保存する
* データベースクエリによるユーザー認証
* ユーザー登録後、すぐに使用可能にする（メールアドレス認証は行わない）
* ログイン維持とパスワード再設定ツールが有効化されている

この構成は、代表的なEコマースサイトの合理的な出発地点となります。Deviseは様々な構成を設定することができますが、それはこのドキュメントの範囲を超えています。さらなる詳細を求める開発者の方は、Devise Wikiをご覧いただくことをおすすめします。

### REST API

REST APIの振る舞いは、通常のユーザーと少し異なります。第一に管理者は他のユーザーがREST APIを使用する前にアクセスキーを生成しなければなりません。鍵生成をしなければいけないのは管理者自身も含みます。しかし`Spree::Api::Config[:requires_authentication]`が`false`に設定されている場合にはこの限りではありません。

`Spree::Api::Config[:requires_authentication]`が`false`にセットされている場合には、参照のみのAPIリクエストは全てのユーザーが可能です。Spree内のデータを更新する場合にはAPIキーが必要となり、ユーザー自身がそれらのレコードを変更する権限を持っていることが必要となります。

鍵の取り扱いについてはあなた次第です。追加対策として、この認証はREST APIによるセッションやクッキーが生成されていないリクエストの度に行わねばなりません。

### 権限

Spreeは、権限の設定のためにCanCanという素晴らしいgemを使用しています。もしあなたがこれに詳しくないのならRyan Batesの素晴らしい[screencast](http://railscasts.com/episodes/192-authorization-with-cancan)を見るべきです。CanCanの詳しい説明はこのガイドの範囲ではありません。

### デフォルトルール

下記のSpreeのコードは`ability.rb`から抜粋したもので、デフォルトの権限ルールについての洞察を提供しています。

```ruby
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
  can :manage, :all
else
  #############################
  can [:read,:update,:destroy], Spree.user_class, :id => user.id
  can :create, Spree.user_class
  #############################
  can :read, Order do |order, token|
    order.user == user || order.token && token == order.token
  end
  can :update, Order do |order, token|
    order.user == user || order.token && token == order.token
  end
  can :create, Order

  can :read, Address do |address|
    address.user == user
  end

  #############################
  can :read, Product
  can :index, Product
  #############################
  can :read, Taxon
  can :index, Taxon
  #############################
end
```

上記のルールは、以下の実際的なルールをSpreeユーザーに付与しています。

* Admin権限は全てにアクセスできる（他のルールは無視されます）
* 誰でも`User`を作成でき、そのアカウントのユーザーだけがそのユーザー情報を読み書きできる。
* 誰でも`Order`を作成でき、その注文のユーザーだけが注文情報を読み書きできる。
* 誰でもproductページを閲覧でき、検索を含む`Products`リストを閲覧できる。
* 誰もが`Taxons`のリストを閲覧できる。

### ルールの適用

CanCanは、それを尋ねられたときにのみ権限の適用が可能となります。言い換えるなら、もしソースコードが権限チェックをしていなければ、権限ベースのアクセス拒否をする方法はないということです。一般的には、Railsのコントローラに適切なコードを付与することで扱われています。より詳しい情報は[CanCan Wiki](https://github.com/ryanb/cancan/wiki)を見てください。

### 権限ルールのカスタマイズ

我々は、エクステンション開発者とそのユーザーが権限をより簡単にカスタマイズできるよう、オリジナルのCanCanのコンセプトを少々変更しました。例えば"artwork extension"によりユーザーが注文に大して独自のartworkを不可できるようにするためには、彼らがその権限を所持できるようルールを追加する必要があります。

カスタム権限のコツは、エクステンションに`AbilityDecorator`を追加し、必要な権限を登録することです。下記のコードは、オーナーのみがartworkを更新閲覧できるようアクセスを制限する例です。

```ruby
class AbilityDecorator
  include CanCan::Ability
  def initialize(user)
    can :read, Artwork do |artwork|
      artwork.order && artwork.order.user == user
    end
    can :update, Artwork do |artwork|
      artwork.order && artwork.order.user == user
    end
  end
end

Spree::Ability.register_ability(AbilityDecorator)
```

### Admin NameSpace内におけるカスタムロール

もしSpreeの管理者パネルにアクセスするカスタムロールを考えているならば、心にとめておくべき検討事項があります。

Spreeは管理者パネルを認可するのに、２つのCanCanの認証コマンドを用いています。`:admin`と認可するアクションの名前です。もしあなたが管理者パネルにアクセスできるカスタムロールを必要としているなら、そのロールは`:admin`と、適切なリソースのアクションの両方へのアクセスロールを`can`しなければなりません。例えば、もし販売担当者がAdmin Orderパネルにアクセス可能だがそれ以外の管理者エリアにアクセスできないようにするなら、`AbilityDecorator`を下記のようにする必要があります。

```ruby
class AbilityDecorator
  include CanCan::Ability
  def initialize(user)
    if user.respond_to?(:has_spree_role?) && user.has_spree_role?('sales_rep')
      can [:admin, :index, :show], Spree::Order
    end
  end
end

Spree::Ability.register_ability(AbilityDecorator)
```

以下のコード、Spreeの`Admin::BaseController`はAdminエリアのコントローラ全てに継承され適用されます。

```ruby
def authorize_admin
  if respond_to?(:model_class, true) && model_class
    record = model_class
  else
    record = Object
  end
  authorize! :admin, record
  authorize! action, record
end
```

もしAdminエリア内に独自のモデルのコントローラを作る必要がある場合、コントローラ内に`model_class`メソッドを使い、操作するモデルを手動で指定する必要があるでしょう。

```ruby
module Spree
  module Admin
    class WidgetsController < BaseController
      def index
        # Relevant code in here
      end

    private
      def model_class
        Widget
      end
    end
  end
end
```

これは、CanCanがデフォルトではAdminエリアにあるオーソライズコントローラを見つけることができないために必要です。`model_class`で指定することにより、SpreeはCanCanにオーソライズコントローラを使うよう伝えることができます。

### Tokenized Permissions

アクセスのために認証を要求することなく、特定のリソースへアクセスできることが望ましい状況も存在します。

Spreeはいわゆる「ゲストチェックアウト」を許可しておりユーザーはメールアドレスのみを提供し、アカウントを作ることを要求しません。この場合、オリジナルの顧客だけが見ることのできる注文へのアクセスを制限したいはずです。その方法として、"tokenized"URLを使います。

    http://example.com/orders?token=aidik313dsfs49d

Spreeは`TokenizedPermission`モデルを提供し、安全なトークンを使い様々なリソースへのアクセスを許可しています。このモデルは`Spree::TokenResource`モジュールと連携して動作します。

```rb
module Spree
  module Core
    module TokenResource
      module ClassMethods
        def token_resource
          has_one :tokenized_permission, :as => :permissable
          delegate :token, :to => :tokenized_permission, :allow_nil => true
          after_create :create_token
        end
      end

      def create_token
        permission = build_tokenized_permission
        permission.token = token = ::SecureRandom::hex(8)
        permission.save!
        token
      end

      def self.included(receiver)
        receiver.extend ClassMethods
      end
    end
  end
end

ActiveRecord::Base.class_eval { include Spree::Core::TokenResource }
```

Orderモデルは、このインターフェースが既に使われているSpreeモデルのひとつです。下記のコードスニペットはどのようにこれを使用すればよいか表しています。

```rb
Spree::Order.class_eval do
  token_resource
end
```

もしデフォルトのCanCanがOrderに対し与えている権限を調べたいなら、認証されていないユーザーがどのようにアクセスを許されているかを見てください。

```rb
can :read, Spree::Order do |order, token|
  order.user == user || order.token && token == order.token
end

can :update, Spree::Order do |order, token|
  order.user == user || order.token && token == order.token
end

can :create, Spree::Order
```

この設定項目はこう名言しています。注文を読み書きするためは、認証された正しいユーザーであること、正しいトークンが提示されていることの両方を満たす必要があります。

最後のステップは、認証が行われる際にトークンがCanCanに渡されることを明示し、コントローラ内で完結させています。

    authorize! action, resource, session[:access_token]

## クレジットカードのデータ

### PCI コンプライアンス

全てのストアオーナーは、クレジットカード情報をPCIコンプライアンスに基づいて送信することを望まれている。SpreeはPCIコンプライアンスに関して絶対的な保障をするものではありません。（その他のこと、詳細については[ライセンス](https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard)をご覧ください）我々ができることは、クレジットカードデータを一般的なセキュリティ対策のもと扱うことです。

### Transmit Exactly Once

Spreeでクレジットカードを扱う場合に厳重に注意しなければならない点は、クレジットカードデータをSSL経由でSpreeに送信しなければならない点です。そのデータはすぐに選択した支払いゲートウェイに転送され、すぐに破棄されます。クレジットカードのデータはデータベースに保存されません（一時的には除く）そのデータはサーバー上のメモリに保存され、破棄される前にその用途に用いられます。

### Payment Profiles

Spreeは'Payment Profile'の使用をサポートしています。これは、あなたのデータベースに顧客のクレジットカード情報を安全に__保存__することを可能にしています。より厳密に言うならば、クレジットカードを再利用するための「トークン」を保存することになります。クレジットカードゲートウェイは事実上クレジットカードを保存していることとなり、Spreeは繊細なクレジットカード詳細を保存することなく、同じカードで新しく課金することが可能になります。

Spreeは、[Authorize.net CIM](http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/)のペイメントプロフィールのサポート対象外です。

### Other Options

サードパーティー製エクステンションであるPaypal's Express Checkout（厳密にはPaypal Expressと呼ばれている）このチェックアウトサービスのタイプはクレジットカード情報を外部にて扱います（あなたのサーバーはそのデータには一切触れない）そしてPCIコンプライアンスの要件を大幅に簡易化します。

また、Braintreeは興味深いゲートウェイオプションを提供しており、その利点はExpressCheckoutに似てサイト内でプロセスが行われているように見えることです。つまり、支払いの間、顧客は店を出ていないように見えます。彼らはこれを'transparent redirect'と読んでおり、BrainTreeのチームは彼らのゲートウェイを使用するRubyデベロッパー、彼らの製品を使うSpreeデベロッパーを助けています。

## Security Alerts

Spreeは定期的に重要なセキュリティ、リリース情報をチェックします。あなたはそれらの情報を管理コンソールページから見ることができます。アラートは読了後、削除することもできます。自動チェックは、
“Configuration” => “General Settings”か、`Spree::Config[:check_for_alerts]`を`false`にすることで無効にすることができます。なお、インストール環境固有のアラートを出すために、チェックの際にいくらかの更新情報が含まれます。以下はアラートリクエストに含まれる構成情報の例です。

```ruby
{
  "name": "Spree Demo Site",
  "rails_version": "3.1.1",
  "version": "0.70.1",
  "rails_env": "production",
  "host": "www.spreecommerce.com"
}
```