はじめに
来週からSalesforceのイベントの中では最大規模であるDreamforceが始まりますね。 毎年Dreamforceでは大きなProductの発表であったり、Salesforceの方向性が示されるイベントではありますが、今年は中でも賞金1億円相当のハッカソンが話題になっています。 日本から参加する方もいるようなので、結果が楽しみですね。 さて、今日はカスタマーポータルが絡んだ共有ルールの設定で、少し困ったことがあったので、
その現象と回避方法について書こうと思います。
発生した問題
問題が発生したケースとしては、カスタマーポータルが設定されている環境で作成した共有ルールを別環境に移行しようとした時のことです。 開発環境では取引先1、取引先2、取引先3といったカスタマーポータル用のAccountを作成しており、取引先1が所有するレコードを取引先2、3にも参照させるために、カスタムオブジェクトに対して以下のような共有ルールを設定していました。
上記共有ルールの設定をステージングの環境に移行するために、変更セットを使いました。 変更セットには「所有者ベースの共有ルール」のコンポーネントも選択できるので便利ですね。 ※ちなみにステージング環境には事前にAccountが作成されている状態です
この変更セットをアップロードして、移行先であるステージング環境側で受信してリリースします。 リリース時にエラーは発生しませんでした。
ところが共有ルールの設定を確認したところ「取引先1が所有しているレコードを2と3に共有させる」ではなく、「取引先3が所有しているレコードを1と2に共有させる」という、移行元の環境とは違う設定になっていました。
この時は共有ルールのみの変更セットなのですぐに気付くことが出来ましたが、変更セットに多くの設定が入っている場合は1つずつ確認するわけにもいかないので、エラーにもならず設定がおかしくなってしまう現象というのは非常に困ります。
特に共有ルールはデータの閲覧範囲を制御するものなので、本来見えてはいけないUserにデータが見えるようになってしまうと、セキュリティ的に大きな問題となります。 何故このような現象が起きたのでしょうか?
問題を解析
まず、共有ルールはカスタマーポータルロールの何をキーにして登録されているかというと、取引先のロールなのでAccountのSalesforceIDかロールのSalesforceIDかなと思いきや、ロールのDeveloperNameを使っています。 画面で言うと下記の部分になります。
おや?ちょっと待ってください。 通常の内部ロールであれば、ロールの作成時にDeveloperNameとなるロール名を付けますが、今回問題が起きたのはカスタマーポータルロールです。 カスタマーポータルロールは、Accountに紐づくContactを作成し、そのContactのUserとなるカスタマーポータルユーザを作成時に自動的に生成されるものなので、DeveloperNameを付けることは出来ません。 となると、この「CustomerUser」というロール名は何なのでしょうか。
いろいろ調べてみると、どうやらこれはカスタマーポータルのロール作成時に、Salesforce側で自動で生成される名前のようです。 ポータルロールはデフォルト3階層で作成されるので、それぞれ "CustomerUser"、 "CustomerExcective"、 "CustomerManager"といった名前になります。※この記事ではCustomerUserを例にしています
ただし、取引先名に半角英数字がある場合は、部分的にその文字が使われるようです。 (例)株式会社ABC ⇒ ABCCustomerUser この「半角英数字がある場合は部分的に使われる」というがポイントです。
これはつまり、AccountのNameが英語名の場合はその名前+"CustomerUser"という名称でロール名が生成されるが、2byte文字のみの場合はDeveloperNmaeに設定することができないので「CustomerUser」という名称が自動で付けられており、2件目以降は重複するので後ろに連番が付いている、ということです。
共有ルールがおかしな紐付けになってしまったのは、それぞれの環境で取引先(カスタマーユーザ)を作成する順番が違い、自動生成されるポータルロールのDeveloperNameが異なっていたことにより発生していました。
共有ルール設定
「CustomerUserの所有をCustomerUser1へ共有する」
DeveloperNameの違い(イメージ)
移行元
CustomerUser ⇒ 取引先1
CustomerUser1 ⇒ 取引先2
移行先
CustomerUser ⇒ 取引先3
CustomerUser1 ⇒ 取引先1
しかも同じCustomerUser,CustomerUser1,CustomerUser2という名前が移行先でも存在するので、リリースでエラーにならず非常に気付きにくいです。
解決方法を探す
まず、パッと思いついたのは、DeveloperNameを付け直すことはできないかということです。 ロールはUserRoleというオブジェクトに管理されており、項目のAccessもupdateableになっています。 ためしに適当なUserRoleを取得して、Force.com IDEのExecute AnonymouserからUpdateしてみました。 ところが以下のようなエラーになりました。
残念ながら更新はできないようです。
そこで共有ルールがどういったメタ情報で管理されているのか見てみることにします。 Force.com IDEで「customObjectSharingRules」というxml定義のメタ情報が取得できるので、対象のカスタムオブジェクトの定義を見てみました。 中身は以下の通りです。
中身を見ると分かる通り、portalRoleAndSubordinatesでロールのDeveloperNameが指定されています。 ここでどのロールが所有しているレコードを、どのロールに共有するといった情報を持っているようです。
このxmlファイルに、新規に共有ルールの定義を書き込んで、正しく保存されることも確認できました。
ということは、変更セットを使わずに共有ルールの移行はcustomObjectSharingRulesのメタ情報を使って、移行先環境にデプロイするのが良さそうです。 後は移行先のUserRoleからDeveloperNameを取得してきて、「開発環境でxxxだったロール名が移行先ではXXXになる」という情報を作成し、そこからxmlを生成すれば情報としては足ります。 xmlの生成方法はいろいろとありますが、今回は社内で使うだけなので、弊社のDCSpiderを使って生成しました。 生成したxmlを移行先のcustomObjectSharingRulesに保存すれば完了です。
まとめ
今回の現象はカスタマーポータルで発生したものですが、パートナーポータルやコミュニティでも、やはりポータルロールが自動で生成されるので、同じ現象は起こると思います。 環境移行に関してはポータルロールが絡むと、まず取引先を作成してポータルロールを内部的に生成しなければいけない部分もあり、単純なクラスやページのデプロイのようにはいかなくなります。
エラーが出ないからといって安心せず、正しく移行が出来ているかは確認が必要ですね。