-
Notifications
You must be signed in to change notification settings - Fork 320
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
Signature verification support #15
Comments
Absolutely! That sounds like a very useful feature. I'd love to review a PR for this. :) |
Okay, thanks. I’ll take a look and send a PR when I get the chance. Let me make sure that I understand this project’s constraints: is the |
Great, thanks! Yes, the current version has these properties:
However:
|
Summary: This commit adds logic to authenticate all Bazel binaries that are downloaded, as long as the user has GPG installed. If a user does not have GPG installed, a new warning will be printed when a binary is downloaded, but Bazelisk will function the same way as before. (GPG is installed by default on Debian and Ubuntu.) No new subprocesses are spawned when an already-downloaded version of Bazel is run. The only appreciable overhead is incurred at download time. Resolves bazelbuild#15. Test Plan: - Remove the `~/.bazelisk` directory. Run `./bazelisk.py version`. Note that it downloads the latest binary and the latest signature, then prints “Authenticity verified” before invoking Bazel. - Run `./bazelisk.py version` again. Note that it does not verify the signature. - Remove the `~/.bazelisk` directory. Symlink `/bin/false` to `~/bin/gpg`, and ensure that the symlink precedes the real `gpg` on your path. Run Bazelisk, and note that it prints a warning that GPG is not available but executes Bazel anyway. Run Bazelisk again, and note that it does not print the warning (because it reuses the existing executable without reauthenticating). Remove the symlink. - Remove the `~/.bazelisk` directory. Edit `bazelisk.py`, changing the `determine_urls` function so that the returned `binary_url` is an arbitrary web page (like `http://example.com/`) but the signature URL is unchanged. Run Bazelisk, and note that Bazelisk reports, “Failed to authenticate binary!”, includes the GPG output (“BAD signature”), and aborts with exit code 2 _without_ invoking Bazel. Run `ls ~/.bazelisk/bin` and note that it does not include the invalid binary (though the signature is still there). Revert the changes to `bazelisk.py`. - Remove the `~/.bazelisk` directory. Create an arbitrary document and use `gpg --detach-sign` to sign it with a key that is not the Bazel signing key. Spawn a web server (`python -m SimpleHTTPServer`) to serve the “malicious executable” and its signature. Edit `bazelisk.py`, changing the `determine_urls` function to point both the binary and the signature to this local web server. Run Bazelisk, and note that it fails to authenticate the binary, with the message “public key not found”. Repeat the above steps in Python 2 and Python 3. Verify that your personal GnuPG database has not been modified (in particular, the Bazel key should not have been installed, and the trust settings should not have been modified). I have tested this on Linux with gpg (GnuPG) 1.4.20. I don’t see any reason that it shouldn’t work on macOS or Windows as long as the gpg(1) interfaces are the same. wchargin-branch: authenticate-binaries
Submitted #17, preserving all those properties (no new dependencies).
Yes: if you could please test this on macOS, that’d be great. My I see that Windows testing is an “idea for the future” according to the |
Summary: This commit adds logic to authenticate all Bazel binaries that are downloaded, as long as the user has GPG installed. If a user does not have GPG installed, a new warning will be printed when a binary is downloaded, but Bazelisk will function the same way as before. (GPG is installed by default on Debian and Ubuntu.) No new subprocesses are spawned when an already-downloaded version of Bazel is run. The only appreciable overhead is incurred at download time. Resolves bazelbuild#15. Test Plan: - Remove the `~/.bazelisk` directory. Run `./bazelisk.py version`. Note that it downloads the latest binary and the latest signature, then prints “Authenticity verified” before invoking Bazel. - Run `./bazelisk.py version` again. Note that it does not verify the signature. - Remove the `~/.bazelisk` directory. Symlink `/bin/false` to `~/bin/gpg`, and ensure that the symlink precedes the real `gpg` on your path. Run Bazelisk, and note that it prints a warning that GPG is not available but executes Bazel anyway. Run Bazelisk again, and note that it does not print the warning (because it reuses the existing executable without reauthenticating). Remove the symlink. - Remove the `~/.bazelisk` directory. Edit `bazelisk.py`, changing the `determine_urls` function so that the returned `binary_url` is an arbitrary web page (like `http://example.com/`) but the signature URL is unchanged. Run Bazelisk, and note that Bazelisk reports, “Failed to authenticate binary!”, includes the GPG output (“BAD signature”), and aborts with exit code 2 _without_ invoking Bazel. Run `ls ~/.bazelisk/bin` and note that it does not include the invalid binary (though the signature is still there). Revert the changes to `bazelisk.py`. - Remove the `~/.bazelisk` directory. Create an arbitrary document and use `gpg --detach-sign` to sign it with a key that is not the Bazel signing key. Spawn a web server (`python -m SimpleHTTPServer`) to serve the “malicious executable” and its signature. Edit `bazelisk.py`, changing the `determine_urls` function to point both the binary and the signature to this local web server. Run Bazelisk, and note that it fails to authenticate the binary, with the message “public key not found”. Repeat the above steps in Python 2 and Python 3. Verify that your personal GnuPG database has not been modified (in particular, the Bazel key should not have been installed, and the trust settings should not have been modified). I have tested this on Linux with gpg (GnuPG) 1.4.20. I don’t see any reason that it shouldn’t work on macOS or Windows as long as the gpg(1) interfaces are the same. wchargin-branch: authenticate-binaries
Summary: This commit adds logic to authenticate all Bazel binaries that are downloaded, as long as the user has GPG installed. If a user does not have GPG installed, a new warning will be printed when a binary is downloaded, but Bazelisk will function the same way as before. (GPG is installed by default on Debian and Ubuntu.) No new subprocesses are spawned when an already-downloaded version of Bazel is run. The only appreciable overhead is incurred at download time. Resolves bazelbuild#15. Test Plan: - Remove the `~/.bazelisk` directory. Run `./bazelisk.py version`. Note that it downloads the latest binary and the latest signature, then prints “Authenticity verified” before invoking Bazel. - Run `./bazelisk.py version` again. Note that it does not verify the signature. - Remove the `~/.bazelisk` directory. Symlink `/bin/false` to `~/bin/gpg`, and ensure that the symlink precedes the real `gpg` on your path. Run Bazelisk, and note that it prints a warning that GPG is not available but executes Bazel anyway. Run Bazelisk again, and note that it does not print the warning (because it reuses the existing executable without reauthenticating). Remove the symlink. - Remove the `~/.bazelisk` directory. Edit `bazelisk.py`, changing the `determine_urls` function so that the returned `binary_url` is an arbitrary web page (like `http://example.com/`) but the signature URL is unchanged. Run Bazelisk, and note that Bazelisk reports, “Failed to authenticate binary!”, includes the GPG output (“BAD signature”), and aborts with exit code 2 _without_ invoking Bazel. Run `ls ~/.bazelisk/bin` and note that it does not include the invalid binary (though the signature is still there). Revert the changes to `bazelisk.py`. - Remove the `~/.bazelisk` directory. Create an arbitrary document and use `gpg --detach-sign` to sign it with a key that is not the Bazel signing key. Spawn a web server (`python -m SimpleHTTPServer`) to serve the “malicious executable” and its signature. Edit `bazelisk.py`, changing the `determine_urls` function to point both the binary and the signature to this local web server. Run Bazelisk, and note that it fails to authenticate the binary, with the message “public key not found”. Repeat the above steps in Python 2 and Python 3. Verify that your personal GnuPG database has not been modified (in particular, the Bazel key should not have been installed, and the trust settings should not have been modified). I have tested this on Linux with gpg (GnuPG) 1.4.20. I don’t see any reason that it shouldn’t work on macOS or Windows as long as the gpg(1) interfaces are the same. wchargin-branch: authenticate-binaries
Fixes bazelbuild#15. Signed-off-by: Piotr Sikora <[email protected]>
Fixes bazelbuild#15. Signed-off-by: Piotr Sikora <[email protected]>
Fixes bazelbuild#15. Signed-off-by: Piotr Sikora <[email protected]>
Fixes bazelbuild#15. Signed-off-by: Piotr Sikora <[email protected]>
Bazel release candidates and releases are accompanied by PGP signatures:
Would you be interested in a pull request to make Bazelisk additionally
download and verify these signatures? (Signature verification is fast:
about a second on my machine.)
The Bazel team public key would be hard-coded into the repository, and
we can use
to verify the binary. (This requires the
bazel-release.pub.gpg
key tobe dearmored, but that’s easy to do.)
The text was updated successfully, but these errors were encountered: