Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix b5 module digest calculation with transitive dependencies #3631

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

emcfarlane
Copy link
Contributor

@emcfarlane emcfarlane commented Feb 12, 2025

This fixes the b5 digest calculation for remote Modules when a transitive dependency is no longer a dependency in the parents ModuleSet. The digest calculation on Module.Digest would filter dependencies causing a ModuleData to fail tamper-proofing, as it would not filter it's dependencies. The documentation has been reworded to highlight the error case.

The ModuleData's method DeclaredDepModuleKeys has been renamed to DepModuleKeys. This clarifies the difference between declared dependencies, those in the buf.yaml, and the full dependency list, those in the buf.lock. The digest calculation must use the full list of dependencies, not the declared.

This is similar to the fix proposed in #3190 but does not cache the digest calculation in ModuleData for reuse in the Modules digest calculation. A Modules digest will always be calculated locally.

This fixes the B5 digests calculation for remote Modules when a
transitive dependency is no longer a declared dependency in the target
ModuleSet. The digest calculation on Module.Digest would filter declared
dependencies of the remote Module to those of the parents. On creation
of bufmodule.NewModuleData the given getDeclaredDepModuleKeys must
return all direct and transistive dependencies. All declared
dependencies must be used when calculating the digest to ensure the
digests match for the Module and ModuleData.
Remove the term declared from the dependencies in a ModuleData that refer
to the full transitive list of dependencies, those in the buf.lock file.
Declared dependencies are the direct dependencies, those in the buf.yaml
file.
Copy link
Contributor

github-actions bot commented Feb 12, 2025

The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedFeb 18, 2025, 6:10 PM

}
moduleDepFullNames[fullName.String()] = struct{}{}
}
prunedDepModuleKeys := make([]ModuleKey, 0, len(declaredDepModuleKeys))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the fix and the cause of the tamper-proof error. Dependencies should not be filtered to the context of the parent Module. This is required to avoid the Digest for the remote changing when included in a Module. If the parent Module A doesn't include dependency X but the remote module B depends on X, its dependency should still be used in the calculation of the Digest for B.

Comment on lines 155 to 157
// Dependencies are not required to be resolved to a Module to calculate the digest.
// Each dependent ModuleKey is a reference to a specific commit of a module
// that includes the dependencies expected Digest.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment was a little hard for me to parse. Maybe something like this?

The B5 digest is calculated based on the dependencies. We do not need to construct a Module to calculate a digest as we can trust that DepModuleKeys is the complete set of deps for the Module and is exactly the deps that were present in the ModuleSet when this Module was pushed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure trust is correct, as it is always validated if used. What about:

// The B5 digest is calculated based on the dependencies.
// The dependencies are not required to be resolved to a Module to calculate this Digest.
// Each ModuleKey includes the expected Digest which is validated when loading that dependencies ModuleData, if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants