internetee-registry/test/services/certificates/certificate_generator_test.rb
oleghasjanov 0fe20bd63b Fixed Certificate#update_crl test to properly verify CRL updater script call
The test for Certificate.update_crl was failing because it didn't correctly
match how the system method is called in the CertificateConcern module.
The implementation calls system with '/bin/bash' as the first argument
and the crl_updater_path as the second argument, but the test was
expecting different parameters.

- Simplified the test_update_crl_should_call_crl_updater_script test to
  directly verify the script path is used without trying to intercept
  the system call
- Added proper environment variable handling for crl_updater_path
- Ensured original method is restored after test execution
2025-04-16 11:47:52 +03:00

321 lines
No EOL
14 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'test_helper'
module Certificates
class CertificateGeneratorTest < ActiveSupport::TestCase
setup do
@generator = Certificates::CertificateGenerator.new(
username: 'test_user',
registrar_code: '1234',
registrar_name: 'Test Registrar',
interface: 'api'
)
end
## Тесты для публичных методов
test "call генерирует CSR, ключ, сертификат и P12, если user_csr не передан" do
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
interface: "api"
)
# Мокаем файловые операции, чтобы избежать ошибок
mock_file = Minitest::Mock.new
mock_file.expect :write, true, [String] # Для ключа, CSR, CRT, P12
File.stub :open, ->(path, mode) { mock_file } do
result = generator.call
assert_instance_of String, result[:private_key], "Приватный ключ должен быть строкой"
assert_instance_of String, result[:csr], "CSR должен быть строкой PEM"
assert_instance_of String, result[:crt], "Сертификат должен быть строкой PEM"
assert_instance_of String, result[:p12], "P12 должен быть строкой DER"
assert_not_nil result[:expires_at], "Дата истечения должна быть установлена"
end
end
test "call использует переданный user_csr и не создает ключ и P12" do
# Создаем ключ и корректный CSR
key = OpenSSL::PKey::RSA.new(2048)
user_csr = OpenSSL::X509::Request.new
user_csr.version = 0
user_csr.subject = OpenSSL::X509::Name.new([["CN", "test_user"]])
user_csr.public_key = key.public_key
user_csr.sign(key, OpenSSL::Digest::SHA256.new)
user_csr_pem = user_csr.to_pem
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
user_csr: user_csr_pem,
interface: "api"
)
result = generator.call
assert_nil result[:private_key], "Приватный ключ не должен генерироваться"
assert_nil result[:p12], "P12 не должен создаваться"
assert_equal user_csr_pem, result[:csr], "CSR должен соответствовать переданному"
assert_not_nil result[:crt], "Сертификат должен быть создан"
assert_not_nil result[:expires_at], "Дата истечения должна быть установлена"
end
test "renew_certificate обновляет сертификат существующего пользователя" do
# Создаем мок-объект существующего сертификата
certificate = Certificate.new
certificate.interface = 'api'
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
certificate: certificate,
interface: "api"
)
mock_file = Minitest::Mock.new
mock_file.expect :write, true, [String] # Для файловых операций
File.stub :open, ->(path, mode) { mock_file } do
result = generator.renew_certificate
assert_instance_of String, result[:crt], "Сертификат должен быть создан"
assert_not_nil result[:expires_at], "Дата истечения должна быть установлена"
end
end
test "renew_certificate вызывает исключение, если сертификат не передан" do
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
interface: "api"
)
assert_raises(RuntimeError, "Certificate must be provided for renewal") do
generator.renew_certificate
end
end
test "renew_certificate с переданным CSR использует этот CSR" do
# Создаем ключ и корректный CSR
key = OpenSSL::PKey::RSA.new(2048)
user_csr = OpenSSL::X509::Request.new
user_csr.version = 0
user_csr.subject = OpenSSL::X509::Name.new([["CN", "test_user"]])
user_csr.public_key = key.public_key
user_csr.sign(key, OpenSSL::Digest::SHA256.new)
user_csr_pem = user_csr.to_pem
# Создаем мок-объект существующего сертификата
certificate = Certificate.new
certificate.interface = 'api'
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
certificate: certificate,
user_csr: user_csr_pem,
interface: "api"
)
result = generator.renew_certificate
assert_nil result[:private_key], "Приватный ключ не должен генерироваться"
assert_nil result[:p12], "P12 не должен создаваться"
assert_equal user_csr_pem, result[:csr], "CSR должен соответствовать переданному"
assert_not_nil result[:crt], "Сертификат должен быть создан"
end
## Тесты для приватных методов
test "generate_from_csr создает сертификат из CSR без ключа и P12" do
# Создаем ключ и корректный CSR
key = OpenSSL::PKey::RSA.new(2048)
user_csr = OpenSSL::X509::Request.new
user_csr.version = 0
user_csr.subject = OpenSSL::X509::Name.new([["CN", "test_user"]])
user_csr.public_key = key.public_key
user_csr.sign(key, OpenSSL::Digest::SHA256.new)
user_csr_pem = user_csr.to_pem
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
user_csr: user_csr_pem,
interface: "api"
)
result = generator.send(:generate_from_csr)
assert_nil result[:private_key], "Приватный ключ не должен генерироваться"
assert_nil result[:p12], "P12 не должен создаваться"
assert_instance_of String, result[:csr], "CSR должен быть строкой PEM"
assert_instance_of String, result[:crt], "Сертификат должен быть строкой PEM"
assert_not_nil result[:expires_at], "Дата истечения должна быть установлена"
end
test "generate_new_certificate создает новый ключ, CSR, сертификат и P12" do
mock_file = Minitest::Mock.new
mock_file.expect :write, true, [String] # Для файловых операций
File.stub :open, ->(path, mode) { mock_file } do
result = @generator.send(:generate_new_certificate)
assert_instance_of String, result[:private_key], "Приватный ключ должен быть строкой"
assert_instance_of String, result[:csr], "CSR должен быть строкой PEM"
assert_instance_of String, result[:crt], "Сертификат должен быть строкой PEM"
assert_instance_of String, result[:p12], "P12 должен быть строкой DER"
assert_not_nil result[:expires_at], "Дата истечения должна быть установлена"
end
end
test "generate_csr_and_key создает CSR и ключ" do
rsa_key = OpenSSL::PKey::RSA.new(4096)
csr = OpenSSL::X509::Request.new
OpenSSL::PKey::RSA.stub :new, rsa_key do
OpenSSL::X509::Request.stub :new, csr do
generated_csr, generated_key = @generator.send(:generate_csr_and_key)
assert_equal csr, generated_csr, "CSR должен быть сгенерирован"
assert_equal rsa_key, generated_key, "Ключ должен быть сгенерирован"
end
end
end
test "sign_certificate подписывает CSR с использованием CA" do
key = OpenSSL::PKey::RSA.new(2048)
csr = OpenSSL::X509::Request.new
csr.version = 0
csr.subject = OpenSSL::X509::Name.new([["CN", "test_user"]])
csr.public_key = key.public_key
csr.sign(key, OpenSSL::Digest::SHA256.new)
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
interface: "api"
)
# Мокаем файловые операции для сохранения сертификата
mock_file = Minitest::Mock.new
mock_file.expect :write, true, [String]
File.stub :open, ->(path, mode) { mock_file } do
cert = generator.send(:sign_certificate, csr)
assert_instance_of OpenSSL::X509::Certificate, cert, "Должен вернуться сертификат"
assert_equal csr.subject.to_s, cert.subject.to_s, "Субъект должен совпадать"
end
end
test "create_p12 создает PKCS12 с ключом и сертификатом" do
key = OpenSSL::PKey::RSA.new(2048)
cert = OpenSSL::X509::Certificate.new
ca_cert = OpenSSL::X509::Certificate.new
p12 = OpenSSL::PKCS12.new
File.stub :read, ca_cert.to_pem do
OpenSSL::X509::Certificate.stub :new, ca_cert do
OpenSSL::PKCS12.stub :create, p12 do
result = @generator.send(:create_p12, key, cert)
assert_equal p12, result, "PKCS12 должен быть создан"
end
end
end
end
test "ensure_directories_exist создает необходимые директории" do
FileUtils.stub :mkdir_p, true do
FileUtils.stub :chmod, true do
assert_nothing_raised do
@generator.send(:ensure_directories_exist)
end
end
end
end
test "ensure_ca_exists проверяет наличие CA файлов и логирует предупреждение" do
Rails.logger.expects(:warn).at_least_once
# Мокаем отсутствие CA файлов
File.stub :exist?, false do
# Вызываем приватный метод
@generator.send(:ensure_ca_exists)
end
end
test "ensure_crl_exists создает CRL, если он отсутствует" do
# Создаем мок-объект для файла
mock_file = Minitest::Mock.new
mock_file.expect :write, true, [String] # Ожидаем вызов write с аргументом типа String
# Мокаем File.open, чтобы он возвращал наш мок-объект
File.stub :open, ->(path, mode) { mock_file } do
# Мокаем отсутствие CRL файла
File.stub :exist?, false do
# Мокаем существование CA сертификата и ключа, если они нужны для логики
File.stub :exist?, true, [Certificates::CertificateGenerator::CA_CERT_PATHS['api']] do
File.stub :exist?, true, [Certificates::CertificateGenerator::CA_KEY_PATHS['api']] do
# Создаем экземпляр класса
generator = Certificates::CertificateGenerator.new(
username: "test_user",
registrar_code: "1234",
registrar_name: "Test Registrar",
interface: "api"
)
# Вызываем приватный метод
generator.send(:ensure_crl_exists)
end
end
end
end
# Проверяем, что все ожидаемые вызовы были выполнены
mock_file.verify
end
test "generate_unique_serial возвращает уникальный серийный номер" do
serial1 = @generator.send(:generate_unique_serial)
serial2 = @generator.send(:generate_unique_serial)
assert_not_equal serial1, serial2, "Серийные номера должны быть уникальными"
assert_instance_of Integer, serial1, "Серийный номер должен быть числом"
end
test "save_private_key сохраняет зашифрованный ключ" do
key = OpenSSL::PKey::RSA.new(2048)
encrypted_key = key.export(OpenSSL::Cipher.new('AES-256-CBC'), Certificates::CertificateGenerator::CA_PASSWORD)
File.stub :write, true do
FileUtils.stub :chmod, true do
assert_nothing_raised do
@generator.send(:save_private_key, encrypted_key)
end
end
end
end
test "save_csr сохраняет CSR" do
csr = OpenSSL::X509::Request.new
File.stub :write, true do
assert_nothing_raised do
@generator.send(:save_csr, csr)
end
end
end
test "save_certificate сохраняет сертификат" do
cert = OpenSSL::X509::Certificate.new
File.stub :write, true do
assert_nothing_raised do
@generator.send(:save_certificate, cert)
end
end
end
end
end