Skip to content

[kafka_actions] add value_skip_bytes / key_skip_bytes to strip producer-side prefixes#23556

Merged
piochelepiotr merged 3 commits intomasterfrom
piotr.wolski/kafka-actions-skip-bytes
May 4, 2026
Merged

[kafka_actions] add value_skip_bytes / key_skip_bytes to strip producer-side prefixes#23556
piochelepiotr merged 3 commits intomasterfrom
piotr.wolski/kafka-actions-skip-bytes

Conversation

@piochelepiotr
Copy link
Copy Markdown
Contributor

Summary

Adds two new fields on read_messages: value_skip_bytes and key_skip_bytes (both int, default 0). When non-zero, the deserializer drops that many leading bytes from the record before applying any other logic — raw / json / bson / protobuf / avro decoding, and Confluent Schema Registry magic-byte detection.

Motivation

Producers commonly prepend a fixed-size envelope to the payload that kafka_actions's existing format paths don't recognize:

  • a 1-byte version flag (e.g. Datadog's V3 stats payload framing: [0x03][framed-snappy][protobuf])
  • a 4-byte tenant ID prepended for sharded multi-tenant topics
  • a non-Confluent schema-registry envelope (AWS Glue, Apicurio, etc.)
  • an application-level compression marker

When the prefix length is known and constant, stripping N bytes is a one-liner that lets the rest of the record decode cleanly through the existing format paths without adding a per-variant format. For producer-side framings that also compress (e.g. Datadog's V3 with framed Snappy) skip_bytes won't be enough on its own — but it's the natural minimal building block, and a follow-up envelope/decompression knob can layer on top of it.

Behavior

  • skip_bytes is applied before raw / json / bson / protobuf / avro decoding, before Schema Registry magic-byte detection, and before the raw base64 path.
  • skip_bytes < 0 returns <deserialization error: skip_bytes must be non-negative, got N>.
  • skip_bytes > len(message) returns <deserialization error: skip_bytes=N exceeds message length M>.
  • skip_bytes == len(message) returns None (empty after strip).
  • Default 0 is a no-op — the file's existing test suite still passes unchanged.

Test plan

  • 8 new unit tests in tests/test_message_deserializer.py:
    • strips a 1-byte prefix and JSON-decodes the rest
    • skip_bytes=0 is identical to omitting the param
    • works in front of raw format
    • rejects negative values
    • rejects values exceeding message length
    • returns None when skipping the entire message
    • end-to-end through DeserializedMessage with value_skip_bytes set on the value but not the key
    • composes correctly with value_uses_schema_registry=True (skip strips an outer envelope, then SR magic byte is honored)
  • All 35 existing deserializer tests still pass.
  • ddev validate models -s kafka_actions reports models in sync with spec.yaml.

Notes

  • ddev validate config -s kafka_actions reports pre-existing errors on the schema_registry_tls_* fields about require_trusted_provider — these reproduce on clean master and are not introduced by this PR.

…ialization

Adds value_skip_bytes and key_skip_bytes to read_messages config. When
non-zero, the deserializer drops that many bytes from the start of the
record before doing any further work (raw / json / bson / protobuf /
avro decoding, and Confluent Schema Registry magic-byte detection).

Use case: producers commonly prepend a fixed-size envelope to the
payload — a 1-byte version flag, a 4-byte tenant id, a non-Confluent
schema-registry header, an application-level compression marker — that
the integration's existing format paths don't recognize. Stripping a
known fixed prefix lets the rest decode cleanly without adding a new
format-specific code path for every variant.

Default 0 (no bytes skipped); negative values and values exceeding the
message length return clear deserialization errors instead of
truncating silently.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d7201bb55

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 290 to 292
if field_name in info.context['configured_fields']:
value = getattr(validators, f'instance_{info.field_name}', identity)(value, field=field)

if info.field_name in SECURE_FIELD_NAMES:
validation.security.check_field_trusted_provider(
info.field_name, value, info.context.get('security_config')
)
else:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore trusted-provider checks for TLS path fields

The _validate branch for configured fields no longer calls validation.security.check_field_trusted_provider, so schema_registry_tls_ca_cert, schema_registry_tls_cert, schema_registry_tls_key, tls_ca_cert, tls_cert, and tls_private_key are now accepted without trusted-provider enforcement. This is a security regression for remote/fleet-configured instances because untrusted config can again supply local file paths for sensitive TLS material that were previously guarded.

Useful? React with 👍 / 👎.

…ance.py

The previous commit ran ddev validate models with an older ddev (14.3.0)
that doesn't recognize the require_trusted_provider flag in spec.yaml.
The regenerated instance.py dropped both the SECURE_FIELD_NAMES set and
the validation.security.check_field_trusted_provider call from the
field _validate branch, regressing the security enforcement on:
  schema_registry_tls_ca_cert, schema_registry_tls_cert,
  schema_registry_tls_key, tls_ca_cert, tls_cert, tls_private_key.

For remote/fleet-configured instances, untrusted config could again
supply local file paths for sensitive TLS material. Restoring the
SECURE_FIELD_NAMES frozenset and the security check matches what
master's instance.py looked like before this PR.

Spec.yaml already declares require_trusted_provider: true on these
fields; only the generated mirror needed restoring.
Apply ruff format to message_deserializer.py and tests, and add the
changelog entry required by the PR check.
@dd-octo-sts
Copy link
Copy Markdown
Contributor

dd-octo-sts Bot commented May 1, 2026

Validation Report

All 20 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file
ci Validate CI configuration and Codecov settings
codeowners Validate every integration has a CODEOWNERS entry
config Validate default configuration files against spec.yaml
dep Verify dependency pins are consistent and Agent-compatible
http Validate integrations use the HTTP wrapper correctly
imports Validate check imports do not use deprecated modules
integration-style Validate check code style conventions
jmx-metrics Validate JMX metrics definition files and config
labeler Validate PR labeler config matches integration directories
legacy-signature Validate no integration uses the legacy Agent check signature
license-headers Validate Python files have proper license headers
licenses Validate third-party license attribution list
metadata Validate metadata.csv metric definitions
models Validate configuration data models match spec.yaml
openmetrics Validate OpenMetrics integrations disable the metric limit
package Validate Python package metadata and naming
readmes Validate README files have required sections
saved-views Validate saved view JSON file structure and fields
version Validate version consistency between package and changelog

View full run

@codecov
Copy link
Copy Markdown

codecov Bot commented May 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.83%. Comparing base (3fb0c5c) to head (dd2192a).
⚠️ Report is 16 commits behind head on master.

Additional details and impacted files
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@datadog-datadog-prod-us1
Copy link
Copy Markdown
Contributor

Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 78.29% (-8.87%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: dd2192a | Docs | Datadog PR Page | Give us feedback!

@piochelepiotr piochelepiotr added this pull request to the merge queue May 4, 2026
Merged via the queue into master with commit 864138f May 4, 2026
61 of 63 checks passed
@piochelepiotr piochelepiotr deleted the piotr.wolski/kafka-actions-skip-bytes branch May 4, 2026 14:42
@dd-octo-sts dd-octo-sts Bot added this to the 7.79.0 milestone May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants