/spec/lib/gitlab/gpg/commit_spec.rb

https://gitlab.com/solidnerd/gitlab-ce · Ruby · 269 lines · 223 code · 45 blank · 1 comment · 0 complexity · 9d9c31787d569297495c8536f69e84a0 MD5 · raw file

  1. require 'rails_helper'
  2. describe Gitlab::Gpg::Commit do
  3. describe '#signature' do
  4. shared_examples 'returns the cached signature on second call' do
  5. it 'returns the cached signature on second call' do
  6. gpg_commit = described_class.new(commit)
  7. expect(gpg_commit).to receive(:using_keychain).and_call_original
  8. gpg_commit.signature
  9. # consecutive call
  10. expect(gpg_commit).not_to receive(:using_keychain).and_call_original
  11. gpg_commit.signature
  12. end
  13. end
  14. let!(:project) { create :project, :repository, path: 'sample-project' }
  15. let!(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
  16. context 'unsigned commit' do
  17. let!(:commit) { create :commit, project: project, sha: commit_sha }
  18. it 'returns nil' do
  19. expect(described_class.new(commit).signature).to be_nil
  20. end
  21. end
  22. context 'known key' do
  23. context 'user matches the key uid' do
  24. context 'user email matches the email committer' do
  25. let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User1.emails.first }
  26. let!(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
  27. let!(:gpg_key) do
  28. create :gpg_key, key: GpgHelpers::User1.public_key, user: user
  29. end
  30. before do
  31. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  32. .with(Gitlab::Git::Repository, commit_sha)
  33. .and_return(
  34. [
  35. GpgHelpers::User1.signed_commit_signature,
  36. GpgHelpers::User1.signed_commit_base_data
  37. ]
  38. )
  39. end
  40. it 'returns a valid signature' do
  41. signature = described_class.new(commit).signature
  42. expect(signature).to have_attributes(
  43. commit_sha: commit_sha,
  44. project: project,
  45. gpg_key: gpg_key,
  46. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  47. gpg_key_user_name: GpgHelpers::User1.names.first,
  48. gpg_key_user_email: GpgHelpers::User1.emails.first,
  49. verification_status: 'verified'
  50. )
  51. expect(signature.persisted?).to be_truthy
  52. end
  53. it_behaves_like 'returns the cached signature on second call'
  54. context 'read-only mode' do
  55. before do
  56. allow(Gitlab::Database).to receive(:read_only?).and_return(true)
  57. end
  58. it 'does not create a cached signature' do
  59. signature = described_class.new(commit).signature
  60. expect(signature).to have_attributes(
  61. commit_sha: commit_sha,
  62. project: project,
  63. gpg_key: gpg_key,
  64. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  65. gpg_key_user_name: GpgHelpers::User1.names.first,
  66. gpg_key_user_email: GpgHelpers::User1.emails.first,
  67. verification_status: 'verified'
  68. )
  69. expect(signature.persisted?).to be_falsey
  70. end
  71. end
  72. end
  73. context 'commit signed with a subkey' do
  74. let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User3.emails.first }
  75. let!(:user) { create(:user, email: GpgHelpers::User3.emails.first) }
  76. let!(:gpg_key) do
  77. create :gpg_key, key: GpgHelpers::User3.public_key, user: user
  78. end
  79. let(:gpg_key_subkey) do
  80. gpg_key.subkeys.find_by(fingerprint: '0522DD29B98F167CD8421752E38FFCAF75ABD92A')
  81. end
  82. before do
  83. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  84. .with(Gitlab::Git::Repository, commit_sha)
  85. .and_return(
  86. [
  87. GpgHelpers::User3.signed_commit_signature,
  88. GpgHelpers::User3.signed_commit_base_data
  89. ]
  90. )
  91. end
  92. it 'returns a valid signature' do
  93. expect(described_class.new(commit).signature).to have_attributes(
  94. commit_sha: commit_sha,
  95. project: project,
  96. gpg_key: gpg_key_subkey,
  97. gpg_key_primary_keyid: gpg_key_subkey.keyid,
  98. gpg_key_user_name: GpgHelpers::User3.names.first,
  99. gpg_key_user_email: GpgHelpers::User3.emails.first,
  100. verification_status: 'verified'
  101. )
  102. end
  103. it_behaves_like 'returns the cached signature on second call'
  104. end
  105. context 'user email does not match the committer email, but is the same user' do
  106. let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User2.emails.first }
  107. let(:user) do
  108. create(:user, email: GpgHelpers::User1.emails.first).tap do |user|
  109. create :email, user: user, email: GpgHelpers::User2.emails.first
  110. end
  111. end
  112. let!(:gpg_key) do
  113. create :gpg_key, key: GpgHelpers::User1.public_key, user: user
  114. end
  115. before do
  116. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  117. .with(Gitlab::Git::Repository, commit_sha)
  118. .and_return(
  119. [
  120. GpgHelpers::User1.signed_commit_signature,
  121. GpgHelpers::User1.signed_commit_base_data
  122. ]
  123. )
  124. end
  125. it 'returns an invalid signature' do
  126. expect(described_class.new(commit).signature).to have_attributes(
  127. commit_sha: commit_sha,
  128. project: project,
  129. gpg_key: gpg_key,
  130. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  131. gpg_key_user_name: GpgHelpers::User1.names.first,
  132. gpg_key_user_email: GpgHelpers::User1.emails.first,
  133. verification_status: 'same_user_different_email'
  134. )
  135. end
  136. it_behaves_like 'returns the cached signature on second call'
  137. end
  138. context 'user email does not match the committer email' do
  139. let!(:commit) { create :commit, project: project, sha: commit_sha, committer_email: GpgHelpers::User2.emails.first }
  140. let(:user) { create(:user, email: GpgHelpers::User1.emails.first) }
  141. let!(:gpg_key) do
  142. create :gpg_key, key: GpgHelpers::User1.public_key, user: user
  143. end
  144. before do
  145. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  146. .with(Gitlab::Git::Repository, commit_sha)
  147. .and_return(
  148. [
  149. GpgHelpers::User1.signed_commit_signature,
  150. GpgHelpers::User1.signed_commit_base_data
  151. ]
  152. )
  153. end
  154. it 'returns an invalid signature' do
  155. expect(described_class.new(commit).signature).to have_attributes(
  156. commit_sha: commit_sha,
  157. project: project,
  158. gpg_key: gpg_key,
  159. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  160. gpg_key_user_name: GpgHelpers::User1.names.first,
  161. gpg_key_user_email: GpgHelpers::User1.emails.first,
  162. verification_status: 'other_user'
  163. )
  164. end
  165. it_behaves_like 'returns the cached signature on second call'
  166. end
  167. end
  168. context 'user does not match the key uid' do
  169. let!(:commit) { create :commit, project: project, sha: commit_sha }
  170. let(:user) { create(:user, email: GpgHelpers::User2.emails.first) }
  171. let!(:gpg_key) do
  172. create :gpg_key, key: GpgHelpers::User1.public_key, user: user
  173. end
  174. before do
  175. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  176. .with(Gitlab::Git::Repository, commit_sha)
  177. .and_return(
  178. [
  179. GpgHelpers::User1.signed_commit_signature,
  180. GpgHelpers::User1.signed_commit_base_data
  181. ]
  182. )
  183. end
  184. it 'returns an invalid signature' do
  185. expect(described_class.new(commit).signature).to have_attributes(
  186. commit_sha: commit_sha,
  187. project: project,
  188. gpg_key: gpg_key,
  189. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  190. gpg_key_user_name: GpgHelpers::User1.names.first,
  191. gpg_key_user_email: GpgHelpers::User1.emails.first,
  192. verification_status: 'unverified_key'
  193. )
  194. end
  195. it_behaves_like 'returns the cached signature on second call'
  196. end
  197. end
  198. context 'unknown key' do
  199. let!(:commit) { create :commit, project: project, sha: commit_sha }
  200. before do
  201. allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
  202. .with(Gitlab::Git::Repository, commit_sha)
  203. .and_return(
  204. [
  205. GpgHelpers::User1.signed_commit_signature,
  206. GpgHelpers::User1.signed_commit_base_data
  207. ]
  208. )
  209. end
  210. it 'returns an invalid signature' do
  211. expect(described_class.new(commit).signature).to have_attributes(
  212. commit_sha: commit_sha,
  213. project: project,
  214. gpg_key: nil,
  215. gpg_key_primary_keyid: GpgHelpers::User1.primary_keyid,
  216. gpg_key_user_name: nil,
  217. gpg_key_user_email: nil,
  218. verification_status: 'unknown_key'
  219. )
  220. end
  221. it_behaves_like 'returns the cached signature on second call'
  222. end
  223. end
  224. end