Proteger secretos con las funciones de la plataforma
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Enumerar las opciones y prácticas recomendadas para almacenar secretos dentro de paquetes gestionados
- Crear credenciales con nombre para definir de manera segura extremos de llamada y sus parámetros de autenticación asociados.
- Describir la forma en que se pueden aprovechar la configuración personalizada protegida y los campos de API de metadatos para almacenar secretos.
Almacenar secretos de aplicaciones en Salesforce
En la unidad anterior, aprendimos cómo identificar secretos y quiénes deberían tener acceso a ellos. El siguiente paso es aprender a protegerlos.
Esta plataforma de Salesforce Platform tiene una gran variedad de funciones que pueden emplearse para almacenar y proteger secretos, incluidas las siguientes:
- Credenciales con nombre
- La configuración personalizada (protegida, desprotegida, no gestionada y gestionada)
- Tipos de metadatos personalizados
En esta unidad, aprendió sobre cada una de estas opciones para almacenar secretos con el fin de garantizar que la información confidencial se restrinja de forma apropiada.
Credenciales con nombre
Las credenciales con nombre son un mecanismo para gestionar de forma segura los valores de autenticación de los servicios y proveedores externos. Proporcionan procesos de implementación de autenticación estándar en un conjunto de entidades seguras y gestionables. Salesforce gestiona toda la autenticación para las llamadas de Apex que especifican una credencial con nombre como extremo de llamada y no tiene que agregar más lógica de autenticación a su código Apex. Es posible definir credenciales con nombre para proporcionar una forma segura y cómoda de configurar estos tipos de llamadas. Una vez creadas, es posible sustituir las referencias codificadas de URL de su código por referencias a credenciales con nombre, lo que generaría un código más limpio, sencillo y seguro.
Las credenciales con nombre son útiles en el momento de definir extremos de llamada a los que se hace referencia en el paquete gestionado. Sin ellas, para configurar una llamada autenticada, el desarrollador tiene que realizar estas tareas adicionales.
- Hacer referencia a la URL como el extremo de llamada
- Registrar la URL en su configuración de sitio remoto
- Incorporar código personalizado para que se encargue de todas las tareas de autenticación asociadas
Por ejemplo, digamos que tiene una aplicación que conecta de forma habitual con un servicio externo para extraer datos. Sin embargo, este servicio externo requiere que cada solicitud incluya una clave de API para la autenticación. Un método común que desarrolladores usan para cumplir con este requisito es incluir esa clave en el código fuente para que se pueda utilizar en cada solicitud. Considere el siguiente ejemplo.
String key = ’supersecurepassword’; HttpRequest req = new HttpRequest(); req.setEndpoint(’https://www.example.com/test?APIKEY=’+key); req.setMethod(’GET’); Http http = new Http(); HTTPResponse res = http.send(req); return res.getBody();
Si bien incluir los secretos en el código es una solución directa, este enfoque presenta tres problemas principales.
- Cualquiera que pueda ver el código fuente puede ver también los secretos incrustados.
- Si se actualiza un secreto, tendrá que cambiar cada instancia de éste en todo el código fuente.
- Portar este secreto entre aplicaciones puede crear muchas otras complicaciones.
¡Aquí es donde las credenciales con nombre pueden aportarnos la solución! En lugar de incluir el valor en el código, puede utilizar credenciales con nombre para almacenar secretos. Puede acudir a la credencial con nombre para acceder al valor secreto como si se tratara de cualquier otra variable en el código.
Beneficios de las credenciales con nombre
Además de proporcionar un método para restringir el acceso a los secretos de sus aplicaciones, las credenciales con nombre también facilitan mucho el mantenimiento de estos secretos. Tras configurar una credencial con nombre, puede cambiarla con facilidad siempre que sea necesario si modifica la configuración. Cualquier instancia del código que haga referencia al secreto siempre retendrá valores actualizados, ya que hacen referencia directamente a la credencial con nombre.
Dónde usar las credenciales con nombre
Aunque es bastante sencillo establecer credenciales con nombre, no son necesariamente una buena solución para cada caso práctico. Son óptimas para protocolos de autenticación estándar como un nombre de usuario y una contraseña, OAuth 2.0, la firma de AWS versión 4 y los JWT firmados.
Las credenciales con nombre se diseñaron para hacer la vida de los administradores y desarrolladores fácil y segura en su organización. Dicho esto, no siempre son la mejor elección. Debido a que los usuarios con el permiso Modifiy All Data (Modificar todos los datos) o Author Apex (Apex de autor) pueden modificar la credencial con nombre o realizar llamadas a esta, también pueden acceder a los datos que protege la credencial con nombre. O bien, pueden extraer las credenciales por su cuenta. Si necesita protección contra estos casos de uso (por ejemplo, si es un proveedor de software independiente que está creando un paquete y necesita hablar de forma privada con sus servicios de nube), considere otras opciones como la configuración personalizada protegida gestionada o los tipos de metadatos personalizados protegidos gestionados. En la siguiente sección, puede leer más sobre esas opciones.
Funcionalidad de nuevo nombre/credencial externa
La funcionalidad de nuevo nombre/credencial externa en Salesforce está diseñada para mejorar la seguridad y optimizar las integraciones externas. Las credenciales externas representan los detalles de cómo Salesforce se autentica en un sistema externo mediante un protocolo de autenticación, lo que genera una vinculación a conjuntos de permisos, perfiles y encabezados personalizados opcionales. Los usuarios con los permisos necesarios pueden ver, crear, modificar y eliminar credenciales externas.
Las credenciales con nombre funcionan como conexiones lógicas a sistemas externos, lo cual elimina la necesidad de incluir URL físicas en código Apex y de gestionar tokens de autenticación en tiendas de datos sin cifrar. Especifican la URL de un extremo de llamada y sus parámetros de autenticación requeridos en una definición. Las credenciales con nombre son compatibles con tipos diferentes, que incluyen SecuredEndpoint, PrivateEndpoint y Legacy (obsoleto).
La interacción entre las credenciales con nombre y las credenciales externas involucra la creación de una credencial externa en primer lugar, que especifique el protocolo de autenticación y el perfil o conjunto de permisos. Luego, se crea una credencial con nombre, que sirve como el extremo de llamada de los servicios externos. Los detalles de autenticación de la credencial externa están vinculados con la credencial con nombre, lo que permite realizar llamadas autenticadas seguras.
Los conjuntos de permisos cumplen una función fundamental en el control del acceso a servicios externos. Las credenciales externas autentican usuarios, mientras que los conjuntos de permisos autorizan a usuarios. Los rectores en credenciales externas se asignan a permisos de usuario, lo que asegura que los usuarios cuenten con la autorización necesaria antes de acceder a sistemas remotos. Las credenciales externas de usuario almacenan tokens cifrados, lo que ofrece una forma segura de gestionar la autenticación específica de usuarios.
Los encabezados personalizados se pueden agregar a credenciales con nombre y a credenciales externas, lo que permite que las llamadas de Salesforce a sistemas remotos incluyan los parámetros personalizados necesarios para responder a las solicitudes. Esta personalización mejora la flexibilidad y abarca varios casos de uso y requisitos de seguridad.
La plataforma de Salesforce recomienda crear y modificar credenciales externas y con nombre mediante la interfaz de usuario de Salesforce, aunque también es posible mediante API de REST de metadatos, herramientas y conexión. En general, la funcionalidad de credenciales externas/con nombre ofrece un enfoque sólido y personalizable para gestionar integraciones externas seguras y autenticadas.
Asegurar secretos distribuidos
Las credenciales con nombre son perfectas para llamadas a servicios externos en una organización en que los administradores pueden acceder a los secretos de autenticación asociados. Sin embargo, ¿qué hacer cuando tiene que evitar que los administradores vean los datos o cuando desea distribuir secretos entre múltiples organizaciones de Salesforce?
En situaciones como esta, el código debe implementarse como un paquete gestionado. Puede iniciar de forma gratuita una organización de Developer Edition que le servirá como organización de empaquetado para su código. Si es socio de AppExchange, puede crear organizaciones de Developer Edition a través de su núcleo de entorno. También puede visitar la página de inscripción en Developer Edition. Dentro de su organización de empaquetado, puede incluir clases de Apex, desencadenadores de Apex, objetos de Salesforce y otras formas comunes de metadatos en un paquete gestionado, lo que permite su sencilla implementación en cualquier otra instancia u organización de Salesforce. Puede considerar un paquete gestionado como una versión más compleja de un archivo Zip.
Desde la perspectiva de la seguridad, los paquetes gestionados (en contraposición a los paquetes no gestionados o el código suelto) aportan muchos beneficios significativos.
- Los paquetes gestionados tienen la mecánica para distribuir parches, correcciones y actualizaciones automáticas si se identifican vulnerabilidades de seguridad.
- Tienen un código fuente oculto (a excepción de las clases de Apex globales expuestas de forma explícita), lo que significa que ninguna lógica de negocio o programa fundamental puede alterarse de forma inadvertida ni modificarse de manera malintencionada y redistribuirse. El código opaco también evita que los secretos que contiene el paquete sean vistos.
- Debido a que debe definir un espacio de nombres exclusivo para su paquete gestionado, evita problemas de espacios de nombres en conflicto. También separa su paquete del espacio de nombres local, lo cual protege aún más los secretos que contiene el paquete. De manera predeterminada, no es posible acceder a los secretos de paquetes mediante código que se ejecute fuera del paquete gestionado.
Gestionar configuraciones personalizadas y tipos de metadatos personalizados protegidos
Aunque solo empaquetando su código en un paquete gestionado tiene gran número de beneficios de seguridad, el uso de un paquete gestionado también ofrece acceso a otras dos funciones disponibles para almacenar y distribuir información: la configuración personalizada protegida y los metadatos personalizados protegidos.
Se puede crear una configuración personalizada para almacenar casi cualquier tipo de datos. Es una opción extremadamente flexible en términos de usos y contenido potenciales. En resumen, la configuración personalizada le permite crear conjuntos de datos personalizados que quedan expuestos a la caché de aplicaciones, de modo que evita realizar consultas repetidas a la base de datos y aumenta la eficiencia de su aplicación. Por ejemplo, una configuración personalizada puede utilizarse para almacenar un conjunto de datos que se utilice para personalizar experiencias de usuarios con una aplicación. O bien, se puede crear una configuración personalizada para almacenar una lista de nombres de productos a los que se haga referencia en muchas páginas con el fin de proporcionar un acceso rápido y sencillo. En lo referente a la seguridad de las aplicaciones, la configuración personalizada puede emplearse para almacenar información confidencial o secretos.
La configuración personalizada puede tener diferentes niveles de visibilidad. Una configuración personalizada protegida contenida en un paquete gestionado no es visible a las organizaciones suscriptoras a través de Apex o la API, lo que la convierte en un buen lugar para almacenar ciertos tipos de secretos. Una configuración personalizada establecida para la visibilidad pública o incluida en un paquete no gestionado es visible a través del lenguaje de descripción de servicios web (WSDL) para compañías. Por lo tanto, es importante encapsular la configuración personalizada en un paquete gestionado si esta aloja información confidencial.
Los campos de metadatos personalizados pueden utilizarse para el almacenamiento de secretos de forma parecida a la configuración personalizada. Para una confidencialidad adecuada, establezca su visibilidad como Protected (Protegida) e inclúyalos en un paquete gestionado. Los campos de API de metadatos personalizados son una excelente elección para almacenar claves de API u otras claves de secretos, por ejemplo.
En referencia a la configuración de la visibilidad, tanto la configuración personalizada como los campos de metadatos tienen varias opciones.
- Pública (local)
- Protegida (local)
- Pública (gestionada)
- Protegida (gestionada)
Mientras las primeras tres opciones son viables para almacenar datos en general, todas las personas en la organización pueden ver valores de datos cuando utilizan estos parámetros. Utilícelos únicamente cuando esté almacenando datos accesibles de forma pública. Para los datos confidenciales, como los secretos de aplicaciones, utilice la opción de configuración de protección gestionada.
La opción de visibilidad opaca, la facilidad de acceso y las funciones de caché hacen que la configuración personalizada y los campos de metadatos sean opciones viables y atractivas para el almacenamiento de secretos.
Crear una configuración personalizada protegida gestionada
Puede crear una configuración personalizada protegida gestionada denominada Secretos de distrito que se pueda utilizar para almacenar secretos de manera segura. Para crear una configuración personalizada protegida en Setup (Configuración), diríjase a Quick Find (Búsqueda rápida), Custom Settings (Configuración personalizada) y haga clic en New (Nuevo). Defina una etiqueta, el nombre de objeto, el tipo de configuración y la visibilidad (establezca esta última en Protegida). Una vez haga clic en Guardar, estará listo para agregar campos personalizados para almacenar los secretos.
Finalmente, ingrese sus secretos dentro de sus campos personalizados protegidos. Debido a que solo se incluyen en el paquete las definiciones de la configuración, necesita una secuencia de comandos Apex o API para rellenar los secretos una vez que se instale el paquete en la organización de destino o suscriptor.
Cómo utilizar la configuración personalizada protegida gestionada
Puede hacer referencia a la configuración personalizada de la misma forma que emplea para hacer referencia a objetos personalizados. Para acceder a la configuración personalizada, puede utilizar campos de fórmula, métodos de configuración personalizada de Apex, la API de SOAP, reglas de validación, etcétera. Las referencias a la configuración personalizada protegida solo pueden realizarse desde el mismo paquete gestionado, es decir, el mismo espacio de nombres. Algunos métodos de Apex comunes para hacer referencia a configuraciones personalizadas son:
-
getInstance()
-
getInstance(userId)
-
getInstance(profileId)
-
getOrgDefaults()
-
getValues(userId)
-
getValues(profileId)
A continuación, se muestra un ejemplo en que se utiliza getInstance()
para acceder a los secretos almacenados como un componente de configuración personalizada.
CustomSettingName__c cmcs=CustomSettingName__c.getInstance();
Tipos de metadatos personalizados
También se pueden definir tipos de metadatos personalizados protegidos para albergar secretos de modo similar a cómo se puede definir una configuración personalizada. Los tipos de metadatos personalizados se deben diseñar para su inclusión en un paquete gestionado a fin de poder ocultarlos y protegerlos de forma eficiente. La diferencia principal es que los datos contenidos en tipos de metadatos personalizados representan los metadatos de su aplicación.
A menudo, esto representa una ventaja. Imagine que usted es un desarrollador que está creando una nueva aplicación en su organización de empaquetado de Developer Edition. Esta aplicación tiene muchas funciones interesantes, que incluyen una integración de API externa con ejemplo.com. Para realizar llamadas a example.com, necesita almacenar una clave de API en algún lugar. Una opción es almacenar la clave secreta de API dentro de un campo personalizado. Esto funciona bien dentro de su propia organización de DE, pero hay un problema con este enfoque.
Además de ser una solución poco segura, existe un problema con el almacenamiento de la clave secreta de API dentro de un campo personalizado cuando se trata de una reimplementación. Cuando intenta trasladar todo el código y personalizaciones a la organización de producción, el valor de la clave secreta no se distribuye de forma simultánea. Los datos no se transfieren a producción junto con el conjunto de cambios. Tiene que insertar el valor de la clave en el campo de forma manual o redactar una secuencia de comandos para que lo complete por usted. Por otro lado, con un tipo de metadatos personalizados, la clave secreta de API se trata como cualquier otra personalización y se traslada a producción. En esta situación, no necesita insertarla de nuevo usted mismo.
Recuerde que, para cargar datos en una configuración personalizada, debe redactar una secuencia de comandos posterior a la instalación. Pero no tiene que escribir secuencias de comandos con los tipos de metadatos personalizados protegidos. Los datos que contiene un tipo de metadatos personalizados están disponibles como metadatos separados, que puede incorporar al paquete. Eso no está nada mal, ¿verdad?
Uno de los aspectos más interesantes sobre los tipos de metadatos personalizados es que se pueden captar mediante SOQL, tal como ocurre con cualquier objeto personalizado. La única diferencia es que los tipos de metadatos tienen un sufijo __mdt
, en vez de __c
. Si necesita seleccionar un tipo de metadatos personalizados, escriba una consulta de la siguiente manera:
SELECT Teacher__c, Coach__c, Counselor__c , Administrator__c FROM District_Profiles__mdt
Esta línea recupera todos los valores de District_Profiles__mdt
. ¡Eso es bastante fácil!
Comparación de configuraciones personalizadas y tipos de metadatos personalizados
Aunque puede utilizar configuraciones personalizadas o tipos de metadatos personalizados para asegurar secretos, existen algunas diferencias entre los dos que merece la pena mencionar. Repasemos cuándo usar cada uno.
Utilice configuraciones personalizadas protegidas cuando:
- Sea necesario actualizar el secreto con frecuencia y deba estar disponible de inmediato. Como los tipos de metadatos deben colocarse en cola e implementarse, los secretos actualizados en los tipos de metadatos no se encuentran disponibles al instante. En este caso, la configuración personalizada es una mejor opción.
- Desee especificar qué perfiles y usuarios pueden acceder a qué secretos. Los tipos de metadatos no ofrecen la granularidad de los tipos de jerarquías de configuración personalizada, en los que se puede especificar para qué perfiles o usuarios deben estar disponibles los secretos. Por ello, es mejor utilizar aquí una configuración personalizada.
Utilice los tipos de metadatos personalizados cuando:
- Desee implementar un secreto común sin tener que realizar pasos de configuración adicionales.
- Los secretos de metadatos personalizados pueden migrarse con facilidad, por ejemplo, desde un entorno aislado o de desarrollo hacia un entorno de producción. En cambio, en las configuraciones personalizadas, los administradores deben redactar secuencias de comandos posteriores a la instalación o crear páginas, ingresar de forma manual los secretos y almacenarlos en el nuevo entorno.
Recursos
-
Blog de desarrolladores de Salesforce: Guía del desarrollador de Apex: Named Credentials as Callout Endpoints
-
Blog de desarrolladores de Salesforce: Cómo usar los tipos de metadatos personalizados para guardar años de desarrollo en configuraciones de aplicaciones
-
Blog de desarrolladores de Salesforce: Guía del desarrollador de Apex: Custom Settings Methods
-
Ayuda de Salesforce: Definir configuraciones personalizadas