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

Introduce plugin keyless verification #2159

Merged
merged 2 commits into from
Dec 8, 2024
Merged

Conversation

wata727
Copy link
Member

@wata727 wata727 commented Nov 10, 2024

Fixes #1351
Closes #1902

TFLint has a mechanism to verify that plugins installed with tflint --init have not been tampered with by a malicious actor. Previously, the only way to do this was for plugin developers to sign the checksum files of their plugin binaries with their PGP key.

However, this approach has some problems: First, the plugin developer needs to manage their own PGP key, second, they need to consider how to distribute the public key.

To solve the problems, this PR introduces keyless verification as a new plugin verification mechanism. For the basic idea of ​​keyless verification see below:

The core technologies adopted here are Artifact Attestations and sigstore-go. Artifact attestation is a new feature published by GitHub that stores and distributes Sigstore bundle containing Fulcio-issued certificates and transparency logs corresponding to artifacts (checksum files for plugin binaries). The sigstore-go is a client library that provides policy-based verification of Sigstore bundles and is already adopted by gh attestation verify.

Keyless verification ensures that the artifact was built by the GitHub Actions workflow for that repository. More specifically, it verifies that the SAN of the Fulcio-issued certificate matches the prefix of the plugin's source attribute. It is important to note that this approach differs from traditional ones in that it does not rely on trusting the signer. In this respect, it is weaker than the PGP approach, since an attacker could release a valid plugin simply by taking control of the repository.

This feature is introduced as an experimental feature, in other words, TFLint will only try to verify a plugin by artifact attestations if it is not signed with a PGP key. This means that official plugins (e.g. tflint-ruleset-aws), or that are already signed with a PGP key are not affected by this change. Even if there is no artifact attestation, there will be no error but just a warning "Plugin not verified" as before.

Here's a flowchart to help you understand if you're affected by this change:

flowchart TD
  q1{"Is it official plugin? (e.g. tflint-ruleset-aws)"} --->|Yes| na(Not Affected)
  q1 --->|No| q2
  q2{"Is it already signed with a PGP key?"} --->|Yes| na
  q2 --->|No| q3
  q3{"Does the repository have artifact attestation?"} --->|No| na
  q3 --->|Yes| a(Affected)
Loading

Third-party plugin developers can immediately benefit from this feature by simply adding actions/attest-build-provenance to their GitHub Actions release workflow. Please refer to terraform-linters/tflint-ruleset-template#103 as an example PR. If you have already created a plugin from the latest template repository, make sure the repository has artifact attestations.

In the future, I plan to remove the built-in PGP key and migrate to this mechanism for official plugins. To test this behavior, this PR introduces a new TFLINT_EXPERIMENTAL environment variable. Running TFLint with TFLINT_EXPERIMENTAL=true will ignore the built-in keys for official plugins and use artifact attestations for verification, and will error out installation of third-party plugins that are not verified by PGP keys or artifact attestations. This way is inspired by COSIGN_EXPERIMENTAL. I also considered adding the new option to the plugin block instead of an environment variable, but I wasn't sure if we would still need it, so I went with this approach.

@wata727 wata727 force-pushed the plugin_keyless_verify branch 2 times, most recently from 308ee5c to 026a3be Compare November 17, 2024 16:59
@wata727 wata727 force-pushed the plugin_keyless_verify branch 4 times, most recently from cde6f60 to a7de118 Compare November 24, 2024 13:23
@wata727 wata727 force-pushed the plugin_keyless_verify branch 2 times, most recently from 6a27c4b to f0b8d52 Compare December 1, 2024 16:36
@wata727 wata727 marked this pull request as ready for review December 3, 2024 17:25
@wata727 wata727 requested a review from bendrucker December 3, 2024 17:26
@wata727
Copy link
Member Author

wata727 commented Dec 3, 2024

@bendrucker Could you take a look at this? Any feedback on the phase-in of plugin keyless verification?

@wata727 wata727 force-pushed the plugin_keyless_verify branch from f0b8d52 to 10d692c Compare December 4, 2024 16:03
Copy link
Member

@bendrucker bendrucker left a comment

Choose a reason for hiding this comment

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

Nice! Just a small comment around the documentation.

docs/user-guide/plugins.md Outdated Show resolved Hide resolved
Co-authored-by: Ben Drucker <bvdrucker@gmail.com>
@wata727 wata727 merged commit 3405edb into master Dec 8, 2024
14 checks passed
@wata727 wata727 deleted the plugin_keyless_verify branch December 8, 2024 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Keyless signing
2 participants