PolicyCondition インターフェース
名前空間
使用方法
evaluate メソッドは、トランザクションセキュリティポリシーで監視されているイベントが発生するとコールされます。通常の実装では、最初にイベントから関心のある項目を選択します。その項目をテストして、監視されている条件を満たすどうか確認します。条件を満たす場合、メソッドは true を返します。
たとえば、同じユーザが複数回ログインしていないかチェックするトランザクションセキュリティポリシーがあるとします。ログインイベントごとに、メソッドは、ログインしているユーザにすでに進行中のログインセッションがあるかどうかをチェックし、ある場合は true を返します。
PolicyCondition メソッド
PolicyCondition のメソッドは次のとおりです。
evaluate(event)
署名
public Boolean evaluate(TxnSecurity.Event event)
パラメータ
- event
- 型: TxnSecurity.Event
- トランザクションセキュリティポリシーに対して確認するイベント。
戻り値
型: Boolean
ポリシーがトリガされると、True が返されます。たとえば、ユーザをシングルログインセッションに限定するポリシーがあるとします。あるユーザが 2 つ目のログインをしようとすると、ポリシーのアクションによって現在のセッションを終了するよう求められます。また、Salesforce システム管理者にもメール通知が送信されます。evaluate() メソッドは、ログインイベントのみを確認し、ユーザの 2 つ目のログインである場合に True を返します。トランザクションセキュリティシステムはアクションと通知を実行しますが、evaluate() メソッドは実行しません。
PolicyCondition の実装例
PolicyCondition の例: localhost ログインのブロック
1global class BlockLocalhostCondition implements TxnSecurity.PolicyCondition {
2
3 public boolean evaluate(TxnSecurity.Event e) {
4 // Get the IP address.
5 String sourceIp = e.data.get('SourceIp');
6 // If it’s localhost the policy is triggered and true is returned.
7 if(sourceIp != null && sourceIp.equals('127.0.0.1')){
8 return true;
9 } else {
10 return false;
11 }
12 }
13}以下は、実装のテストクラスです。
1@isTest
2public class TestLogin {
3 public static testMethod void testLocalhostLogin() {
4 Map<String, String> eventData = new Map<String, String>();
5
6 /* Insert localhost IP address into the event data map */
7 eventData.put('SourceIp', '127.0.0.1');
8
9 TxnSecurity.Event e = new TxnSecurity.Event(
10 '00Dxxx123123123', /* organizationId */
11 '005xxx123123123', /* userId */
12 'AuthSession', /* entityName */
13 'Login', /* action */
14 'LoginHistory', /* resourceType */
15 '01pR00000009D2H', /* entityId */
16 Datetime.newInstance(2015, 9, 15), /* timeStamp */
17 eventData; /* data - Map containing information about the event */ )
18
19 /* We are unit testing a PolicyCondition that triggers
20 when an event is generated from localhost */
21 BlockLocalhostCondition condition = new BlockLocalhostCondition();
22
23 /* Assert that the condition is triggered */
24 System.assertEquals(true, condition.evaluate(e));
25 }
26
27 public static testMethod void testNonLocalhostLogin() {
28 Map<String, String> eventData = new Map<String, String>();
29
30 /* Insert non-localhost IP address into the event data map */
31 eventData.put('SourceIp', '1.1.1.1');
32
33 TxnSecurity.Event e = new TxnSecurity.Event(
34 '00Dxxx123123123', /* organizationId */
35 '005xxx123123123', /* userId */
36 'AuthSession', /* entityName */
37 'Login', /* action */
38 'LoginHistory', /* resourceName */
39 '01pR00000009D2H', /* entityId */
40 Datetime.newInstance(2015, 9, 15), /* timeStamp */
41 eventData; /* data - Map containing information about the event */ )
42
43 /* We are unit testing a PolicyCondition that triggers
44 when an event is generated from localhost */
45 BlockLocalhostCondition condition = new BlockLocalhostCondition();
46
47 /* Assert that the condition is NOT triggered */
48 System.assertEquals(false, condition.evaluate(e));
49 }
50}PolicyCondition の例: 大量データのエクスポートのブロック
システム管理者または API 権限のある他の顧客は、SOAP API、REST API、または Bulk API を使用して、すべての顧客データを一括ダウンロードできます。このセキュリティポリシーは、API ベースのデータのダウンロードを 2,000 レコードに制限し、ポリシーがトリガされた場合にシステム管理者にリアルタイムで通知します。
1public global class DataLoaderExportGt2KRecords implements TxnSecurity.PolicyCondition
2{
3 public boolean evaluate(TxnSecurity.Event event){
4 if(Boolean.valueOf(event.data.get('IsApi'))){ // For any API request
5 Integer numberOfRecords = Integer.valueOf(event.data.get('NumberOfRecords'));
6 if (numberOfRecords >= 2000){
7 return true;
8 }
9 return false;
10 }
11 }
12}この例を拡張して、Lexi Loader またはデータローダのパートナークライアント ID を含める特定の条件を追加することもできます。
1if('LexiLoader/'.equals(clientId)||'DataLoaderPartnerUI/'.equals(clientId) && numberOfRecords >= 2000){
2 return true;
3 }PolicyCondition の例: 高保証セッション
Salesforce の四半期レポートには非公開の機密データを記載できます。さらに、これらのレポートにアクセスするチームに、このデータを参照する前に必ず高保証の 2 要素認証 (2FA) を使用させることができます。このポリシーは 2FA を義務付けますが、チームに 2FA の要件を満たす手段がなければ高保証セッションを提供できません。前提条件として、まず Salesforce 環境に 2FA を設定します。
この例では、特定のレポートとこのレポートにアクセスする特定のロールに 2FA を適用するポリシーの機能が強調表示されています。ここで定義されるレポートは、「Quarterly Report FY 2016 (2016 会計年度の四半期レポート)」という名前のレポートです。ロール階層を使用して CEO の直属部下であるユーザ全員を定義します。これらのユーザは、レポートにアクセスする前に 2FA を使用して高保証セッションを設定する必要があります。
1global class ConfidentialDataCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event event) {
3 if(event.resourceType == 'Reports'){ // If the event is about reports...
4 List<Report> reports = [SELECT Name FROM Report WHERE Id = :event.entityId];
5 if(reports.size() > 0){ // and if there’s a report...
6 String name = (String) reports.get(0).get('Name');
7 if(!String.isBlank(name) && name.containsIgnoreCase('Quarterly Report FY 2016')){
8 return true; // and if the name meets our criteria, trigger the policy.
9 }
10 }
11 }
12 return false; // Otherwise the policy is not triggered.
13 }
14}PolicyCondition の例: プラットフォームブラウザの制限
アクセスを制限するポリシー例を次に示します。多くの組織では、標準ハードウェアを設定し、さまざまなブラウザの特定のバージョンをサポートしています。この標準を使用して、通常と異なるデバイスからログインが発生したときにアクションを行うことにより、影響が大きいユーザのセキュリティリスクを軽減できます。たとえば、��社の CEO が通常はサンフランシスコから Macbook を使用するか、iPhone で Salesforce1 モバイルアプリケーションを使用して Salesforce にログインするとします。別の場所から Chromebook を使用したログインが発生した場合、それは非常に疑わしいと言えます。企業役員が使用するプラットフォームをハッカーが知っているとは限らないため���このポリシーによりセキュリティ侵害の可能性が低減されます。
この例では、顧客の組織は、CEO が OS X と Safari ブラウザを実行する Macbook を使用していることを知っているとします。その他のものを使用して CEO のログイン情報でログインしようとすると、自動的にブロックされます。
1global class CeoBrowserAccessPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event event) {
3 if (event.resourceType == 'LoginHistory') { // If it’s a login history event
4 LoginHistory lHistoryObj =[SELECT Platform, Browser FROM LoginHistory WHERE Id =:
5 event.data.get('LoginHistoryId')]; // Get the platform & browser from login history
6 String platform = lHistoryObj.Platform;
7 String browser = lHistoryObj.Browser;
8 if (platform == 'Mac OSX' && browser.startsWith('Safari')) {
9 return false; // Safari on the Mac OSX is OK, so the policy isn’t triggered
10 }
11 return true; // Not Safari or Mac OSX, so the policy is triggered
12 }
13 return false; // Not a login history event, so the policy isn’t triggered
14 }
15}PolicyCondition の例: 場所別のアクセスのブロック
組織でリモートオフィスを設置したりグローバルプレゼンスを高めたりすることができますが、国際法に従って Salesforce 組織へのアクセスを制限する必要のある場合があります。こうした制限は、特定の国からのアクセスに対して行うこともあれば、例外的なログインアクティビティが生じたときにアラートを取得することもあります。
この例では、北朝鮮からログインしているユーザをブロックするポリシーを作成します。ユーザが北朝鮮にいながら企業 VPN を使用している場合は、VPN ゲートウェイがシンガポールか米国にあるものと考えられます。この VPN ゲートウェイから Salesforce が米国内に所在する会社の IP アドレスを確認するため、ログインに成功することがあります。
1global class BlockAccessFromNKPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 List<LoginHistory> loginHistoryObj = // Get the login history
4 [SELECT LoginGeoId FROM LoginHistory WHERE Id = :e.data.get('LoginHistoryId')];
5 String loginGeoId = (String) loginHistoryObj.get(0).get('LoginGeoId'); // Get the geo info
6 List<LoginGeo> loginGeoObj = [SELECT Country FROM LoginGeo WHERE Id = :loginGeoId];
7 String country = (String) loginGeoObj.get(0).get('Country'); // Get the country name
8 if(country == 'North Korea') {
9 return true; // The policy is triggered for North Korea
10 }
11 return false;
12 }
13}郵便番号や市区郡など、他の特定の値へのアクセスを制限することもできます。
PolicyCondition の例: OS 別のアクセスのブロック
特定のモバイルプラットフォームの脆弱性や、Salesforce にアクセス中にスクリーンショットをキャプチャしてデータを読み取る機能に懸念のある場合があります。デバイスがセキュリティクライアントを実行していない場合、明確に特定された既知の脆弱性があるオペレーティングシステムを使用しているデバイスプラットフォームからのアクセスを制限することができます。この例では、Android 5.0 以前を使用するデバイスをブロックするポリシーを作成します。
1global class BlockAndroidDevicesPolicyPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 LoginHistory lHistoryObj = [SELECT Platform FROM LoginHistory WHERE Id = :e.data.get('LoginHistoryId')];
4 if (lHistoryObj != null) { // If this was a login event...
5 String platform = lHistoryObj.Platform;
6 if (platform.contains('Android') && platform.compareTo('Android 5') < 0) {
7 return true; // check for the platform name and then the version.
8 }
9 }
10 return false; // Not Android 5.0 or less.
11 }
12}PolicyCondition の例: Apex API コールアウトの使用
広告やスパムの送信者は、成功しているコミュニティに頻繁にメッセージを投稿して、ユーザがリンクをクリックする可能性を高めようとすることがよくあります。リンクには望ましくないコンテンツが含まれている可能性があります。Salesforce 外のテクノロジを使用して、さまざまなサービスに基づいてコンテンツをスキャンまたはフィルタできます。
次の例では、コミュニティに望ましくないテキストがあり、ポリシーは API コールアウトを実行して、コンテンツが基準に準拠しているかどうかを確認します。この例では、WDYL.com のシンプルな Google 検索 API を使用しています。
1global class ChatterMessageLangFilter implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 String body = e.data.get('Body');
4 HttpRequest req = new HttpRequest();
5 req.setMethod('GET'); // Set HTTPRequest Method
6
7 //Set HTTPRequest header properties
8 req.setHeader('content-type', 'text');
9 req.setHeader('Connection','keep-alive');
10 req.setEndpoint('http://www.wdyl.com/profanity?q=' + EncodingUtil.urlEncode(body,'UTF-8'));
11 Boolean isProfanity;
12 Http http = new Http();
13 HTTPResponse response = http.send(req);
14 if(response.getStatusCode() != 200 /* Failure */){
15 isProfanity = false; // If we can’t call out successfully, don’t trigger the policy.
16 } else {
17 JSONParser parser = JSON.createParser(response.getBody());
18 while (parser.nextToken() != null) {
19 if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
20 (parser.getText() == 'response')) {
21 parser.nextToken(); // Get the value.
22 isProfanity = Boolean.valueOf(parser.getText());
23 }
24 }
25 }
26 return isProfanity;
27 }
28}PolicyCondition の例: 接続アプリケーションによるアクセスのブロック
時として、共有または取引先のアクセス権設定の定義により、接続アプリケーションにシステム (組織) 全体のデータにアクセスする API 権限が設定されていることがあります。他方、接続アプリケーションのエンドユーザはアクセスが特定のデータセットに制限されています。この矛盾により、API キーを特定し、データベースに直接コマンドライン検索を実行してリードを探し出すことでセキュリティリスクが増大することがあります。次のポリシーは、こうした状況を回避して、会社のリード情報に関するデータの損失を阻止します。
1global class DataLoaderLeadExportCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e){
3 if(Boolean.valueOf(e.data.get('IsApi'))){
4
5 // The event data is a Map<String, String>. We need to call the valueOf()
6 // method on appropriate data types to use them in our logic.
7 String entityName = e.data.get('EntityName');
8 String connectedAppId = e.data.get(‘ConnectedAppId’);
9 Integer numberOfRecords = Integer.valueOf(e.data.get('NumberOfRecords'));
10 Integer executionTimeMillis = Integer.valueOf(e.data.get('ExecutionTime'));
11
12 // We're looking for leads accessed by a specific connected app that is
13 // transferring more than 2,000 records in more than a second - a large transfer.
14 if ('Lead'.equals(entityName) &&
15 connectedAppId == '0CiD00000004Cce' &&
16 numberOfRecords > 2000 && executionTimeMillis > 1000 ){
17 return true;
18 }
19 }
20 return false;
21 }
22}