Apex: Object and Field Security Made Easy

Apex: Object and Field Security Made Easy

3cf3d4d85fad3d196c1127018a370418?s=128

Chris Peterson

May 29, 2019
Tweet

Transcript

  1. Apex Security Object and Field Security Made Easy @TedLF Ted

    Freeman, Lead Software Engineer @ca_peterson Chris Peterson, Director of Product Management
  2. Forward-Looking Statement This presentation may contain forward-looking statements that involve

    risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services. The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of any litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site. Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements. Statement under the Private Securities Litigation Reform Act of 1995
  3. Current State of Field Level Security in Apex Returning a

    simple query return [SELECT Name, Owner.Name FROM Account];
  4. Current State of Field Level Security in Apex Becomes a

    complex, error prone task if (Schema.SObjectType.Account.isAccessible() && Schema.SObjectType.Account.fields.Name.isAccessible() && Schema.SObjectType.Account.fields.OwnerId.isAccessible() && Schema.SObjectType.Account.fields.OwnerId.getReferenceTo()[0].getDescribe().isAccessible()) { return [SELECT Name, Owner.Name FROM Account]; } else { throw new AuraHandledException('Access Denied'); }
  5. Current State of Field Level Security in Apex Returning a

    slightly less simple query return [SELECT Name, Account.Owner FROM Account WITH SECURITY_ENFORCED]; Pros: • Fully automated FLS and CRUD checks on the query • Dead simple Cons: • Can't gracefully degrade • Doesn't cover DML • No good tools for sanitizing SObjects from untrusted sources • Beta (GA planned for Winter '20) ◦ Not blessed for Security Review until GA
  6. Introducing The Security.stripInaccessible() Method SObjectAccessDecision Security.stripInaccessible( AccessType accessCheckType, List<SObject> sourceRecords,

    [Boolean enforceRootObjectCRUD]) AccessType Enum DescribeFieldResult method AccessType.READABLE isAccessible() AccessType.CREATABLE isCreatable() AccessType.UPDATABLE isUpdateable() Open Pilot! Summer '19
  7. The SObjectAccessDecision Object Contains results of stripInaccessble Methods • global

    List<SObject> getRecords() A clone of the input records with inaccessible fields removed • global Set<Integer> getModifiedIndexes() All indexes of the input list that had fields stripped • global Map<String, Set<String> getRemovedFields() Contains details on all the fields that were removed from one or more records. Nested collection so that cross-object relationship fields can also be included
  8. Example Use Cases 1. Removing Fields Prior to DML 2.

    Removing Fields for Presentation 3. Removing Fields from a Heterogeneous List 4. Live Demo: Stopping injection in LWC
  9. Example 1 - Removing Fields Prior to DML List<Account> accounts

    = new List<Account>{ new Account(Name='Account1', AnnualRevenue=1000), new Account(Name='Account2') }; // Strip fields that are not creatable SObjectAccessDecision decision = Security.stripInaccessible( AccessType.CREATABLE, accounts); User does not have permission to create Annual Revenue
  10. // Safe insert - does not create AnnualRevenue insert decision.getRecords();

    // Print results for (SObject strippedAccount : decision.getRecords()) { System.debug('Inserted account: ' + strippedAccount); } System.debug('Modified records: ' + decision.getModifiedIndexes()); System.debug('Removed fields: ' + decision.getRemovedFields()); Debuggable feedback on what was changed Example 1 - Removing Fields Prior to DML
  11. Execution Log: Details Inserted account: Account:{Name=Account1, Id=00130000001nFfpIAE} Inserted account: Account:{Name=Account2,

    Id=00130000001nFfqIAE} Modified records: {0} Removed fields: {Account={AnnualRevenue}} User does not have permission to create Annual Revenue Example 1 - Removing Fields Prior to DML
  12. Example 2 - Removing Fields for Presentation User does not

    have permission to read Social Security Number Id Name Amount Business Unit User a0030000000iZbYIAU Expense_Report1 1000 Marketing 00530000000HgGwIAK a0030000000iZbZIAU Expense_Report2 4000 Sales 00530000000HgGxIAK Id Social Security 00530000000HgGwIAK 555-44-3333 00530000000HgGxIAK 777-88-9999 Expense Report Table User Table
  13. Example 2 - Removing Fields for Presentation // Strip fields

    that are not readable SObjectAccessDecision decision = Security.stripInaccessible( AccessType.READABLE, [SELECT Name, Amount__c, Business_Unit__c, User__r.Social_Security__c FROM Expense_Report__c] ); User does not have permission to read Social Security Number
  14. Example 2 - Removing Fields for Presentation // Print results

    - does not display Social Number for (SObject obj : decision.getRecords()) { Expense_Report__c rpt = (Expense_Report__c)obj; System.debug('Expense Report: ' + rpt); User usr = (User)rpt.getSobject('User__r'); System.debug('User: ' + usr); } System.debug('Modified records: ' + decision.getModifiedIndexes()); System.debug('Removed fields: ' + decision.getRemovedFields()); User does not have permission to read Social Security Number
  15. Example 2 - Removing Fields for Presentation User does not

    have permission to read Social Security Number Execution Log: Details Expense Report: Expense_Report__c:{Name=Expense_Report1, Amount__c=1000, Business_Unit__c=Marketing, User__c=00530000000HgGwIAK, Id=a0030000000iZbYIAU} User:{Id=00530000000HgGwIAK} Expense Report: Expense_Report__c:{Name=Expense_Report2, Amount__c=4000, Business_Unit__c=Sales, User__c=00530000000HgGxIAK, Id=a0030000000iZbZIAU} User:{Id=00530000000HgGxIAK} Modified records: {0, 1} Removed fields: {User={Social_Security__c}}
  16. Example 3 - Removing Fields from a Heterogeneous List List<SObject>

    project = new List<SObject>{ new Account(Name='Account1', Flag1__c=1), new Opportunity(Name='Opportunity1') }; SObjectAccessDecision decision = Security.stripInaccessible( AccessType.UPDATABLE, project); The sourceRecords argument can contain different types of SObjects
  17. Example 3 - Removing Fields from a Heterogeneous List //

    Verify stripped records for (SObject strippedRecord : decision.getRecords()) { switch on strippedRecord { when Account a { System.assertEquals(true, a.isSet('Name')); System.assertEquals(false, a.isSet('Flag1__c')); } when Opportunity o { System.assertEquals(true, o.isSet('Name')); } } } The sourceRecords argument can contain different types of SObjects
  18. LWC Demo

  19. We want your feedback! The only reason it's a pilot

    is so we can change things. https://sfdc.co/stripinacessible-feedback @ca_peterson or
  20. None