[PATCH guix-artwork] website: Add post about ‘guix git authenticate’.
(address . guix-patches@gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
* website/posts/git-authenticate.md: New file.
---
website/posts/git-authenticate.md | 217 ++++++++++++++++++++++++++++++
1 file changed, 217 insertions(+)
create mode 100644 website/posts/git-authenticate.md
Hello Guix!
In my quest to make the world a better place *cough* I thought I’d
take the recent improvements to ‘guix git authenticate’¹ as an
opportunity to spread the word about Git checkout authentication,
about the tool, and to send a call for action—I’d love to see
someone implement it or a variant thereof for a broader audience.
I’d like to publish this blog post in the coming days.
Feedback welcome!
Thanks,
Ludo’.
Toggle diff (227 lines)
diff --git a/website/posts/git-authenticate.md b/website/posts/git-authenticate.md
new file mode 100644
index 0000000..9950b37
--- /dev/null
+++ b/website/posts/git-authenticate.md
@@ -0,0 +1,217 @@
+title: Authenticate your Git checkouts!
+author: Ludovic Courtès
+tags: Security, Software development
+date: 2024-05-06 14:14
+---
+
+You clone a Git repository, then pull from it. How can you tell its
+contents are “authentic”—i.e., coming from the “genuine” project you
+think you’re pulling from, written by the fine human beings you've been
+working with? With commit signatures and “verified” badges ?
+flourishing, you’d think this has long been solved—but nope!
+
+Four years after Guix [deployed its own
+tool](https://guix.gnu.org/en/blog/2020/securing-updates/) to allow
+users to authenticate updates fetched with `guix pull` (which uses Git
+under the hood), the situation hasn’t changed all that much: the vast
+majority of developers using Git simply do not authenticate the code
+they pull. That’s pretty bad. It’s the modern-day equivalent of
+sharing unsigned tarballs and packages like we’d blissfully do in the
+past century.
+
+The authentication mechanism Guix uses for
+[channels](https://guix.gnu.org/manual/devel/en/html_node/Channels.html)
+is available to any Git user through the [`guix git
+authenticate`](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+command. This post is a guide for Git users who are not necessarily
+Guix users but are interested in using this command for their own
+repositories. Before looking into the command-line interface and how we
+improved it to make it more convenient, let’s dispel any
+misunderstandings or misconceptions.
+
+# Why you should care
+
+When you run `git pull`, you’re fetching a bunch of commits from a
+server. If it’s over HTTPS, you’re authenticating *the server* itself,
+which is nice, but that does not tell you who the code actually comes
+from—the server might be compromised and an attacker pushed code to the
+repository. Not helpful. At all.
+
+But hey, maybe you think you’re good because everyone on your project is
+signing commits and tags, and because you’re disciplined, you routinely
+run `git log --show-signature` and check those “Good signature” GPG
+messages. Maybe you even have those fancy “? verified” badges as found
+[on
+GitLab](https://docs.gitlab.com/ee/user/project/repository/signed_commits/gpg.html)
+and [on
+GitHub](https://docs.github.com/en/authentication/managing-commit-signature-verification).
+
+Signing commits is part of the solution, but it’s not enough to
+_authenticate_ a set of commits that you pull; all it shows is that,
+well, those commits are signed. Badges aren’t much better: the presence
+of a “verified” badge only shows that the commit is signed by the
+OpenPGP key *currently registered* for the corresponding GitLab/GitHub
+account. If you register a new key, or if you leave the project, your
+commits lose their badge. Not helpful either, not to mention that this
+is all tied to the hosting site you’re on, outside of Git’s control.
+
+Being able to ensure that when you run `git pull`, you’re getting code
+that _genuinely_ comes from authorized developers of the project is
+basic security hygiene. Obviously it cannot protect against efforts to
+infiltrate a project to eventually get commit access and insert
+malicious code—the kind of multi-year plot that led to the [xz
+backdoor](https://tukaani.org/xz-backdoor/)—but if you don’t even
+protect against unauthorized commits, then all bets are off.
+
+Authentication is something we naturally expect from `apt update`,
+`pip`, `guix pull`, and similar tools; why not treat `git pull` to the
+same standard?
+
+# Initial setup
+
+The [`guix git
+authenticate`](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+command authenticates Git checkouts, unsurprisingly. It’s currently
+part of Guix because that’s where it was brought to life, but it can be
+used on any Git repository. This section focuses on how to use it; you
+can learn about the motivation, its design, and its implementation in
+[the 2020 blog
+post](https://guix.gnu.org/en/blog/2020/securing-updates/), in the 2022
+peer-reviewed academic paper entitled [_Building a Secure Software
+Supply Chain with
+GNU Guix_](https://doi.org/10.22152/programming-journal.org/2023/7/1),
+or in this 20mn
+[presentation](https://archive.fosdem.org/2023/schedule/event/security_where_does_that_code_come_from/).
+
+To support authentication of your repository with `guix git
+authenticate`, you need to follow these steps:
+
+ 0. Enable commit signing on your repo: `git config commit.gpgSign
+ true`. (Git now supports other signing methods but here we need
+ OpenPGP signatures.)
+
+ 1. Create a `keyring` branch containing all the OpenPGP keys of all
+ the committers, along these lines:
+
+ ```
+ git checkout --orphan keyring
+ git reset --hard
+ gpg --export alice@example.org > alice.key
+ …
+ git add *.key
+ git commit -a -m "Add committer keys."
+ ```
+
+ All the files must end in `.key`. You must never remove keys from
+ that branch: keys of users who left the project are necessary to
+ authenticate past commits.
+
+ 2. Back to the main branch, add a `.guix-authorizations` file, listing
+ the OpenPGP keys of authorized committers—we’ll get back to its
+ format below.
+
+ 3. Commit! This becomes the _introductory commit_ from which
+ authentication can proceed. The _introduction_ of your repository
+ is the ID of this commit and the OpenPGP fingerprint of the key
+ used to sign it.
+
+That’s it. From now on, anyone who clones the repository can
+authenticate it. The first time, run:
+
+```
+guix git authenticate COMMIT SIGNER
+```
+
+… where `COMMIT` is the commit ID of the introductory commit, and
+`SIGNER` is the OpenPGP fingerprint of the key used to sign that commit
+(make sure to enclose it in double quotes if there are spaces!). As a
+repo maintainer, you must advertise this introductory commit ID and
+fingerprint on a web page or in a `README` file so others know what to
+pass to `guix git authenticate`.
+
+The commit and signer are now recorded on the first run in
+`.git/config`; next time, you can run it without any arguments:
+
+```
+guix git authenticate
+```
+
+The other new feature is that the first time you run it, the command
+installs *pre-push and pre-merge hooks* (unless preexisting hooks are
+found) such that your repository is automatically authenticated from
+there on every time you run `git pull` or `git push`.
+
+`guix git authenticate` exits with a non-zero code and an error message
+when it stumbles upon a commit that lacks a signature, that is signed by
+a key not in the `keyring` branch, or that is signed by a key not listed
+in `.guix-authorizations`.
+
+# Maintaining the list of authorized committers
+
+The `.guix-authorizations` file in the repository is central: it lists
+the OpenPGP fingerprints of authorized committers. Any commit that is
+*not* signed by a key listed in the `.guix-authorizations` file of its
+parent commit(s) is considered inauthentic—and an error is reported.
+The [format of
+`.guix-authorizations`](https://guix.gnu.org/manual/devel/en/html_node/Specifying-Channel-Authorizations.html#channel_002dauthorizations)
+is based on [S-expressions](https://en.wikipedia.org/wiki/S-expression)
+and looks like this:
+
+```scheme
+;; Example '.guix-authorizations' file.
+
+(authorizations
+ (version 0) ;current file format version
+
+ (("AD17 A21E F8AE D8F1 CC02 DBD9 F8AE D8F1 765C 61E3"
+ (name "alice"))
+ ("2A39 3FFF 68F4 EF7A 3D29 12AF 68F4 EF7A 22FB B2D5"
+ (name "bob"))
+ ("CABB A931 C0FF EEC6 900D 0CFB 090B 1199 3D9A EBB5"
+ (name "charlie"))))
+```
+
+The `name` bits are hints and do not have any effect; what matters is
+the fingerprints that are listed. You can obtain them with GnuPG by
+running commands like:
+
+```
+gpg --fingerprint charlie@example.org
+```
+
+At any time you can add or remove keys from `.guix-authorizations` and
+commit the changes; those changes take effect for child commits. For
+example, if we add Billie’s fingerprint to the file in commit _A_, then
+Billie becomes an authorized committer in *descendants* of commit _A_
+(we must make sure to add Billie’s key as a file in the `keyring`
+branch, too, as we saw above); Billie is still unauthorized in branches
+that lack _A_. If we remove Charlie’s key from the file in commit _B_,
+then Charlie is no longer an authorized committer, except in branches
+that start before _B_. This should feel rather natural.
+
+That’s pretty much all you need to know to get started! [Check the
+manual](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+for more info.
+
+All the information needed to authenticate the repository is contained
+in the repository itself—it does not depend on a forge or key server.
+That’s a good property to allow anyone to authenticate it, to ensure
+determinism and transparency, and to avoid lock-in.
+
+# Interested? You can help!
+
+`guix git authenticate` is a great tool that you can start using today
+so you and fellow co-workers can be sure you’re getting the right code!
+It solves an important problem that, to my knowledge, hasn’t really been
+addressed by any other tool.
+
+Maybe you’re interested but don’t feel like installing Guix “just” for
+this tool. Maybe you’re not into Scheme and Lisp and would rather use a
+tool written in your favorite language. Or maybe you think—and
+rightfully so—that such a tool ought to be part of Git proper.
+
+That’s OK, we can talk! We’re open to discussing with folks who’d like
+to come up with alternative implementations—check out the articles
+mentioned above if you’d like to take that route. And we’re open to
+contributing to a standardization effort. Let’s [get in
+touch](https://guix.gnu.org/contact/)!
base-commit: a4153e25c8fc37920a56330a60734f4205f3dcb0
--
2.41.0