The Summer ’16 release comes with new features on Shield Platform encryption adding more “trust” capabilities to your customers. As an ISV, you can now take advantage of these features, but you must adapt your packages first.

Contents

What is Shield Platform Encryption?

Shield Platform Encryption is the infrastructure that enables your customers to easily and securely encrypt "data at rest" in Salesforce while preserving critical business functionality. Shield Platform Encryption allows your company to confidently prove compliance with privacy policies, regulatory requirements, and contractual obligations for handling private data.

Watch the following videos to learn more:


Platform Encryption is not a solution for:

  • Data Residency
  • Multi-Cloud Encryption (Other non-Salesforce Data)
  • Object/Field Level Security
  • Sharing Model
  • Protection Against User Credential Compromise


NOTE: Most global data protection regulations discuss using encryption as an advanced access control to securing data at-rest. While most regulations do not mandate the use of encryption as a required control, they certain suggest using the same. As an example, PCI (Payment Card Industry) claim encrypted at-rest while stored in the cloud.

Why encryption is important to your customers (and you)

The world is changing, and encryption of data at rest is becoming a requirement, and likely to become a standard like SSL/TLS is today. Shield Platform Encryption has been adopted primarily by enterprise organizations in highly regulated industries; Financial Services, Insurance and Healthcare & Life Science. Many others, coming from industries like Professional Services, Retail and High Tech, are using it to add an extra layer of security to their private, sensitive and proprietary data at rest.

In previous releases, customers could encrypt a set of standard objects’ standard fields. With the Summer ’16 release, they can also encrypt managed custom fields from managed packages. As an editor of your packages, you must take actions to ensure your customers can encrypt your managed custom fields to stay aligned with your customers’ decision regarding compliance, regulations or privacy policies. We'll go over the exact steps and options for updating your packages later in this article.

Remember that for new customers installing your managed package, the customer must contact Salesforce support to enable Shield Platform Encryption.

As an ISV testing your compatibility you will also need to contact support to enable encryption on your custom managed fields.

What if you don't support encryption of your managed custom fields?

If regulations require that customers encrypt the fields in your managed packages, and you aren't supporting that, then the customer may choose to uninstall your package. Or they might not install your package in the first place. Being aligned with your customers’ needs means positioning your app ahead of the industry, revealing new opportunities, and being a major key differentiator to other apps.

 

Encrypted fields and their impact

You can now embed encryption for managed (supported) custom fields. These fields are controlled by the subscriber, and the complete list of fields is in the help topic Which Fields Can I Encrypt? Note that you can also embed encryption in a Knowledge Article's File, and you can sort encrypted fields in Reports & Dashboards.

Encrypted fields are compatible with

  • Lightning Experience,
  • Salesforce for Outlook,
  • ExactTarget Connector,
  • Salesforce to Salesforce,
  • Organization Sync.

More details are in the Summer '16 Release Notes.

Impact of Platform Encryption on applications

Proper and secure encryption impacts various existing functionality that would expose the encrypted field. Therefore, it is not possible to:

  • reference encrypted fields in SOQL “WHERE”, “ORDER BY”, “GROUP BY” clauses
  • reference encrypted fields as External IDs or Unique
  • reference encrypted fields as filters in conditional sharing rules
  • encrypt standard fields if legacy portals are active in the org
  • set Skinny tables with encrypted fields (planned, forward looking statement)
  • filter reports, list-views… on encrypted fields

Note that there are workarounds to some of the previous list, and these are covered in a later section in this document.

You'll also want to take a look at the Tradeoffs and Limitations of Shield Platform Encryption.

Impact of Platform Encryption on ISVs

New changes in the Summer '16 release may result in failed package installations and runtime errors. This will happen if you have unsupported functionality (for example a WHERE clause) that uses a customer-encrypted field.

Specifically, the following scenarios are possible:

  • Your customer has an encrypted a field and is installing your package that uses this field in an unsupported manner. The package installation will fail.
  • Your customer installs your package (still with the same unsupported encryption, like a where clause with a field) and then the customer cannot encrypt this field anymore.
  • Your package embeds an unsupported SOQL clause on an encrypted field (in a dynamic SOQL request). A runtime error will occur.

If customers can't encrypt the fields they want, they will either not buy your package, or they'll uninstall it. So it's very important you take immediate action to make your packages comply with these recent changes.


 

Six steps process to adapt your package to Shield Platform Encryption

In this section we'll guide you through how to adapt your packages to the latest changes in Summer '16 and beyond. All of these steps are explained in detail below. An overview of the steps goes like this:

  1. Check how your package supports encryption for standard objects’ standard fields. This will let you know which standard objects’ standard fields your package supports encrypted as-is and if not, why it doesn't support each of them.
  2. Check how your package supports encryption for your package’s managed custom fields. Similar to step 1, this will let you know which managed custom fields your package supports encrypted as-is and if not, why it doesn't support each of them.
  3. Define your immediate and longer term strategies regarding Platform Encryption. After doing the first two steps you'll know if it makes sense to encrypt every field, or which fields you won't support as encrypted and why. Your immediate and long-term strategies will define a roadmap for your package to be Platform Encryption ready.
  4. Start development to support your immediate strategy. Adapt your package for the fields you listed in your immediate strategy, which should be the most important ones.
  5. Package and distribute a new release of your package. Note that we strongly recommend you have only one package with Platform Encryption. Otherwise, in addition to having two packages (two contracts, two security reviews to pass, etc.) you would not be able to support a customer just having subscribed to Platform Encryption without uninstalling a package an reinstalling the other. A nightmare for your customer as well as for you!
  6. Start development to support your longer term strategy. Your package needs to be adapted to support Platform Encryption for the fields you listed in your longer term strategy, all the remaining ones.

Step 1: Check how your package supports encryption for standard objects’ standard fields

  1. Create an org from EH by selecting Test/Demo and then Partner Enterprise then enable Platform Encryption
    • Create 2 cases to activate Platform Encryption and to activate Encryption on Custom Managed fields for Orgs created prior to Summer'15 or if needed in  sandbox org.
  2. Encrypt all supported standard objects’ standard fields and Files & Attachments.
  3. Install your package in this org.
    • Not successful?
      (means your package uses a field in a way it’s not possible when encrypted)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted on Step 3 when defining your short and long term strategies.
      => loop to "3"
    • Successful?
      => continue this process.
  4. Load data into your org to run exhaustive tests.
    • Not successful?
      (means you use a field in dynamic SOQL a way it is not possible when encrypted in a trigger, an @Future class or any other piece of code or Workflow)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted when defining your short and long term strategies.
      => loop to "4".
    • Successful?
      => continue this process.
  5. Test extensively and exhaustively the application (ending with reports and dashboards)
    • Not successful?
      (means you use a field in dynamic SOQL a way it is not possible when encrypted or use it as a filter in a report)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted on Step 3 when defining your short and long term strategies.
      => loop to "5".
    • Successful?
      => continue this process.
  6. End of this test.
    • You now have the list of all standard objects’ standard fields you support as encrypted and the ones you do not.

Step2: Check if and how your package supports encryption for your package’s managed custom fields

  1. Remove all data from the org you used in the previous step.
    • Not possible because there are too many relationships and links (or any other reason)?
      => create a new org, activate Platform Encryption and encrypt all standard objects’ standard fields you support encrypted.
      => continue this process.
    • Possible?
      => remove all data, clean the trash.
      => continue this process.
  2. Encrypt all your package’s encrypted fields.
    • Not successful?
      (means your package uses a field in a way it’s not possible when encrypted)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted on Step 3 when defining your short and long term strategies.
      => loop to "2"
    • Successful?
      => continue this process.
  3. Load data into your org to run exhaustive tests.
    • Not successful?
      (means you use a field in dynamic SOQL a way it is not possible when encrypted in a trigger, an @Future class or any other piece of code or Workflow)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted on Step 3 when defining your short and long term strategies.
      => loop to "3".
    • Successful?
      => continue this process.
  4. Test extensively and exhaustively the application (ending with reports and dashboards)
    • Not successful?
      (means you use a field in dynamic SOQL a way it is not possible when encrypted or use it as a filter in a report)
      => un-encrypt this field and note it. You’ll decide if you want to support it as encrypted on Step 3 when defining your short and long term strategies.
      => loop to “4”.
    • Successful?
      => continue this process.
  5. End of this test.

Step 3: Define your immediate and longer term strategies re-Platform Encryption

In this step you'll answer the question "which standard objects’ standard fields and package’s managed custom fields will you support to be encrypted and which ones you won’t, now and in your coming releases?".

Answers depend on the importance for every field to be encryptable:

  • In business, compliance, regulatory, contractual… aspects for your customers to accept this field to not be encryptable
  • In technical point of view to support this field as encrypted in your package
  • In a functional point of view (feature missing) if this field is encrypted
  • In a performance point of view if this field is encrypted

There are 3 options for each field:

  • Option #1: you decide to support this field now as being encryptable and manage your package accordingly
  • Option #2: you decide you will support this field as being encryptable in a future release
  • Option #3: you decide this field cannot be encrypted

Encrypting a field can impact features provided by your package:

  • Functional impact:
    • You cannot do exactly the same when the field is encrypted or not.
      • For example, programmed query filtering complexity can be limited when fields are encrypted to reduce code complexity as it has to be done in Apex using several SOSL queries rather than in SOQL where clauses.
      • For example, filtering in reports is not possible on encrypted fields.
  • Performances impact:
    • Some features are longer to execute when fields are encrypted due to additional code needed for the workaround.
      • For example, displaying a very long ordered and grouped list in a programmed page (Visualforce page or Lightning Component) can take longer as you have to do this work by yourself in Apex rather than within the SOQL query.
  • Technical impact:
    • Some features are not available anymore when the field is encrypted.
    • For example, not possible to run a batch running on a query having an encrypted field in a where or order by clause.
    • For example, displaying a very long ordered and grouped list in a programmed page (Visualforce page or Lightning Component) can be impossible if the list is too large and exceed the heap memory available when you do his work by yourself in Apex rather than within the SOQL query.

Check and decide which fields you will support as encryptable and if this option has a functional, performances or technical impact on your application. Of course, your strategy can be to support encryption with restrictions a field in first release and with less and less restriction in the coming ones.

Think carefully about commercial impact of Option #3 if customers really need or want to encrypt this field. It is better to limit features when a field is encrypted than to not support it as encrypted.

Think carefully when you decide to “support later” encryption of standard objects’ standard fields as they are shared across multiple applications (Sales Cloud, Service Cloud, other ISV applications, customer’s customizations...). By protecting them you do impact all applications and your position can become weaker in front of customer’s decision to encrypt these fields.

Step 4: Start development to support your immediate strategy

Change your code according to your strategy, using the workarounds published later in this document for fields you support as encryptable.

To “protect” a field to not be encrypted, include it in the WHERE clause of an SOQL query in a not used class you include in your package.

This anti-pattern can be used for “support encryption later” and “cannot be encrypted” fields.

Step 5: Package and distribute a new release of your package

At this point, the Summer ’16 release is now rolled-out. Customers are able to encrypt managed custom fields in addition to standard objects’ standard fields.

Create new versions of you package and update your listing to inform customers and prospects.

Step 6: Start development to support your longer term strategy

Do as when you were preparing your package for your immediate strategy.

Add more fields, limit number of fields you will support later or never and limit functional, performances and technical restrictions when fields are encrypted.

 

Technical details for developers

Testing field’s status to decide what to do

Because key limitations’ workaround can impact your application in a functional, performances or technical point of view, you can decide to run different code according to field’s status.

4 functions help you to decide: isEncryptable(), isFilterable(), isSortable() and isGroupable().

As of today, when a field is encrypted, isEncryptable() returns true while the 3 other ones return false. We strongly recommend you to use the 3 detailed functions ( isFilterable(), isSortable() and isGroupable() )rather than isEncryptable().


Key limitations and their workarounds

Check for code examples implementing these workarounds.

Can't reference encrypted fields in SOQL/WHERE queries

  1. Use SOSL/FIND instead.
  2. Reference non-encrypted fields instead, if possible.
  3. If you're not expecting too many results, you can query the records and then run a "for" loop with if / then / else, searching for the value.
    • This can be done after a 1st filtering level to reduce number of records to filter in Apex.
    • Take care of performances!

Can't apply encryption on Number and Currency field types

  1. You can often keep private, sensitive, or regulated data safe without encrypting associated Currency or Number fields. Encrypting these fields can have broad functional consequences across the platform, such as disruptions to roll-up summary reports and calculations.
  2. If it isn't used in calculation, it can be stored in a custom Text field instead, and apply encryption on that.

Can't sort encrypted fields in ORDER BY clauses

  1. Sorting encrypted fields can be executed programmatically in APEX in runtime and can be a good solution for custom pages customers are developing.

Can’t group encrypted fields in GROUP BY SOQL clauses

  1. Instead of grouping by the encrypted field value, evaluate whether you can switch to grouping by the record ID instead (or any other non-encrypted value)

Can't set encrypted field as External ID or Unique

  1. Use a custom Web Service instead of standard APIs to receive records and build the logic programmatically in Apex.
  2. Do not consider using a PII as an external ID. Use a technical ID stored in the 3rd party system or store Salesforce ID in the 3rd party system.

Can’t apply encryption on Picklist values

  1. Store the Picklist values in a custom Text fields in a custom dedicated entity instead, so that you would be able to maintain this list efficiently declaratively, without writing code. You can apply encryption on these text fields if you want.
  2. Now using VF page components, you can build a picklist field *programmatically*, which will be pulling the values from the text fields. This component can be added to the existing layout and the selected value can be stored in a custom Text field, encrypted, in the existing entity. <a name="CodeExamples"></a>

 

 

Code examples implementing these workarounds

WHERE Clause: Use of SOSL or SOQL dynamically

You have an SOQL request in your code using a potentially encrypted field (“MailingCity” in “Contact”) in a WHERE clause

Your code as of today:

List<Contact> conts = [Select ID, Name, MailingCity from Contact WHERE MailingCity = ‘Paris’];

Your code to support field BillingCity to be encrypted:

List<Contact> conts;
If (Schema.sObjectType.Contact.fields.MailingCity.isFilterable() ){
      //Filterable, so use SOQL
      conts = Database.query('Select ID, Name, MailingCity from Contact WHERE MailingCity = \'PARIS\'');

} else {
      //Not filterable, so use SOSL
      List<List<SObject>> searchList = [FIND 'PARIS' IN ALL Fields RETURNING Contact (Id, Name, MailingCity)];
      conts = searchList.get(0);
}

ORDER BY Clause: use of SOQL or Apex dynamically

You have an SOQL request in your code using a potentially encrypted field (“MailingCity” in “Contact”) in an ORDER BY clause.

Your code as of today:

List<Contact> conts = [Select ID, Name, MailingCity from Contact order by MailingCity);

Your code to support field MailingCity to be encrypted:

list<contact> orderedContacts = new list<contact>();
If (Schema.sObjectType.Contact.fields.MailingCity.isSortable() ){
      //Groupable, so use SOQL
      orderedContacts = Database.query('select id, name, mailingCity from Contact order by mailingcity');
} else {
      //Not sortable, so simple SOQL + Apex to sort by
      list<contact> allContacts = Database.query('select id, name, mailingCity from Contact');
      map<string,Contact> orderedContactsMap =new map<string,contact>();
      list<string> listMailingCity= new list<string>();
      //sort the mailingCity
      for (contact c: allContacts){
            orderedContactsMap.put(c.mailingCity,c);
            listMailingCity.add(c.mailingCity);
      }
      listMailingCity.sort();
      //build the list order by mailing city
      for (string mc :listMailingCity){
            orderedContacts.add(orderedContactsMap.get(mc));
      }
}

GROUP BY Clause: Use of SOQL or Apex dynamically

You have an SOQL request in your code using a potentially encrypted field (“MailingCity” in “Contact”) in a GROUP BY clause.

Your code as of today:

list<aggregateResult> aggContacts = [select mailingCity,COUNT(ID)q from Contact group by mailingcity];
map<string, integer> NumberOfContactPerCity = new Map<string, integer>();
for ( aggregateResult a: aggContacts){
      NumberOfContactPerCity.put(( string)a.get('mailingCity'), (integer) a.get('q'));
}

Your code to support field MailingCity to be encrypted:

map<string, integer> NumberOfContactPerCity = new Map<string, integer>();
If (Schema.sObjectType.Contact.fields.MailingCity.isGroupable() ){
      //Groupable, so use SOQL
      list<aggregateResult> aggContacts = Database.query('select mailingCity,COUNT(ID)q from Contact group by mailingcity');
      for ( aggregateResult a: aggContacts){
            NumberOfContactPerCity.put(( string)a.get('mailingCity'), (integer) a.get('q'));
      }
} else {
      //Not Groupable, so simple SOQL + Apex to group by
      list<contact> allContacts = Database.query('select mailingCity,ID from Contact');
      for (contact c: allContacts){
            //check if mailingcity already in map
            if (NumberOfContactPerCity.containsKey(c.mailingCity)){
                  // +1
                  NumberOfContactPerCity.put(c.mailingCity, NumberOfContactPerCity.get(c.mailingCity)+1);
            } else {
                  NumberOfContactPerCity.put(c.mailingCity,1);
            }
      }
}

Additional Resources

Official Salesforce Documentation

Other Resources

Note that the following resources may not be regularly maintained.