aws-sdk-rails 3.5.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06b6734cbbe89bfbec53e688f583d78fb1a1fed48420c0a6b279d0025c8a65d3
4
- data.tar.gz: 6a84d18c8fbb5807bb88e1b3c803ed94a72bb6287abc244341dfb1e05a595923
3
+ metadata.gz: 49d723b9b6fd27217d47fec5d67a8e215eea7249b190dcd724d949539c4fccdc
4
+ data.tar.gz: 0d99a46f3109fa5ea2950045a4e24ea85f630c9458d510bffe208dca65fcce22
5
5
  SHA512:
6
- metadata.gz: 339b7acd4cdc666589ec5921ac583b1b8ed17101fedf6637af957ede0863b0aebe025333ddbb8fdb1fe9a491d2f82f76b7cde81d62ad1eab6c58ae34605c8ecf
7
- data.tar.gz: c5d8b881c1f5a9521800bc89dd491266088a03dd98845590e5d498e22538baee8f14a014048a3155adcc411a5ded72bc35e02f456097f1d838a4e3cbff905e02
6
+ metadata.gz: 3411b20bf529a39dc0c3f45259f5b470cf74885a8c87937c5f874714ba0f840c33e6609f9904c673d0879bacddb30e1f8d9d2f8173ca229a7d4d264be6880e05
7
+ data.tar.gz: e2e4626edffb9ee1be443330ec975875ac97569034d985a551f24557d33c3c09cc6120f4f47a48bad15673f3481d52d5544349f8e2f109127a0714f0354d1b41
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.5.0
1
+ 3.6.0
@@ -7,6 +7,7 @@ require_relative 'aws/rails/sqs_active_job/configuration'
7
7
  require_relative 'aws/rails/sqs_active_job/executor'
8
8
  require_relative 'aws/rails/sqs_active_job/job_runner'
9
9
  require_relative 'aws/rails/sqs_active_job/lambda_handler'
10
+ require_relative 'aws/rails/middleware/ebs_sqs_active_job_middleware'
10
11
 
11
12
  require_relative 'action_dispatch/session/dynamodb_store'
12
13
  require_relative 'active_job/queue_adapters/amazon_sqs_adapter'
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module Rails
5
+ # Middleware to handle requests from the SQS Daemon present on Elastic Beanstalk worker environments.
6
+ class EbsSqsActiveJobMiddleware
7
+ INTERNAL_ERROR_MESSAGE = 'Failed to execute job - see Rails log for more details.'
8
+ INTERNAL_ERROR_RESPONSE = [500, { 'Content-Type' => 'text/plain' }, [INTERNAL_ERROR_MESSAGE]].freeze
9
+ FORBIDDEN_MESSAGE = 'Request with aws-sqsd user agent was made from untrusted address.'
10
+ FORBIDDEN_RESPONSE = [403, { 'Content-Type' => 'text/plain' }, [FORBIDDEN_MESSAGE]].freeze
11
+
12
+ def initialize(app)
13
+ @app = app
14
+ @logger = ActiveSupport::Logger.new(STDOUT)
15
+ end
16
+
17
+ def call(env)
18
+ request = ActionDispatch::Request.new(env)
19
+
20
+ # Pass through unless user agent is the SQS Daemon
21
+ return @app.call(env) unless from_sqs_daemon?(request)
22
+
23
+ @logger.debug('aws-rails-sdk middleware detected call from Elastic Beanstalk SQS Daemon.')
24
+
25
+ # Only accept requests from this user agent if it is from localhost or a docker host in case of forgery.
26
+ unless request.local? || sent_from_docker_host?(request)
27
+ @logger.warn("SQSD request detected from untrusted address #{request.remote_ip}; returning 403 forbidden.")
28
+ return FORBIDDEN_RESPONSE
29
+ end
30
+
31
+ # Execute job or periodic task based on HTTP request context
32
+ periodic_task?(request) ? execute_periodic_task(request) : execute_job(request)
33
+ end
34
+
35
+ private
36
+
37
+ def execute_job(request)
38
+ # Jobs queued from the Active Job SQS adapter contain the JSON message in the request body.
39
+ job = Aws::Json.load(request.body.string)
40
+ job_name = job['job_class']
41
+ @logger.debug("Executing job: #{job_name}")
42
+
43
+ begin
44
+ ActiveJob::Base.execute(job)
45
+ rescue NoMethodError, NameError => e
46
+ @logger.error("Job #{job_name} could not resolve to a class that inherits from Active Job.")
47
+ @logger.error("Error: #{e}")
48
+ return INTERNAL_ERROR_RESPONSE
49
+ end
50
+
51
+ [200, { 'Content-Type' => 'text/plain' }, ["Successfully ran job #{job_name}."]]
52
+ end
53
+
54
+ def execute_periodic_task(request)
55
+ # The beanstalk worker SQS Daemon will add the 'X-Aws-Sqsd-Taskname' for periodic tasks set in cron.yaml.
56
+ job_name = request.headers['X-Aws-Sqsd-Taskname']
57
+ @logger.debug("Creating and executing periodic task: #{job_name}")
58
+
59
+ begin
60
+ job = job_name.constantize.new
61
+ job.perform_now
62
+ rescue NoMethodError, NameError => e
63
+ @logger.error("Periodic task #{job_name} could not resolve to an Active Job class - check the spelling in cron.yaml.")
64
+ @logger.error("Error: #{e}.")
65
+ return INTERNAL_ERROR_RESPONSE
66
+ end
67
+
68
+ [200, { 'Content-Type' => 'text/plain' }, ["Successfully ran periodic task #{job_name}."]]
69
+ end
70
+
71
+ # The beanstalk worker SQS Daemon sets a specific User-Agent headers that begins with 'aws-sqsd'.
72
+ def from_sqs_daemon?(request)
73
+ current_user_agent = request.headers['User-Agent']
74
+
75
+ !current_user_agent.nil? && current_user_agent.start_with?('aws-sqsd')
76
+ end
77
+
78
+ # The beanstalk worker SQS Daemon will add the custom 'X-Aws-Sqsd-Taskname' header for periodic tasks set in cron.yaml.
79
+ def periodic_task?(request)
80
+ !request.headers['X-Aws-Sqsd-Taskname'].nil? && request.headers['X-Aws-Sqsd-Taskname'].present?
81
+ end
82
+
83
+ def sent_from_docker_host?(request)
84
+ app_runs_in_docker_container? && request.remote_ip == '172.17.0.1'
85
+ end
86
+
87
+ def app_runs_in_docker_container?
88
+ @app_runs_in_docker_container ||= `[ -f /proc/1/cgroup ] && cat /proc/1/cgroup` =~ /docker/
89
+ end
90
+ end
91
+ end
92
+ end
@@ -13,6 +13,10 @@ module Aws
13
13
  Aws::Rails.log_to_rails_logger
14
14
  end
15
15
 
16
+ initializer 'aws-sdk-rails.insert_middleware' do |app|
17
+ Aws::Rails.add_sqsd_middleware(app)
18
+ end
19
+
16
20
  rake_tasks do
17
21
  load 'tasks/dynamo_db/session_store.rake'
18
22
  load 'tasks/aws_record/migrate.rake'
@@ -64,5 +68,21 @@ module Aws
64
68
  end
65
69
  end
66
70
  end
71
+
72
+ # Register a middleware that will handle requests from the Elastic Beanstalk worker SQS Daemon.
73
+ # This will only be added in the presence of the AWS_PROCESS_BEANSTALK_WORKER_REQUESTS environment variable.
74
+ # The expectation is this variable should only be set on EB worker environments.
75
+ def self.add_sqsd_middleware(app)
76
+ is_eb_worker_hosted = Aws::Util.str_2_bool(ENV['AWS_PROCESS_BEANSTALK_WORKER_REQUESTS'].to_s.downcase)
77
+
78
+ return unless is_eb_worker_hosted
79
+
80
+ if app.config.force_ssl
81
+ # SQS Daemon sends requests over HTTP - allow and process them before enforcing SSL.
82
+ app.config.middleware.insert_before(ActionDispatch::SSL, Aws::Rails::EbsSqsActiveJobMiddleware)
83
+ else
84
+ app.config.middleware.use(Aws::Rails::EbsSqsActiveJobMiddleware)
85
+ end
86
+ end
67
87
  end
68
88
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-sdk-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-06 00:00:00.000000000 Z
11
+ date: 2021-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-record
@@ -124,6 +124,7 @@ files:
124
124
  - lib/active_job/queue_adapters/amazon_sqs_async_adapter.rb
125
125
  - lib/aws-sdk-rails.rb
126
126
  - lib/aws/rails/mailer.rb
127
+ - lib/aws/rails/middleware/ebs_sqs_active_job_middleware.rb
127
128
  - lib/aws/rails/notifications.rb
128
129
  - lib/aws/rails/railtie.rb
129
130
  - lib/aws/rails/sqs_active_job/configuration.rb