production.log

株式会社リブセンスでエンジニアをやっている星直史のブログです。

InstagramグラフAPIのプラットフォーム利用規約違反対応をしました

概要

SnapmartアプリではInstagramグラフAPIを使用しているのですが、8月下旬にMeta社より「プラットフォーム違反しているからAPI利用停止するね」とお達しがありました。*1
Instagram連携不具合解消のお知らせ | Snapmart(スナップマート)公式ブログ

この記事では、InstagramグラフAPIのプラットフォーム利用規約違反対応内容を紹介していきます。

Meta社からの指摘事項

Meta社からは以下の指摘をされました。

Platform Terms 6.a.i.1: You must always have in effect and maintain administrative, physical, and technical safeguards that do the following: Meet or exceed industry standards given the sensitivity of the Platform Data

For more information, visit:
- Developer Policies: https://developers.facebook.com/devpolicy
- Platform Terms: https://developers.facebook.com/terms

In particular, for your app we require your compliance with Steps A, B, C, D, E, F, G, and H. Ensure you label your evidence accordingly - so, for example, if a screenshot shows the results of a recent security vulnerabilities test you conducted, label that attachment C.

  • [A] Enforce encryption at rest for all Platform Data storage (e.g., all database files, backups, object storage buckets) - Please attach a screenshot of how you implement encryption at rest on your system such as a screenshot of the encryption controls enabled on your data server, etc.
  • [B] Enforce TLS 1.2 encryption or greater for all network connections where Platform Data is transmitted – Please upload evidence of how you enforce TLS 1.2 encryption such as a screenshot of the encryption controls enabled on your servers or logs that monitor your encryption of data in transit.
  • [C] Test your app and systems for vulnerabilities and security issues at least every 12 months – Screenshots of any vulnerability and/or security scans and assessments performed in the last 12 months.
  • [D] Protect sensitive data like credentials and access tokens – Screenshots of the system/tool that you use to protect sensitive data like credentials and access tokens such as a vault or secrets manager.
  • [F] Require multi-factor authentication for remote access – Screenshot of the tools/configurations that you use that prove that you implement multi-factor authentication for remote access.
  • [H] Have a system for keeping system code and environments updated, including servers, virtual machines, distributions, libraries, packages, and anti-virus software – Screenshots of any updates performed on the system; security patches and any additional evidence to validate if the system code and environments are updated promptly. For example dependabot on GitHub.

Meta社が何を基準にSnapmartアプリに目をつけたのかは不明ですが、兎にも角にも主にセキュリティ面において業界標準以上の水準を目指しましょうということですね(白目)

[A] Enforce encryption at rest for all Platform Data storage (e.g., all database files, backups, object storage buckets) - Please attach a screenshot of how you implement encryption at rest on your system such as a screenshot of the encryption controls enabled on your data server, etc.

広義のデータストレージにおいて、暗号化してくださいということですね。
SnapmartではAWSを利用しているので、対象になるのはS3とRDSです。

S3

SSE(Server Side Encryption)を有効にします。
こちらはマネジメントコンソールから設定することができます。

2023年1月5日以降は、デフォルトで暗号化されるようになったようです。

docs.aws.amazon.com

RDS

RDSに関しても暗号化を行います。
また、S3と同様にマネジメントコンソールから操作が可能です。
具体的な手順は以下の通りです。

  1. インスタンスを停止
  2. 暗号化するRDSのスナップショットを作成
  3. 作成したスナップショットを暗号化を有効にしてコピーする
  4. コピーしたスナップショットからRDSを復元
  5. 元RDSのインスタンス名を適当な名前に変更
  6. 復元したRDSのインスタンス名をもともと使っていたインスタンス名に変更

RDSの暗号化はインスタンスを新規作成する際にしか設定できないため、暗号化設定されていないインスタンスの場合は必ずサービス停止をする必要があります。
また、手順6の通り、インスタンス名を変更さえすればエンドポイントが変わらないため、アプリケーションの変更は不要になります。

[B] Enforce TLS 1.2 encryption or greater for all network connections where Platform Data is transmitted – Please upload evidence of how you enforce TLS 1.2 encryption such as a screenshot of the encryption controls enabled on your servers or logs that monitor your encryption of data in transit.

TLS1.2以上で通信をしてくださいということですね!
こちらに関しては、ELBの設定で対応します。
手順は以下の通りです。

  1. マネジメントコンソールから EC2 -> ロードバランシング -> ロードバランサーにアクセス
  2. ロードバランサーを指定し、リスナータブをクリック
  3. HTTPS のプロトコルを探し、変更をクリック

TLSのセキュリティポリシーは様々なのですが、公式のドキュメントに記載されている対応状況がわかりやすかったです。

docs.aws.amazon.com

今回は、TLS 1.2以上で通信させたいため、以下のポリシーを適用させる必要があります。

  • ELBSecurityPolicy-TLS-1-2-Ext-2018-06
  • ELBSecurityPolicy-TLS-1-2-2017-01

ただし、クライントの利用環境(使用しているブラウザなど)によってはTLS 1.0でしか通信できない -> 「いきなり見れなくなった!」となる可能性があります。
それを避けるために以下の確認し、どのポリシーを適用するか判断する必要があります。

  1. ブラウザごとにTLS1.2の使用状況を確認
  2. GAなどでユーザーのブラウザ使用分布を確認

また、設定変更後しばらくの間はWebサーバーのアクセス数の変化などを監視してビジネスへ悪影響が出ていないか確認するとより安心できます。

[D] Protect sensitive data like credentials and access tokens – Screenshots of the system/tool that you use to protect sensitive data like credentials and access tokens such as a vault or secrets manager.

アクセストークンを暗号化しましょう!ということですね。
SnapmartではRuby on Railsを使用しているため、アクセストークンの保存と取得をattr_encryptedとうgemを使用することにしました。

GitHub - attr-encrypted/attr_encrypted: Generates attr_accessors that encrypt and decrypt attributes

[F] Require multi-factor authentication for remote access – Screenshot of the tools/configurations that you use that prove that you implement multi-factor authentication for remote access.

リモートアクセスする際は多要素認証を設定してください!ということですね。
対応の対象は2点です。

  1. AWS マネジメントコンソールへのアクセス時のMFA設定
  2. Webサーバーへのアクセス時のMFA設定

1は当たり前すぎるので、割愛します。

Webサーバーへのアクセス時のMFA設定

大まかな手順は以下の通りです。

  1. サーバーにGoogle Authenticatorのインストール
  2. sshdの設定ファイル(/etc/ssh/sshd_config)修正
  3. sshdのPAM設定ファイル(/etc/pam.d/sshd)修正
  4. ログイン時のbash profileファイル(/etc/profile.d/google-authenticator)修正
  5. 1Password登録

具体的な設定は以下のサイトが大変参考になりました。

dev.classmethod.jp

[H] Have a system for keeping system code and environments updated, including servers, virtual machines, distributions, libraries, packages, and anti-virus software – Screenshots of any updates performed on the system; security patches and any additional evidence to validate if the system code and environments are updated promptly. For example dependabot on GitHub.

セキュリティパッチをしっかり当てられる環境にしましょう!ということですね。
対象はアプリケーションとシステム(サーバー)とアプリケーションの2つです。

アプリケーション

そもそもGitHubのdependabotを使うといいよと、例を挙げています。

docs.github.com

GitHubのdependabotにはいくつか種類があります。

  • Dependabot alerts: 脆弱性が検知し通知を行う
  • Dependabot security updates: 検知された脆弱性対策としてPRを作成する
  • Dependabot version updates: 以前するパッケージのバージョンのPRを作成する

以上のような機能があるので、至れり尽くせりですね。

システム(サーバー)

後述します。

[C] Test your app and systems for vulnerabilities and security issues at least every 12 months – Screenshots of any vulnerability and/or security scans and assessments performed in the last 12 months.

12ヶ月に一度は、アプリとシステムの脆弱性とセキュリティの問題をテストしましょう!とのことですね。 前述のセキュリティパッチを当てる項目と合わせて考えると、脆弱性とセキュリティパッチの検知 -> 適用という仕組みを作れば、プラットフォームポリシーのCとHを同時に満たせそうです。

システムの脆弱性管理とセキュリティパッチ

システムに関しては、AWSの以下のサービスを利用するアプローチをとりました。

  • Amazon Inspectorで脆弱性管理をする
  • AWS Systems Manager(SSM) Patch Managerでパッチを自動適用する

純粋に2つのサービスを利用すれば良い...と思うのですが!SSMの独自概念を理解するのに多少時間がかかりました。
こちらでも、クラスメソッドさんの記事が大変参考になりました。

Amazon Inspector の開始方法 - Amazon Inspector

AWS Systems Manager エージェント(SSM Agent)の現行のバージョンを確認して最新バージョンにアップデートする | DevelopersIO
SSM Agent ステータスの確認とエージェントの起動 - AWS Systems Manager

【AWS Systems Manager】パッチマネージャーの パッチベースライン と パッチグループ の概念を勉強する | DevelopersIO
【AWS Systems Manager】パッチマネージャー実行時の関連リソースを、絵で見て(完全に)理解する。 | DevelopersIO
【脆弱性対応】AWS Systems Manager Patch Manager を使ったパッチ戦略の例 | DevelopersIO

アプリケーションの脆弱性検知

アプリケーションの脆弱性検知はOWASP ZAPを使用することにしました。
OWASP ZAPは界隈では有名な統合ペネトレーションテストツールです。

www.zaproxy.org

OWASP ZAPを最小限の設定で行おうとすると、ページ数の多いサイトでは非常に時間がかかってしまいます。
例えばSnapmartの素材販売サイトでは、特に以下のPathのページ数が多く、600万ページ以上あります。

  • https://snapmart.jp/photos?keyword={検索キーワード}
  • https://snapmart.jp/photos/{素材ID}

ただし、両方Pathのレスポンスは検索キーワードもしくは素材IDに合致したデータを返すだけであり、基本構造に変わりはないページであるため、
必ずしも全ページを対象にしなくても良く、任意のページを1ページ検証させるだけで、必要な要件を満たせます。
このように、検出対象の絞り込みを行うことで、効率良く脆弱性検出が可能になります。

検出結果は任意の形式でエクスポートできるので、提出が非常に楽でした。

まとめ

以上、Meta社のプラットフォーム違反に対して対応を行ってきました。
脆弱性対策とセキュリティ強化が求められたのですが、多くの場合AWSの各種サービスで対応できたのは非常に良かったです。
その後、Meta社へ申請を行い、無事に通ったことや、恒久対応ができたため、次にお達しがあった際は迅速に対応できそうです。
また、個人的にはこれまでセキュリティに関して門外漢だったのですが、今回の対応によって足を踏み入れることができたのは良かったです。

*1:せめて事前通知してほしかった