smime_certificate_spec.rb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe SMIMECertificate, type: :model do
  4. describe '.for_sender_email_address' do
  5. let(:lookup_address) { 'smime1@example.com' }
  6. context 'no certificate present' do
  7. it 'returns nil' do
  8. expect(described_class.for_sender_email_address(lookup_address)).to be_nil
  9. end
  10. end
  11. context 'certificate present' do
  12. context 'with private key' do
  13. let!(:certificate) { create(:smime_certificate, :with_private, fixture: lookup_address) }
  14. it 'returns certificate' do
  15. expect(described_class.for_sender_email_address(lookup_address)).to eq(certificate)
  16. end
  17. end
  18. context 'without private key' do
  19. before do
  20. create(:smime_certificate, fixture: lookup_address)
  21. end
  22. it 'returns nil' do
  23. expect(described_class.for_sender_email_address(lookup_address)).to be_nil
  24. end
  25. end
  26. context 'different letter case' do
  27. let(:fixture) { 'CaseInsenstive@eXample.COM' }
  28. let(:lookup_address) { 'CaseInsenStive@Example.coM' }
  29. context 'with private key' do
  30. let!(:certificate) { create(:smime_certificate, :with_private, fixture: fixture) }
  31. it 'returns certificate' do
  32. expect(described_class.for_sender_email_address(lookup_address)).to eq(certificate)
  33. end
  34. end
  35. end
  36. end
  37. end
  38. describe 'for_recipipent_email_addresses!' do
  39. context 'no certificate present' do
  40. let(:lookup_addresses) { ['smime1@example.com', 'smime2@example.com'] }
  41. it 'raises ActiveRecord::RecordNotFound' do
  42. expect { described_class.for_recipipent_email_addresses!(lookup_addresses) }.to raise_error(ActiveRecord::RecordNotFound)
  43. end
  44. end
  45. context 'not all certificates present' do
  46. let(:existing_address) { 'smime1@example.com' }
  47. let(:not_existing_address) { 'smime2@example.com' }
  48. let(:lookup_addresses) { [existing_address, not_existing_address] }
  49. before do
  50. create(:smime_certificate, fixture: existing_address)
  51. end
  52. it 'raises ActiveRecord::RecordNotFound' do
  53. expect { described_class.for_recipipent_email_addresses!(lookup_addresses) }.to raise_error(ActiveRecord::RecordNotFound)
  54. end
  55. context 'exception message' do
  56. let(:message) do
  57. described_class.for_recipipent_email_addresses!(lookup_addresses)
  58. rescue => e
  59. e.message
  60. end
  61. it 'does not contain found address' do
  62. expect(message).not_to include(existing_address)
  63. end
  64. it 'contains address not found' do
  65. expect(message).to include(not_existing_address)
  66. end
  67. end
  68. end
  69. context 'all certificates present' do
  70. let(:lookup_addresses) { ['smime1@example.com', 'smime2@example.com'] }
  71. let!(:certificates) do
  72. lookup_addresses.map do |existing_address|
  73. create(:smime_certificate, fixture: existing_address)
  74. end
  75. end
  76. it 'returns certificates' do
  77. expect(described_class.for_recipipent_email_addresses!(lookup_addresses)).to include(*certificates)
  78. end
  79. end
  80. context 'different letter case' do
  81. let(:fixture) { 'CaseInsenstive@eXample.COM' }
  82. let(:lookup_addresses) { ['CaseInsenStive@Example.coM'] }
  83. let!(:certificates) do
  84. [ create(:smime_certificate, fixture: fixture) ]
  85. end
  86. it 'returns certificates' do
  87. expect(described_class.for_recipipent_email_addresses!(lookup_addresses)).to eq(certificates)
  88. end
  89. end
  90. end
  91. describe '#email_addresses' do
  92. context 'certificate with single email address' do
  93. let(:email_address) { 'smime1@example.com' }
  94. let(:certificate) { create(:smime_certificate, fixture: email_address) }
  95. it 'returns the mail address' do
  96. expect(certificate.email_addresses).to eq([email_address])
  97. end
  98. end
  99. context 'certificate with multiple email addresses' do
  100. let(:email_addresses) { ['smimedouble@example.com', 'smimedouble@example.de'] }
  101. let(:certificate) { create(:smime_certificate, fixture: 'smimedouble@example.com') }
  102. it 'returns all mail addresses' do
  103. expect(certificate.email_addresses).to eq(email_addresses)
  104. end
  105. end
  106. end
  107. describe '#expired?' do
  108. let(:certificate) { create(:smime_certificate, fixture: fixture) }
  109. context 'expired' do
  110. let(:fixture) { 'expiredsmime1@example.com' }
  111. it 'returns true' do
  112. expect(certificate.expired?).to be true
  113. end
  114. end
  115. context 'valid' do
  116. let(:fixture) { 'smime1@example.com' }
  117. it 'returns false' do
  118. expect(certificate.expired?).to be false
  119. end
  120. end
  121. end
  122. context 'certificate parsing' do
  123. context 'expiration dates' do
  124. shared_examples 'correctly parsed' do |fixture|
  125. let(:certificate) { create(:smime_certificate, fixture: fixture) }
  126. it "handles '#{fixture}' fixture" do
  127. expect(certificate.not_before_at).to a_kind_of(ActiveSupport::TimeWithZone)
  128. expect(certificate.not_after_at).to a_kind_of(ActiveSupport::TimeWithZone)
  129. end
  130. end
  131. it_behaves_like 'correctly parsed', 'smime1@example.com'
  132. it_behaves_like 'correctly parsed', 'smime2@example.com'
  133. it_behaves_like 'correctly parsed', 'smime3@example.com'
  134. it_behaves_like 'correctly parsed', 'CaseInsenstive@eXample.COM'
  135. it_behaves_like 'correctly parsed', 'RootCA'
  136. it_behaves_like 'correctly parsed', 'IntermediateCA'
  137. it_behaves_like 'correctly parsed', 'ChainCA'
  138. end
  139. end
  140. it 'ensures uniqueness of records' do
  141. expect { create_list(:smime_certificate, 2, fixture: 'smime1@example.com') }.to raise_error(ActiveRecord::RecordInvalid, %r{Validation failed})
  142. end
  143. describe 'Cannot encrypt if multiple S/MIME certificates exist and one is expired #4029' do
  144. let(:lookup_address) { 'smime1@example.com' }
  145. before do
  146. create(:smime_certificate, :with_private, fixture: lookup_address, not_before_at: '2021-04-07', not_after_at: '2021-04-07', fingerprint: 'A')
  147. create(:smime_certificate, :with_private, fixture: lookup_address, not_before_at: '2022-04-07', not_after_at: '2042-04-07', fingerprint: 'B')
  148. end
  149. describe '.for_sender_email_address' do
  150. it 'does return the latest certificate when there is also an old expired certificate' do
  151. expect(described_class.for_sender_email_address('smime1@example.com').fingerprint).to eq('B')
  152. end
  153. end
  154. describe '.for_recipipent_email_addresses!' do
  155. it 'does return the latest certificate when there is also an old expired certificate' do
  156. expect(described_class.for_recipipent_email_addresses!(['smime1@example.com']).first.fingerprint).to eq('B')
  157. end
  158. end
  159. end
  160. end