Apex トランザクションセキュリティの高度な実装例
| 使用可能なインターフェース: Salesforce Classic および Lightning Experience |
| 使用可能なエディション: Enterprise Edition、Unlimited Edition、および Developer Edition Salesforce Shield または Salesforce Event Monitoring アドオンサブスクリプションが必要です。 |
異なる IP アドレスからのログイン
この例では、過去 24 時間でいずれかのユーザーが異なる IP アドレスからログインしたときにトリガーされるポリシーが実装されています。
1global class MultipleLoginEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when LoginEvent loginEvent {
5 return evaluate(loginEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(LoginEvent loginEvent) {
17 AggregateResult[] results = [SELECT SourceIp
18 FROM LoginHistory
19 WHERE UserId = :loginEvent.UserId
20 AND LoginTime = LAST_N_DAYS:1
21 GROUP BY SourceIp];
22 if(!results.isEmpty()) {
23 return true;
24 }
25 return false;
26 }
27}特定の IP アドレスからのログイン
この例では、セッションが特定の IP アドレスから作成されたときにトリガーされるポリシーが実装されています。
1global class SourceIpEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when LoginEvent loginEvent {
5 return evaluate(loginEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(LoginEvent loginEvent) {
17 if (loginEvent.SourceIp.equals('1.1.1.1')) {
18 return true;
19 }
20 return false;
21 }
22}データのエクスポート
この例では、2,000 件を超えるリードで次のいずれかの操作が実行されたときにトリガーされるトランザクションセキュリティポリシーが実装されています。
- UI で表示
- SOQL クエリを使用してエクスポート
- リストビューからエクスポート
- レポートからエクスポート
1global class LeadViewAndExportCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when ApiEvent apiEvent {
5 return evaluate(apiEvent.QueriedEntities, apiEvent.RowsProcessed);
6 }
7 when ReportEvent reportEvent {
8 return evaluate(reportEvent.QueriedEntities, reportEvent.RowsProcessed);
9 }
10 when ListViewEvent listViewEvent {
11 return evaluate(listViewEvent.QueriedEntities, listViewEvent.RowsProcessed);
12 }
13 when null {
14 return false;
15 }
16 when else{
17 return false;
18 }
19 }
20 }
21
22 private boolean evaluate(String queriedEntities, Decimal rowsProcessed){
23 if(queriedEntities.contains('Lead') && rowsProcessed > 2000){
24 return true;
25 }
26 return false;
27 }
28}機密データへのアクセス
このポリシーは、特定のレポートにアクセスする全員に 2 要素認証の使用を義務付けます。
Salesforce の四半期レポートには非公開の機密データを記載できます。レポートにアクセスするチームが、このデータを参照する前に必ず高保証の 2 要素認証 (2FA) を使用するようにします。このポリシーは 2FA を義務付けますが、チームが 2FA の要件を満たす手段がなければ高保証セッションを提供できません。前提条件として、まず Salesforce 環境に 2FA を設定します。
この例では、特定のレポートに 2FA を適用するポリシーの機能が強調表示されています。ここで定義されるレポートは、「Quarterly Report」 (四半期レポート) という名前のレポートです。レポートにアクセスするユーザーは、2FA を使用して高保証セッションを設定する必要があります。
1global class ConfidentialDataEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when ReportEvent reportEvent {
5 return evaluate(reportEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(ReportEvent reportEvent) {
17 // Check if this is a quarterly report.
18 if (reportEvent.Name.contains('Quarterly Report')) {
19 return true;
20 }
21 return false;
22 }
23}ブラウザーチェック
このポリシーは、オペレーティングシステムとブラウザーの組み合わせが分かっているユーザーが、異なるオペレーティングシステム上で別のブラウザーを使用してログインしようとするとトリガーされます。
多くの組織では、標準ハードウェアを設定し、さまざまなブラウザーの特定のバージョンをサポートしています。この標準を使用して、通常と異なるデバイスからログインが発生したときにアクションを行うことにより、影響が大きいユーザーのセキュリティリスクを軽減できます。たとえば、自社の CEO が通常はサンフランシスコから MacBook を使用するか、iPhone で Salesforce モバイルアプリケーションを使用して Salesforce にログインするとします。別の場所から Chromebook を使用したログインが発生した場合、それは非常に疑わしいと言えます。企業役員が使用するプラットフォームをハッカーが知っているとは限らないため、このポリシーによりセキュリティ侵害の可能性が低減されます。
この例では、顧客の組織は、CEO が OS X と Safari ブラウザーを実行する MacBook を使用していることを知っているとします。その他のものを使用して CEO のログイン情報でログインしようとすると、自動的にブロックされます。
1global class AccessEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when LoginEvent loginEvent {
5 return evaluate(loginEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(LoginEvent loginEvent) {
17 // If it's a Login attempt from our CEO's user account.
18 if (loginEvent.UserId == '005x0000005VmCu'){
19 // The policy is triggered when the CEO isn’t using Safari on Mac OSX.
20 if (!loginEvent.Platform.contains('Mac OSX') ||
21 !loginEvent.Browser.contains('Safari')) {
22 return true;
23 }
24 }
25 return false;
26 }
27}国ごとのログインのブロック
このポリシーは、国ごとにアクセスをブロックします。
組織にリモートオフィスがあり、海外展開しているが、国際法に従って Salesforce 組織へのアクセスを制限したいと考えているとします。
この例では、北朝鮮からログインしているユーザーをブロックするポリシーを作成します。ユーザーが北朝鮮にいながら企業 VPN を使用している場合は、VPN ゲートウェイがシンガポールか米国にあるものと考えられます。Salesforce は VPN ゲートウェイおよび米国内に所在する会社の IP アドレスを認識するため、このユーザーは正常にログインできます。
1global class CountryEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when LoginEvent loginEvent {
5 return evaluate(loginEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(LoginEvent loginEvent) {
17 // Get the login's country.
18 String country = String.valueOf(loginEvent.Country);
19
20 // Trigger policy and block access for any user trying to log in from North Korea.
21 if(country.equals('North Korea')) {
22 return true;
23 }
24 return false;
25 }
26}郵便番号や市区郡など、他の値へのアクセスを制限することもできます。
オペレーティングシステムのブロック
このポリシーは、Android OS の旧バージョンを使用しているユーザーのアクセスをブロックします。
特定のモバイルプラットフォームの脆弱性や、Salesforce にアクセス中にスクリーンショットを撮影してデータを読み取る機能に懸念のある場合があります。デバイスがセキュリティクライアントを実行していない場合、既知の脆弱性があるオペレーティングシステムを使用しているデバイスプラットフォームからのアクセスを制限することができます。このポリシーは、Android 5.0 以前を使用するデバイスをブロックします。
1global class AndroidEventCondition implements TxnSecurity.EventCondition {
2 public boolean evaluate(SObject event) {
3 switch on event{
4 when LoginEvent loginEvent {
5 return evaluate(loginEvent);
6 }
7 when null {
8 return false;
9 }
10 when else{
11 return false;
12 }
13 }
14 }
15
16 private boolean evaluate(LoginEvent loginEvent) {
17 String platform = loginEvent.Platform;
18 // Block access from Android versions less than 5
19 if (platform.contains('Android') && platform.compareTo('Android 5') < 0) {
20 return true;
21 }
22 return false;
23 }
24}