Learn Debezium - Security & Data Privacy
Episode 10 of 23

Learn Debezium - Security & Data Privacy

This episode covers securing database connections with TLS, configuring database authentication and service accounts, payload encryption in Kafka and sensitive data retention, and GDPR/PII compliance and data masking strategies.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Data flowing from a database to Kafka passes through several points that can be intercepted: the network between the connector and the database, the network between the worker and the broker, and Kafka's storage itself. Episode 10 covers how to secure each of those points, while also addressing privacy aspects like PII and GDPR compliance.

The principle you'll hold throughout this episode is simple: never send sensitive data further than necessary, and always encrypt at every hop. Every property discussed has a role in realizing that principle.

Securing Database Connections with TLS

The connection between Debezium and the source database must be encrypted. For MySQL, Debezium supports the following SSL modes:

Enabling TLS to MySQL
{
  "database.ssl.mode": "required",
  "database.ssl.truststore": "/kafka/truststore.jks",
  "database.ssl.truststore.password": "changeme"
}

The available database.ssl.mode values:

  • disabled: no encryption — development only.
  • preferred: encrypts if the server supports it.
  • required: encryption mandatory, without server identity verification.
  • verify_ca and verify_identity: encryption plus certificate verification.

For PostgreSQL, the database.sslmode property uses standard libpq values such as require and verify-full. Prepare a truststore containing the CA inside a volume mounted into the connect container.

Verify that the TLS connection is really active by checking the connector logs: a message mentioning a cipher suite or an encrypted connection indicates TLS is working. Don't just rely on configuration — make sure the actual connection is encrypted.

Combine TLS with the database.ssl.mode setting that matches your trust level in your infrastructure. In environments with an internal CA, verify_identity is the safest choice because it also validates the server hostname.

Database Authentication and Service Accounts

The connector runs with a dedicated identity we created in episode 3. For production, this identity should follow the principle of least privilege and be auditable:

PythonService account with least privilege
CREATE USER 'debezium'@'%' IDENTIFIED BY 'dbz';
GRANT SELECT, RELOAD, SHOW DATABASES,
      REPLICATION SLAVE, REPLICATION CLIENT
  ON *.* TO 'debezium'@'%';

Credentials must not be written in plain text in the configuration. Use environment variables or secrets from a vault that are resolved when the connector is registered:

Credentials via environment
{
  "database.user": "${env:DEBEZIUM_DB_USER}",
  "database.password": "${env:DEBEZIUM_DB_PASSWORD}"
}

With the ${env:...} pattern, passwords never appear in the REST API or connector configuration files.

Encrypting Payloads in Kafka and Retaining Sensitive Data

Data that reaches Kafka also needs to be secured. Recommended layers:

  • TLS on brokers for traffic between workers and Kafka.
  • At-rest encryption on Kafka's storage volumes.
  • Field-level encryption for the most sensitive columns, done before events are written.

Beyond encryption, manage retention: sensitive data shouldn't live in topics forever. Set retention according to your storage policy:

Limiting topic retention
docker exec -it kafka /opt/kafka/bin/kafka-configs.sh \
  --bootstrap-server localhost:9092 \
  --alter --entity-type topics --entity-name dbserver1.inventory.customers \
  --add-config retention.ms=2592000000

With retention.ms: 2592000000 (30 days), personal data isn't stored longer than the policy allows.

GDPR/PII Compliance and Data Masking

GDPR compliance requires personal data to be protected and deletable. Two main Debezium tools for this:

First, column filtering so PII never leaves the database. Second, the MaskField SMT to replace sensitive values with placeholders:

Masking sensitive columns
{
  "transforms": "mask",
  "transforms.mask.type": "org.apache.kafka.connect.transforms.MaskField$Value",
  "transforms.mask.fields": "email,phone_number",
  "transforms.mask.replacement": "***"
}

With MaskField$Value, the email and phone_number columns are replaced with *** in all events, so the original data never leaves the secure zone.

Warning

Masking SMT works on the payload side; it's not encryption. For truly sensitive columns, do field-level encryption and manage decryption keys separately from the pipeline.

Conclusion

Episode 10 completes the security dimension of a CDC pipeline: TLS for database connections, service accounts with least privilege and credentials from secrets, encryption and retention in Kafka, and the combination of filtering and masking for privacy compliance.

The key takeaways:

  • Enable TLS from the connector to the database with required mode or stricter.
  • Use a separate service account with least privilege and credentials from secrets.
  • Encrypt Kafka traffic and storage, then limit sensitive data retention.
  • Filtering and the MaskField SMT prevent PII from leaving the secure zone.
  • Masking isn't a substitute for encryption when it comes to highly sensitive data.

In the next episode, episode 11, we'll discuss connector lifecycle and GitOps — managing connector configuration as code, deploying via GitOps and automation, versioning and rollback, and validating changes before rollout.

Learn Debezium - Security & Data Privacy | Learn Debezium