こんにちは。ホスティング事業部 事業開発チームの @kinosuke01 です。夜更かしグセがひどいので、今年の抱負を「きちんと寝る」に設定したのですが、なかなか達成が難しいです。
さて、少し前の話ですが、ロリポップ!レンタルサーバーでは、2023年3月に選りすぐりのWordPressの有料テーマを購入できる機能をリリースしました。「どのテーマがいいかわからない!」というユーザーの思いに少しでも答えられればと思い、開発を行ったものです。
この記事では、有料テーマ取り扱いに伴って必要になったセキュアな配布機能の紹介をしたいと思います。
背景と要件
WordPressは、ブログやWebサイトを作る事ができるCMSです。WordPressには無料のものから有料のものまで多種多様なテーマがあり、zipファイルで配布されているものを、サイトにインストールして使用します。
また、ロリポップには、このWordPressをホスティングサーバーに簡単にインストールできる機能があります。ユーザーはホスティングサーバーへのファイル設置やデータベースの設定などを行うことなく、ロリポップのコントロールパネルを操作するだけで、WordPressの利用を開始できる便利機能です。
今回、有料テーマの取り扱いに伴い「購入済の有料テーマがある場合は、それを選択してインストールすることで、最初からテーマが組み込まれた状態でWordPress製のサイトを利用することができる」という機能を簡単インストールに追加する必要がありました。
簡単インストールの仕組み
WordPress簡単インストールの仕組みについて説明します。有料テーマ取り扱い"前"の設計はこうなっていました。
内部でwpcliというWordPressのCLIツールを用いて、WordPress本体やテーマのダウンロードを行いインストールを実行しています。ここでWordPress本体やテーマのダウンロード元となっているのが「アーカイブサーバー」です。アーカイブサーバーは、静的ファイルを返すだけのシンプルなWebサーバーで、各種zipファイルをホストしており、ダウンロードに関してのアクセス制限はありません。
有料テーマ対応における課題
ここで「簡単インストール時に有料テーマを同時にインストール」の実現方法について考える必要があります。
すぐに思いつくのは、アーカイブサーバーに有料テーマのzipファイルを設置する方法です。これならすぐに実現できそうです。
しかし、そうすると問題ありました。購入したユーザーのみが利用できるテーマのzipファイルのはずなのに、URLがもし分かってしまったら誰でも何回でもダウンロードできてしまうのです。
何らかのアクセス制限を検討する必要がありました。
アクセス制限の方法を決める
アクセス制限には、Bearer認証やBasic認証など様々な方法があります。
まず、wpcliで対応している認証方法はあるのか、公式ドキュメントを読んでみたのですが、そのような情報は見当たりませんでした。
仕方がないので、wpcliやwpcliがincludeしているWordPressのコードを読んだり、実験することで確認を行いました。その結果わかったのは、Basic認証は使えず、HTTPヘッダの指定不可でBearer認証も使えないということでした。しかし、幸いにもURLに含まれるクエリパラメータは使えることはわかりました。
これを踏まえて、クエリパラメータに有効期限つきのトークンを付与した署名付きURLを採用することにしました。
## 署名付きURLの例
https://example.com/wordpress/wordpress-x.x-ja.zip?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzU3NzM2NTIsImlhdCI6MTY3NTc3MzU5Miwic3ViIjoicHJvdGVjdGVkL3dvcmRwcmVzcy90aGVtZXMvbmV3LXN0YW5kYXJkLTQuMC4zLnppcCJ9.NHDTRZ1lR5WnBAc6d2cBiKe3hReAQ5OnxWqUZjRWDUs
構成を考える - オブジェクトストレージを使う案
ここから、署名付きURLを実現する構成を考えていきます。すぐに思いつくのは、パブリッククラウドのオブジェクトストレージを使う方法です。
既存のアーカイブサーバーをオブジェクトストレージに置き換えて、APIから署名付きURLを取得し、取得したURLからダウンロードを行います。さらに、パブリッククラウドのオブジェクトストレージはマネージドなサービスなので、保守の手間がかからないメリットもあります。
しかし、これには1点問題がありました。コストの問題です。
簡単インストールが実行されるほど、オブジェクトストレージからインターネットへのデータ転送送信量が増えるため、その分従量課金されてしまいます。試算してみたところ、対策を検討したほうがよさそうでした。
構成を考える - オブジェクトストレージの前段にキャッシュサーバーを置く案
オブジェクトストレージからのインターネットへのデータ転送送信量を減らすために、その前段にキャッシュサーバーを設ける方法を検討しました。
キャッシュサーバーに署名付きURLを払い出すAPIを実装します。そのAPIから署名つきURLを取得し、そのURLからダウンロードを行う形式です。署名付きURLの向き先はキャッシュサーバ- で、キャッシュがあればそのファイルを返し、キャッシュがなければオブジェクトストレージからファイルを取得しキャッシュしたうえでファイルを返す構成で考えています。
この構成で試算したところ、オブジェクトストレージにかかる料金を大幅に削減することができました。よさそうです。
実装してリリースする
ここまでの検討を踏まえて実装を行いました。
キャッシュサーバーの実装はGo言語で行いました。また署名つきURLに付与するトークンは、ステートレスで管理がラクという理由からjwtを使用しています。
また、キャッシュサーバーは保守性を考慮して、Kubernetesクラスター上に構築しました。キャッシュはPod内のファイルシステムに保存します。一度キャッシュしたファイルが更新されることはほぼないので、有効期限は設けていません。もし仮にキャッシュファイルをパージしたい場合は、ロールアウトをするだけで済みます。
そして、無事リリースに至ることができました。
まとめ
WordPress有料テーマ取り扱いに伴うアーカイブサーバーの刷新について、紹介しました。
この記事を書いているときにも、取り扱っているWordPress有料テーマが増えました。どのテーマがいいか悩んでいる方の道しるべになれば、嬉しいです。