No More Worries About Sensitive Data in Boomi:  Secure Handling with Dynamic Encryption and Decryption

No More Worries About Sensitive Data in Boomi: Secure Handling with Dynamic Encryption and Decryption

This article presents a scalable, adaptable approach to encrypt and decrypt sensitive payloads in Boomi processes, ensuring secure data handling while allowing controlled access for authorized troubleshooting.

When Should You Use Dynamic Encryption and Decryption?

When dealing with sensitive data, it’s best to deploy Boomi processes in Bridge Mode or General Mode with Payload Purge enabled. These settings prevent sensitive data from being permanently logged within Boomi’s execution history, adding a layer of security by avoiding any record of sensitive payloads. However, this approach can complicate troubleshooting for support teams, as they lack access to the original payload data for identifying and reproducing issues.

Dynamic encryption and decryption resolve this challenge by logging encrypted payloads to external storage systems like Azure Blob, Log Analytics, or a secure database. Support teams can review these encrypted payloads without compromising data security, as only authorized personnel with decryption keys can view the actual data. This solution meets both security and support requirements.

Challenge with Boomi's Standard PGP Decryption

While Boomi offers native PGP encryption, it has certain limitations that impact security and flexibility::

  • Static Key Limitation: Boomi’s standard PGP decryption requires the decryption key to be configured directly on the Boomi platform. This key cannot be dynamically passed, meaning it is stored within Boomi, making it potentially accessible to any Boomi user with platform access.
  • Security Risk: Boomi does not allow hiding or securing the PGP decryption key within the platform itself, there’s a risk that unauthorized users could gain access to the key and decrypt sensitive information.


1. Solution Overview

In Boomi integrations, certain processes handle sensitive data that must be protected from exposure during both transit and storage. This design presents a solution to dynamically encrypt sensitive data and, when necessary, decrypt it securely for authorized personnel. By implementing this solution, organizations can reduce security risks, meet compliance requirements, and maintain streamlined troubleshooting capabilities.

Gif: Architecture Diagram: This design outlines how Boomi processes interact with Azure for secure data encryption and decryption. Sensitive data is encrypted before being logged or stored, allowing secure troubleshooting access only for authorized personnel.
Solution Architecture: Boomi & Azure Sensitive Payload Encryption

2. Scope of Solution

This encryption and decryption approach is aimed at:

  • Encrypting data payloads for processes handling personally identifiable information (PII) or other sensitive data.

GIF: Boomi PGP Encrypt Process
Boomi Standard PGP Encryption Process

  • Developing a secure decryption API to provide authorized personnel access to decrypt sensitive data when troubleshooting in production.

GIf: Boomi Decryption Process
Boomi Dynamically PGP Decryption Process

3. Where to Apply Encryption in Boomi Process

To ensure sensitive data is securely logged and stored, various use cases have been identified where encryption can be applied in Boomi processes. These methods allow encrypted data to be handled safely across different logging scenarios:

Use Case 1 - Direct Logging

Sensitive data is often logged directly through Notify shapes in Boomi, which can expose it to potential security risks. This use case addresses how to replace direct logging with encrypted logging.

Use Case 2 - Logging Subprocesses

Subprocesses log data to the Boomi Atom queue, storing payloads in server logs. Update existing logging subprocesses to incorporate PGP encryption before queuing payloads.

Use Case 3 - Error Handling with Blob/ Log Analytics/ DB Storage

In error-handling scenarios, sensitive data is often stored in external systems such as Azure Blob Storage, Log Analytics, or databases. This use case focuses on encrypting payloads before storing them externally to safeguard data during troubleshooting

Have Centralized Configuration and Management

To manage encryption across multiple processes, a centralized Boomi Configuration Repository Table (CRT) setup is recommended - Encryption Flags: Toggle encryption for each process via a central CRT. Decision Shape: Use decision shapes to dynamically check the CRT and determine if encryption is required. Centralized Subprocesses: Streamline integration by using common encrypted subprocesses for reusability and easier future updates.

Each of these use cases ensures that sensitive data remains protected across various logging scenarios in Boomi. By implementing encryption at these critical points, organizations can strengthen data security and compliance while maintaining flexibility in troubleshooting processes.


4. PGP Key Management and Storage

Efficient management and storage of encryption keys are crucial:

  • Key Segmentation: Use separate PGP keys for each environment (PROD, PRE-PROD, Non-PROD).
  • Secure Key Storage: Implement secure storage practices, such as Azure Key Vault, for PGP private keys.


5. Decryption Process for Troubleshooting

To support production troubleshooting, a decryption API is designed to securely decrypt data for authorized users:

  • API Design: The API accepts encrypted data, decrypts it using stored private keys, and returns the decrypted payload.
  • Authentication: Secure the API using Azure API Management (APIM) to ensure only authorized personnel can access decryption functionality.


6. Backup Decryption Process

In rare cases where API access may be unavailable, a secondary decryption process using Boomi’s native PGP decrypt capabilities can serve as a backup. However, due to security considerations, this method is reserved for test environments or urgent situations.


7. Summary

This solution aims to balance security, continuity, and availability. Encryption reduces data exposure risks, and backup decryption processes ensure troubleshooting continuity without compromising security standards.

By implementing dynamic encryption and secure decryption in Boomi, organizations can enhance data protection and maintain efficient support capabilities, ultimately aligning with stringent security and compliance requirements.


8. Boomi PGP Decryption Groovy Script

import com.boomi.execution.ExecutionUtil
import java.util.Properties
import java.io.InputStream
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.util.Base64
import java.security.Security
import org.bouncycastle.openpgp.PGPCompressedData
import org.bouncycastle.openpgp.PGPEncryptedDataList
import org.bouncycastle.openpgp.PGPLiteralData
import org.bouncycastle.openpgp.PGPObjectFactory
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData
import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection
import org.bouncycastle.openpgp.PGPUtil
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator

logger = ExecutionUtil.getBaseLogger()

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider())

def getPrivateKey(InputStream privateKeyStream, char[] passphrase) {
    try {
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
            PGPUtil.getDecoderStream(privateKeyStream),
            new JcaKeyFingerprintCalculator()
        )
        PGPSecretKey key = null
        PGPPrivateKey privateKey = null

        Iterator keyRingIter = pgpSec.getKeyRings()
        while (keyRingIter.hasNext()) {
            Iterator keyIter = ((PGPSecretKeyRing) keyRingIter.next()).getSecretKeys()
            while (keyIter.hasNext()) {
                key = (PGPSecretKey) keyIter.next()
                try {
                    privateKey = key.extractPrivateKey(
                        new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(passphrase)
                    )
                    if (privateKey != null) {
                        return privateKey
                    }
                } catch (Exception e) {
                    logger.info("Error extracting private key: ${e.message}")
                }
            }
        }
        throw new IllegalArgumentException("No suitable private key found in the provided key ring.")
    } catch (Exception e) {
        logger.severe("Error in getPrivateKey: ${e.message}")
        throw e
    }
}

def decryptData(byte[] encryptedData, PGPPrivateKey privateKey) {
    try {
        InputStream encryptedStream = PGPUtil.getDecoderStream(new ByteArrayInputStream(encryptedData))
        PGPObjectFactory pgpF = new PGPObjectFactory(encryptedStream, new JcaKeyFingerprintCalculator())
        Object o = pgpF.nextObject()

        if (!(o instanceof PGPEncryptedDataList)) {
            o = pgpF.nextObject()
        }

        if (!(o instanceof PGPEncryptedDataList)) {
            throw new IllegalArgumentException("No encrypted data found.")
        }

        PGPEncryptedDataList encList = (PGPEncryptedDataList) o
        PGPPublicKeyEncryptedData pbe = null

        for (int i = 0; i < encList.size(); i++) {
            pbe = (PGPPublicKeyEncryptedData) encList.get(i)
            if (pbe.getKeyID() == privateKey.getKeyID()) {
                break
            }
        }

        if (pbe == null) {
            throw new IllegalArgumentException("No matching public key encrypted data found.")
        }

        InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(privateKey))
        PGPObjectFactory pgpFact = new PGPObjectFactory(clear, new JcaKeyFingerprintCalculator())
        PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject()
        pgpFact = new PGPObjectFactory(cData.getDataStream(), new JcaKeyFingerprintCalculator())
        PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject()
        InputStream unc = ld.getInputStream()
        ByteArrayOutputStream out = new ByteArrayOutputStream()
        int ch
        while ((ch = unc.read()) >= 0) {
            out.write(ch)
        }
        return out.toByteArray()
    } catch (Exception e) {
        logger.severe("Error in decryptData: ${e.message}")
        throw e
    }
}

for (int i = 0; i < dataContext.getDataCount(); i++) {
    InputStream is = dataContext.getStream(i)
    Properties props = dataContext.getProperties(i)
    byte[] encryptedContent = is.readAllBytes()

    // Retrieve and validate private key and passphrase from properties
    String base64PrivateKey = props.getProperty("document.dynamic.userdefined.DDP_PGP_PrivateKey")
    String passphrase = props.getProperty("document.dynamic.userdefined.DDP_PGP_PassKey")

    try {
        
        logger.info("Decryption - Logic Started")
        
        if (base64PrivateKey == null || base64PrivateKey.trim().isEmpty()) {
            throw new IllegalArgumentException("Private key is missing or empty.")
        }

        if (passphrase == null || passphrase.trim().isEmpty()) {
            throw new IllegalArgumentException("Passkey is missing or empty.")
        }

        // Decode the base64 private key
        byte[] decodedKey = Base64.getDecoder().decode(base64PrivateKey)
        InputStream privateKeyStream = new ByteArrayInputStream(decodedKey)

        logger.info("Decryption - PrivateKey Phrased Started")
        PGPPrivateKey privateKey = getPrivateKey(privateKeyStream, passphrase.toCharArray())
        logger.info("Decryption - PrivateKey Phrased Ended")
        
        logger.info("Decryption - DecryptData Logic Started")
        byte[] decryptedData = decryptData(encryptedContent, privateKey)
        logger.info("Decryption - DecryptData Logic Ended")
        
        InputStream os = new ByteArrayInputStream(decryptedData)
        dataContext.storeStream(os, props)
        logger.info("Decryption - Logic Ended")
        
    } catch (IllegalArgumentException e) {
        logger.severe("Validation error: ${e.message}")
        throw new RuntimeException("Validation error: ${e.message}")
    } catch (Exception e) {
        logger.severe("Decryption failed: ${e.message}")
        throw new RuntimeException("Decryption failed: ${e.message}")
    }
}        

Keywords:

  • How to secure sensitive data in #Boomi
  • Dynamic encryption and decryption for sensitive payloads in #Boomi
  • Encrypt and decrypt sensitive data in #Boomi processes
  • Secure data logging for sensitive information in #Boomi
  • Implement dynamic encryption in #Boomi for data security
  • Protect PII and sensitive data in #Boomi with encryption
  • Using #PGP encryption to secure payloads in #Boomi
  • Secure API integration for data decryption in #Boomi

Hashtags: #Boomi #DellBoomi #DataSecurity #DynamicEncryption #DataEncryption #CloudIntegration #iPaaS #SensitiveData #DataProtection #EncryptionDecryption #SecureIntegrations #BoomiBestPractices #PIIProtection #Compliance #DataPrivacy #AzureIntegration #DevOps #APIs #IntegrationPlatform #PGP #PGPEncryption #PGPDecryption #BoomiCustomScript #PublicPrivateKeys #CloudSecurity #InformationSecurity #DataIntegrity #SecurityCompliance #EncryptionKeys #AccessControl #Troubleshooting #SecureAPIs #DataGovernance #SecureDataHandling

Medium Link ?? https://medium.com/@harish-runku/no-more-worries-about-sensitive-data-in-boomi-secure-handling-with-dynamic-encryption-and-ff6d3a09669c

Rohit Jain

EY| TOGAF?| Certified Scrum Master?| Integration Architect (MuleSoft, Dell Boomi, Dell Boomi MDM, Oracle SOA, IICS)| Apigee| Oracle Certified| Mule Certified| iPaaS

4 个月

Insightful

要查看或添加评论,请登录

Harish Runku的更多文章

社区洞察

其他会员也浏览了