Hi Tomas, > In the end more steps were required than I expected. And the signing sadly > required patching git-authenticate.scm in the fork. I put together a script > that automates this process, maybe it will be useful to others as well:
Thanks a lot for sharing this! I'm also interested in maintaining my own fork, so I spent some time going through the script [0]. It's well-written and quite sophisticated; I spent a lot of time reading the Guile manual :) I was even hoping that we could have something like it in Guix itself. It could really help reduce the frustration from slow patch review, as Felix pointed out in response to mine [1] - people who need unmerged functionality can simply apply the patches to their own forks and pull from them until their patches are applied. However, your patch to git-authenticate.scm [2] gave me pause. In trying to understand why it was necessary, I read the 'Securing Updates' Guix blog post [3], and was reminded of the /authorization invariant/ that git-authenticate relies on. Quoting the blog post: > A commit is considered authentic if and only if it is signed by one of > the keys listed in the .guix-authorizations file of each of its > parents. This is the authorization invariant. Now the reason I bring this up is this - it looks like the patch you're relying on breaks the authorization invariant. And further, I don't see any way to have an authenticated local fork without breaking it! I'm hoping to be wrong about this; I was hoping you could check my understanding here. >From the patch message: > When Guix fork is created (from commit A), new commit (authorizing the new > signing key K) is created (I). Later, when update from Guix proper (U) is > merged, new merge commit is created (M): > > M > / \ > I U > \ / > A > > The M is signed with the K. However since the K is allowed by only one > parent (I), it will not be in the set of authorized keys (intersection of keys > from I and U). This is the authorization invariant in action. > Solution is to reverse the direction of the check (Guix proper checks from > newest to oldest) and use all keys from already authenticated parents. I am > pretty sure the security guarantees are the same, and we will be able to > successfully authenticate merge commits like M. Now, I could be misunderstanding this, but the idea I'm getting from reading the diff that follows is that any key that was previously used to sign any commit will be considered as a valid key to sign other commits - it need not be present in the .guix-authorizations of every parent. Which violates the invariant. I was hoping that maybe it's actually OK to do this, as you suggested; but unfortunately I thought of a problem - it would mean that once someone has a single signed commit in the Guix repo, their ability to make authenticated commits can never be revoked. Even if their key is removed from .guix_authorizations, their key will always make it into the set of valid keys via `authenticated-commits`. There are probably more possible attacks. And this brings me (finally!) to the point of my message - I do not see any way to have an authenticated local fork, given the current design of `guix git authenticate`. As long as we have the authorization invariant, we won't be able to merge upstream Guix into our own master branch and preserve authentication (unless, of course, we're authorized committers ourselves). So, what do you think? Does this make sense? If it does, I'll CC guix-devel on this; I think we do need a way for people to have their own forks going forward, and it would be a shame if we have to give up authentication to do it. [0] https://git.wolfsden.cz/guix/tree/etc/fork-guix [1] https://lists.gnu.org/archive/html/guix-devel/2025-01/msg00072.html [2] https://git.wolfsden.cz/guix/tree/etc/0001-git-authenticate-Trust-all-keys-from-already-authent.patch [3] https://guix.gnu.org/en/blog/2020/securing-updates/
