You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ssh_key_test.go 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "path/filepath"
  10. "testing"
  11. "time"
  12. auth_model "code.gitea.io/gitea/models/auth"
  13. "code.gitea.io/gitea/modules/git"
  14. api "code.gitea.io/gitea/modules/structs"
  15. "github.com/stretchr/testify/assert"
  16. )
  17. func doCheckRepositoryEmptyStatus(ctx APITestContext, isEmpty bool) func(*testing.T) {
  18. return doAPIGetRepository(ctx, func(t *testing.T, repository api.Repository) {
  19. assert.Equal(t, isEmpty, repository.Empty)
  20. })
  21. }
  22. func doAddChangesToCheckout(dstPath, filename string) func(*testing.T) {
  23. return func(t *testing.T) {
  24. assert.NoError(t, os.WriteFile(filepath.Join(dstPath, filename), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s at time: %v", dstPath, time.Now())), 0o644))
  25. assert.NoError(t, git.AddChanges(dstPath, true))
  26. signature := git.Signature{
  27. Email: "test@example.com",
  28. Name: "test",
  29. When: time.Now(),
  30. }
  31. assert.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
  32. Committer: &signature,
  33. Author: &signature,
  34. Message: "Initial Commit",
  35. }))
  36. }
  37. }
  38. func TestPushDeployKeyOnEmptyRepo(t *testing.T) {
  39. onGiteaRun(t, testPushDeployKeyOnEmptyRepo)
  40. }
  41. func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
  42. // OK login
  43. ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  44. ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  45. keyname := fmt.Sprintf("%s-push", ctx.Reponame)
  46. u.Path = ctx.GitPath()
  47. t.Run("CreateEmptyRepository", doAPICreateRepository(ctx, true))
  48. t.Run("CheckIsEmpty", doCheckRepositoryEmptyStatus(ctx, true))
  49. withKeyFile(t, keyname, func(keyFile string) {
  50. t.Run("CreatePushDeployKey", doAPICreateDeployKey(ctx, keyname, keyFile, false))
  51. // Setup the testing repository
  52. dstPath := t.TempDir()
  53. t.Run("InitTestRepository", doGitInitTestRepository(dstPath))
  54. // Setup remote link
  55. sshURL := createSSHUrl(ctx.GitPath(), u)
  56. t.Run("AddRemote", doGitAddRemote(dstPath, "origin", sshURL))
  57. t.Run("SSHPushTestRepository", doGitPushTestRepository(dstPath, "origin", "master"))
  58. t.Run("CheckIsNotEmpty", doCheckRepositoryEmptyStatus(ctx, false))
  59. t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
  60. })
  61. }
  62. func TestKeyOnlyOneType(t *testing.T) {
  63. onGiteaRun(t, testKeyOnlyOneType)
  64. }
  65. func testKeyOnlyOneType(t *testing.T, u *url.URL) {
  66. // Once a key is a user key we cannot use it as a deploy key
  67. // If we delete it from the user we should be able to use it as a deploy key
  68. reponame := "ssh-key-test-repo"
  69. username := "user2"
  70. u.Path = fmt.Sprintf("%s/%s.git", username, reponame)
  71. keyname := fmt.Sprintf("%s-push", reponame)
  72. // OK login
  73. ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  74. ctxWithDeleteRepo := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
  75. otherCtx := ctx
  76. otherCtx.Reponame = "ssh-key-test-repo-2"
  77. otherCtxWithDeleteRepo := ctxWithDeleteRepo
  78. otherCtxWithDeleteRepo.Reponame = otherCtx.Reponame
  79. failCtx := ctx
  80. failCtx.ExpectedCode = http.StatusUnprocessableEntity
  81. t.Run("CreateRepository", doAPICreateRepository(ctx, false))
  82. t.Run("CreateOtherRepository", doAPICreateRepository(otherCtx, false))
  83. withKeyFile(t, keyname, func(keyFile string) {
  84. var userKeyPublicKeyID int64
  85. t.Run("KeyCanOnlyBeUser", func(t *testing.T) {
  86. dstPath := t.TempDir()
  87. sshURL := createSSHUrl(ctx.GitPath(), u)
  88. t.Run("FailToClone", doGitCloneFail(sshURL))
  89. t.Run("CreateUserKey", doAPICreateUserKey(ctx, keyname, keyFile, func(t *testing.T, publicKey api.PublicKey) {
  90. userKeyPublicKeyID = publicKey.ID
  91. }))
  92. t.Run("FailToAddReadOnlyDeployKey", doAPICreateDeployKey(failCtx, keyname, keyFile, true))
  93. t.Run("FailToAddDeployKey", doAPICreateDeployKey(failCtx, keyname, keyFile, false))
  94. t.Run("Clone", doGitClone(dstPath, sshURL))
  95. t.Run("AddChanges", doAddChangesToCheckout(dstPath, "CHANGES1.md"))
  96. t.Run("Push", doGitPushTestRepository(dstPath, "origin", "master"))
  97. t.Run("DeleteUserKey", doAPIDeleteUserKey(ctx, userKeyPublicKeyID))
  98. })
  99. t.Run("KeyCanBeAnyDeployButNotUserAswell", func(t *testing.T) {
  100. dstPath := t.TempDir()
  101. sshURL := createSSHUrl(ctx.GitPath(), u)
  102. t.Run("FailToClone", doGitCloneFail(sshURL))
  103. // Should now be able to add...
  104. t.Run("AddReadOnlyDeployKey", doAPICreateDeployKey(ctx, keyname, keyFile, true))
  105. t.Run("Clone", doGitClone(dstPath, sshURL))
  106. t.Run("AddChanges", doAddChangesToCheckout(dstPath, "CHANGES2.md"))
  107. t.Run("FailToPush", doGitPushTestRepositoryFail(dstPath, "origin", "master"))
  108. otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
  109. dstOtherPath := t.TempDir()
  110. t.Run("AddWriterDeployKeyToOther", doAPICreateDeployKey(otherCtx, keyname, keyFile, false))
  111. t.Run("CloneOther", doGitClone(dstOtherPath, otherSSHURL))
  112. t.Run("AddChangesToOther", doAddChangesToCheckout(dstOtherPath, "CHANGES3.md"))
  113. t.Run("PushToOther", doGitPushTestRepository(dstOtherPath, "origin", "master"))
  114. t.Run("FailToCreateUserKey", doAPICreateUserKey(failCtx, keyname, keyFile))
  115. })
  116. t.Run("DeleteRepositoryShouldReleaseKey", func(t *testing.T) {
  117. otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
  118. dstOtherPath := t.TempDir()
  119. t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
  120. t.Run("FailToCreateUserKeyAsStillDeploy", doAPICreateUserKey(failCtx, keyname, keyFile))
  121. t.Run("MakeSureCloneOtherStillWorks", doGitClone(dstOtherPath, otherSSHURL))
  122. t.Run("AddChangesToOther", doAddChangesToCheckout(dstOtherPath, "CHANGES3.md"))
  123. t.Run("PushToOther", doGitPushTestRepository(dstOtherPath, "origin", "master"))
  124. t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtxWithDeleteRepo))
  125. t.Run("RecreateRepository", doAPICreateRepository(ctxWithDeleteRepo, false))
  126. t.Run("CreateUserKey", doAPICreateUserKey(ctx, keyname, keyFile, func(t *testing.T, publicKey api.PublicKey) {
  127. userKeyPublicKeyID = publicKey.ID
  128. }))
  129. dstPath := t.TempDir()
  130. sshURL := createSSHUrl(ctx.GitPath(), u)
  131. t.Run("Clone", doGitClone(dstPath, sshURL))
  132. t.Run("AddChanges", doAddChangesToCheckout(dstPath, "CHANGES1.md"))
  133. t.Run("Push", doGitPushTestRepository(dstPath, "origin", "master"))
  134. })
  135. t.Run("DeleteUserKeyShouldRemoveAbilityToClone", func(t *testing.T) {
  136. sshURL := createSSHUrl(ctx.GitPath(), u)
  137. t.Run("DeleteUserKey", doAPIDeleteUserKey(ctx, userKeyPublicKeyID))
  138. t.Run("FailToClone", doGitCloneFail(sshURL))
  139. })
  140. })
  141. }