Only allow Bulk API for specific API users

In Salesforce either you have API access or you don’t. Following recent events you might want to restrict access to specific API types (think Bulk, REST etc.) to certain users. Doing this can be done with a Transaction Policy based on events from real-time Shield Event Monitoring using an Apex event condition. The below event condition only allows the ApiEvent to go through if the user has been assigned the Data_Steward permission set if it’s a Bulk API request. Assigning this permission set could even be a permission that automatically times out to further the security posture.

global class BlockBulkAPIEventCondition implements TxnSecurity.EventCondition {

    public boolean evaluate(SObject event) {
        // cast event object
        final ApiEvent ev = (ApiEvent)event;
        
        // if not a Bulk API event simply allow
        if (ev.ApiType.indexOf('Bulk') < 0) return false;

        // this is for the Bulk API ensure permset assignment
        final Id userId = ev.UserId;
        final PermissionSetAssignment permsetAssign = 
            [SELECT Id FROM PermissionSetAssignment 
             WHERE permissionset.Name = 'Data_Steward' 
             AND AssigneeId =: userId LIMIT 1] ?? null;
        return null == permsetAssign;
    }

}

Scratch org with Salesforce Event Monitoring

Note to self – scratch org definition file to create a scratch org with Event Monitoring enabled. This is a super easy way to quickly spin up an org with Event Monitoring for testing or development. As always the trick is to know the feature and the settings to avoid the manual setup.

{
  "orgName": "foo",
  "edition": "Developer",
  "country": "US",
  "features": ["EventLogFile", "PersonAccounts"],
  "settings": {
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "mobileSettings": {
      "enableS1EncryptedStoragePref2": false
    },
    "eventSettings": {
      "enableEventLogGeneration": true,
      "enableTransactionSecurityPolicies": true,
      "enableDeleteMonitoringData": true,
      "enableLoginForensics": true,
      "enableStreamingApi": true,
      "enableTerminateOldestSession": true,
      "enableDynamicStreamingChannel": false,
      "bypassMeteringBlock" :false
    }
  }
}