|
| 1 | +// Copyright 2025 The Gitea Authors. All rights reserved. |
| 2 | +// SPDX-License-Identifier: MIT |
| 3 | + |
| 4 | +package asymkey |
| 5 | + |
| 6 | +import ( |
| 7 | + "strings" |
| 8 | + "testing" |
| 9 | + |
| 10 | + asymkey_model "code.gitea.io/gitea/models/asymkey" |
| 11 | + "code.gitea.io/gitea/models/db" |
| 12 | + "code.gitea.io/gitea/models/unittest" |
| 13 | + user_model "code.gitea.io/gitea/models/user" |
| 14 | + "code.gitea.io/gitea/modules/git" |
| 15 | + "code.gitea.io/gitea/modules/setting" |
| 16 | + "code.gitea.io/gitea/modules/test" |
| 17 | + |
| 18 | + "github.com/stretchr/testify/assert" |
| 19 | + "github.com/stretchr/testify/require" |
| 20 | +) |
| 21 | + |
| 22 | +func TestParseCommitWithSSHSignature(t *testing.T) { |
| 23 | + assert.NoError(t, unittest.PrepareTestDatabase()) |
| 24 | + |
| 25 | + // Here we only need to do some tests that "tests/integration/gpg_ssh_git_test.go" doesn't cover |
| 26 | + |
| 27 | + // -----BEGIN OPENSSH PRIVATE KEY----- |
| 28 | + // b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW |
| 29 | + // QyNTUxOQAAACC6T6zF0oPak8dOIzzT1kXB7LrcsVo04SKc3GjuvMllZwAAAJgy08upMtPL |
| 30 | + // qQAAAAtzc2gtZWQyNTUxOQAAACC6T6zF0oPak8dOIzzT1kXB7LrcsVo04SKc3GjuvMllZw |
| 31 | + // AAAEDWqPHTH51xb4hy1y1f1VeWL/2A9Q0b6atOyv5fx8x5prpPrMXSg9qTx04jPNPWRcHs |
| 32 | + // utyxWjThIpzcaO68yWVnAAAAEXVzZXIyQGV4YW1wbGUuY29tAQIDBA== |
| 33 | + // -----END OPENSSH PRIVATE KEY----- |
| 34 | + sshPubKey, err := asymkey_model.AddPublicKey(t.Context(), 999, "user-ssh-key-any-name", "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILpPrMXSg9qTx04jPNPWRcHsutyxWjThIpzcaO68yWVn", 0) |
| 35 | + require.NoError(t, err) |
| 36 | + _, err = db.GetEngine(t.Context()).ID(sshPubKey.ID).Cols("verified").Update(&asymkey_model.PublicKey{Verified: true}) |
| 37 | + require.NoError(t, err) |
| 38 | + |
| 39 | + t.Run("UserSSHKey", func(t *testing.T) { |
| 40 | + commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree a3b1fad553e0f9a2b4a58327bebde36c7da75aa2 |
| 41 | +author user2 <[email protected]> 1752194028 -0700 |
| 42 | +committer user2 <[email protected]> 1752194028 -0700 |
| 43 | +gpgsig -----BEGIN SSH SIGNATURE----- |
| 44 | + U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAguk+sxdKD2pPHTiM809ZFwey63L |
| 45 | + FaNOEinNxo7rzJZWcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 |
| 46 | + AAAAQBfX+6mcKZBnXckwHcBFqRuXMD3vTKi1yv5wgrqIxTyr2LWB97xxmO92cvjsr0POQ2 |
| 47 | + 2YA7mQS510Cg2s1uU1XAk= |
| 48 | + -----END SSH SIGNATURE----- |
| 49 | +
|
| 50 | +init project |
| 51 | +`)) |
| 52 | + require.NoError(t, err) |
| 53 | + |
| 54 | + // the committingUser is guaranteed by the caller, parseCommitWithSSHSignature doesn't do any more checks |
| 55 | + committingUser := &user_model.User{ID: 999, Name: "user-x"} |
| 56 | + ret := ParseCommitWithSSHSignature(t.Context(), commit, committingUser) |
| 57 | + require.NotNil(t, ret) |
| 58 | + assert.True(t, ret.Verified) |
| 59 | + assert.Equal(t, committingUser.Name+" / "+sshPubKey.Fingerprint, ret.Reason) |
| 60 | + assert.False(t, ret.Warning) |
| 61 | + assert.Equal(t, committingUser, ret.SigningUser) |
| 62 | + assert.Equal(t, committingUser, ret.CommittingUser) |
| 63 | + assert.Equal(t, sshPubKey.ID, ret.SigningSSHKey.ID) |
| 64 | + }) |
| 65 | + |
| 66 | + t.Run("TrustedSSHKey", func(t *testing.T) { |
| 67 | + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() |
| 68 | + defer test. MockVariableValue( &setting. Repository. Signing. SigningEmail, "[email protected]")() |
| 69 | + |
| 70 | + commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree 9a93ffa76e8b72bdb6431910b3a506fa2b39f42e |
| 71 | +author User Two <[email protected]> 1749230009 +0200 |
| 72 | +committer User Two <[email protected]> 1749230009 +0200 |
| 73 | +gpgsig -----BEGIN SSH SIGNATURE----- |
| 74 | + U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgfpjiJ1VpbcT5svDW6qgB8kPujl |
| 75 | + KK74epLnUT2hAs8T0AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 |
| 76 | + AAAAQDX2t2iHuuLxEWHLJetYXKsgayv3c43r0pJNfAzdLN55Q65pC5M7rG6++gT2bxcpOu |
| 77 | + Y6EXbpLqia9sunEF3+LQY= |
| 78 | + -----END SSH SIGNATURE----- |
| 79 | +
|
| 80 | +Initial commit with signed file |
| 81 | +`)) |
| 82 | + require.NoError(t, err) |
| 83 | + committingUser := &user_model.User{ |
| 84 | + ID: 2, |
| 85 | + Name: "User Two", |
| 86 | + |
| 87 | + } |
| 88 | + ret := ParseCommitWithSSHSignature(t.Context(), commit, committingUser) |
| 89 | + require.NotNil(t, ret) |
| 90 | + assert.True(t, ret.Verified) |
| 91 | + assert.False(t, ret.Warning) |
| 92 | + assert.Equal(t, committingUser, ret.CommittingUser) |
| 93 | + if assert.NotNil(t, ret.SigningUser) { |
| 94 | + assert.Equal(t, "gitea", ret.SigningUser.Name) |
| 95 | + assert. Equal( t, "[email protected]", ret. SigningUser. Email) |
| 96 | + } |
| 97 | + }) |
| 98 | +} |
0 commit comments