Newer Version Available
PolicyCondition インターフェース
名前空間
使用方法
evaluate メソッドは、トランザクションセキュリティポリシーで監視されているイベントが発生するとコールされます。通常の実装では、最初にイベントから関心のある項目を選択します。その項目をテストして、監視されている条件を満たすどうか確認します。条件を満たす場合、メソッドは true を返します。
たとえば、同じユーザが複数回ログインしていないかチェックするトランザクションセキュリティポリシーがあるとします。ログインイベントごとに、メソッドは、ログインしているユーザにすでに進行中のログインセッションがあるかどうかをチェックし、ある場合は true を返します。
ポリシーを実装している組織でポリシー条件インターフェースを使用している場合、ポリシーのテストクラスは不要です。ポリシーを別の組織に移動する場合、新しい組織で Apex ポリシーのテストクラスが必要です。ポリシーを Sandbox から本番組織に移動するか、変更セットと共に移動するか、または他の方法で移動するかに関係なくテストが必要です。なぜでしょうか? ポリシーを開発環境外で使用できるようにする場合、ポリシーをテストして適切に機能することを確認する必要があるためです。
エラーが発生する可能性があるため、カスタムポリシーには DML ステートメントを含めないでください。トランザクションポリシーの評価中に Apex を介してカスタムメールを送信すると、レコードが別のレコードに明示的に関連付けられていなくても、エラーが表示されます。詳細は、『Apex 開発者ガイド』の「Apex DML 操作」を参照してください。
PolicyCondition のメソッド
PolicyCondition のメソッドは次のとおりです。
evaluate(event)
署名
public Boolean evaluate(TxnSecurity.Event event)
パラメータ
- event
- 型: TxnSecurity.Event
- トランザクションセキュリティポリシーに対して確認するイベント。
戻り値
型: Boolean
ポリシーがトリガされると、True が返されます。たとえば、ユーザをシングルログインセッションに限定するポリシーがあるとします。あるユーザが 2 つ目のログインをしようとすると、ポリシーのアクションによって現在のセッションを終了するよう求められます。また、Salesforce システム管理者にもメール通知が送信されます。evaluate() メソッドは、ログインイベントのみを確認し、ユーザの 2 つ目のログインである場合に True を返します。トランザクションセキュリティシステムはアクションと通知を実行しますが、evaluate() メソッドは実行しません。
トランザクションセキュリティの Apex ポリシー
| 使用可能なエディション: Salesforce Classic および Lightning Experience |
| 使用可能なエディション: Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition Salesforce Shield または Salesforce Event Monitoring アドオンサブスクリプションを購入する必要があります。 |
ポリシーの Apex インターフェースを生成する前に条件値を指定していなかった場合、後で条件を追加できます。条件を変更するために、ポリシーを有効化する前に、Apex コードを編集して条件を含めることができます。条件を含めないと、ポリシーはトリガされません。
エラーが発生する可能性があるため、カスタムポリシーには DML ステートメントを含めないでください。トランザクションポリシーの評価中に Apex を介してカスタムメールを送信すると、レコードが別のレコードに明示的に関連付けられていなくても、エラーが表示されます。詳細は、『Apex 開発者ガイド』の「Apex DML 操作」を参照してください。
トランザクションセキュリティポリシーを削除しても、TxnSecurity.PolicyCondition 実装は削除されません。Apex コードを他のポリシーで再利用できます。
Apex トランザクションセキュリティの実装例
| 使用可能なエディション: Salesforce Classic (一部の組織で使用可能) および Lightning Experience の両方 |
| 使用可能なエディション: Enterprise Edition、Performance Edition、Unlimited Edition、および Developer Edition Salesforce Shield または Salesforce Event Monitoring アドオンサブスクリプションを購入する必要があります。 |
例
1global class LoginPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 AggregateResult[] results = [SELECT SourceIp
4 FROM LoginHistory
5 WHERE UserId = :e.userId
6 AND LoginTime = LAST_N_DAYS:1
7 GROUP BY SourceIp];
8 if(!results.isEmpty() && results.size() > 1) {
9 return true;
10 }
11 return false;
12 }
13}例
1global class SessionPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3
4 LoginHistory eObj = [SELECT SourceIp FROM LoginHistory WHERE Id = :e.data.get('LoginHistoryId')];
5 if (eObj.SourceIp == '1.1.1.1') {
6 return true;
7 }
8 return false;
9 }
10}例
1global class LeadExportPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3
4 Integer numberOfRecords = Integer.valueOf(e.data.get('NumberOfRecords'));
5 String entityName = e.data.get('EntityName');
6
7 if ('Lead'.equals(entityName) && numberOfRecords > 1000) {
8 return true;
9 }
10
11 return false;
12 }
13}例
1global class ReportsPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 if(e.data.get('SessionLevel') == 'STANDARD' ){
4 return true;
5 }
6 return false;
7 }
8}例
1global class ConnectedAppsPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 if(e.data.get('SessionLevel') == 'STANDARD' && (e.entityId == '0CiD00000004Cce')){
4 return true;
5 }
6 return false;
7 }
8}例
[トランザクションセキュリティポリシー] ページで、localhost ログインをブロックするポリシーを作成します。次に生成された Apex ポリシーを示します。
1global class BlockLocalhostLoginPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 // Get the LoginHistoryId to in turn select the SourceIp address.
4 String loginHistoryId = e.data.get('LoginHistoryId');
5 // Retrieve SourceIp from LoginHistory.
6 LoginHistory eObj =
7 [SELECT SourceIp FROM LoginHistory WHERE id = :e.data.get('LoginHistoryId')];
8 // If the Source IP is localhost (127.0.0.1), trigger the policy and return true.
9 if(eObj.SourceIp == '127.0.0.1') {
10 return true;
11 }
12 return false;
13 }
14}例
システム管理者または API 権限のある他の顧客は、SOAP API、REST API、または Bulk API を使用して、すべての顧客データを一括ダウンロードできます。このセキュリティポリシーは、API ベースのデータのダウンロードを 2,000 レコードに制限し、ポリシーがトリガされた場合にシステム管理者にリアルタイムで通知します。
1global class DataLoaderExportPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 Boolean isApi = Boolean.valueOf(e.data.get('IsApi')) { // For any API request...
4 Integer numberOfRecords = Integer.valueOf(e.data.get('NumberOfRecords'));
5 if (isApi && numberOfRecords >= 2000) {
6 return true;
7 }
8 return false;
9 }
10 }
11}例
Salesforce の四半期レポートには非公開の機密データを記載できます。さらに、これらのレポートにアクセスするチームに、このデータを参照する前に必ず高保証の 2 要素認証 (2FA) を使用させることができます。このポリシーは 2FA を義務付けますが、チームに 2FA の要件を満たす手段がなければ高保証セッションを提供できません。前提条件として、まず Salesforce 環境に 2FA を設定します。
この例では、特定のレポートに 2FA を適用するポリシーの機能が強調表示されています。ここで定義されるレポートは、「Quarterly Report」(四半期レポート) という名前のレポートです。レポートにアクセスするユーザは、2FA を使用して高保証セッションを設定する必要があります。
1global class ConfidentialDataPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 if (e.resourceType == 'Dashboard') { // If the event is about Dashboards...
4 Dashboard dashboard =
5 [SELECT DeveloperName FROM Dashboard WHERE id = :e.entityId];
6 String name = String.valueOf(dashboard.DeveloperName);
7 // Check if this is a quarterly report.
8 if (name.containsIgnoreCase('Quarterly Report')) {
9 return true;
10 }
11 }
12 return false;
13 }
14}例
多くの組織では、標準ハードウェアを設定し、さまざまなブラウザの特定のバージョンをサポートしています。この標準を使用して、通常と異なるデ��イスからログインが発生したときにアクションを行うことにより、影響が大きいユーザのセキュリティリスクを軽減できます。たとえば、自社の CEO が通常はサンフランシスコから MacBook を使用するか、iPhone で Salesforce モバイルアプリケーションを使用して Salesforce にログインするとします。別の場所から Chromebook を使用したログインが発生した場合、それは非常に疑わしいと言えます。企業役員が使用するプラットフォームをハッカーが知っているとは限らないため、このポリシーによりセキュリティ侵害の可能性が低減されます。
この例では、顧客の組織は、CEO が OS X と Safari ブラウザを実行する MacBook を使用していることを知っているとします。その他のものを使用して CEO のログイン情報でログインしようとすると、自動的にブロックされます。
1global class CeoBrowserAccessPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 // If it's a Login attempt from our CEO's user account.
4 if (e.action == 'Login' && e.userId == '005x0000005VmCu') {
5 // Get the platform & browser from LoginHistory for this login attempt.
6 LoginHistory loginAttempt =
7 [SELECT Platform, Browser FROM LoginHistory
8 WHERE Id = :e.data.get('LoginHistoryId')];
9 String platform = loginAttempt.Platform;
10 String browser = loginAttempt.Browser;
11 // The policy is triggered when the CEO isn’t using Safari on Mac OSX.
12 if (!platform.equals('Mac OSX') || !browser.startsWith('Safari')) {
13 return true;
14 }
15 }
16 return false;
17 }
18}例
組織でリモートオフィスを設置したりグローバルプレゼンスを高めたりすることができますが、国際法に従って Salesforce 組織へのアクセスを制限する必要のある場合があります。
この例では、北朝鮮からログインしているユーザをブロックするポリシーを作成します。ユーザが北朝鮮にいながら企業 VPN を使用している場合は、VPN ゲートウェイがシンガポールか米国にあるものと考えられます。この VPN ゲートウェイから Salesforce が米国内に所在する会社の IP アドレスを確認するため、ログインに成功することがあります。
1global class BlockAccessFromNKPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 // Get the login history.
4 LoginHistory loginAttempt =
5 [SELECT LoginGeoId FROM LoginHistory WHERE Id = :e.data.get('LoginHistoryId')];
6 // Get the login's geographical info.
7 String loginGeoId = String.valueOf(loginAttempt.LoginGeoId);
8 LoginGeo loginGeo = [SELECT Country FROM LoginGeo WHERE Id = :loginGeoId];
9 // Get the country at that location.
10 String country = String.valueOf(loginGeo.Country);
11 // Trigger policy and block access for any user trying to log in from North Korea.
12 if(country.equals('North Korea')) {
13 return true;
14 }
15 return false;
16 }
17}郵便番号や市区郡など、他の値へのアクセスを制限することもできます。
例
特定のモバイルプラットフォームの脆弱性や、Salesforce にアクセス中にスクリーンショットをキャプチャしてデータを読み取る機能に懸念のある場合があります。デバイスがセキュリティクライアントを実行していない場合、明確に特定された既知の脆弱性があるオペレーティングシステムを使用しているデバイスプラットフォームからのアクセスを制限することができます。このポリシーは、Android 5.0 以前を使用するデバイスをブロックします。
1global class BlockOldAndroidDevicesPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 LoginHistory loginAttempt =
4 [SELECT Platform FROM LoginHistory WHERE Id = :e.data.get('LoginHistoryId')];
5 if (loginAttempt != null) {
6 String platform = loginHistory.Platform;
7 if (platform.contains('Android') && platform.compareTo('Android 5') < 0) {
8 return true;
9 }
10 }
11 return false; // Allow access from Android versions greater than 5.
12 }
13}例
投稿内の特定の語をスキャンまたは検索できます。この例では、「Salesforce」という語が含まれる投稿を検索し、それらの投稿をブロックします。語のリストをループ処理したり、語の出現数の累計値を継続的に取得したりする条件を記述することもできます。
1global class ChatterMessageWordFilterPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event event) {
3 String body = event.data.get('Body');
4
5 if(body.containsIgnoreCase('Salesforce')) {
6 return true;
7 }
8 return false;
9 }
10}例
広告やスパムの送信者は、成功しているコミュニティに頻繁にメッセージを投稿して、ユーザがリンクをクリックする可能性を高めようとすることがよくあります。リンクには望ましくないコンテンツが含まれている可能性があります。Salesforce 外のテクノロジを使用して、さまざまなサービスに基づいてコンテンツをスキャンまたはフィルタできます。
このポリシーは、API コールアウトを実行して、コンテンツが基準に準拠しているかどうかを確認し、www.purgomalum.com/profanitylist で指定された、一般的に認められている英語の冒涜的な言葉をブロックするサービスを使用します。
1global class ChatterMessageProfanityFilterPolicyCondition implements TxnSecurity.PolicyCondition {
2 public boolean evaluate(TxnSecurity.Event e) {
3 String body = e.data.get('Body');
4
5 //Create HTTPRequest and specify its type and properties.
6 HttpRequest request = new HttpRequest();
7 request.setMethod('GET');
8 request.setHeader('content-type', 'text/plain');
9 request.setHeader('Connection', 'keep-alive');
10 request.setEndpoint('http://www.purgomalum.com/service/containsprofanity?text=' +
11 EncodingUtil.urlEncode(body,'UTF-8'));
12
13 Http http = new Http();
14 HTTPResponse response = http.send(request);
15
16 if (response.getStatusCode() == 200 && response.getBody().equals('true')) {
17 return true; // Callout succeeded and found profanity in the message.
18 }
19 return false; // Callout failed or no profanity was found.
20 }
21}例
時として、共有または取引先のアクセス権設定の定義により、接続アプリケーションに組織全体のデータにアクセスする API 権限が設定されていることがあります。他方、接続アプリケーションのエンドユーザはアクセスが特定のデータセットに制限されています。この矛盾により、API キーを特定し、データベースに直接コマンドライン検索を実行してリードを探し出すことでセキュリティリスクが増大することがあります。次のポリシーは、こうした状況を回避して、会社のリード情報に関するデータの損失を阻止します。
1global class DataLoaderLeadExportPolicyCondition 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
6 // valueOf() method on appropriate data types to use them here.
7 String resourceType = e.data.get('resourceType');
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 a second - a large transfer.
14 if ('Lead'.equals(resourceType) &&
15 '0CiD00000004Cce'.equals(connectedAppId) &&
16 numberOfRecords > 2000 &&
17 executionTimeMillis > 1000) {
18 return true;
19 }
20 }
21 return false;
22 }
23}