smime_certificate_spec.rb 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe SMIMECertificate, type: :model do
  4. describe '.find_for_multiple_email_addresses' do
  5. let(:filter) { { key: key_filter, usage: usage_filter, ignore_usable: ignore_usable_filter } }
  6. context 'send encrypted mail to recipient' do
  7. let(:ignore_usable_filter) { false }
  8. let(:key_filter) { 'public' }
  9. let(:usage_filter) { :encryption }
  10. context 'when recipient certificate is missing' do
  11. it 'returns no certificate' do
  12. expect { described_class.find_for_multiple_email_addresses!(['smime1@example.com'], filter: filter, blame: true) }.to raise_error(ActiveRecord::RecordNotFound)
  13. end
  14. end
  15. context 'when recipient certificate is available and usable for encryption' do
  16. let!(:certificate) { create(:smime_certificate, fixture: 'alice@acme.corp+sign+encrypt') }
  17. it 'returns the certificate' do
  18. expect(described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true)).to eq([certificate])
  19. end
  20. end
  21. context 'when recipient certificate is available, but not usable for encryption' do
  22. before do
  23. create(:smime_certificate, fixture: 'alice@acme.corp+sign')
  24. end
  25. it 'returns no certificate' do
  26. expect { described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true) }.to raise_error(ActiveRecord::RecordNotFound)
  27. end
  28. end
  29. context 'when multiple recipient certificates are available' do
  30. let!(:certificate) do
  31. create(:smime_certificate, fixture: 'alice@acme.corp+sign')
  32. create(:smime_certificate, fixture: 'alice@acme.corp+encrypt')
  33. end
  34. it 'only returns certificates usable for encryption' do
  35. expect(described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true)).to eq([certificate])
  36. end
  37. end
  38. end
  39. context 'receive signed e-mail' do
  40. let(:ignore_usable_filter) { false }
  41. let(:key_filter) { 'public' }
  42. let(:usage_filter) { :signature }
  43. context 'when sender certificate is not usable for signature verification' do # rubocop:disable RSpec/RepeatedExampleGroupBody
  44. before do
  45. create(:smime_certificate, fixture: 'alice@acme.corp+encrypt')
  46. end
  47. it 'returns no certificate' do
  48. expect { described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true) }.to raise_error(ActiveRecord::RecordNotFound)
  49. end
  50. end
  51. context 'when sender certificate is usable for signature verification' do
  52. let!(:certificate) { create(:smime_certificate, fixture: 'alice@acme.corp+sign+encrypt') }
  53. it 'returns the certificate' do
  54. expect(described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true)).to eq([certificate])
  55. end
  56. end
  57. context 'when sender certificate is only usable for encryption' do # rubocop:disable RSpec/RepeatedExampleGroupBody
  58. before do
  59. create(:smime_certificate, fixture: 'alice@acme.corp+encrypt')
  60. end
  61. it 'returns no certificate' do
  62. expect { described_class.find_for_multiple_email_addresses!(['alice@acme.corp'], filter: filter, blame: true) }.to raise_error(ActiveRecord::RecordNotFound)
  63. end
  64. end
  65. context 'when sender certificate is missing' do
  66. it 'returns no certificate' do
  67. expect { described_class.find_for_multiple_email_addresses!(['smime1@example.com'], filter: filter, blame: true) }.to raise_error(ActiveRecord::RecordNotFound)
  68. end
  69. end
  70. end
  71. context 'send signed e-mail' do
  72. let(:ignore_usable_filter) { false }
  73. let(:key_filter) { 'private' }
  74. let(:usage_filter) { :signature }
  75. context 'when no sender private key is available' do
  76. before { create(:smime_certificate, fixture: 'alice@acme.corp+sign') }
  77. it 'returns no certificate' do
  78. expect(described_class.find_by_email_address('alice@acme.corp', filter: filter)).to eq([])
  79. end
  80. end
  81. context 'when the sender certificate has expired' do
  82. before do
  83. create(:smime_certificate, :with_private, fixture: 'alice@acme.corp+sign+encrypt+expired')
  84. end
  85. it 'returns no certificate' do
  86. expect(described_class.find_by_email_address('alice@acme.corp', filter: filter)).to eq([])
  87. end
  88. end
  89. context 'when a sender certificate with a private key is present' do
  90. let!(:certificate) { create(:smime_certificate, :with_private, fixture: 'alice@acme.corp+sign') }
  91. it 'returns the certificate' do
  92. expect(described_class.find_by_email_address('alice@acme.corp', filter: filter)).to eq([certificate])
  93. end
  94. end
  95. context 'when an expired sender certificate and an usable sender certificate is available' do
  96. let!(:usable_certificate) { create(:smime_certificate, :with_private, fixture: 'alice@acme.corp+sign+encrypt') }
  97. before do
  98. create(:smime_certificate, :with_private, fixture: 'alice@acme.corp+sign+encrypt+expired')
  99. end
  100. it 'returns the usable certificate' do
  101. expect(described_class.find_by_email_address('alice@acme.corp', filter: filter)).to eq([usable_certificate])
  102. end
  103. end
  104. end
  105. end
  106. describe '#email_addresses' do
  107. context 'certificate with single email address' do
  108. let(:email_address) { 'smime1@example.com' }
  109. let(:certificate) { create(:smime_certificate, fixture: email_address) }
  110. it 'returns the mail address' do
  111. expect(certificate.email_addresses).to eq([email_address])
  112. end
  113. end
  114. context 'certificate with multiple email addresses' do
  115. let(:email_addresses) { ['smimedouble@example.com', 'smimedouble@example.de'] }
  116. let(:certificate) { create(:smime_certificate, fixture: 'smimedouble@example.com') }
  117. it 'returns all mail addresses' do
  118. expect(certificate.email_addresses).to eq(email_addresses)
  119. end
  120. end
  121. end
  122. describe '#expired?' do
  123. let(:certificate) { create(:smime_certificate, fixture: fixture) }
  124. context 'expired' do
  125. let(:fixture) { 'expiredsmime1@example.com' }
  126. it 'returns true' do
  127. expect(certificate.parsed.expired?).to be true
  128. end
  129. end
  130. context 'valid' do
  131. let(:fixture) { 'smime1@example.com' }
  132. it 'returns false' do
  133. expect(certificate.parsed.expired?).to be false
  134. end
  135. end
  136. end
  137. context 'certificate parsing' do
  138. context 'expiration dates' do
  139. shared_examples 'correctly parsed' do |fixture|
  140. let(:certificate) { create(:smime_certificate, fixture: fixture) }
  141. it "handles '#{fixture}' fixture" do
  142. expect(certificate.parsed.not_before).to a_kind_of(Time)
  143. expect(certificate.parsed.not_after).to a_kind_of(Time)
  144. end
  145. end
  146. it_behaves_like 'correctly parsed', 'smime1@example.com'
  147. it_behaves_like 'correctly parsed', 'smime2@example.com'
  148. it_behaves_like 'correctly parsed', 'smime3@example.com'
  149. it_behaves_like 'correctly parsed', 'CaseInsenstive@eXample.COM'
  150. it_behaves_like 'correctly parsed', 'RootCA'
  151. it_behaves_like 'correctly parsed', 'IntermediateCA'
  152. it_behaves_like 'correctly parsed', 'ChainCA'
  153. end
  154. end
  155. it 'ensures uniqueness of records' do
  156. expect { create_list(:smime_certificate, 2, fixture: 'smime1@example.com') }.to raise_error(ActiveRecord::RecordInvalid, %r{Validation failed})
  157. end
  158. end