diff --git a/Gemfile.lock b/Gemfile.lock index 164602a8ef2..56607b7fda8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,10 +29,10 @@ GIT GIT remote: https://github.com/18F/identity-idp-functions.git - revision: 44f46a7fe2afa7894c665b09fd015fe41fd86450 - ref: 44f46a7fe2afa7894c665b09fd015fe41fd86450 + revision: 67f44016ca8c58ebaf46c969401da941a06eefd6 + ref: 67f44016ca8c58ebaf46c969401da941a06eefd6 specs: - identity-idp-functions (0.6.0) + identity-idp-functions (0.7.6) aws-sdk-s3 (>= 1.73) aws-sdk-ssm (>= 1.55) retries (>= 0.0.5) diff --git a/app/controllers/lambda_callback/document_proof_result_controller.rb b/app/controllers/lambda_callback/document_proof_result_controller.rb index ef992405a3b..30dff6ba6c3 100644 --- a/app/controllers/lambda_callback/document_proof_result_controller.rb +++ b/app/controllers/lambda_callback/document_proof_result_controller.rb @@ -15,8 +15,18 @@ def result_id_parameter end def document_result_parameter - params.require(:document_result).permit(:exception, :success, :timed_out, - errors: {}, context: {}) + params.require(:document_result).permit( + :billed, + :exception, + :raw_alerts, + :result, + :success, + :timed_out, + context: {}, + errors: {}, + pii_from_doc: {}, + raw_alerts: [], + ) end def track_exception_in_result(result) diff --git a/app/jobs/vendor_document_verification_job.rb b/app/jobs/vendor_document_verification_job.rb deleted file mode 100644 index 34a148f3564..00000000000 --- a/app/jobs/vendor_document_verification_job.rb +++ /dev/null @@ -1,16 +0,0 @@ -class VendorDocumentVerificationJob - # rubocop:disable Lint/UnusedMethodArgument - def self.perform(document_capture_session_result_id:, - encryption_key:, - front_image_iv:, - back_image_iv:, - selfie_image_iv:, - front_image_url:, - back_image_url:, - selfie_image_url:, - liveness_checking_enabled:) - - FormResponse.new(success: true, errors: {}) - end - # rubocop:enable Lint/UnusedMethodArgument -end diff --git a/app/services/idv/actions/verify_document_action.rb b/app/services/idv/actions/verify_document_action.rb index f7298d8d0b0..a9bf267864e 100644 --- a/app/services/idv/actions/verify_document_action.rb +++ b/app/services/idv/actions/verify_document_action.rb @@ -33,19 +33,31 @@ def enqueue_job verify_document_capture_session_uuid_key, ) document_capture_session.requested_at = Time.zone.now - document_capture_session.store_proofing_pii_from_doc({}) + document_capture_session.store_proofing_pii_from_doc({}) # generates a result_id - VendorDocumentVerificationJob.perform( - document_capture_session_result_id: document_capture_session.result_id, - encryption_key: params[:encryption_key], - front_image_iv: params[:front_image_iv], - back_image_iv: params[:back_image_iv], - selfie_image_iv: params[:selfie_image_iv], - front_image_url: params[:front_image_url], - back_image_url: params[:back_image_url], - selfie_image_url: params[:selfie_image_url], - liveness_checking_enabled: params[:liveness_checking_enabled], + callback_url = Rails.application.routes.url_helpers.document_proof_result_url( + result_id: document_capture_session.result_id, ) + + LambdaJobs::Runner.new( + job_class: Idv::Proofer.document_job_class, + args: { + encryption_key: params[:encryption_key], + front_image_iv: params[:front_image_iv], + back_image_iv: params[:back_image_iv], + selfie_image_iv: params[:selfie_image_iv], + front_image_url: params[:front_image_url], + back_image_url: params[:back_image_url], + selfie_image_url: params[:selfie_image_url], + liveness_checking_enabled: liveness_checking_enabled?, + callback_url: callback_url, + trace_id: amzn_trace_id, + }, + ).run do |doc_auth_result| + document_capture_session.store_proofing_pii_from_doc(doc_auth_result[:document_result]) + + nil + end end end end diff --git a/app/services/idv/proofer.rb b/app/services/idv/proofer.rb index c1357118cbb..4357f3bb0ce 100644 --- a/app/services/idv/proofer.rb +++ b/app/services/idv/proofer.rb @@ -7,9 +7,11 @@ def validate_vendors! if mock_fallback_enabled? require 'identity-idp-functions/proof_address_mock' require 'identity-idp-functions/proof_resolution_mock' + require 'identity-idp-functions/proof_document_mock' else require 'identity-idp-functions/proof_address' require 'identity-idp-functions/proof_resolution' + require 'identity-idp-functions/proof_document' end end @@ -29,6 +31,14 @@ def address_job_class end end + def document_job_class + if mock_fallback_enabled? + IdentityIdpFunctions::ProofDocumentMock + else + IdentityIdpFunctions::ProofDocument + end + end + def mock_fallback_enabled? AppConfig.env.proofer_mock_fallback == 'true' end diff --git a/lib/lambda_jobs/git_ref.rb b/lib/lambda_jobs/git_ref.rb index 7a6bd4fbe9c..a679c85bffa 100644 --- a/lib/lambda_jobs/git_ref.rb +++ b/lib/lambda_jobs/git_ref.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module LambdaJobs - GIT_REF = '44f46a7fe2afa7894c665b09fd015fe41fd86450' + GIT_REF = '67f44016ca8c58ebaf46c969401da941a06eefd6' end diff --git a/spec/controllers/idv/doc_auth_controller_spec.rb b/spec/controllers/idv/doc_auth_controller_spec.rb index 60e089f1547..5dc81f0e1af 100644 --- a/spec/controllers/idv/doc_auth_controller_spec.rb +++ b/spec/controllers/idv/doc_auth_controller_spec.rb @@ -175,8 +175,30 @@ end describe 'async document verify' do + let(:front_image_url) { 'http://foo.com/bar1' } + let(:back_image_url) { 'http://foo.com/bar2' } + let(:selfie_image_url) { 'http://foo.com/bar3' } + let(:encryption_key) { SecureRandom.random_bytes(32) } + let(:front_image_iv) { SecureRandom.random_bytes(12) } + let(:back_image_iv) { SecureRandom.random_bytes(12) } + let(:selfie_image_iv) { SecureRandom.random_bytes(12) } + before do mock_document_capture_step + + encryption_helper = IdentityIdpFunctions::EncryptionHelper.new + stub_request(:get, front_image_url). + to_return(body: encryption_helper.encrypt( + data: '{}', key: encryption_key, iv: front_image_iv, + )) + stub_request(:get, back_image_url). + to_return(body: encryption_helper.encrypt( + data: '{}', key: encryption_key, iv: back_image_iv, + )) + stub_request(:get, selfie_image_url). + to_return(body: encryption_helper.encrypt( + data: '{}', key: encryption_key, iv: selfie_image_iv, + )) end let(:successful_response) do { success: true }.to_json @@ -186,13 +208,13 @@ it 'successfully submits the images' do put :update, params: { step: 'verify_document', document_capture_session_uuid: 'foo', - encryption_key: 'bar', - front_image_iv: 'iv1', - back_image_iv: 'iv2', - selfie_image_iv: 'iv3', - front_image_url: 'http://foo.com/bar1', - back_image_url: 'http://foo.com/bar2', - selfie_image_url: 'http://foo.com/bar3' } + encryption_key: Base64.encode64(encryption_key), + front_image_iv: Base64.encode64(front_image_iv), + back_image_iv: Base64.encode64(back_image_iv), + selfie_image_iv: Base64.encode64(selfie_image_iv), + front_image_url: front_image_url, + back_image_url: back_image_url, + selfie_image_url: selfie_image_url } expect(response.status).to eq(202) expect(response.body).to eq(successful_response) @@ -213,13 +235,13 @@ it 'successfully submits the images' do put :update, params: { step: 'verify_document', document_capture_session_uuid: 'foo', - encryption_key: 'bar', - front_image_iv: 'iv1', - back_image_iv: 'iv2', - selfie_image_iv: 'iv3', - front_image_url: 'http://foo.com/bar1', - back_image_url: 'http://foo.com/bar2', - selfie_image_url: 'http://foo.com/bar3' } + encryption_key: Base64.encode64(encryption_key), + front_image_iv: Base64.encode64(front_image_iv), + back_image_iv: Base64.encode64(back_image_iv), + selfie_image_iv: Base64.encode64(selfie_image_iv), + front_image_url: front_image_url, + back_image_url: back_image_url, + selfie_image_url: selfie_image_url } expect(response.status).to eq(202) expect(response.body).to eq(successful_response) diff --git a/spec/controllers/lambda_callback/document_proof_result_controller_spec.rb b/spec/controllers/lambda_callback/document_proof_result_controller_spec.rb index 0cc5ee68f6b..1262e4c0633 100644 --- a/spec/controllers/lambda_callback/document_proof_result_controller_spec.rb +++ b/spec/controllers/lambda_callback/document_proof_result_controller_spec.rb @@ -29,11 +29,27 @@ end it 'accepts and stores successful document proofing results' do - post :create, params: { result_id: document_capture_session.result_id, - document_result: { success: true, exception: '' } } + post :create, params: { + result_id: document_capture_session.result_id, + document_result: { + success: true, + exception: '', + pii_from_doc: { + first_name: 'Test', + last_name: 'McTest', + }, + }, + } proofing_result = document_capture_session.load_proofing_result - expect(proofing_result.result).to include(exception: '', success: 'true') + expect(proofing_result.result).to include( + exception: '', + success: 'true', # Q: why does this get converted from bool to string? + pii_from_doc: { + first_name: 'Test', + last_name: 'McTest', + }, + ) end it 'accepts and stores unsuccessful document proofing results' do diff --git a/spec/features/idv/doc_auth/document_capture_step_spec.rb b/spec/features/idv/doc_auth/document_capture_step_spec.rb index bb065556949..5d15b829a64 100644 --- a/spec/features/idv/doc_auth/document_capture_step_spec.rb +++ b/spec/features/idv/doc_auth/document_capture_step_spec.rb @@ -9,17 +9,11 @@ let(:user) { user_with_2fa } let(:liveness_enabled) { 'false' } let(:fake_analytics) { FakeAnalytics.new } - let(:document_capture_async_uploads_enabled) { false } - let(:doc_auth_enable_presigned_s3_urls) { false } before do allow(AppConfig.env).to receive(:document_capture_step_enabled). and_return(document_capture_step_enabled) allow(AppConfig.env).to receive(:liveness_checking_enabled). and_return(liveness_enabled) - allow(FeatureManagement).to receive(:doc_auth_enable_presigned_s3_urls). - and_return(doc_auth_enable_presigned_s3_urls) - allow(FeatureManagement).to receive(:document_capture_async_uploads_enabled). - and_return(document_capture_async_uploads_enabled) allow(LoginGov::Hostdata::EC2).to receive(:load). and_return(OpenStruct.new(region: 'us-west-2', account_id: '123456789')) sign_in_and_2fa_user(user) @@ -322,11 +316,10 @@ end context 'when using async uploads', :js do - let(:document_capture_async_uploads_enabled) { true } - let(:doc_auth_enable_presigned_s3_urls) { true } - before do - allow(VendorDocumentVerificationJob).to receive(:perform).and_call_original + allow(LambdaJobs::Runner).to receive(:new). + with(hash_including(job_class: Idv::Proofer.document_job_class)). + and_call_original end it 'proceeds to the next page with valid info' do @@ -349,29 +342,26 @@ click_on 'Submit' expect(page).to have_current_path(next_step, wait: 20) - expect(VendorDocumentVerificationJob).to have_received(:perform) do |params| + expect(LambdaJobs::Runner).to have_received(:new) do |args:, **| original = File.read('app/assets/images/logo.png') - decipher = OpenSSL::Cipher.new('aes-256-gcm') - decipher.decrypt - decipher.key = Base64.decode64(params[:encryption_key]) + encryption_helper = IdentityIdpFunctions::EncryptionHelper.new + encryption_key = Base64.decode64(args[:encryption_key]) Capybara.current_driver = :rack_test # ChromeDriver doesn't support `page.status_code` page.driver.get front_url expect(page).to have_http_status(200) - decipher.iv = Base64.decode64(params[:front_image_iv]) - decipher.auth_tag = page.body[-16..-1] - decipher.auth_data = '' - front_plain = decipher.update(page.body[0..-17]) + decipher.final + front_plain = encryption_helper.decrypt( + data: page.body, iv: Base64.decode64(args[:front_image_iv]), key: encryption_key, + ) expect(front_plain.b).to eq(original.b) page.driver.get back_url expect(page).to have_http_status(200) - decipher.iv = Base64.decode64(params[:back_image_iv]) - decipher.auth_tag = page.body[-16..-1] - decipher.auth_data = '' - back_plain = decipher.update(page.body[0..-17]) + decipher.final + back_plain = encryption_helper.decrypt( + data: page.body, iv: Base64.decode64(args[:back_image_iv]), key: encryption_key, + ) expect(back_plain.b).to eq(original.b) end end