diff --git a/Gemfile b/Gemfile index b518920..9fdab9d 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,6 @@ source 'https://rubygems.org' gemspec group :development, :test do - gem 'rspec', '~> 3.12' - gem 'faker', '~> 3.1', '>= 3.1.1' -end \ No newline at end of file + gem 'rspec', '~> 3.12' + gem 'faker', '~> 3.1', '>= 3.1.1' +end diff --git a/lib/pki_express.rb b/lib/pki_express.rb index f631f77..c10e9c4 100644 --- a/lib/pki_express.rb +++ b/lib/pki_express.rb @@ -11,6 +11,7 @@ require_relative 'pki_express/authentication' require_relative 'pki_express/cades_signature' require_relative 'pki_express/cades_signature_starter' +require_relative 'pki_express/cades_signer' require_relative 'pki_express/check_service_result' require_relative 'pki_express/command_error' require_relative 'pki_express/commands' diff --git a/lib/pki_express/cades_signer.rb b/lib/pki_express/cades_signer.rb new file mode 100644 index 0000000..ae8581b --- /dev/null +++ b/lib/pki_express/cades_signer.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module PkiExpress + class CadesSigner < Signer + attr_accessor :commitment_type, :encapsulated_content + attr_accessor :overwrite_original_file, :output_file_path + + def initialize(config = PkiExpressConfig.new) + super(config) + @version_manager = VersionManager.new + @encapsulated_content = true + @commitment_type = false + @overwrite_original_file = false + end + + def pdf_to_sign_path=(path) + raise 'The provided file to be signed was not found' unless File.exist?(path) + + @pdf_to_sign_path = path + end + + def sign(get_cert = false) + raise 'The file to be signed was not set' unless @pdf_to_sign_path + if @overwrite_original_file == false && @output_file_path.nil? + raise 'The output destination was not set' + end + + args = [@pdf_to_sign_path] + + # Logic to overwrite original file or use the output file + if @overwrite_original_file + args.append('--overwrite') + else + args.append(@output_file_path) + end + + # Verify and add common options between signers + verify_and_add_common_options(args) + + unless @encapsulated_content + args.append('--detached') + end + + if @commitment_type + args.append('--commitment-type', @commitment_type) + end + + if get_cert + # This operation can only be used on + # version greater than 1.8 of the PKI Express. + @version_manager.require_version('1.8') + # Invoke command. + result = invoke(Commands::SIGN_CADES, args) + + # Parse output and return model. + model = JSON.parse(Base64.decode64(result[0])) + PKCertificate.new(model['signer']) + else + # This operation can only be used on + # version greater than 1.3 of the PKI Express. + @version_manager.require_version('1.3') + + invoke_plain(Commands::SIGN_CADES, args) + end + end + end +end diff --git a/lib/pki_express/commands.rb b/lib/pki_express/commands.rb index 1f158f9..c14e308 100644 --- a/lib/pki_express/commands.rb +++ b/lib/pki_express/commands.rb @@ -1,25 +1,27 @@ +# frozen_string_literal: true + module PkiExpress class Commands - SIGN_CADES = 'sign-cades', - SIGN_PADES = 'sign-pades', - SIGN_XML = 'sign-xml', - START_CADES = 'start-cades', - START_PADES = 'start-pades', - START_XML = 'start-xml', - COMPLETE_SIG = 'complete-sig', - OPEN_PADES = 'open-pades', - OPEN_CADES = 'open-cades', - EDIT_PDF = 'edit-pdf', - MERGE_CMS = 'merge-cms', - START_AUTH = 'start-auth', - COMPLETE_AUTH = 'complete-auth', - STAMP_PDF = 'stamp-pdf', - READ_CERT = 'read-cert', - GEN_KEY = 'gen-key', - CREATE_PFX = 'create-pfx', - CHECK_SERVICE = 'check-service', - DISCOVER_SERVICES = 'discover-services', - PASSWORD_AUTHORIZE = 'pwd-auth', + SIGN_CADES = 'sign-cades' + SIGN_PADES = 'sign-pades' + SIGN_XML = 'sign-xml' + START_CADES = 'start-cades' + START_PADES = 'start-pades' + START_XML = 'start-xml' + COMPLETE_SIG = 'complete-sig' + OPEN_PADES = 'open-pades' + OPEN_CADES = 'open-cades' + EDIT_PDF = 'edit-pdf' + MERGE_CMS = 'merge-cms' + START_AUTH = 'start-auth' + COMPLETE_AUTH = 'complete-auth' + STAMP_PDF = 'stamp-pdf' + READ_CERT = 'read-cert' + GEN_KEY = 'gen-key' + CREATE_PFX = 'create-pfx' + CHECK_SERVICE = 'check-service' + DISCOVER_SERVICES = 'discover-services' + PASSWORD_AUTHORIZE = 'pwd-auth' COMPLETE_SERVICE_AUTH = 'complete-service-auth' end -end \ No newline at end of file +end diff --git a/spec/fixtures/sample.file b/spec/fixtures/sample.file new file mode 100644 index 0000000..e69de29 diff --git a/spec/pki_express/cades_signer_spec.rb b/spec/pki_express/cades_signer_spec.rb new file mode 100644 index 0000000..206ffec --- /dev/null +++ b/spec/pki_express/cades_signer_spec.rb @@ -0,0 +1,130 @@ +require_relative '../spec_helper' + +module PkiExpress + class CadesSigner < Signer + def invoke(command, args = [], _plain_output) + { command: command, args: args } + end + end +end + +module PkiExpress + describe CadesSigner do + let(:cades_signer) { PkiExpress::CadesSigner.new } + + describe 'initializer' do + it { expect(cades_signer).to be_a(PkiExpress::CadesSigner) } + it { expect(cades_signer.encapsulated_content).to be_truthy } + it { expect(cades_signer.encapsulated_content).to be_truthy } + it { expect(cades_signer.commitment_type).to be_falsey } + it { expect(cades_signer.overwrite_original_file).to be_falsey } + + it do + expect(cades_signer.instance_variable_get(:@version_manager)) + .to be_a(PkiExpress::VersionManager) + end + end + + describe '#pdf_to_sign_path=' do + context 'when the file exists' do + it do + expect { cades_signer.pdf_to_sign_path = ('./spec/fixtures/invalid.pdf') } + .to raise_error(StandardError, 'The provided file to be signed was not found') + end + end + + context 'when the file does not exist' do + it do + cades_signer.pdf_to_sign_path = ('./spec/fixtures/sample.file') + + expect(cades_signer.instance_variable_get(:@pdf_to_sign_path)) + .to eq('./spec/fixtures/sample.file') + end + end + end + + describe '#sign' do + let(:cades_signer) { PkiExpress::CadesSigner.new } + + before do + cades_signer.pdf_to_sign_path = ('./spec/fixtures/sample.file') + cades_signer.output_file_path = ('/tmp/output.file') + + allow(cades_signer).to receive(:verify_and_add_common_options).and_return(true) + end + + it do + expect(cades_signer.sign).to eq( + command: 'sign-cades', + args: %w[./spec/fixtures/sample.file /tmp/output.file] + ) + end + + context 'when overwrite_original_file is true' do + it do + cades_signer.overwrite_original_file = true + + expect(cades_signer.sign).to eq( + command: 'sign-cades', + args: %w[./spec/fixtures/sample.file --overwrite] + ) + end + end + + context 'when encapsulated_content is not true' do + it do + cades_signer.encapsulated_content = false + + expect(cades_signer.sign).to eq( + command: 'sign-cades', + args: %w[./spec/fixtures/sample.file /tmp/output.file --detached] + ) + end + end + + context 'when commitment_type is true' do + it do + cades_signer.commitment_type = true + + expect(cades_signer.sign).to eq( + command: 'sign-cades', + args: [ + './spec/fixtures/sample.file', + '/tmp/output.file', + '--commitment-type', + true + ] + ) + end + end + + context 'when get_cert is true' do + let(:version_manager) { cades_signer.instance_variable_get(:@version_manager) } + + before do + allow(version_manager).to receive(:require_version).and_call_original + end + + it do + begin; cades_signer.sign(true); rescue; end + + expect(version_manager).to have_received(:require_version).with('1.8').once + end + end + + context 'when get_cert is not true' do + let(:version_manager) { cades_signer.instance_variable_get(:@version_manager) } + + before do + allow(version_manager).to receive(:require_version).and_call_original + end + + it do + cades_signer.sign(false) + + expect(version_manager).to have_received(:require_version).with('1.3').once + end + end + end + end +end diff --git a/spec/pki_express/pki_express_config_spec.rb b/spec/pki_express/pki_express_config_spec.rb index d9aa2d2..054caa7 100644 --- a/spec/pki_express/pki_express_config_spec.rb +++ b/spec/pki_express/pki_express_config_spec.rb @@ -3,71 +3,71 @@ require_relative '../spec_helper' module PkiExpress - describe PkiExpressConfig do - it 'should set valid default values when no value is passed in contructor' do - config = PkiExpressConfig.new - expect(config.pki_express_home).to be_nil - expect(File.directory?(config.temp_folder)).to be(true) - expect(File.directory?(config.transfer_data_folder)).to be(true) - end + describe PkiExpressConfig do + it 'should set valid default values when no value is passed in contructor' do + config = PkiExpressConfig.new + expect(config.pki_express_home).to be_nil + expect(File.directory?(config.temp_folder)).to be(true) + expect(File.directory?(config.transfer_data_folder)).to be(true) + end - it 'should set pki_express_home folder when a valid path is passed' do - fake_pki_express_home = Dir.mktmpdir('pkie') - config = PkiExpressConfig.new(fake_pki_express_home) - expect(config.pki_express_home).to equal(fake_pki_express_home) - Dir.rmdir(fake_pki_express_home) - end + it 'should set pki_express_home folder when a valid path is passed' do + fake_pki_express_home = Dir.mktmpdir('pkie') + config = PkiExpressConfig.new(fake_pki_express_home) + expect(config.pki_express_home).to equal(fake_pki_express_home) + Dir.rmdir(fake_pki_express_home) + end - it 'should raise ArgumentError when an invalid path is passed' do - expect { PkiExpressConfig.new(Faker::String.random) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when an invalid path is passed' do + expect { PkiExpressConfig.new(Faker::String.random) }.to raise_error(ArgumentError) + end - it 'should raise ArgumentError when a path is passed but doesn\'t exist' do - fake_pki_express_home = Faker::File.dir - expect { PkiExpressConfig.new(fake_pki_express_home) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when a path is passed but doesn\'t exist' do + fake_pki_express_home = Faker::File.dir + expect { PkiExpressConfig.new(fake_pki_express_home) }.to raise_error(ArgumentError) + end - it 'should set temp_folder when a valid path is passed' do - fake_temp_folder = Dir.mktmpdir('pkie') - config = PkiExpressConfig.new(nil, fake_temp_folder) - expect(config.temp_folder).to equal(fake_temp_folder) - Dir.rmdir(fake_temp_folder) - end + it 'should set temp_folder when a valid path is passed' do + fake_temp_folder = Dir.mktmpdir('pkie') + config = PkiExpressConfig.new(nil, fake_temp_folder) + expect(config.temp_folder).to equal(fake_temp_folder) + Dir.rmdir(fake_temp_folder) + end - it 'should set temp_folder with a default folder when no path is passed' do - config1 = PkiExpressConfig.new - config2 = PkiExpressConfig.new - expect(config1.temp_folder).to equal(config2.temp_folder) - end + it 'should set temp_folder with a default folder when no path is passed' do + config1 = PkiExpressConfig.new + config2 = PkiExpressConfig.new + expect(config1.temp_folder).to equal(config2.temp_folder) + end - it 'should raise ArgumentError when an invalid path is passed' do - expect { PkiExpressConfig.new(nil, Faker::String.random) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when an invalid path is passed' do + expect { PkiExpressConfig.new(nil, Faker::String.random) }.to raise_error(ArgumentError) + end - it 'should raise ArgumentError when a path is passed but doesn\'t exist' do - fake_pki_express_home = Faker::File.dir - expect { PkiExpressConfig.new(nil, fake_pki_express_home) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when a path is passed but doesn\'t exist' do + fake_pki_express_home = Faker::File.dir + expect { PkiExpressConfig.new(nil, fake_pki_express_home) }.to raise_error(ArgumentError) + end - it 'should set transfer_data_folder when a valid path is passed' do - fake_transfer_data_folder = Dir.mktmpdir('pkie') - config = PkiExpressConfig.new(nil, nil, fake_transfer_data_folder) - expect(config.transfer_data_folder).to equal(fake_transfer_data_folder) - Dir.rmdir(fake_transfer_data_folder) - end + it 'should set transfer_data_folder when a valid path is passed' do + fake_transfer_data_folder = Dir.mktmpdir('pkie') + config = PkiExpressConfig.new(nil, nil, fake_transfer_data_folder) + expect(config.transfer_data_folder).to equal(fake_transfer_data_folder) + Dir.rmdir(fake_transfer_data_folder) + end - it 'should set transfer_data_folder with temp_folder value when no path is passed' do - config = PkiExpressConfig.new - expect(config.transfer_data_folder).to equal(config.temp_folder) - end + it 'should set transfer_data_folder with temp_folder value when no path is passed' do + config = PkiExpressConfig.new + expect(config.transfer_data_folder).to equal(config.temp_folder) + end - it 'should raise ArgumentError when an invalid path is passed' do - expect { PkiExpressConfig.new(nil, nil, Faker::String.random) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when an invalid path is passed' do + expect { PkiExpressConfig.new(nil, nil, Faker::String.random) }.to raise_error(ArgumentError) + end - it 'should raise ArgumentError when a path is passed but doesn\'t exist' do - fake_pki_express_home = Faker::File.dir - expect { PkiExpressConfig.new(nil, nil, fake_pki_express_home) }.to raise_error(ArgumentError) - end + it 'should raise ArgumentError when a path is passed but doesn\'t exist' do + fake_pki_express_home = Faker::File.dir + expect { PkiExpressConfig.new(nil, nil, fake_pki_express_home) }.to raise_error(ArgumentError) end -end \ No newline at end of file + end +end diff --git a/spec/pki_express/pki_express_operator_spec.rb b/spec/pki_express/pki_express_operator_spec.rb index 38bd36a..6589f47 100644 --- a/spec/pki_express/pki_express_operator_spec.rb +++ b/spec/pki_express/pki_express_operator_spec.rb @@ -1,31 +1,31 @@ require_relative '../spec_helper' module PkiExpress - describe PkiExpressOperator do - it "should remove files created by child classes when GC remove its instance" do - operator = ChildOperator.new - temp_files = [] - (1..3).each { - created_file = operator.create_temp_file - temp_files.append(created_file) - expect(File.exist?(created_file)).to equal(true) - } - operator = nil - GC.start + describe PkiExpressOperator do + it "should remove files created by child classes when GC remove its instance" do + operator = ChildOperator.new + temp_files = [] + (1..3).each { + created_file = operator.create_temp_file + temp_files.append(created_file) + expect(File.exist?(created_file)).to equal(true) + } + operator = nil + GC.start - temp_files.each do |file| - expect(File.exist?(file)).to equal(false) - end - end + temp_files.each do |file| + expect(File.exist?(file)).to equal(false) + end end - - class ChildOperator < PkiExpressOperator - def initialize(config=PkiExpressConfig.new) - super(config) - end + end - def create_temp_file - super - end + class ChildOperator < PkiExpressOperator + def initialize(config=PkiExpressConfig.new) + super(config) end -end \ No newline at end of file + + def create_temp_file + super + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 92d36a4..c82936b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'json' +require 'base64' + require_relative '../lib/pki_express' RSpec.configure do |config|