[GITEA] Add noreply email address as verified for SSH signed Git commits
- When someone really wants to avoid sharing their email, they could
configure git to use the noreply email for git commits. However if they
also wanted to use SSH signing, it would not show up as verified as the
noreply email address was technically not an activated email address for
the user.
- Add unit tests for the `ParseCommitWithSSHSignature` function.
- Resolves https://codeberg.org/Codeberg/Community/issues/946
(cherry picked from commit 1685de7eba
)
This commit is contained in:
parent
9f6bffdaf9
commit
b1e8858de9
4 changed files with 166 additions and 0 deletions
|
@ -14,6 +14,7 @@ func TestMain(m *testing.M) {
|
||||||
FixtureFiles: []string{
|
FixtureFiles: []string{
|
||||||
"gpg_key.yml",
|
"gpg_key.yml",
|
||||||
"public_key.yml",
|
"public_key.yml",
|
||||||
|
"TestParseCommitWithSSHSignature/public_key.yml",
|
||||||
"deploy_key.yml",
|
"deploy_key.yml",
|
||||||
"gpg_key_import.yml",
|
"gpg_key_import.yml",
|
||||||
"user.yml",
|
"user.yml",
|
||||||
|
|
|
@ -36,6 +36,12 @@ func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *
|
||||||
log.Error("GetEmailAddresses: %v", err)
|
log.Error("GetEmailAddresses: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the noreply email address as verified address.
|
||||||
|
committerEmailAddresses = append(committerEmailAddresses, &user_model.EmailAddress{
|
||||||
|
IsActivated: true,
|
||||||
|
Email: committer.GetPlaceholderEmail(),
|
||||||
|
})
|
||||||
|
|
||||||
activated := false
|
activated := false
|
||||||
for _, e := range committerEmailAddresses {
|
for _, e := range committerEmailAddresses {
|
||||||
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
|
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
|
||||||
|
|
146
models/asymkey/ssh_key_commit_verification_test.go
Normal file
146
models/asymkey/ssh_key_commit_verification_test.go
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright 2023 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package asymkey
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseCommitWithSSHSignature(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
sshKey := unittest.AssertExistsAndLoadBean(t, &PublicKey{ID: 1000, OwnerID: 2})
|
||||||
|
|
||||||
|
t.Run("No commiter", func(t *testing.T) {
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, &git.Commit{}, &user_model.User{})
|
||||||
|
assert.False(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, NoKeyFound, commitVerification.Reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Commiter without keys", func(t *testing.T) {
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, &git.Commit{Committer: &git.Signature{Email: user.Email}}, user)
|
||||||
|
assert.False(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, NoKeyFound, commitVerification.Reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Correct signature with wrong email", func(t *testing.T) {
|
||||||
|
gitCommit := &git.Commit{
|
||||||
|
Committer: &git.Signature{
|
||||||
|
Email: "non-existent",
|
||||||
|
},
|
||||||
|
Signature: &git.CommitGPGSignature{
|
||||||
|
Payload: `tree 2d491b2985a7ff848d5c02748e7ea9f9f7619f9f
|
||||||
|
parent 45b03601635a1f463b81963a4022c7f87ce96ef9
|
||||||
|
author user2 <non-existent> 1699710556 +0100
|
||||||
|
committer user2 <non-existent> 1699710556 +0100
|
||||||
|
|
||||||
|
Using email that isn't known to Forgejo
|
||||||
|
`,
|
||||||
|
Signature: `-----BEGIN SSH SIGNATURE-----
|
||||||
|
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgoGSe9Zy7Ez9bSJcaTNjh/Y7p95
|
||||||
|
f5DujjqkpzFRtw6CEAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
|
||||||
|
AAAAQIMufOuSjZeDUujrkVK4sl7ICa0WwEftas8UAYxx0Thdkiw2qWjR1U1PKfTLm16/w8
|
||||||
|
/bS1LX1lZNuzm2LR2qEgw=
|
||||||
|
-----END SSH SIGNATURE-----
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, gitCommit, user2)
|
||||||
|
assert.False(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, NoKeyFound, commitVerification.Reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Incorrect signature with correct email", func(t *testing.T) {
|
||||||
|
gitCommit := &git.Commit{
|
||||||
|
Committer: &git.Signature{
|
||||||
|
Email: "user2@example.com",
|
||||||
|
},
|
||||||
|
Signature: &git.CommitGPGSignature{
|
||||||
|
Payload: `tree 853694aae8816094a0d875fee7ea26278dbf5d0f
|
||||||
|
parent c2780d5c313da2a947eae22efd7dacf4213f4e7f
|
||||||
|
author user2 <user2@example.com> 1699707877 +0100
|
||||||
|
committer user2 <user2@example.com> 1699707877 +0100
|
||||||
|
|
||||||
|
Add content
|
||||||
|
`,
|
||||||
|
Signature: `-----BEGIN SSH SIGNATURE-----`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, gitCommit, user2)
|
||||||
|
assert.False(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, NoKeyFound, commitVerification.Reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Valid signature with correct email", func(t *testing.T) {
|
||||||
|
gitCommit := &git.Commit{
|
||||||
|
Committer: &git.Signature{
|
||||||
|
Email: "user2@example.com",
|
||||||
|
},
|
||||||
|
Signature: &git.CommitGPGSignature{
|
||||||
|
Payload: `tree 853694aae8816094a0d875fee7ea26278dbf5d0f
|
||||||
|
parent c2780d5c313da2a947eae22efd7dacf4213f4e7f
|
||||||
|
author user2 <user2@example.com> 1699707877 +0100
|
||||||
|
committer user2 <user2@example.com> 1699707877 +0100
|
||||||
|
|
||||||
|
Add content
|
||||||
|
`,
|
||||||
|
Signature: `-----BEGIN SSH SIGNATURE-----
|
||||||
|
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgoGSe9Zy7Ez9bSJcaTNjh/Y7p95
|
||||||
|
f5DujjqkpzFRtw6CEAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
|
||||||
|
AAAAQBe2Fwk/FKY3SBCnG6jSYcO6ucyahp2SpQ/0P+otslzIHpWNW8cQ0fGLdhhaFynJXQ
|
||||||
|
fs9cMpZVM9BfIKNUSO8QY=
|
||||||
|
-----END SSH SIGNATURE-----
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, gitCommit, user2)
|
||||||
|
assert.True(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, "user2 / SHA256:TKfwbZMR7e9OnlV2l1prfah1TXH8CmqR0PvFEXVCXA4", commitVerification.Reason)
|
||||||
|
assert.Equal(t, sshKey, commitVerification.SigningSSHKey)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Valid signature with noreply email", func(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.Service.NoReplyAddress, "noreply.example.com")()
|
||||||
|
|
||||||
|
gitCommit := &git.Commit{
|
||||||
|
Committer: &git.Signature{
|
||||||
|
Email: "user2@noreply.example.com",
|
||||||
|
},
|
||||||
|
Signature: &git.CommitGPGSignature{
|
||||||
|
Payload: `tree 4836c7f639f37388bab4050ef5c97bbbd54272fc
|
||||||
|
parent 795be1b0117ea5c65456050bb9fd84744d4fd9c6
|
||||||
|
author user2 <user2@noreply.example.com> 1699709594 +0100
|
||||||
|
committer user2 <user2@noreply.example.com> 1699709594 +0100
|
||||||
|
|
||||||
|
Commit with noreply
|
||||||
|
`,
|
||||||
|
Signature: `-----BEGIN SSH SIGNATURE-----
|
||||||
|
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgoGSe9Zy7Ez9bSJcaTNjh/Y7p95
|
||||||
|
f5DujjqkpzFRtw6CEAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
|
||||||
|
AAAAQJz83KKxD6Bz/ZvNpqkA3RPOSQ4LQ5FfEItbtoONkbwV9wAWMnmBqgggo/lnXCJ3oq
|
||||||
|
muPLbvEduU+Ze/1Ol1pgk=
|
||||||
|
-----END SSH SIGNATURE-----
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
commitVerification := ParseCommitWithSSHSignature(db.DefaultContext, gitCommit, user2)
|
||||||
|
assert.True(t, commitVerification.Verified)
|
||||||
|
assert.Equal(t, "user2 / SHA256:TKfwbZMR7e9OnlV2l1prfah1TXH8CmqR0PvFEXVCXA4", commitVerification.Reason)
|
||||||
|
assert.Equal(t, sshKey, commitVerification.SigningSSHKey)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
-
|
||||||
|
id: 1000
|
||||||
|
owner_id: 2
|
||||||
|
name: user2@localhost
|
||||||
|
fingerprint: "SHA256:TKfwbZMR7e9OnlV2l1prfah1TXH8CmqR0PvFEXVCXA4"
|
||||||
|
content: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKBknvWcuxM/W0iXGkzY4f2O6feX+Q7o46pKcxUbcOgh user2@localhost"
|
||||||
|
# private key (base64-ed) LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFNd0FBQUF0emMyZ3RaVwpReU5UVXhPUUFBQUNDZ1pKNzFuTHNUUDF0SWx4cE0yT0g5anVuM2wva082T09xU25NVkczRG9JUUFBQUpocG43YTZhWisyCnVnQUFBQXR6YzJndFpXUXlOVFV4T1FBQUFDQ2daSjcxbkxzVFAxdElseHBNMk9IOWp1bjNsL2tPNk9PcVNuTVZHM0RvSVEKQUFBRUFxVm12bmo1LzZ5TW12ck9Ub29xa3F5MmUrc21aK0tBcEtKR0crRnY5MlA2QmtudldjdXhNL1cwaVhHa3pZNGYyTwo2ZmVYK1E3bzQ2cEtjeFViY09naEFBQUFFMmQxYzNSbFpFQm5kWE4wWldRdFltVmhjM1FCQWc9PQotLS0tLUVORCBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0=
|
||||||
|
mode: 2
|
||||||
|
type: 1
|
||||||
|
verified: true
|
||||||
|
created_unix: 1559593109
|
||||||
|
updated_unix: 1565224552
|
||||||
|
login_source_id: 0
|
Loading…
Reference in a new issue