mirror of
https://git.savannah.gnu.org/git/guix.git
synced 2026-05-28 03:51:53 +02:00
channels: 'latest-channel-instance' authenticates Git checkouts.
Fixes <https://bugs.gnu.org/22883>. * guix/channels.scm (<channel>)[introduction]: New field. (<channel-introduction>): New record type. (%guix-channel-introduction): New variable. (%default-channels): Use it. (<channel-metadata>)[keyring-reference]: New field. (%default-keyring-reference): New variable. (read-channel-metadata, read-channel-metadata-from-source): Initialize the 'keyring-reference' field. (commit-short-id, verify-introductory-commit) (authenticate-channel): New procedures. (latest-channel-instance): Call 'authenticate-channel' when CHANNEL has an introduction. * tests/channels.scm (gpg+git-available?, commit-id-string): New procedures. ("authenticate-channel, wrong first commit signer"): ("authenticate-channel, .guix-authorizations"): New tests. * doc/guix.texi (Invoking guix pull): Mention authentication.
This commit is contained in:
@@ -31,15 +31,28 @@
|
||||
#:use-module ((guix build utils) #:select (which))
|
||||
#:use-module (git)
|
||||
#:use-module (guix git)
|
||||
#:use-module (guix git-authenticate)
|
||||
#:use-module (guix openpgp)
|
||||
#:use-module (guix tests git)
|
||||
#:use-module (guix tests gnupg)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (srfi srfi-34)
|
||||
#:use-module (srfi srfi-35)
|
||||
#:use-module (srfi srfi-64)
|
||||
#:use-module (rnrs bytevectors)
|
||||
#:use-module (rnrs io ports)
|
||||
#:use-module (ice-9 control)
|
||||
#:use-module (ice-9 match))
|
||||
|
||||
(define (gpg+git-available?)
|
||||
(and (which (git-command))
|
||||
(which (gpg-command)) (which (gpgconf-command))))
|
||||
|
||||
(define commit-id-string
|
||||
(compose oid->string commit-id))
|
||||
|
||||
|
||||
(test-begin "channels")
|
||||
|
||||
(define* (make-instance #:key
|
||||
@@ -389,4 +402,113 @@
|
||||
(channel-news-for-commit channel commit5 commit1))
|
||||
'(#f "tag-for-first-news-entry")))))))
|
||||
|
||||
(unless (gpg+git-available?) (test-skip 1))
|
||||
(test-assert "authenticate-channel, wrong first commit signer"
|
||||
(with-fresh-gnupg-setup (list %ed25519-public-key-file
|
||||
%ed25519-secret-key-file
|
||||
%ed25519bis-public-key-file
|
||||
%ed25519bis-secret-key-file)
|
||||
(with-temporary-git-repository directory
|
||||
`((add ".guix-channel"
|
||||
,(object->string
|
||||
'(channel (version 0)
|
||||
(keyring-reference "master"))))
|
||||
(add ".guix-authorizations"
|
||||
,(object->string
|
||||
`(authorizations (version 0)
|
||||
((,(key-fingerprint
|
||||
%ed25519-public-key-file)
|
||||
(name "Charlie"))))))
|
||||
(add "signer.key" ,(call-with-input-file %ed25519-public-key-file
|
||||
get-string-all))
|
||||
(commit "first commit"
|
||||
(signer ,(key-fingerprint %ed25519-public-key-file))))
|
||||
(with-repository directory repository
|
||||
(let* ((commit1 (find-commit repository "first"))
|
||||
(intro ((@@ (guix channels) make-channel-introduction)
|
||||
(commit-id-string commit1)
|
||||
(openpgp-public-key-fingerprint
|
||||
(read-openpgp-packet
|
||||
%ed25519bis-public-key-file)) ;different key
|
||||
#f)) ;no signature
|
||||
(channel (channel (name 'example)
|
||||
(url (string-append "file://" directory))
|
||||
(introduction intro))))
|
||||
(guard (c ((message? c)
|
||||
(->bool (string-contains (condition-message c)
|
||||
"initial commit"))))
|
||||
(authenticate-channel channel directory
|
||||
(commit-id-string commit1)
|
||||
#:keyring-reference-prefix "")
|
||||
'failed))))))
|
||||
|
||||
(unless (gpg+git-available?) (test-skip 1))
|
||||
(test-assert "authenticate-channel, .guix-authorizations"
|
||||
(with-fresh-gnupg-setup (list %ed25519-public-key-file
|
||||
%ed25519-secret-key-file
|
||||
%ed25519bis-public-key-file
|
||||
%ed25519bis-secret-key-file)
|
||||
(with-temporary-git-repository directory
|
||||
`((add ".guix-channel"
|
||||
,(object->string
|
||||
'(channel (version 0)
|
||||
(keyring-reference "channel-keyring"))))
|
||||
(add ".guix-authorizations"
|
||||
,(object->string
|
||||
`(authorizations (version 0)
|
||||
((,(key-fingerprint
|
||||
%ed25519-public-key-file)
|
||||
(name "Charlie"))))))
|
||||
(commit "zeroth commit")
|
||||
(add "a.txt" "A")
|
||||
(commit "first commit"
|
||||
(signer ,(key-fingerprint %ed25519-public-key-file)))
|
||||
(add "b.txt" "B")
|
||||
(commit "second commit"
|
||||
(signer ,(key-fingerprint %ed25519-public-key-file)))
|
||||
(add "c.txt" "C")
|
||||
(commit "third commit"
|
||||
(signer ,(key-fingerprint %ed25519bis-public-key-file)))
|
||||
(branch "channel-keyring")
|
||||
(checkout "channel-keyring")
|
||||
(add "signer.key" ,(call-with-input-file %ed25519-public-key-file
|
||||
get-string-all))
|
||||
(add "other.key" ,(call-with-input-file %ed25519bis-public-key-file
|
||||
get-string-all))
|
||||
(commit "keyring commit")
|
||||
(checkout "master"))
|
||||
(with-repository directory repository
|
||||
(let* ((commit1 (find-commit repository "first"))
|
||||
(commit2 (find-commit repository "second"))
|
||||
(commit3 (find-commit repository "third"))
|
||||
(intro ((@@ (guix channels) make-channel-introduction)
|
||||
(commit-id-string commit1)
|
||||
(openpgp-public-key-fingerprint
|
||||
(read-openpgp-packet
|
||||
%ed25519-public-key-file))
|
||||
#f)) ;no signature
|
||||
(channel (channel (name 'example)
|
||||
(url (string-append "file://" directory))
|
||||
(introduction intro))))
|
||||
;; COMMIT1 and COMMIT2 are fine.
|
||||
(and (authenticate-channel channel directory
|
||||
(commit-id-string commit2)
|
||||
#:keyring-reference-prefix "")
|
||||
|
||||
;; COMMIT3 is signed by an unauthorized key according to its
|
||||
;; parent's '.guix-authorizations' file.
|
||||
(guard (c ((unauthorized-commit-error? c)
|
||||
(and (oid=? (git-authentication-error-commit c)
|
||||
(commit-id commit3))
|
||||
(bytevector=?
|
||||
(openpgp-public-key-fingerprint
|
||||
(unauthorized-commit-error-signing-key c))
|
||||
(openpgp-public-key-fingerprint
|
||||
(read-openpgp-packet
|
||||
%ed25519bis-public-key-file))))))
|
||||
(authenticate-channel channel directory
|
||||
(commit-id-string commit3)
|
||||
#:keyring-reference-prefix "")
|
||||
'failed)))))))
|
||||
|
||||
(test-end "channels")
|
||||
|
||||
Reference in New Issue
Block a user