-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #469 from etalab/feature/dat-571-se-brancher-avec-…
…lapi-jcop Feature/dat 571 se brancher avec lapi jcop
- Loading branch information
Showing
34 changed files
with
588 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.malware-badge { | ||
display: inline-block; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class RunMalwareScanOnAttachments < ApplicationInteractor | ||
def call | ||
attachment_names.each do |attachment_name| | ||
attachment = context.authorization_request.public_send(attachment_name) | ||
|
||
MalwareScanJob.perform_later(attachment.id) | ||
end | ||
end | ||
|
||
private | ||
|
||
def attachment_names | ||
context.authorization_request.form.authorization_request_class.documents | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class MalwareScanJob < ApplicationJob | ||
RETRY_WAIT_TIME = 5.minutes | ||
|
||
retry_on Faraday::ServerError, wait: RETRY_WAIT_TIME, attempts: :infinite | ||
retry_on Faraday::ConnectionFailed, wait: RETRY_WAIT_TIME, attempts: :infinite | ||
|
||
def perform(attachment_id) | ||
@attachment = ActiveStorage::Attachment.find_by(id: attachment_id) | ||
|
||
return if @attachment.blank? || @attachment.blob.blank? | ||
|
||
create_and_start_scan | ||
end | ||
|
||
private | ||
|
||
def create_and_start_scan | ||
MalwareScan.create!(uuid:, attachment: @attachment) | ||
|
||
MalwareScanRetrieveStateJob.perform_later(uuid) | ||
end | ||
|
||
def uuid | ||
scan[:uuid] | ||
end | ||
|
||
def scan | ||
@scan ||= JeCliqueOuPasAPIClient.new.analyze(@attachment) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
class MalwareScanRetrieveStateJob < ApplicationJob | ||
include KeepTrackOfJobAttempts | ||
|
||
RETRY_WAIT_TIME = 1.minute | ||
RETRIES = 60 | ||
|
||
class MalwareScanRetrieveStateJobError < StandardError; end | ||
|
||
retry_on MalwareScanRetrieveStateJobError, wait: RETRY_WAIT_TIME, attempts: RETRIES | ||
retry_on Faraday::ServerError, wait: RETRY_WAIT_TIME, attempts: RETRIES | ||
retry_on Faraday::ConnectionFailed, wait: RETRY_WAIT_TIME, attempts: RETRIES | ||
|
||
def perform(uuid) | ||
@uuid = uuid | ||
|
||
@result_analyze = api_client.result(@uuid) | ||
|
||
raise MalwareScanRetrieveStateJobError if safety_state.blank? | ||
|
||
malware_scan.update!(safety_state:, analyzed_at:) | ||
rescue MalwareScanRetrieveStateJobError, Faraday::ServerError, Faraday::ConnectionFailed | ||
malware_scan.update!(safety_state: :unknown, analyzed_at: Time.zone.now.to_i) if attempts == RETRIES | ||
end | ||
|
||
private | ||
|
||
def malware_scan | ||
@malware_scan ||= MalwareScan.find_by(uuid: @uuid) | ||
end | ||
|
||
def safety_state | ||
case @result_analyze[:is_malware] | ||
when true | ||
:unsafe | ||
when false | ||
:safe | ||
end | ||
end | ||
|
||
def analyzed_at | ||
Time.zone.at(@result_analyze[:analyzed_at]) | ||
end | ||
|
||
def api_client | ||
@api_client ||= JeCliqueOuPasAPIClient.new | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module ActiveStorageAttachmentExtension | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
has_one :malware_scan, dependent: :destroy | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class MalwareScan < ApplicationRecord | ||
belongs_to :attachment, class_name: 'ActiveStorage::Attachment' | ||
|
||
enum :safety_state, { pending: 0, safe: 1, unsafe: 2, unknown: 3 } | ||
|
||
validates :uuid, presence: true, uniqueness: true | ||
validates :safety_state, presence: true | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
class JeCliqueOuPasAPIClient | ||
def analyze(attachment) | ||
@blob = attachment.blob | ||
|
||
response = request_analyze_with_file | ||
parsed_response = JSON.parse(response.body) | ||
|
||
{ | ||
uuid: parsed_response['uuid'], | ||
error: parsed_response['error'] | ||
} | ||
end | ||
|
||
def result(uuid) | ||
response = request_results(uuid:) | ||
parsed_response = JSON.parse(response.body) | ||
|
||
{ | ||
is_malware: parsed_response['is_malware'], | ||
analyzed_at: parsed_response['timestamp'], | ||
error: parsed_response['error'] | ||
} | ||
end | ||
|
||
private | ||
|
||
def request_analyze_with_file | ||
with_temp_file do |file| | ||
faraday_client(multipart: true).post( | ||
analyze_url, | ||
file_payload(file:), | ||
headers(file:) | ||
) | ||
end | ||
end | ||
|
||
def request_results(uuid:) | ||
faraday_client.get(results_url(uuid), nil, headers) | ||
end | ||
|
||
def with_temp_file | ||
temp_file = create_temp_file | ||
yield temp_file | ||
ensure | ||
temp_file.close | ||
temp_file.unlink | ||
end | ||
|
||
def create_temp_file | ||
Tempfile.new(temp_file_params).tap do |file| | ||
file.binmode | ||
file.write(@blob.download) | ||
file.rewind | ||
end | ||
end | ||
|
||
def temp_file_params | ||
[@blob.filename.base, @blob.filename.extension_with_delimiter] | ||
end | ||
|
||
def file_payload(file:) | ||
{ file: Faraday::Multipart::FilePart.new(file, @blob.content_type) } | ||
end | ||
|
||
def faraday_client(multipart: false) | ||
Faraday.new(ssl: { cert_store: }) do |faraday| | ||
if multipart | ||
faraday.request :multipart | ||
faraday.request :url_encoded | ||
faraday.adapter Faraday.default_adapter | ||
end | ||
end | ||
end | ||
|
||
def headers(file: nil) | ||
base_headers = { 'X-Auth-token': token } | ||
|
||
return base_headers unless file | ||
|
||
base_headers.merge( | ||
'Content-Type': 'multipart/form-data', | ||
'Content-Length': File.size(file).to_s, | ||
'Transfer-Encoding': 'chunked' | ||
) | ||
end | ||
|
||
def analyze_url | ||
"#{host}/submit" | ||
end | ||
|
||
def results_url(uuid) | ||
"#{host}/results/#{uuid}" | ||
end | ||
|
||
def host | ||
Rails.application.credentials.je_clique_ou_pas[:host] | ||
end | ||
|
||
def token | ||
Rails.application.credentials.je_clique_ou_pas[:token] | ||
end | ||
|
||
def cert_store | ||
OpenSSL::X509::Store.new.tap { |store| store.add_cert(certificate) } | ||
end | ||
|
||
def certificate | ||
OpenSSL::X509::Certificate.new(Rails.application.credentials.je_clique_ou_pas[:certificate]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
N6qthRTcH/UHF7SjIX0glK/jyjnOfYvUTB+5oi/V/709FFP/Er24XaapswYUvCZDd5xCvtWvfkMm4Exl2Li4TYkcDuY1aIHcmc1XigcvMTffHD7HFriP/rKfSNex7qAZw7TlXSmrtqbKj0QhKePFPqS/PcotYaQIInapGkMwndwbusUc8dc5hcMi/lvWLZIrcNm+nI4gHOP3/zE9PsPDdIfCwgiRrlCNRf1IVExbaQDgEPMHsosrktXtSv4Yk1tDnJ9N14WnVsA47kiXAcGm24ULrWFR9VXj/Q6gGMqfZuM/xD2xz7rur4ZiAsJR/WZzInj0O8vRHZ/Ietv/3c8yE26JzyuNPrJRferTsvh5m898T0X9zFkkGB96fliA3KDNGkYjY7MOqQSN7PJ623ymBd3hdOD9WGpaTDSUUadsoRFR3yVqq8A4W5cBA/M1kF9Sp6dmLBbkAHdLpo9yYvDkhnjD5kujOp5L56Bn8Kh9i/8nU/xn8tKWbu+yFrkRuK1eQqbNVHg+9eNO+9X2veh1Ao1PkITEX2DjHiHqxyTi04NSh6/Sr22Daw5MObRBeIi/HtItOTRhNbrTa6z01w+s3xHbe2W+8eU4ie/smKkNo7Ydk8XKxeH7teB8HeTy3MjK+o+PZ9dDP6r5uuc/aga2wgWe7yoyMT+bQbTqZ2oKlgeqMxpLh0SHIMK+491qyIo4Bob8HDNq6QccyCsKwAsMSIYW1/9VQYgXGOG/587u3vquxD2Ifee6T9bGVktO95VIK98vugweTGfALnGeJDOEknUoYwLwdomEgixaM2FAjHlY7a5nVIU0eM7TC2yvGVJCyA==--4qKCoHap6TM0T1Ek--Mdhas1TZvBaKsUkG7c4nwQ== | ||
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--3OgOYyjw719TRBIk--50OoKpf1k7uWV1NTk8EXTQ== |
Oops, something went wrong.