* How to create and maintain a personal Guix fork?
@ 2023-09-03 18:31 wolf
2023-09-05 16:18 ` Felix Lechner via
0 siblings, 1 reply; 9+ messages in thread
From: wolf @ 2023-09-03 18:31 UTC (permalink / raw)
To: help-guix
[-- Attachment #1: Type: text/plain, Size: 3253 bytes --]
Hello Guix,
Table of Contents
_________________
1. Introduction
2. How to create a fork?
.. 1. guix time-machine
.. 2. Any other limitations?
3. How to keep the fork up to date?
.. 1. Authentication
4. Conclusion
1 Introduction
==============
I would like to start my own fork of the upstream Guix, in order to be
able to use some patches I require. I went through the documentation,
but I am unclear on few details, so I hope someone will be kind enough
to help me.
2 How to create a fork?
=======================
While documentation does describe most of this, I want to make sure I
did figure out all the step (and their ordering).
1. Create a git repository (git.example.org/guix)
2. Add my signing key (with fingerprint F) into a file name.key on the
keyring branch, producing commit with hash H1. Push it.
3. Add my signing key (with fingerprint F) into the
.guix-authorizations file, commit the changes, producing commit
with hash H2. Push it.
4. Create a channel description file:
,----
| (list (channel
| (name 'guix)
| (url "https://git.example.org/guix")
| ;; Enable signature verification:
| (introduction
| (make-channel-introduction
| "H2"
| (openpgp-fingerprint
| "F")))))
`----
The %default-channels is missing.
Q: Can %default-channels contain multiple channels? Should I
rather replace 'guix in that variable?
5. Guix pull using the file from 4.
6. Reconfigure the system/home.
From this point on I should be running my own fork, from commits in my
git repository, with things like authentication properly working,
correct? Did I miss any required steps?
2.1 guix time-machine
~~~~~~~~~~~~~~~~~~~~~
How does the time-machine interact with this setup? Since any time
travel would likely interact with commits before the channel
introduction, will it even work? If now, is there a way around it?
2.2 Any other limitations?
~~~~~~~~~~~~~~~~~~~~~~~~~~
Will I encounter any other limitations with this setup? Are there
things that will just not work? Or will this behave exactly like
upstream Guix (- the patches)? I guess I am curious if I should
expect any foot guns (and where).
3 How to keep the fork up to date?
==================================
The other question is how to keep my "fork" up to date. I am inclined
to just use git merge, and periodically merge changes from the
upstream. Are there any downsides to that? If it is relevant, I
expect the flow to be unidirectional, from Guix to my fork.
3.1 Authentication
~~~~~~~~~~~~~~~~~~
I need to also keep the keyring branch synchronized, correct?
Will authentication work properly with merge-based workflow? Will the
commits being merged have their signatures checked? Or will it check
just the merge commits?
4 Conclusion
============
Did I miss anything? Does anyone have any tips before I give this a
try?
Thanks,
W.
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2023-09-03 18:31 How to create and maintain a personal Guix fork? wolf
@ 2023-09-05 16:18 ` Felix Lechner via
2023-09-25 13:06 ` wolf
0 siblings, 1 reply; 9+ messages in thread
From: Felix Lechner via @ 2023-09-05 16:18 UTC (permalink / raw)
To: help-guix; +Cc: wolf
Hi Wolf,
On Sun, Sep 3, 2023 at 11:31 AM wolf <wolf@wolfsden.cz> wrote:
>
> I would like to start my own fork of the upstream Guix
That's great news! I think it's the only way to contribute important
changes to Guix. You may find some helpful information at the end of
this message:
https://lists.gnu.org/archive/html/guix-devel/2023-08/msg00121.html
I pull unauthenticated right now but should probably add my key to
'lechner-experimental' on Codeberg. Thanks!
Kind regards
Felix
P.S. Perhaps you meant to force a reply to the list alone. I copied you, anyway.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2023-09-05 16:18 ` Felix Lechner via
@ 2023-09-25 13:06 ` wolf
2025-01-10 19:06 ` 45mg
0 siblings, 1 reply; 9+ messages in thread
From: wolf @ 2023-09-25 13:06 UTC (permalink / raw)
To: Felix Lechner; +Cc: help-guix
[-- Attachment #1: Type: text/plain, Size: 1130 bytes --]
On 2023-09-05 09:18:45 -0700, Felix Lechner wrote:
> Hi Wolf,
>
> On Sun, Sep 3, 2023 at 11:31 AM wolf <wolf@wolfsden.cz> wrote:
> >
> > I would like to start my own fork of the upstream Guix
>
> That's great news! I think it's the only way to contribute important
> changes to Guix. You may find some helpful information at the end of
> this message:
>
> https://lists.gnu.org/archive/html/guix-devel/2023-08/msg00121.html
>
> I pull unauthenticated right now but should probably add my key to
> 'lechner-experimental' on Codeberg. Thanks!
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:
https://git.sr.ht/~graywolf/guix/tree/master/item/etc/fork-guix
>
> Kind regards
> Felix
>
> P.S. Perhaps you meant to force a reply to the list alone. I copied you, anyway.
Have a nice day,
W.
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2023-09-25 13:06 ` wolf
@ 2025-01-10 19:06 ` 45mg
2025-01-10 23:59 ` Tomas Volf
0 siblings, 1 reply; 9+ messages in thread
From: 45mg @ 2025-01-10 19:06 UTC (permalink / raw)
To: Tomas Volf, Felix Lechner; +Cc: help-guix
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/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2025-01-10 19:06 ` 45mg
@ 2025-01-10 23:59 ` Tomas Volf
2025-01-11 8:47 ` 45mg
0 siblings, 1 reply; 9+ messages in thread
From: Tomas Volf @ 2025-01-10 23:59 UTC (permalink / raw)
To: 45mg; +Cc: Felix Lechner, help-guix
[-- Attachment #1: Type: text/plain, Size: 6626 bytes --]
Hello,
thank you so much for actually reading this (and the script) and writing
back. It always give me warm feelings when the bottomless abyss called
Guix mailing list responds. :)
45mg <45mg.writes@gmail.com> writes:
> 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.
Yes, it breaks it.
> And further, I don't see any way to have an authenticated local fork
> without breaking it!
For this very reason. It simply is not possible to have authenticated
fork for a project secured by guix-authenticate.
>
> 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 think you are slightly misunderstanding the invariant. Quoting the
relevant part:
> if it is signed by one of the keys listed in the .guix-authorizations
> file of *each of its parents*"
Emphasis is mine. These "parents" are parents in the git sense of the
word, which is well defined. Copying the example from above:
M
/ \
I U
\ /
A
M has exactly two parents, I and U. It has 3 *ancestors*, I, U and A.
The intention in the code is to use the parents of M (so I, U) and do an
union instead of an intersection of keys valid in both parents.
>
> 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.
Were you actually able to demonstrate this attack? I did quick test and
was not able to reproduce.
The thought process behind the change is that since you check the keys
from the parents, and those parents are already authenticated, all keys
should be equally valid and acceptable to be used for signing the child
commit. I still *think* that should be fully safe.
I spent quite some time trying to come up with attacks against my
version back when I wrote it, and did not figure out anything. However!
It is always possible there are bugs (either in the code or in my
understanding).
It would be great if you are able to demonstrate that this attack is
possible. It would allow me to correct my understanding and fix the
code.
>
> 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
Yeah, I agree. That is the reason why I wrote the script and carry the
patch. I just was not able to find any other way to get it working.
> (unless, of course, we're authorized committers ourselves).
My cynical take is that this is the very reason this issue is not taken
seriously. For all "people in charge" it works, even in private forks.
>
> 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.
I agree, but I already raised the issue in my original thread, and there
was no action from the committers, I am not sure this is high enough on
the priority list. But your are of course free to try, maybe this time
there will be takers. ^_^
>
> [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/
Have a nice 2025,
Tomas
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 853 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2025-01-10 23:59 ` Tomas Volf
@ 2025-01-11 8:47 ` 45mg
2025-01-11 12:13 ` Tomas Volf
0 siblings, 1 reply; 9+ messages in thread
From: 45mg @ 2025-01-11 8:47 UTC (permalink / raw)
To: Tomas Volf, 45mg; +Cc: Felix Lechner, help-guix
Hi Tomas!
Tomas Volf <~@wolfsden.cz> writes:
> Hello,
>
> thank you so much for actually reading this (and the script) and writing
> back. It always give me warm feelings when the bottomless abyss called
> Guix mailing list responds. :)
I know the feeling ^_^
[...]
> The intention in the code is to use the parents of M (so I, U) and do
> an union instead of an intersection of keys valid in both parents.
>
>> 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.
>
> Were you actually able to demonstrate this attack? I did quick test and
> was not able to reproduce.
[...]
> It would be great if you are able to demonstrate that this attack is
> possible. It would allow me to correct my understanding and fix the
> code.
I have included below a script that demonstrates an attack on `guix git
authenticate` that only works with your patch.
It's not the same attack as what I outlined above; I think that one
would depend on the implementation details of your patch (if it's even
viable at all; I haven't tested).
Rather, the attack I demonstrate below should work as long as the core
idea of your patch ("union instead of an intersection of keys valid in
both parents") is implemented.
You should be able to run it once you change the values of GUIX and
REPO.
--8<---------------cut here---------------start------------->8---
#!/bin/sh
### Copyright (C) 2025 45mg <45mg.writes@gmail.com>
### SPDX-License-Identifier: AGPL-3.0-only
# This script demonstrates an attack on `guix git authenticate` when it is built
# with Tomas Volf's patch:
# https://git.wolfsden.cz/guix/tree/etc/0001-git-authenticate-Trust-all-keys-from-already-authent.patch
# It allows a key that was previously authorized and then removed to get new
# commits into the master branch.
# Here is an outline of the attack:
# - A, who is a trusted committer, creates the repo and adds a commit that will
# serve as the channel introduction.
# - A then adds B as a committer, and B makes an authenticated commit on the
# master branch.
# - A then removes B as a committer. B should not be able to get any commits
# into master from here on.
# - B creates a branch starting from their authenticated commit, adds a
# malicious commit to it, and merges their branch into master.
# Since Tomas's patch considers the union of parent keys as valid, rather than
# the intersection, this attack works - all commits made are considered
# authenticated.
GUIX='path/to/patched-guix-clone/pre-inst-env guix'
REPO=wherever/we/should/create/the/guix-auth-attack-repo
# Make sure you're using Guix built with Tomas Volf's patch.
$GUIX --version
### Create test keys
# Create a temporary substitute for ~/.gnupg
export GNUPGHOME=/tmp/guix-auth-attack-gnupg/
rm -rf $GNUPGHOME
mkdir -p $GNUPGHOME
# gpg expects correct perms
chmod 700 $GNUPGHOME
chown $(whoami) $GNUPGHOME
# Generate the keys
gpg --batch --gen-key <<EOF
%echo Generating A's OpenPGP key...
Key-Type: default
Name-Real: A
%no-protection
%commit
%echo done.
%echo Generating B's OpenPGP key...
Key-Type: default
Name-Real: B
%no-protection
%commit
%echo done.
EOF
# Get the key fingerprints
KEY_A=$(gpg --with-colons --list-keys --with-fingerprint A | awk -F: '$1 == "fpr" {print $10;}')
KEY_B=$(gpg --with-colons --list-keys --with-fingerprint B | awk -F: '$1 == "fpr" {print $10;}')
### Demonstrate the attack
#### A sets up the repo
# Init the repo.
rm -rf $REPO
mkdir -p $REPO
cd $REPO
git init
# Create the keyring branch, and add A and B's keys.
git switch --orphan keyring
git config user.name A
git config user.email A@no.mail
gpg --armor --export -o A-"${KEY_A::8}".key "$KEY_A"
gpg --armor --export -o B-"${KEY_B::8}".key "$KEY_B"
git add -- A-"${KEY_A::8}".key B-"${KEY_B::8}".key
git commit -m "Add keys for A and B."
# Create the initial commit, which will be the channel introduction.
# It will be signed with A's key.
git switch --orphan master
cat > .guix-authorizations <<EOF
(authorizations
(version 0)
(("$KEY_A"
(name "A"))))
EOF
git add -- .guix-authorizations
git config commit.gpgsign true
git config user.signingkey $KEY_A
git commit -m "Initial commit and channel introduction."
INIT_COMMIT=$(git rev-parse HEAD)
#### A authorizes B
cat > .guix-authorizations <<EOF
(authorizations
(version 0)
(("$KEY_A"
(name "A"))
("$KEY_B"
(name "B"))))
EOF
git add -- .guix-authorizations
git commit -m "Authorize B."
#### B creates a branch and merges it
git config user.name B
git config user.email B@no.mail
git config user.signingkey $KEY_B
git switch --create to-merge
touch b-file
git add -- b-file
git commit -m "Add b-file."
B_COMMIT=$(git rev-parse HEAD)
git switch master
git merge to-merge -m "Merge to-merge."
#### A removes B's authorization
git config user.name A
git config user.email A@no.mail
git config user.signingkey $KEY_A
cat > .guix-authorizations <<EOF
(authorizations
(version 0)
(("$KEY_A"
(name "A"))))
EOF
git add -- .guix-authorizations
git commit -m "Remove B's authorization."
#### The attack
# B creates a branch starting from their signed commit, adds a malicious commit,
# and merges it into master!
git config user.name B
git config user.email B@no.mail
git config user.signingkey $KEY_B
git switch --create malicious $B_COMMIT
touch malicious-file
git add -- malicious-file
git commit -m "Add malicious file."
git switch master
git merge malicious -m "Merge malicious."
#### `guix git authenticate` to show that the attack works
$GUIX git authenticate $INIT_COMMIT "$KEY_A"
# If you set $GUIX to a guix executable built without Tomas's patch, the attack
# will fail.
--8<---------------cut here---------------end--------------->8---
[...]
> My cynical take is that this is the very reason this issue is not taken
> seriously. For all "people in charge" it works, even in private forks.
Well, it could also be that many of them didn't read this far into the
thread; since the title doesn't really indicate that you found a
fundamental flaw in `guix git authenticate`, they might not have seen
any reason to pay attention.
At any rate - we shall see ;)
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2025-01-11 8:47 ` 45mg
@ 2025-01-11 12:13 ` Tomas Volf
2025-01-12 6:36 ` 45mg
0 siblings, 1 reply; 9+ messages in thread
From: Tomas Volf @ 2025-01-11 12:13 UTC (permalink / raw)
To: 45mg; +Cc: Felix Lechner, help-guix
[-- Attachment #1: Type: text/plain, Size: 1276 bytes --]
45mg <45mg.writes@gmail.com> writes:
> I have included below a script that demonstrates an attack on `guix git
> authenticate` that only works with your patch.
>
> It's not the same attack as what I outlined above; I think that one
> would depend on the implementation details of your patch (if it's even
> viable at all; I haven't tested).
>
> Rather, the attack I demonstrate below should work as long as the core
> idea of your patch ("union instead of an intersection of keys valid in
> both parents") is implemented.
You are right! Well fuck. Luckily the security impact is ~0 due to
various reasons, but this is still something I need to fix.
I do have some ideas regarding how to do it, but all of them are fixes
intended to solve "authenticating my Guix fork", not general fixes for
guix-git-authenticate. But I think it can be made to work (sadly it
will not be pretty though).
For this weekend I already have plans (packaging apcupsd, yeey), but I
will try to write them down and report back with the options next week,
I no longer trust myself to write this without supervision. :/
Thanks again once more,
Tomas
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 853 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2025-01-11 12:13 ` Tomas Volf
@ 2025-01-12 6:36 ` 45mg
2025-01-14 22:17 ` Tomas Volf
0 siblings, 1 reply; 9+ messages in thread
From: 45mg @ 2025-01-12 6:36 UTC (permalink / raw)
To: Tomas Volf, 45mg; +Cc: Felix Lechner, help-guix
Hi Tomas,
Tomas Volf <~@wolfsden.cz> writes:
> I do have some ideas regarding how to do it, but all of them are fixes
> intended to solve "authenticating my Guix fork", not general fixes for
> guix-git-authenticate. But I think it can be made to work (sadly it
> will not be pretty though).
I think I may have an idea myself; one that seems reasonably clean,
would fix our use-case of authenticating our own personal Guix forks,
and would even allow pulling branches from other people's forks and
authenticating those.
We could allow users to specify additional channel introductions. So,
there's always one primary introduction, but there can also be one or
more additional ones.
Then, when authenticating commits, we choose the introduction that is
the most recent ancestor of the latest commit, and authenticate that
range.
For commits that have multiple parents - ie. merge commits - we weaken
the invariant as follows:
1. If all parents have the primary introduction as their most recent
ancestor, then the invariant holds as usual.
2. If one or more parents has the primary introduction as its most
recent ancestor (call these the 'primary parents'), and the rest have
any of the additional introductions, then the merge commit is
authenticated if and only if:
a) it's signed by a key authorized in all of the primary parents, AND
b) the /first parent/ [^] of the merge commit is a primary parent.
3. If all parents have the same additional introduction as their most
recent ancestor, then the invariant holds as usual.
4. If none of the parents have the primary introduction as their most
recent ancestor, nor do they have the same additional introduction,
then the merge commit cannot be authenticated.
[^] Quoting from the Pro Git book [1]:
> ...the first parent of a merge commit is from the branch you were on
> when you merged (frequently master), while the second parent of a
> merge commit is from the branch that was merged...
The idea is - the primary introduction is for the part of the tree under
YOUR control. When you fork Guix and create your own branch, you use the
initial commit on your branch as the primary channel introduction. You
add upstream Guix's primary channel introduction as an additional
channel introduction. If you add anyone else's fork as a remote and pull
one of their branches, you add their primary introduction as one of your
additional introductions.
Thus, any merge into one of YOUR branches (ie. any branch with the
primary introduction as the most recent ancestor) only needs to be
signed by a key that's authorized on that branch.
But you can't merge into a branch from upstream Guix or someone else's
authenticated fork (unless you're authorized to commit to those),
because the first parent of the merge commit would not be a primary
parent (see 2b) - it would be a commit on someone else's branch. And
people not authorized by you can't merge into your branch either,
because of 2a. And finally, you can't merge someone else's fork and
upstream, or anything like that. The merge commit would not be
authenticated in any of these cases.
What do you think? I don't actually know when I can work on a patch for
this (I've spent far too much time on this issue already), but it'd be
nice to have a sanity check on this anyway, so that if the approach is
fundamentally flawed in some obvious way that I'm missing, then I don't
have to waste my time on it.
[1] https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: How to create and maintain a personal Guix fork?
2025-01-12 6:36 ` 45mg
@ 2025-01-14 22:17 ` Tomas Volf
0 siblings, 0 replies; 9+ messages in thread
From: Tomas Volf @ 2025-01-14 22:17 UTC (permalink / raw)
To: 45mg; +Cc: Felix Lechner, help-guix
[-- Attachment #1: Type: text/plain, Size: 5077 bytes --]
45mg <45mg.writes@gmail.com> writes:
> Hi Tomas,
>
> Tomas Volf <~@wolfsden.cz> writes:
>
>> I do have some ideas regarding how to do it, but all of them are fixes
>> intended to solve "authenticating my Guix fork", not general fixes for
>> guix-git-authenticate. But I think it can be made to work (sadly it
>> will not be pretty though).
>
> I think I may have an idea myself; one that seems reasonably clean,
> would fix our use-case of authenticating our own personal Guix forks,
> and would even allow pulling branches from other people's forks and
> authenticating those.
>
> We could allow users to specify additional channel introductions. So,
> there's always one primary introduction, but there can also be one or
> more additional ones.
>
> Then, when authenticating commits, we choose the introduction that is
> the most recent ancestor of the latest commit, and authenticate that
> range.
>
> For commits that have multiple parents - ie. merge commits - we weaken
> the invariant as follows:
>
> 1. If all parents have the primary introduction as their most recent
> ancestor, then the invariant holds as usual.
>
> 2. If one or more parents has the primary introduction as its most
> recent ancestor (call these the 'primary parents'), and the rest have
> any of the additional introductions, then the merge commit is
> authenticated if and only if:
> a) it's signed by a key authorized in all of the primary parents, AND
> b) the /first parent/ [^] of the merge commit is a primary parent.
>
> 3. If all parents have the same additional introduction as their most
> recent ancestor, then the invariant holds as usual.
>
> 4. If none of the parents have the primary introduction as their most
> recent ancestor, nor do they have the same additional introduction,
> then the merge commit cannot be authenticated.
>
> [^] Quoting from the Pro Git book [1]:
>> ...the first parent of a merge commit is from the branch you were on
>> when you merged (frequently master), while the second parent of a
>> merge commit is from the branch that was merged...
Problem here is that this (which parent is first) is just a convention
that the attacker does not have to follow. Example:
--8<---------------cut here---------------start------------->8---
/tmp/xx $ git commit-tree -p HEAD -p HEAD~1 -m M HEAD^{tree}
c040e61bc184b5971f68c4b794c3158350b5d5e9
/tmp/xx $ g show c040e61bc184b5971f68c4b794c3158350b5d5e9
commit c040e61bc184b5971f68c4b794c3158350b5d5e9
Merge: 40ef875 17451b8
Author: Tomas Volf <~@wolfsden.cz>
Date: Tue Jan 14 23:12:17 2025 +0100
M
/tmp/xx $ git commit-tree -p HEAD~1 -p HEAD -m M HEAD^{tree}
ec74e368519b667d8d280639db6642b28d37eb53
/tmp/xx $ g show ec74e368519b667d8d280639db6642b28d37eb53
commit ec74e368519b667d8d280639db6642b28d37eb53
Merge: 17451b8 40ef875
Author: Tomas Volf <~@wolfsden.cz>
Date: Tue Jan 14 23:12:32 2025 +0100
M
--8<---------------cut here---------------end--------------->8---
Notice that I have created two commits, and they have the same parents,
just in swapped order.
Does this change anything? I admit I have read your email fairly
quickly due to real life constraints, and would need to draw a picture
or two to make sure I actually understand it.
>
> The idea is - the primary introduction is for the part of the tree under
> YOUR control. When you fork Guix and create your own branch, you use the
> initial commit on your branch as the primary channel introduction. You
> add upstream Guix's primary channel introduction as an additional
> channel introduction. If you add anyone else's fork as a remote and pull
> one of their branches, you add their primary introduction as one of your
> additional introductions.
>
> Thus, any merge into one of YOUR branches (ie. any branch with the
> primary introduction as the most recent ancestor) only needs to be
> signed by a key that's authorized on that branch.
>
> But you can't merge into a branch from upstream Guix or someone else's
> authenticated fork (unless you're authorized to commit to those),
> because the first parent of the merge commit would not be a primary
> parent (see 2b) - it would be a commit on someone else's branch. And
> people not authorized by you can't merge into your branch either,
> because of 2a. And finally, you can't merge someone else's fork and
> upstream, or anything like that. The merge commit would not be
> authenticated in any of these cases.
>
> What do you think? I don't actually know when I can work on a patch for
> this (I've spent far too much time on this issue already), but it'd be
> nice to have a sanity check on this anyway, so that if the approach is
> fundamentally flawed in some obvious way that I'm missing, then I don't
> have to waste my time on it.
>
> [1] https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 853 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-01-14 22:18 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-03 18:31 How to create and maintain a personal Guix fork? wolf
2023-09-05 16:18 ` Felix Lechner via
2023-09-25 13:06 ` wolf
2025-01-10 19:06 ` 45mg
2025-01-10 23:59 ` Tomas Volf
2025-01-11 8:47 ` 45mg
2025-01-11 12:13 ` Tomas Volf
2025-01-12 6:36 ` 45mg
2025-01-14 22:17 ` Tomas Volf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).