Shawn O. Pearce wrote: > * New protocol extension to send-pack/receive-pack pair: > > If server wants to require (or optionally) accept a signed push > event it sends a new capability string when it advertises its > current known heads: > > auth-1=[0-9a-f]{40} [...] > <auth><pgp_sig> > > auth ::= 'auth' ' ' <name> ' ' '<' <email> '>' '\n' > name ::= like a commit author-name > email ::= like a commit author-email > pgp_sig ::= armored signature from PGP > > receive-pack expects this new auth pkt-line if the client asked > to enable the auth-1 capablity in the first command. > > If receive-pack was configured (say by config receive.auth) > to require authentication then it closes the connection if the > client didn't request the capablity in the first command. > > receive-pack can generate the same SHA-1 hash from the commands > it read from send-pack, and can verify the PGP signature on the > auth line. > > This assures us the command stream wasn't modified, and likely > originated from the named identity. The rest of the packfile > data is already well protected by its own SHA-1 footer and the > individual object SHA-1s, and the roots pointing into that DAG > (or sub-DAG) mentioned in the commands were verified by the PGP > signature of them. Ok - but I think if the client is pushing a signed tag to the tagname listed in the signed body of the tag, that no extra signature should be necessary. It's only commits that need the extra information. And remember, for global replication of the data between untrusted nodes to be possible, the signatures must be saved somewhere. I have sketched a simple design below. > * PGP public key storage: > > Use a "hidden" ref called "refs/access-keys" to store a commit. > The access control change log is a normal Git commit chain. > > The tree under this commit stores a file per <email> string. > Public keys for auth line validation are located by <email>, > from the tip of this branch. > > This branch could be a symlink to another repository (e.g. > a site-wide "admin" repository) and the ODB for that other > repository could be an alternate for this repository. > > > * ref/access-keys security: > > Probably an update or pre-receive hook could verify pushes > to this branch by something like this: > > - If the only difference between $old_sha1 $new_sha1 is > a modification of $GIT_PUSHER_EMAIL then allow it > (user is replacing their own key); > > - If the only difference between $old_sha1 $new_sha1 is > modifications of names other than $GIT_PUSHER_EMAIL but > the file content differences are only $GIT_PUSHER_EMAIL > signing those public keys then allow it (the user doing > the push is publishing some trust); > > - If the difference between $old_sha1 $new_sha1 is new > keys added or existing keys removed then allow it only > if $GIT_PUSHER_EMAIL is also listed inside of the > "admin/" subtree and the new key is also signed by > $GIT_PUSHER_EMAIL's key. Ok perhaps it is best to wrap all this up in a single state branch, that has in it: access-keys/ - tree with one key per e-mail address access - maps reference globs to e-mail addresses permitted to change them - with a "+" if the address may rewind the ref owners - maps reference globs to e-mail addresses permitted to add entries to the "access" map above signatures/ - stores any detached signatures. only the signatures verifying updates since the last commit to the access meta-branch need to be stored packed-refs - the new list of references (the refs/access commitid is naturally absent or the same as the parent), or just the changed references. You don't necessarily need a new commit on this for every single push, just once "every so often", and perhaps for safety once for every change to the access file. This branch should then be auditable; replicating tools can go and verify that there have been no unauthorized changes. Forks don't necessarily need special treatment; they can exist under refs/forks/foobar/ - similar to the refs/remotes/ namespace, and have their own independent ACL branches within. Allowing "grant" permissions to refspaces would need to be handled specially; you can't simply grant access to change refs/access; the actual push to refs/access would need inspecting to see if the changed "access" file comes within the rights of the user that signed the update. I think this seems about right for a first cut. Possibly bigger projects like Debian would like to say that for certain ref spaces, multiple signatures are required, so that no one PGP key retains complete control. But I think these things are easily added as features on top of this basic infrastructure. Sound like something worth working towards? Sam. - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html