gittuf/internal/gitinterface/commit_test.go
Aditya Sirish 0d4be41b91
Early gitsign support
This commit introduces early, experimental support for gitsign
signatures on git commits. It uses TAP-18 to specify sigstore identity
constraints in delegations.

The feature introduced here depends on unreleased prototype code in
go-securesystemslib and is also insufficiently tested due to some
sigstore library constraints.

See: #73

Signed-off-by: Aditya Sirish <aditya@saky.in>
2023-08-07 15:27:37 -04:00

198 lines
6 KiB
Go

package gitinterface
import (
"bytes"
"context"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/adityasaky/gittuf/internal/signerverifier"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
format "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/jonboulle/clockwork"
sslibsv "github.com/secure-systems-lab/go-securesystemslib/signerverifier"
"github.com/stretchr/testify/assert"
)
func TestCreateCommitObject(t *testing.T) {
gitConfig := &config.Config{
Raw: &format.Config{
Sections: format.Sections{
&format.Section{
Name: "user",
Options: format.Options{
&format.Option{
Key: "name",
Value: "Jane Doe",
},
&format.Option{
Key: "email",
Value: "jane.doe@example.com",
},
},
},
},
},
}
clock := clockwork.NewFakeClockAt(time.Date(1995, time.October, 26, 9, 0, 0, 0, time.UTC))
commit := createCommitObject(gitConfig, plumbing.ZeroHash, plumbing.ZeroHash, "Test commit", clock)
enc := memory.NewStorage().NewEncodedObject()
if err := commit.Encode(enc); err != nil {
t.Error(err)
}
assert.Equal(t, plumbing.NewHash("dce09cc0f41eaa323f6949142d66ead789f40f6f"), enc.Hash())
}
func TestVerifyCommitSignature(t *testing.T) {
gpgSignedCommit := createTestSignedCommit(t)
// FIXME: fix gitsign testing
gitsignSignedCommit := &object.Commit{
Hash: plumbing.NewHash("d6b230478965e25477263aa65f1ca6d23d0c0d97"),
Author: object.Signature{
Name: "Aditya Sirish",
Email: "aditya@saky.in",
When: time.Date(2023, time.August, 1, 15, 44, 23, 0, time.FixedZone("", -4*3600)),
},
Committer: object.Signature{
Name: "Aditya Sirish",
Email: "aditya@saky.in",
When: time.Date(2023, time.August, 1, 15, 44, 23, 0, time.FixedZone("", -4*3600)),
},
PGPSignature: `-----BEGIN SIGNED MESSAGE-----
MIIEMAYJKoZIhvcNAQcCoIIEITCCBB0CAQExDTALBglghkgBZQMEAgEwCwYJKoZI
hvcNAQcBoIIC0DCCAswwggJToAMCAQICFHIJCrBVHxoHlGos++k1xJxcElGaMAoG
CCqGSM49BAMDMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2ln
c3RvcmUtaW50ZXJtZWRpYXRlMB4XDTIzMDgwMTE5NDQzMVoXDTIzMDgwMTE5NTQz
MVowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD8d752TJfGtANVYoiJJn+o6
JPKj5NwEZs1AcVRT2qElikVun5t+bQ07iDFa/Xiun5ytZrEK2YJVgqdntLd6hSOj
ggFyMIIBbjAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYD
VR0OBBYEFAuYzgyBA01YSSN1v0fYenGo7+PcMB8GA1UdIwQYMBaAFN/T6c9WJBGW
+ajY6ShVosYuGGQ/MBwGA1UdEQEB/wQSMBCBDmFkaXR5YUBzYWt5LmluMCwGCisG
AQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEE
AYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBigYKKwYB
BAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6O
AAABibKhcJgAAAQDAEcwRQIgcWuz6NhFgdL0fNni6j0SOQnAgFpPEaN8jDH70mbD
uPMCIQCX8koEnIX4c9crMT1hfoBBf1Z/CHJ6HLLHpQwWfEUMIzAKBggqhkjOPQQD
AwNnADBkAjBozIBaBtEu7JUyYLH7Ly698E0o8DdIOmqcUMUYWNC6zyJVdrL5gAla
mQSxfObSQasCMHQuw8youTjmFJXT7pNOYX4DW25knt+6P+W/m6zwcRRe3dMjmUAB
gdBJb32+XXJMRDGCASYwggEiAgEBME8wNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2
MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUCFHIJCrBVHxoHlGos++k1
xJxcElGaMAsGCWCGSAFlAwQCAaBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEw
HAYJKoZIhvcNAQkFMQ8XDTIzMDgwMTE5NDQzMlowLwYJKoZIhvcNAQkEMSIEIBe6
VHcVlkO8jRm/fbUipwxwxNaI7UFDAL38Jl8eUj/5MAoGCCqGSM49BAMCBEgwRgIh
AIYiRbnVeWjjgX2XwljDryzQN5RhUQaVH/AcUj+tbvWxAiEAhm9l3BU58tQsgyJW
oYBpMWLgg6AUzpxx9mITZ2EKr4c=
-----END SIGNED MESSAGE-----
`,
Message: "Test commit\n",
TreeHash: plumbing.NewHash("4b825dc642cb6eb9a060e54bf8d69288fbee4904"),
}
keyBytes, err := os.ReadFile(filepath.Join("test-data", "gpg-pubkey.asc"))
if err != nil {
t.Fatal(err)
}
gpgKey := &sslibsv.SSLibKey{
KeyType: signerverifier.GPGKeyType,
Scheme: signerverifier.GPGKeyType,
KeyVal: sslibsv.KeyVal{
Public: strings.TrimSpace(string(keyBytes)),
},
}
fulcioKey := &sslibsv.SSLibKey{
KeyType: signerverifier.FulcioKeyType,
Scheme: "fulcio",
KeyVal: sslibsv.KeyVal{
Identity: "aditya@saky.in",
Issuer: "https://github.com/login/oauth",
},
}
t.Run("gpg signed commit", func(t *testing.T) {
err = VerifyCommitSignature(context.Background(), gpgSignedCommit, gpgKey)
assert.Nil(t, err)
})
// FIXME: fix gitsign testing
// t.Run("gitsign signed commit", func(t *testing.T) {
// err := VerifyCommitSignature(context.Background(), gitsignSignedCommit, fulcioKey)
// assert.Nil(t, err)
// })
t.Run("use gpg signed commit with gitsign key", func(t *testing.T) {
err := VerifyCommitSignature(context.Background(), gpgSignedCommit, fulcioKey)
assert.ErrorIs(t, err, ErrIncorrectVerificationKey)
})
t.Run("use gitsign signed commit with gpg key", func(t *testing.T) {
err := VerifyCommitSignature(context.Background(), gitsignSignedCommit, gpgKey)
assert.ErrorIs(t, err, ErrIncorrectVerificationKey)
})
}
func createTestSignedCommit(t *testing.T) *object.Commit {
t.Helper()
repo, err := git.Init(memory.NewStorage(), memfs.New())
if err != nil {
t.Fatal(err)
}
clock := clockwork.NewFakeClockAt(time.Date(1995, time.October, 26, 9, 0, 0, 0, time.UTC))
testCommit := &object.Commit{
Author: object.Signature{
Name: "Jane Doe",
Email: "jane.doe@example.com",
When: clock.Now(),
},
Committer: object.Signature{
Name: "Jane Doe",
Email: "jane.doe@example.com",
When: clock.Now(),
},
Message: "Test commit",
TreeHash: plumbing.ZeroHash,
}
commitEncoded := repo.Storer.NewEncodedObject()
if err := testCommit.EncodeWithoutSignature(commitEncoded); err != nil {
t.Fatal(err)
}
r, err := commitEncoded.Reader()
if err != nil {
t.Fatal(err)
}
signingKeyBytes, err := os.ReadFile(filepath.Join("test-data", "gpg-privkey.asc"))
if err != nil {
t.Fatal(err)
}
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(signingKeyBytes))
if err != nil {
t.Fatal(err)
}
sig := new(strings.Builder)
if err := openpgp.ArmoredDetachSign(sig, keyring[0], r, nil); err != nil {
t.Fatal(err)
}
testCommit.PGPSignature = sig.String()
return testCommit
}