Slide 1

Slide 1 text

Apex Security Object and Field Security Made Easy @TedLF Ted Freeman, Lead Software Engineer @ca_peterson Chris Peterson, Director of Product Management

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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'); }

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Introducing The Security.stripInaccessible() Method SObjectAccessDecision Security.stripInaccessible( AccessType accessCheckType, List sourceRecords, [Boolean enforceRootObjectCRUD]) AccessType Enum DescribeFieldResult method AccessType.READABLE isAccessible() AccessType.CREATABLE isCreatable() AccessType.UPDATABLE isUpdateable() Open Pilot! Summer '19

Slide 7

Slide 7 text

The SObjectAccessDecision Object Contains results of stripInaccessble Methods • global List getRecords() A clone of the input records with inaccessible fields removed • global Set getModifiedIndexes() All indexes of the input list that had fields stripped • global Map 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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Example 1 - Removing Fields Prior to DML List accounts = new List{ 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

Slide 10

Slide 10 text

// 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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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}}

Slide 16

Slide 16 text

Example 3 - Removing Fields from a Heterogeneous List List project = new List{ 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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

LWC Demo

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

No content