Skip to content

Use versioned wheelsmith prefix for downloader v2 targets#23937

Open
dkirov-dd wants to merge 9 commits into
masterfrom
dk/harden-downloader-v2-delegations
Open

Use versioned wheelsmith prefix for downloader v2 targets#23937
dkirov-dd wants to merge 9 commits into
masterfrom
dk/harden-downloader-v2-delegations

Conversation

@dkirov-dd
Copy link
Copy Markdown
Contributor

@dkirov-dd dkirov-dd commented Jun 5, 2026

What does this PR do?

Hardens the v2 TUF pointer downloader (datadog_checks_downloader.download_v2) and aligns its target lookups with the TUF-on-CI storage-path contract:

  • Updates v2 pointer target resolution from <package>/<version>.json to wheelsmith/v1/<package>/<version>.json (and wheelsmith/v1/<package>/latest.json). The wheelsmith/ prefix is the client/publisher storage namespace required by the delegated target layout, and v1/ versions the pointer-file contract.
  • Documents the contract boundary: the downloader and publisher must agree on target paths and pointer schema, while TUF metadata remains free to change which delegation signs those stable paths.
  • Tightens _validate_pointer to reject obvious wheel_path attacks (//-scheme bypass, .. segments, non-canonical paths) and to enforce the expected types/shapes for digest (64-char lowercase hex) and length (non-negative int, not bool).
  • Adds TestUpdaterContract asserting Updater.get_targetinfo is called with the stable wheelsmith/v1/<package>/<version>.json path alone — no role kwarg is passed to the TUF client.
  • Adds TestDelegationTraversal, an end-to-end test that stands up a real signed v2-style TUF repository with a wheelsmith delegated targets role over a local HTTP server and verifies get_pointer resolves through both paths and path_hash_prefixes delegations.
  • Extends TestMalformedPointer with path-traversal / scheme-bypass cases, digest/length type and shape checks, a zero-length-wheel happy path, and a forward-compatibility test for unknown pointer keys.

Motivation

TUF-on-CI expects the first top-level directory under targets/ to correspond to the delegated target namespace. For the downloader and publisher pipeline, that means the stable v2 pointer target path is now:

wheelsmith/v1/<package>/<version-or-latest>.json

That path has two explicit layers:

  • wheelsmith/: the TUF-on-CI storage/delegation namespace.
  • v1/: the pointer-file contract version.

As long as this path remains stable, the repository can later replace the planned single delegation with hash-bin delegations, nested delegations, or another compatible topology without changing the downloader: tuf.ngclient.Updater.get_targetinfo(path) walks the TUF delegation metadata for that path.

By contrast, changes to the target path or pointer JSON schema are downloader-facing contract changes and require either a downloader update or compatibility aliases/fields. This PR makes that boundary explicit and adds tests that lock in the expected behavior.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Add qa/required if this PR needs QA validation, or qa/skip-qa if it does not. Exactly one of the two is required. (qa/skip-qa: behavior is covered by unit/integration-style local TUF tests and affects repository path/validation logic, not a manually QA-able integration behavior.)
  • If you need to backport this PR to another branch, you can add the backport/<branch-name> label to the PR and it will automatically open a backport PR once this one is merged

dkirov-dd added 2 commits June 5, 2026 13:18
…n pointer validation

The v2 TUF pointer downloader already routes every target lookup through
`Updater.get_targetinfo(target_path)`, so python-tuf walks delegations on
its own based on the `paths` or `path_hash_prefixes` declared in the
parent Targets metadata. There is no need for the downloader to know any
delegated-role name. Make that contract explicit and lock it in with tests
so it can't regress when the production repository's delegation layout
evolves.

Implementation:
- Document the delegation-agnostic design at the module level.
- Tighten `_validate_pointer` to reject obvious wheel_path attacks (`//`
  scheme bypass, `..` segments, non-canonical paths) and enforce the
  expected types and shapes for `digest` (64-char lowercase hex) and
  `length` (non-negative int, not bool).

Tests:
- Add `TestUpdaterContract` asserting `get_targetinfo` is called with the
  target path alone (no role kwarg, no role-prefixed path).
- Add `TestDelegationTraversal` that stands up a real signed v2-style
  TUF repository with one delegated targets role (over a local HTTP
  server) and verifies `get_pointer` resolves through both `paths` and
  `path_hash_prefixes` delegations without the downloader naming the
  role. Also verifies unmatched paths surface as `TargetNotFoundError`.
- Extend `TestMalformedPointer` with path-traversal/scheme-bypass cases,
  digest/length type and shape checks, a zero-length-wheel happy path,
  and a forward-compatibility test for unknown pointer keys.
@dkirov-dd dkirov-dd added the qa/skip-qa Automatically skip this PR for the next QA label Jun 5, 2026
@datadog-official
Copy link
Copy Markdown
Contributor

datadog-official Bot commented Jun 5, 2026

Tests  Code Coverage

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 98.94%
Overall Coverage: 86.80% (-0.74%)

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

⚠️ Major version bump
The changelog type changed or removed was used in this Pull Request, so the next release will bump major version. Please make sure this is a breaking change, or use the fixed or added type instead.

@dkirov-dd dkirov-dd changed the title Harden datadog_checks_downloader v2 tests and lock in delegation-agnostic contract Use integrations prefix for datadog_checks_downloader v2 targets Jun 5, 2026
@dkirov-dd dkirov-dd changed the title Use integrations prefix for datadog_checks_downloader v2 targets Use versioned integrations prefix for downloader v2 targets Jun 5, 2026
@dkirov-dd dkirov-dd marked this pull request as ready for review June 5, 2026 16:14
@dkirov-dd dkirov-dd requested a review from a team as a code owner June 5, 2026 16:14
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: 6df9147cff

ℹ️ 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".

SPEC_VERSION = '1.0.31'
EXPIRY = datetime(2099, 1, 1, tzinfo=timezone.utc)
TOP_LEVEL_ROLES = ('root', 'targets', 'snapshot', 'timestamp')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add type hints to new helper signatures

The repository instructions in /workspace/integrations-core/AGENTS.md require newly generated Python code to add type hints to methods/functions. This new helper is unannotated, and the same applies to other new helpers such as serve_directory, so the new test support code violates the documented standard; please annotate the parameters and return types before merging.

Useful? React with 👍 / 👎.

@dkirov-dd dkirov-dd changed the title Use versioned integrations prefix for downloader v2 targets Use versioned wheelsmith prefix for downloader v2 targets Jun 5, 2026
@dd-octo-sts
Copy link
Copy Markdown
Contributor

dd-octo-sts Bot commented Jun 5, 2026

Validation Report

All 21 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file
ci Validate CI configuration and code coverage 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
qa-label Validate the pull request declares whether it needs QA for the next Agent release
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

downloader qa/skip-qa Automatically skip this PR for the next QA team/agent-integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant