checklist snippets

Ruby on Rails Security Checklist

Tagged security, checklist, ruby on rails, ruby  Languages ruby

Checklist

* Don't store passwords (config/database.yml, db/seeds.rb), API keys (Amazon AWS), the Rails secret token (config/initializers/secret_token.rb), etc in version control. * Don't store production passwords and API keys on developer laptops. * Inject secrets, API keys, etc with e.g. dotenv * Don't import production data to other environments without obfuscating or cleaning data. * Use a different secret token in production than staging, development, and other environments. * AR serialize and store (YAML) is using eval. Don't use YAML, use JSON. * Don't write redirect_to params[:url]. If you have to then add only_path: true, or use URI.parse to get the path component. * ActiveRecord is not safe from SQL injection. See http://rails-sqli.org for details. * Enforce password strength. * Set cookie timeout expire_after: 30.minutes. * Hash passwords before storing them in a database (has_secure_password). * Don't use GET for actions that change data (RequestForgeryProtection). * Uploaded files should be sanitized, name, path, etc. * Downloads of uploaded files should most likely be authorized (send_file , Downloads done right).

Recommended Software

* secure_headers gem (Content Security Policy) * mod_security (Apache & nginx web application firewall) * rack::attack gem (Similar to mod_security) * bundler_audit gem (Checks Gemfile.lock for vulnerable gems)

Further resources

* Ruby on Rails Security Guide * XSS (Cross Site Scripting) Prevention Cheat Sheet * Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet * DOM based XSS Prevention Cheat Sheet * HTML5 Security Cheat Sheet * SQL Injection Prevention Cheat Sheet * Attack Surface Analysis Cheat Sheet * Ruby on Rails Cheatsheet * http://12factor.net/config * http://gauntlt.org/


Checklist for how to write background jobs/workers

Tagged at-least-once, at-most-once, order, checklist, sidekiq, worker  Languages 

Checklist

  1. Idempotent

    Jobs should be idempotent. If a job is performed multiple times the work should only be performed once, or at least the end-result should be the same.

  1. Optimistic/pessimistic/distributed locking

    You need to use different types of strategies to prevent code from being executed more than once in a distributed environment. Jobs can be executed twice under many circumstances, e.g. because of:

Solving these issues can be done with, e.g.: optimistic locking, pessimistic locking, and distributed locking, e.g. with redis-semaphore.

  1. Retry Set retry to zero for jobs that don’t need to or shouldn’t be retried.
  1. Priority Specify a queue and a queue priority for jobs that need a higher or lower priority.
  1. Transactions Does the job need database transactions? Use transactions e.g. when a job does more than one insert, update, delete, or create, otherwise you will end up having data duplication/inconsistency issues.
  1. Messaging Sidekiq is not a messaging queue. At-least-once execution is 100% guaranteed by Sidekiq Pro. I don’t trust that guarantee 100%, but that is another story. The question is: what happens if the job fails (dead job queue, dev null)? What you usually need is “job successfully executed at-least-once” not “job executed at-least once”.

Ensuring jobs are performed at-least-once and at-most-once


You can’t rely on Sidekiq, or any other messaging or job queue, to execute your job (business logic) once and exactly once. All work needs to be checked for consistency.

For example, messages/jobs can be lost under many circumstances, and the same job (business logic) can be executed an unlimited amount of times unless your application takes the necessary steps to ensure that the job is performed correctly. A background processing/messaging server should be considered unreliable.

At-least-once

Use a reconsiliation step, e.g. a separate worker that runs once per day, to make sure jobs are executed at least once: http://www.mikeperham.com/2014/05/27/the-reconciliation-step/

  1. Databases: At-least-once is achieved when you have the data in your database and are polling to see if the job has been performed. Locking => performance issues.
  2. Sidekiq: At-least-once is achieved when you monitor the dead job queue 100% using available eyeballs.
  3. Messaging queues: At-least-once is achieved through message acknowledgment and/or through monitoring the dead letter queue 100% using available eyeballs.

At-most-once

Use a flag, nonce, or a guid to ensure a job is only run once, i.e. do nothing if a job is queued twice for some reason. Avoid locking database tables when possible. Use optimistic/pessimistic/distributed locks when locking is needed.

Order

  • Should jobs be executed in order?
  • What happens if job is executed, e.g., 1 month too late?

Conclusion


Don’t trust your messaging and background processing server to do its job without either manual supervision (eyeballs) or automated supervision (at-least-once and at-most-once).