-
Notifications
You must be signed in to change notification settings - Fork 0
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 #1 from cul/aws_checksum_verification_and_websocke…
…t_server_implementation Add aws checksum verification logic and websocket server implementation
- Loading branch information
Showing
33 changed files
with
992 additions
and
12 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
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,46 @@ | ||
# frozen_string_literal: true | ||
|
||
class FixityCheckChannel < ApplicationCable::Channel | ||
FIXITY_CHECK_STREAM_PREFIX = "#{CHECK_PLEASE['action_cable_stream_prefix']}fixity_check:".freeze | ||
|
||
# A websocket client subscribes by sending this message: | ||
# { | ||
# "command" => "subscribe", | ||
# "identifier" => { "channel" => "FixityCheckChannel", "job_identifier" => "cool-job-id1" }.to_json | ||
# } | ||
def subscribed | ||
return if params[:job_identifier].blank? | ||
|
||
stream_name = "#{FIXITY_CHECK_STREAM_PREFIX}#{params[:job_identifier]}" | ||
Rails.logger.debug "A client has started streaming from: #{stream_name}" | ||
stream_from stream_name | ||
end | ||
|
||
def unsubscribed | ||
# Any cleanup needed when channel is unsubscribed | ||
return if params[:job_identifier].blank? | ||
|
||
stream_name = "#{FIXITY_CHECK_STREAM_PREFIX}#{params[:job_identifier]}" | ||
Rails.logger.debug "A client has stopped streaming from: #{stream_name}" | ||
stop_stream_from stream_name | ||
end | ||
|
||
# A websocket client runs this command by sending this message: | ||
# { | ||
# "command" => "run_fixity_check_for_s3_object", | ||
# "identifier" => { "channel" => "FixityCheckChannel", "job_identifier" => "cool-job-id1" }.to_json, | ||
# "data" => { | ||
# "action" => "run_fixity_check_for_s3_object", "bucket_name" => "some-bucket", | ||
# "object_path" => "path/to/object.png", "checksum_algorithm_name" => "sha256" | ||
# }.to_json | ||
# } | ||
def run_fixity_check_for_s3_object(data) | ||
Rails.logger.debug("run_fixity_check_for_s3_object action received with job_identifier: #{params[:job_identifier]}") | ||
job_identifier = params[:job_identifier] | ||
bucket_name = data['bucket_name'] | ||
object_path = data['object_path'] | ||
checksum_algorithm_name = data['checksum_algorithm_name'] | ||
|
||
AwsCheckFixityJob.perform_later(job_identifier, bucket_name, object_path, checksum_algorithm_name) | ||
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,36 @@ | ||
# frozen_string_literal: true | ||
|
||
class ApiController < ActionController::API | ||
include ActionController::HttpAuthentication::Token::ControllerMethods | ||
|
||
rescue_from ActiveRecord::RecordNotFound do | ||
render json: errors('Not Found'), status: :not_found | ||
end | ||
|
||
private | ||
|
||
# Returns 406 status if format requested is not json. This method can be | ||
# used as a before_action callback for any controllers that only respond | ||
# to json. | ||
def ensure_json_request | ||
return if request.format.blank? || request.format == :json | ||
|
||
head :not_acceptable | ||
end | ||
|
||
# Renders with an :unauthorized status if no request token is provided, or renders with a | ||
# :forbidden status if the request uses an invalid request token. This method should be | ||
# used as a before_action callback for any controller actions that require authorization. | ||
def authenticate_request_token | ||
authenticate_or_request_with_http_token do |token, _options| | ||
ActiveSupport::SecurityUtils.secure_compare(CHECK_PLEASE['remote_request_api_key'], token) | ||
end | ||
end | ||
|
||
# Generates JSON with errors | ||
# | ||
# @param String|Array json response describing errors | ||
def errors(errors) | ||
{ errors: Array.wrap(errors).map { |e| { message: e } } } | ||
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,44 @@ | ||
# frozen_string_literal: true | ||
|
||
class FixityChecksController < ApiController | ||
before_action :authenticate_request_token | ||
|
||
# POST /fixity_checks/run_fixity_check_for_s3_object | ||
def run_fixity_check_for_s3_object | ||
bucket_name = fixity_check_params['bucket_name'] | ||
object_path = fixity_check_params['object_path'] | ||
checksum_algorithm_name = fixity_check_params['checksum_algorithm_name'] | ||
|
||
checksum_hexdigest, object_size = CheckPlease::Aws::ObjectFixityChecker.check( | ||
bucket_name, object_path, checksum_algorithm_name | ||
) | ||
|
||
render plain: { | ||
bucket_name: bucket_name, object_path: object_path, checksum_algorithm_name: checksum_algorithm_name, | ||
checksum_hexdigest: checksum_hexdigest, object_size: object_size | ||
}.to_json | ||
rescue StandardError => e | ||
render plain: { | ||
error_message: e.message, | ||
bucket_name: bucket_name, object_path: object_path, checksum_algorithm_name: checksum_algorithm_name | ||
}.to_json, status: :bad_request | ||
end | ||
|
||
private | ||
|
||
def fixity_check_response(bucket_name, object_path, checksum_algorithm_name, checksum_hexdigest, object_size) | ||
run_fixity_check_for_s3_object | ||
{ | ||
bucket_name: bucket_name, object_path: object_path, checksum_algorithm_name: checksum_algorithm_name, | ||
checksum_hexdigest: checksum_hexdigest, object_size: object_size | ||
}.to_json | ||
end | ||
|
||
def fixity_check_params | ||
params.require(:fixity_check).tap do |fixity_check_params| | ||
fixity_check_params.require(:bucket_name) | ||
fixity_check_params.require(:object_path) | ||
fixity_check_params.require(:checksum_algorithm_name) | ||
end | ||
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,67 @@ | ||
# frozen_string_literal: true | ||
|
||
class AwsCheckFixityJob < ApplicationJob | ||
queue_as CheckPlease::Queues::CHECK_FIXITY | ||
|
||
def perform(job_identifier, bucket_name, object_path, checksum_algorithm_name) | ||
response_stream_name = "#{FixityCheckChannel::FIXITY_CHECK_STREAM_PREFIX}#{job_identifier}" | ||
|
||
checksum_hexdigest, object_size = CheckPlease::Aws::ObjectFixityChecker.check( | ||
bucket_name, | ||
object_path, | ||
checksum_algorithm_name, | ||
on_chunk: progress_report_lambda(response_stream_name) | ||
) | ||
|
||
# Broadcast message when job is complete | ||
broadcast_fixity_check_complete( | ||
response_stream_name, bucket_name, object_path, checksum_algorithm_name, checksum_hexdigest, object_size | ||
) | ||
rescue StandardError => e | ||
broadcast_fixity_check_error(response_stream_name, e.message, bucket_name, object_path, checksum_algorithm_name) | ||
end | ||
|
||
def broadcast_fixity_check_complete( | ||
response_stream_name, bucket_name, object_path, checksum_algorithm_name, checksum_hexdigest, object_size | ||
) | ||
ActionCable.server.broadcast( | ||
response_stream_name, | ||
{ | ||
type: 'fixity_check_complete', | ||
data: { | ||
bucket_name: bucket_name, object_path: object_path, | ||
checksum_algorithm_name: checksum_algorithm_name, | ||
checksum_hexdigest: checksum_hexdigest, object_size: object_size | ||
} | ||
}.to_json | ||
) | ||
end | ||
|
||
def broadcast_fixity_check_error( | ||
response_stream_name, error_message, bucket_name, object_path, checksum_algorithm_name | ||
) | ||
ActionCable.server.broadcast( | ||
response_stream_name, | ||
{ | ||
type: 'fixity_check_error', | ||
data: { | ||
error_message: error_message, bucket_name: bucket_name, | ||
object_path: object_path, checksum_algorithm_name: checksum_algorithm_name | ||
} | ||
}.to_json | ||
) | ||
end | ||
|
||
def progress_report_lambda(response_stream_name) | ||
lambda do |_chunk, _bytes_read, chunk_counter| | ||
return unless (chunk_counter % 100).zero? | ||
|
||
# We periodically broadcast a message to indicate that the processing is still happening. | ||
# This is so that a client can check whether a job has stalled. | ||
ActionCable.server.broadcast( | ||
response_stream_name, | ||
{ type: 'fixity_check_in_progress' }.to_json | ||
) | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
server 'check-please-dev.library.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
server 'fixity-test-2.svc.cul.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
# Current branch is suggested by default in development | ||
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp |
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,5 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
server 'check-please.library.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
server 'not-available-yet.library.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
# In test/prod, suggest latest tag as default version to deploy | ||
ask :branch, proc { `git tag --sort=version:refname`.split("\n").last } |
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,5 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
server 'check-please-test.library.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
server 'not-available-yet.library.columbia.edu', user: fetch(:remote_user), roles: %w[app db web] | ||
# In test/prod, suggest latest tag as default version to deploy | ||
ask :branch, proc { `git tag --sort=version:refname`.split("\n").last } |
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
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
Oops, something went wrong.