Introducing the Salesforce Shield Platform Encryption REST API
The Salesforce Shield Platform Encryption API enables you to bring your own key (BYOK)—that is, to control your own tenant secrets on your own premises. Use the POST, GET, and PUT operations to create your tenant secrets, import them into Salesforce, and rotate them as needed. The Encryption REST API is available in API versions 38.0 and later.
The API provides powerful and simple web services for interacting with Lightning Platform. This API is customized for use with Shield Platform Encryption features and gives you easy access to the special objects and functionality it provides.
Getting Started
If you plan to work with many records, you may also need the Bulk API. Using Bulk API 2.0 or Bulk API requires basic familiarity with software development, web services, and the Salesforce user interface. Because both Bulk APIs are asynchronous, Salesforce doesn’t guarantee a service level agreement.
Note
To get set up to use the Salesforce REST API, see the REST API Developer Guide. The guide explains the API’s characteristics and architecture and how to set up your development environment.
Run some sample REST requests in your development org to learn the API basics. Trying out the examples now makes it easier to build your applications later.
Start with a development platform with authorization set up on it. The REST API client needs a valid sessionId to use. If you don’t have a platform, see the REST API Developers Guide for information about creating one.
To use the encryption API calls, you must have the Manage Encryption Keys permission and have Shield Platform Encryption enabled in your org. If you don’t have both, nothing is returned.
Note
The Encryption API isn’t part of the regular Lightning Platform REST API. It’s available with the Salesforce Shield or Shield Platform Encryption add-on licenses.
See Also
Use the Platform Encryption API
Use the Platform Encryption API to manage tenant secrets. You can complete most key management and auditing tasks via the API that you can do in the user interface.
Set Up Your REST Client
To work through these examples, we’ll use Python to prepare a Simple Salesforce REST API client.
To initialize a Simple Salesforce REST API client named sf, use this sample code to create a Salesforce instance called sf.
1from simple_salesforce import Salesforce
2URL ='https://{SF_SERVER}/services/Soap/u/37.0'
3sf = Salesforce(session_id={sessionId}, instance_url=URL, version='44.0')Now you can use the Salesforce instance sf to issue REST API calls, like this:
1sf.restful({TS_URL}, {request_params}, method = ‘GET’|'POST'|’PATCH’|’DELETE’)Or you can use the equivalent calls provided by the Simple Salesforce module, like this:
1sf.TenantSecret.[get|create|update]({parameters})Create a Tenant Secret
Use the POST method to create a tenant secret. Usually, you can create one tenant secret every 24 hours in production orgs, and once every 4 hours in sandbox orgs. You can generate tenant secrets for the Search Index and Event Bus types once every 7 days.
-
Use the POST method to create a tenant secret, using the TenantSecret specific URL.
1# extract TenantSecret endpoint URL, e.g. 2# https://myorg.salesforce.com/services/data/v44.0/sobjects/TenantSecret/ 3TS_URL = sf.TenantSecret.base_url -
To generate a new tenant secret, use a REST POST command, without parameters.
1sf.restful(TS_URL, {}, method = 'POST') -
Or use the Simple Salesforce equivalent.
1sf.TenantSecret.create({'Type':"SearchIndex"})Tenant secrets default to the Data in Salesforce type. Tenant secrets of this type encrypt data in fields, attachments, and files other than search index files. Specify a
Typeother thanDataif you want to use a different type of tenant secret. For more information, see Shield Platform Encryption Key Material Types in Salesforce Help or the TenantSecret entry in the API Object Reference Guide.
The complete response contains an ordered dictionary that looks like this:
1[ (u'id', u'02G41000000HLXrEAO'), (u'success', True), (u'errors', []) ]You can also use the POST method to create a callout connection that fetches a cache-only key tenant secret from a key service outside of Salesforce.
-
Make sure that Bring Your Own Key (BYOK) is enabled in your org. Then turn on Allow Cache-Only Keys with BYOK from the Advanced Settings page in Setup.
-
Create a certificate that’s compatible with customer-supplied key material. See Generate a BYOK-Compatible Certificate in Salesforce Help.
-
Create a named credential to serve as your authenticated callout mechanism. You can define your named credential through Setup or directly with Apex. Specify a BYOK-compatible certificate and an HTTPS endpoint.
-
Configure the connection to your remote key service. This connection uses a named credential and its associated certificate to fetch a specified cache-only key tenant secret.
1remote_params = { ‘Source’: ‘Remote’, 2‘RemoteKeyIdentifier’: ..., 3‘RemoteKeyServiceId': ..., 4‘RemoteKeyCertificate’: ...} 5 6sf.TenantSecret.create(remote_params)
Upload a Tenant Secret
Use the POST method to upload a tenant secret to your org.
-
Find your tenant secret’s encrypted form, hash and the name of the BYOK-specific certificate name used to encrypt the plain text form of the original tenant secret.
(The original tenant secret is never sent to Salesforce.)
Here’s a sample of code you might use to get this information.
1### reading encrypted secret and secret hash from files. 2with open("encrypted_secret.b64") as f: 3encrypted_secret = f.read().translate(None, '\n') 4with open("plaintext_secret_hash.b64") as f: 5secret_hash=f.read().translate(None, '\n') 6# select certificate name 7Cert_name = “MyActivePECertificate” -
Upload your tenant secret by sending a POST call specifying the encrypted secret, secret hash, and certificate name.
1sf.TenantSecret.create({ 2'SecretValue':encrypted_secret, 3'SecretValueHash':secret_hash, 4'SecretValueCertificate':cert_name })
The actual parameters for this create request will look like this:
1sf.TenantSecret.create({
2'SecretValue':'Zk/xUSIkqKNYKoiZoidet4UQkNc3Q9H3Wxf6+fxbqbtfBdp2If5DHbGjy9pe9xRx18tiXzw77u1Dwa4suHgk1je1EfH0Nh0WDZw
3BLkgJDOTsw4j7mwxYWmbfjOqz4Lix8gk9WSstJPwxwvASPyJ/XttTqeMQSkh03BLBlghRkB40YY57QIfnrHPnLUvIcMwVm0fmYtCHMvfsvNtcpgPgs
4WMQTQ9WuBnmqgeq+94+NDtg4kFLMDqPUdSd19KI0KOXTedy2XldLBI72A/6C7Qb7xBdNrtlXJVqZEI/nQ8wluVWIhh7ZN/tsPjtFJ6k3iFuv1FTzTX
5dRZJ1icOSfOTyHVWbMpgUS/V2+AR2MV2SgtPOWrd7GIyqKQC0Ohveh/Hiz0H1VwnJIH6Wupjuf4Ocdt/XkjEcqYfp6vLnbQ8mGRUrTPfNXz14I1XfA
6iU2BdfNlkRXOe1iVMMBDV/MPM5jTXyHCdD1TKDmSR7O3q/HNUeqUvOJVjSd3MclNdLo9SjEdS9/liMX8juk7dxht1GfJ3c4E41upyZtRxmhf7lFEIr
7okpLixqTb0vpUhTRzzHHgb5PI6XiZM4DFLaXw6tj12B9ZFRo/jxpEOUzRtbVYqjbJEhoSq+XkxfId0PAwn+/0EL7/5YxQk9uy69T5nDPOospmt+/6W
8XNjUHPIqGQ1+4s=' ,
9'SecretValueHash':'hhAJ7E7Zn6sfQKvHbm+JiAz/WDPHnFSMmfkEXxkc2Qs=',
10'SecretValueCertificate':’MyActivePECertificate’ })Retrieve a Tenant Secret
Use the GET method to read information about a tenant secret that’s been uploaded to your org.
Retrieve all the available information about your tenant secret by sending a GET command specifying the tenant secret ID.
A tenant secret ID looks like this: u'02G41000000HLXrEAO'
Tip
1sf.TenantSecret.get(tenant_secret_id)All attributes of the tenant secret are returned in a JSON dictionary that looks like this:
1([
2 (u'attributes',
3 OrderedDict([
4 (u'type', u'TenantSecret'),
5 (u'url', u'/services/data/v37.0/sobjects/TenantSecret/02G41000000HLXrEAO')])),
6 (u'Id', u'02G41000000HLXrEAO'),
7 (u'IsDeleted', False),
8 (u'CreatedDate', u'2016-09-09T08:21:50.000+0000'),
9 (u'CreatedById', u'00541000000IQT3AAO'),
10 (u'LastModifiedDate', u'2016-09-09T08:21:50.000+0000'),
11 (u'LastModifiedById', u'00541000000IQT3AAO'),
12 (u'SystemModstamp', u'2016-09-09T08:21:50.000+0000'),
13 (u'Description', None),
14 (u'SecretValue',
15 u'CgMyMDISEPrWDhfoajtUkEKAkO1/bDwaMIqgtRHI0ft+zVbkIzrQBcjZ8XUvgxUvTZiyXnNIIC04iRAyr57R8/DdY8UUZy1MbA=='),
16 (u'Version', 1),
17 (u'Status', u'Active')
18 ])Export a Tenant Secret
Use the GET method to export a tenant secret to a file.
-
Export your tenant secret by sending a GET command specifying the ID of the secret and the secret value, in its encrypted form.
1exportedString = sf.TenantSecret.get(tenant_secret_id)['SecretValue']The secret is written out to a file that looks like this:
1'CgMyMDISEPrWDhfoajtUkEKAkO1/bDwaMIqgtRHI0ft+zVbkIzrQBcjZ8XUvgxUvTZiyXnNIIC04iRAyr57R8/DdY8UUZy1MbA==' -
Save this in case you want to re-import your secret.
1# export encrypted tenant secret to a file 2with open('exported-TenantSecret001.txt', 'wb') as f: 3f.write(exportedString)
Destroy a Tenant Secret
You can use the PATCH method to destroy a tenant secret when you are certain you don’t need it.
(Technically, you can’t really destroy a tenant secret. Instead, you update it with an empty value or change its status.)
After you destroy a tenant secret, related data is not accessible unless you reimport a previously exported secret.
Important
In version 43.0 and earlier, destroy a tenant secret by passing in the SecretValue with an empty string.
1sf.TenantSecret.update(tid, {"SecretValue":""})In version 44.0 and later, destroy a tenant secret by passing in the new Status value instead of a SecretValue.
1sf.TenantSecret.update(tid, {"Status":"Destroyed"})You can change a Salesforce-generated or customer-supplied tenant secret’s Status from Archived to Destroyed or Destroyed to Archived.
In version 44.0 and later, you can change the Status of the most recent version of a cache-only key tenant secret from Destroyed to Active or Active to Destroyed. For example, if you have two versions of a cache-only key tenant secret, you can update version 2 but not version 1.
Note
The secret is destroyed, but its hash is preserved to support validation in case you need to reimport a copy of the secret.
Import a Tenant Secret
You can reimport an HSM or customer-supplied tenant secret that you have exported using the PATCH method. If you use the Cache-Only Key Service, you can reactivate a cache-only key tenant secret instead of importing it.
In API version 43.0 and earlier, import an HSM or customer-supplied tenant secret by passing in the SecretValue with the string you saved when you exported the tenant secret.
1# read exported secret from file
2with open('exported-TenantSecret001.txt',) as f:
3f.read(exportedString)
4
5sf.TenantSecret.update(tenant_secret_id, {"SecretValue":exportedString})In API version 44.0 and later, import an HSM or customer-supplied tenant secret by passing in the new Status along with the SecretValue.
1# read exported secret from file
2with open('exported-TenantSecret001.txt',) as f:
3f.read(exportedString)
4
5sf.TenantSecret.update(tenant_secret_id, {"Status":"Archived", "SecretValue":exportedString})You can’t import cache-only tenant secrets, but you can reactivate them. To reactivate a cache-only key tenant secret, update its Status without referencing the SecretValue.
1sf.TenantSecret.update(tenant_secret_id, {"Status":"Archived"})You can reactivate cache-only tenant secret in versions 44.0 and later.
You can change a Salesforce-generated or customer-supplied tenant secret’s Status from Archived to Destroyed or Destroyed to Archived.
In version 44.0 and later, you can change the Status of the most recent version of a cache-only key tenant secret from Destroyed to Active or Active to Destroyed. For example, if you have two versions of a cache-only key tenant secret, you can update version 2 but not version 1.
Note