Cómo almacenar información confidencial

Durante estas fechas (Navidades),  es fundamental saber guardar ciertos secretos 😉 .

Saber qué secretos ocultar, a quién y a quién no ocultarlos, y cuanto esfuerzo nos a va suponer ocultarlo. Aparecen varias opciones y así no romper la magia de los más pequeños demasiado pronto.

Sucede de igual manera en Salesforce cuando deseamos almacenar secretos o información confidencial.

Este es el primero, de una serie de artículos en ahondar en cómo almacenar información confidencial en Salesforce, con las variables qué, a quién se lo queremos ocultar (incluso a los administradores), y con qué nivel se lo queremos ocultar.

Con estas variables, analizaré en esta entrada 7 mecanismos distintos, muy distintos entre ellos, que espero cubran la mayoría de los casos de uso que puedan aparecer.

Estos son los mecanismos comentados:

  1. Configuración de OWD+FLS
  2. Encrypted Custom Fields
  3. Named Credentials
  4. Clase Crypto con funciones de encriptación
  5. Protected Custom Settings
  6. Protected Custom Metadata Types
  7. Shield Platform Encryption

…pero, exactamente qué queremos conseguir?

Pues no es una respuesta simple y directa, porque existen numerosos casos de uso, con distintas necesidades, pero me atrevo a generalizar con los siguientes requerimientos:

  1. Ocultar la información para que únicamente pueda ser vista exactamente por ciertas personas. Esto puede incluir, y es aquí donde empiezan los matices, que las puedan ver o no los administradores de nuestra ORG, los developers de nuestra ORG, el soporte de Salesforce, usuarios concretos, etc.
  2. Que el esfuerzo dedicado y su coste de implantación sea conocido previamente (incluyendo la curva de aprendizaje).
  3. Que la definición de las estructuras y el contenido de los secretos puedan ser desplegables en otras instancias.
  4. Que se disponga de ocultación mientras reside en la base de datos (At Rest) y/ó durante la transferencia del navegador ó hacia el navegador ó entre sistemas (In Transit).
  5. Que los secretos puedan ser de diferente tipología, es decir, campos de datos en algunos casos de uso, listas de valores, credenciales de acceso, pero también de documentos y/o ficheros en otros.

Las necesidades y los casos de uso pueden ser diferentes combinaciones de los puntos anteriores, de ahí, que la versatilidad de la plataforma se refleja en sus diferentes mecanismos, que vamos a ver a continuación.

1. Configuración OWD + CRUD/FLS

Consiste en la creación de campos custom en objetos, cuya configuración de acceso está limitada a una configuración muy determinada:

  • OWD en modo Private: de forma que solo los propietarios, ascendentes y co-propietarios ad-hoc pueden acceder al objeto.
  • CRUD/FLS para el campo: no debe configurarse ningún acceso y configurar Not Visible sobre el campo para Profile o Permission Set.

Ventajas e Inconvenientes

  • Realmente lo que estamos haciendo, es mediante mecanismos de control de acceso a datos, esconder la información de los usuarios que no queremos.
  • La información del campo, no está encriptada en la base de datos y es visible a muchos usuarios (co-propietarios, usuarios con permisos como View All Data, Modify All Data, ascendentes en la jerarquía de roles, etc.) y limitarlo supone un reto importante.
  • Se obtiene con poco esfuerzo, ya que son mecanismos de todos conocidos.
  • Está sujeta, a que en un cambio de la configuración de FLS ó OWD realizada por un administrador, este campo pase a ser visible sin darse cuenta.
  • Dado que APEX se ejecuta en modo privilegiado, los desarrolladores pueden acceder a esta información fácilmente, e incluso modificarla. Si además se utilizan clases con without sharing y/o no se llevan a cabo las comprobaciones de CRUD en Apex mediante (Accessible) cuando no utilizamos la notación object.field, el acceso podría realizarse para cualquier usuario que esté ejecutando el código.
  • En caso de que el campo se actualice mediante el uso de una Visualforce page, si no marcamos el campo como transient, su valor será visible en el view state de vuelta, con lo que la información quedará expuesta.

Como vemos no podemos considerar esta opción como una opción fiable cuando queremos almacenar información sensible o secreta, ya que está sujeta a factores externos que pueden variar la configuración inicial y en ningún momento está protegida para usuarios avanzados, pero su mínimo esfuerzo de implantación puede suponer un primer paso inmediato, mientras se valorar alternativas más eficaces.

2. Encrypted Custom Fields

Los Encrypted Custom Fields (en adelante ECF) permiten encriptar los valores que los usuarios introduzcan en él.

Creación de un campo Custom Encriptado

La encriptación que se realizar es mediante AES-128, que podemos considerar suficiente, mediante una clave que podemos importar (generada seguramente por nuestra área de seguridad).

Sus características principales son:

  1. Solo los usuarios con el permiso View Encrypted Data tienen acceso a los valores para lectura.
  2. Se requiere el uso de un campo <apex:outputField> si queremos mostrar el valor en un Visualforce Page.
  3. Existen limitaciones importantes (consultar la documentación para conocerlas todas), pero las más importantes para su uso en mi opinión son:
    1. No puede ser un campo Unique, External Id, ni tener valores por defecto.
    2. Limitado a 175 caracteres.
    3. No disponible en filtros de List Views, Reports, etc., ni se puede usar como criterio en Reports.
    4. Los valores podrían ser editables por cualquier usuario, por lo que es necesario utilizar Validation Rules, FLS , ó restricciones de Layout para evitar modificaciones indeseadas.
Ejemplo de creación de un campo encriptado para el almacenamiento de un número de tarjeta bancaria

Ventajas e Inconvenientes

  1. Su uso es muy simple, y con pocos pasos podemos configurar la encriptación de un nuevo campo, utilizando claves propias y proporcionar una máscara de datos intuitiva para los usuarios.
  2. Dadas sus restricciones, sólo es utilizable en casos muy concretos, de creación de nuevos campos (aunque es posible realizar un proceso de exportación de datos, creación de campo encriptado e importación posterior), con limitación del tipo de dato a 175 caracteres.
  3. Su acceso es mediante el permiso View Encripted Data, lo que limita fácilmente a qué usuarios deseamos proporcionar el acceso (siendo un permiso global, no por objeto 😦 ), pero nuevamente expone a que un administrador fácilmente pueda ampliar esa visibilidad a otros usuarios sin advertirlo.
  4. Solo permite la encriptación At Rest, el valor está encriptado en la base de datos de Salesforce, pero no, si por ejemplo lo exponemos en un Web Service.
  5. Deben conocerse las peeculiaridades de uso, dado que existen situaciones como la copia del valor de un ECF mediante Workflows o mediante Triggers que permiten copiarlos hacia un campo no encriptado, obteniendo acceso así al valor.
Cuando asignamos el permiso View Encrypted Data aparecen los campos encriptados con acceso de escritura

Visualización del registro con un campo encriptado con una máscara de Tarjeta bancaria

Aunque limitados, y para casos de uso concretos, los ECF son el primer acceso a encriptación de datos en la plataforma, y con poco esfuerzo y sin coste adicional, permite a cualquier administrador, encriptar campos que con una correcta gestión de la visibilidad de los  campos, ofrecen una alternativa suficiente y satisfactoria y  para ocultar y encriptar ciertos datos confidenciales.

Aún así, considero que no es adecuado para almacenar información que debemos asegurar  como secreta.

3. Named Credentials

Aunque ya dediqué un artículo describiendo las ventajas del uso de las Named Credentials en Salesforce, creo que es conveniente ampliar sus características en referencia  su capacidad para almacenar información sensible/confidencial para la conexión a un servicio remoto, que es un caso muy común en las integraciones con Salesforce.

Las Named Credentials (en adelante NC) son un mecanismo estándar, destinado a evitar la dispersión de las credenciales de acceso a servicios externos en nuestro código Apex.

Esto mecanismo permite la repetición tanto de la URL destino, como de las credenciales de acceso y de los certificados en el caso que fueran necesario, descargando así a los developers, de toda la gestión.

Además, simplifica el mecanismo de autenticación, ya que implementa ciertos automatismos de autenticación del servicio liberando así al developer de la utilización de cabeceras, en autenticación básica con username/password ó en el protocolo OAuth (estrictamente debería ser OpenId , pero …).

Uso de Named Credentials para almacenar las credenciales de acceso a un servicio remoto

Ventajas e Inconvenientes

  1. Las Named Credentials permiten almacenar credenciales de acceso a servicios, que estarán ocultas tanto developers e incluso a los administradores (las podrá modificar pero no consultar). Por lo tanto, además de conseguir una simplificación del código de autenticación, se minimiza la dispersión de credenciales a servicios.
  2. El password nunca es visible en la interfaz de usuario ni en los Logs, pero si el username y la URL de conexión. Por tanto, dado que el administrador puede modificar la URL destino y el username, podría introducir una URL de un servicio remota maliciosa que obtuviera las credenciales que se han introducido.
  3. En despliegues, solo se transfiere la definición de la NC, no los valores que hayamos definido para la URL, credenciales, certificados, etc. Esto, que puede parecer un inconveniente, no lo es si tenemos en cuenta, que quizás se desea tener una única definición de NC para todos los entornos pero con distintos valores dependiendo del entorno.
    1. Es decir, quizás para acceder a un servicio remoto, utilizamos una NC, que en las Sandbox de Desarrollo, apunta a un endpoint sin coste de suscripción, pero con coste y credenciales distintas para los entornos de PRE y PRO. Esto se consigue con una única definición de 1 única NC.
    2. Por el contrario, podemos requerir NCs diferenciadas(NCDesarrollo, NCProduccion, etc.) para los distintos entornos que tengamos, pero en este caso, nos veremos obligados a incluir más código para identificar en tiempo de ejecución en qué entorno estamos y usar la NC adecuada, o modificar el código dependiendo de en qué entorno estamos.
    3. Por lo que ambas opciones tienes sus PROs y sus CONs, y dependerá de cada caso de uso, como solucionarlo. En cualquier caso, necesitaremos un proceso post-despliegue, para informar de las credenciales.

Las NC son por un mecanismo básico, simple y muy útil para simplificar nuestras comunicaciones con sistemas remotos. Aún así, como vemos no están sujetas a garantizar secretos, ni asegurar modificaciones que puedan sustraer las credenciales, siendo su utilización será beneficiosa para simplificar nuestro código y la gestión de las integraciones, pero no para almacenar credenciales que deban ser completamente confidenciales.

4. Clase Crypto: funciones de encriptación

Salesforce proporciona una clase que permite la encriptación mediante Apex, denominada Crypto.

Las capacidades de la clase incluyen encriptar y desencriptar, pero también la gestión de firmas electrónicas, generación de Hash/Digests, etc. En nuestro caso, nos centramos en las parejas de métodos Encrypt() / Decrypt() ó EncryptWithManagedIv() / DecryptWithManagedIv().

Estas parejas de métodos, solo se diferencian en un aspecto técnico, en qué uno de los valores para generar la encriptación, el denominado (Initialization Vector) es generado por nosotros externamente o indicamos a Salesforce que lo genere mediante una línea de código adicional.

La encriptación/desencriptación se lleva a cabo utilizando una única clave, lo que se denomina, clave simétrica, lo que siendo muy cómodo, requiere de un procedimiento de custodia muy férreo, para asegurar que nuestra clave no ha sido comprometida.

El uso de esta clase es muy sencillo, y lo podemos ver en el siguiente ejemplo que he preparado:

Código de la classe que permite Encriptar y Desencriptar – la variable clave, que contiene la clave generada AES-128 generada por Salesforce, debe ser protegido y custodiado, por lo que debería ser desplegado mediante los mecanismos de Protected Package (Custom Setting o Custom Metadata Type).
Clase de Test donde básicamente encriptamos nuestro secreto e invocamos a ambas funciones.
Log generado donde podemos ver los resultados esperados.

El código está disponible en este Repositorio público.

Ventajas e Inconvenientes

  • Es muy versátil, dado que permite encriptar cualquier contenido que podamos transformar en una cadena de texto en binario 64 como imágenes, documentos, etc.
  • Permite la encriptación At-Rest e In-transit y es compatible con sistemas externos, siempre que comparta la clave para encriptar/desencriptar y se utilice AES como algoritmo.
  • Este mecanismo requiere Apex y conocimiento de gestión de claves en Apex.
  • Si la clave se ve comprometida, un tercero podrá tener acceso a toda la información encriptada, por eso, se requiere un mecanismo seguro de almacenamiento para la clave, como Protected Custom Settings o Protected Custom Metadata Types (que veremos a continuación) y un procedimiento estricto de custodia. Esto amplia los requerimientos para utilizarlo y requiere de un inicialmente no valorado.
  • Cuando lo que se pretende es que varios sistemas intercambien información encriptada con Salesforce con este mecanismo, el estándar de encriptación es AES. En estos casos, el procedimiento de custodia y aseguramiento de que la clave no ha sido comprometida se vuelve tan crucial como complejo.

Como acabamos de ver, requerimos de un “almacenamiento seguro de la clave”, que solo se consigue mediante el uso de Protected Packages, pero, ¿qué son? Veámoslo.

¿Qué es un Package y qué tipos existen?

Todos los mecanismos que hemos visto hasta ahora, padecen de una misma debilidad, de alguna manera u otra, administradores o developers de la ORG pueden acceso, publicarlos sin conocimiento, modificarlos ó sabotearlos.

Por tanto, si queremos garantizar que estos “secretos” mantienen su confidencialidad inalterada, deberemos considerar estos 2 mecanismos:

  • Protected Custom Settings
  • Protected Custom Metadata Types

Ambos mecanismos se basan en la misma idea, utilizar un Managed Package para garantizar la protección de la información.

Los Packages, son contenedores de componentes, facilitando así el concepto de despliegue contenerizado. Por ejemplo: permiten empaquetar Clases Apex, Definición de objetos, Custom Settings, etc., y desplegarlos en otras Sandbox via Change Sets o Metadata API.

Existen 2 tipos de Packages:

  • Unmanaged: permite empaquetar componentes que formaran parte de la ORG donde se instala, como cualquier otro objeto creado anteriormente. Los componentes de este contenedor, ya sea código Apex, objetos, Apps, etc., serán accesibles y modificables por cualquiera que tenga permisos. Un caso de uso típico del uso de este paquete es un despliegue interno entre Sandboxes de un mismo cliente o el despliegue de un proyecto Open Source.
  • Managed: permite la creación de un contenedor en un custom namespace que permite el despliegue en otras ORGs, pero cuyo contenido será ofuscado hasta donde quiera el creador del package. Este mecanismo, permite por ejemplo, desplegar paquetes en App Exchange, actualizables, para que otros usuarios los puedan desplegar en su ORG, pero sin perjudicar la propiedad intelectual del creador (no tienen acceso a nuestro código Apex, si nosotros no lo queremos), ya que no se pueden modificar los componentes si no lo indica el creador.

Y de aquí surge la idea: Si creamos  un Custom Settings o un Custom Metadata Type con la información confidencial y lo empaquetamos dentro de un Managed Package, estaremos blindando su acceso y su modificación.

Veamos pues cada uno de estos 2 mecanismos.

5. Protected Custom Settings

Normalmente, al definir un Custom Setting, casi toda la documentación explica que se parece a un Custom Object, en mi opinión esa definición lleva a confusión, y por eso ofrezco esta alternativa:

  • Custom Setting es un objeto de 2a clase (no se pueden definir Validation Rules, Sharing Rules, etc)  que permite definir un contenedor de campos.
  • Puede ser accedido como un Custom Object, con SOQL, también a través de la notación Object.Field en Visualforce, y también a través de la caché, y mediante este último mecanismo las operaciones no cuentan contra los SOQL Limits.
  • Existen 2 tipos List y Hierarchy: List es equivalente a los registros de cualquier objeto, mientras que Hierarchy, permite definir que si se consulta por Profile o por Usuario específico se devuelva un valor u otro.
  • Permite indicar que su visibilidad es Protected.

Esta última característica es clave, porque cuando combinamos Protected dentro de un Managed Packaged, conseguimos el hermetismo que deseamos para nuestra información confidencial.

La clave en la definición está en definir la visibilidad como Protected

2 características fundamentales del Protected Custom Setting son:

  • Durante el despliegue no se transfieren los valores: esto implica que deberemos proporcionar un script post-instalación o rutina para informar los campos.
  • Permite la actualización después del despliegue del Setting: esto implica que podemos ofrecer este custom setting como el repositorio de información confidencial, que con los permisos adecuados podrá ser actualizado (por ejemplo por el usuario).
Así queda la definición completa de nuestro Custom Setting: en este caso lo utilizamos para almacenar credenciales de conexión por usuario. Podríamos definir cualquier otra estructura, es muy flexible.
Aquí vemos como la definición de un Custom Setting de tipo Hierarchy, permite especificar que valor deberá devolverse en función de es Esteve Graells el que está logado, o si es cualquier otro System Administrator que no sea Esteve Graells o cualquier usuario con Profile Standard Plaftorm User
Vemos la información confidencial, este acceso y visualización NO será posible, cuando despleguemos el Custom Setting dentro de un Managed Package ya que hemos indicado que está PROTECTED.

Ventajas e Inconvenientes

  • Permite una actualización de la información de forma controlada.
  • Solo es accesible a través de Apex dentro del mismo Package, no es posible modificar los valores externamente sin código dispuesto por el creador del paquete (siempre que esté bien configurado).
  • Permite el despliegue mediante Change Sets o API, pero únicamente de la estructura del Custom Setting, no de los valores (en nuestro caso de la información confidencial).
  • Por tanto, se requiere un script post-instalación (via Data Loader por ejemplo) ó permitir la actualización de los valores mediante código.
  • Requiere de la creación de un Managed Package (no es nada complicada su creación) pero así se aumenta el coste de mantenimiento, dado que ahora tenemos un componente adicional que gestionar.

IMHO por fin hemos llegado a un mecanismo que correctamente configurado, nos permite ocultar completamente información confidencial y solo proporcionar el acceso a quienes realmente deseemos. Veremos que el “correctamente configurado” es clave, en la siguiente entrada, pero por ahora, supongamos que lo estamos haciendo bien.

Veamos ahora como los Custom Metadata Types, complementan a los Custom Settings en el almacenamiento y gestión de nuestros “secretos”.

6. Protected Custom Metadata Types

El mecanismo más completo para desplegar valores de configuración son los Custom Metadata Types (en adelante CMT). Además, siguiendo el mismo esquema anterior, al empaquetarlos en un Managed Packaged pasan a ser el mecanismo más completo y seguro.

Los Custom Metadata Types tienen gran parecido a los Custom Objects: la gran diferencia es que un Custom Metadata Type permite el despliegue de registros junto a su estructura, que no es posible con un Custom Object. Se dice que los Custom MEtadata Types son como los tomates, parecen verduras son una fruta.

A diferencia de los Custom Settings permiten el despliegue no solo de las estructuras si no también de sus valores. Además, permiten establecer relaciones con otros objetos y con otros CMT, contiene Validation Rules, etc., ampliando así el abanico de capacidades.

Su definición es muy parecida a la de un Custom Object:

Durante la creación del Package ya indicamos que este nuevo Type solo será visible desde el mismo Package.
Podemos crear campos de diferentes tipos, como ya sabíamos
Especificamos como permitimos la actualización del campo una vez se ha instalado el package, respetando los cambios que haya podido realizar por el usuario (si se lo hemos permitido claro), solo por usuarios con el permission Customize Application o nadie.
Declarado el registro, podemos declararlo como Protected, que tiene varias implicaciones, detalladas a continuación

Podemos ver en las diferentes capturas, como este Type, está completamente preparado para ser empaquetado y además protegido.

Es muy importante tener en cuenta la granularidad de protección que puede ser del Type, de los campos o de los registros, es decir, tenemos 3 niveles. Es decir, podemos No proteger el Type (dejándolo Public), pero proteger registros concretos cuando forman parte de un Managed Package, teniendo ciertas implicaciones:

  • El código Apex dentro del mimo Package podrá leer el registro.
  • El código Apex desde un Unmanaged Package podrá leer el registro.
  • El código Apex desde un Managed Package que no defina este Type, no podrá leer el registro.
  • Solo es posible modificar registros protegidos mediante un package upgrade.
  • Si un Protected Type se modifica para ser público los registros protegidos, permanecen protegidos.

Ventajas e inconvenientes

  • Permiten el despliegue mediante Metadata API de estructuras y valores evitando así scripts post-instalación. Además durante la creación del paquete, podemos seleccionar cuales de los registros del Type formaran parte del Package, y por tanto, no hace falta desplegar todos los registros que hayamos establecido si no es necesario.
  • Capacidad de protección a nivel de componente, a nivel de campo e incluso a nivel de registro. Es decir, los CMT están  totalmente preparados para ser protegidos.
  • Su acceso no supone coste en su consulta, pero también pueden ser accesibles mediante SOQL como cualquier otro objeto.
  • Debemos utilizar un correcto esquema de acceso, porque en caso contrario, es posible que alguien con conocimientos pueda acceder a esos valores (lo veremos en la siguiente entrada) mediante código Apex.
  • Requerimos nuevamente usar un Managed Package, que es un elemento adicional de configuración.

Finalmente, destacar que si optamos por únicamente permitir la actualización de ciertos campos mediante un Upgrade del Package, esto supone un proceso engorroso en caso de necesidad de actualización urgente.

7. Shield Platform Encryption

Shield Platform Encryption (en adelante SPE) es un producto con coste de licencia adicional que proporciona a las compañías las capacidades de encriptación para cumplir con ciertas regulaciones existentes en algunas industrias.

Está formado por 3 áreas:

  1. Event Monitoring
  2. Field Audit Trail
  3. Platform Encryption (siendo esta área la que nos interesa)

Si nos centramos en el área de encriptación, sus principales características son:

  • Permite encriptar ciertos campos estándar de ciertos objetos: Account, Person Account, Contact, Lead, Opportunity, Case, Case Comment, Activity, Contract y List Email (debe comprobarse qué campos están permitidos).
  • Permite encriptar campos Custom (algunas limitaciones aplican).
  • Permite encriptar ficheros y adjuntos.
  • Permite encriptar Chatter (excepto ciertos componentes).
  • Permite encriptar índices de búsqueda.
  • Permite encriptar Change Data Capture Events.
  • Permite aportar la clave de encriptación propia del cliente, y realizar una gestión de su ciclo de vida pudiendo (tener 1 clave activa, otras archivadas y destruidas)
  • Utiliza la encriptación AES-256.

Es decir mediante un mecanismo interno a la plataforma, sin necesidad de programación, podemos conseguir cumplir normativas de encriptación de datos confidenciales.

Dadas sus características y limitaciones, debe estudiarse detalladamente sus implicaciones, pero dado que podemos usarla sin ningún coste en una ORG de developer, podemos realizar tantas pruebas como sean necesarias.

Con SPE activada, la encriptación es simplemente un point-and-click, liberándonos de operaciones de encriptación ni conocimientos específicos
Ejemplo de como encriptar un campo Custom en un objeto Custom
SPE permite la gestión de claves, para importar nuestras propias claves y renovarlas o cambiarlas según marque nuestro procedimiento de Seguridad de la Información

Conclusiones

Como hemos visto, y este era mi objetivo, existen diversas formas de ocultar la información, y todas responden a ciertos casos de uso mejor que otras.

En los casos de uso más ambiciosos, deberemos optar por Custom Metadata Types o Hierarchy Custom Settings o la utilización de la Shield Encryption Platform.

Las 2 soluciones estándar, requieren la creación de un Managed Packaged, con un incremento de la deuda técnica, para configurar y gestionar ese paquete, pero el esfuerzo vale la pena.

En contados casos de uso deberíamos optar por el uso de Custom Objects o Custom Settings de tipo List, ya que sus capacidades son inferiores y no están preparados para ser empaquetados en paquetes como los CMT.

De forma recurrente en esta entrada he mencionado la “configuración de forma correcta” de un Custom Setting o un Custom Metadata Type. Y será en el siguiente entrada, donde te mostraré el patrón de diseño y el proceso completo de creación, configuración y despliegue de un Protected Custom Metadata Type.

Finalmente, debemos estar atentos a como los Locked Packages en la 2nd Generation Packaging de Salesforce DX, afectará al empaquetado de información confidencial, aunque creo que el concepto general será el mismo, empaquetar un Custom Metadata Type pero en lugar de con el clásico Managed Packaged, con el reciente Locked Package.

Espero que te sea de ayuda, y recuerda que desvelar secretos navideños implica desvanecer una magia especial 🙂 .

Enlaces interesantes

    1. Storing Sensitive Data
    2. Trailhead Module: Secure Secret Storage
    3. Storing secrets or passwords using manage package in Salesforce
    4. Tighten Your Security with Salesforce Shield Platform Encryption
    5. Video – Secure Coding: Storing Secrets in Your Salesforce Instance
    6. Video – Encrypt Sensitive Data while Preserving Platform Functionality
    7. Video – Secure Development on the Salesforce Platform – Part 3
    8. Secure Secret Storage on the Salesforce Platform
    9. Using the Apex Crypto Class
    10. Package Custom Metadata Types and Records
    11. How to Package Custom Metadata Types
    12. Trailhead: Package Custom Metadata Types
    13. Trailhead: Shield Plaftorm Encryption
    14. Strengthen Your Data’s Security with Shield Platform Encryption

La imagen de portada es gentileza de Freepik.