Skip to content

Instantly share code, notes, and snippets.

@auxesis
Created August 23, 2022 01:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save auxesis/cb77ee0934ce2271d4919b6ee66f8c8f to your computer and use it in GitHub Desktop.
Save auxesis/cb77ee0934ce2271d4919b6ee66f8c8f to your computer and use it in GitHub Desktop.
# lib/tasks/active_stash.rake
def model_fields(model)
model.column_names
end
def models
Rails.application.eager_load!
ApplicationRecord.descendants
end
def secured_by_active_stash?(fields)
fields.include?("stash_id")
end
def name_rules
[
{ name: "name", display_name: "names", column_names: ["name"] },
{ name: "last_name", display_name: "last names", column_names: ["lastname", "lname", "surname"] },
{ name: "phone", display_name: "phone numbers", column_names: ["phone", "phonenumber"] },
{ name: "date_of_birth", display_name: "dates of birth", column_names: ["dateofbirth", "birthday", "dob"] },
{ name: "postal_code", display_name: "postal codes", column_names: ["zip", "zipcode", "postalcode", "postcode"] },
{ name: "oauth_token", display_name: "OAuth tokens", column_names: ["accesstoken", "refreshtoken"] },
]
end
def suspected_personal_data(model)
fields = model_fields(model)
matches = {}
fields.each do |field|
suspects = name_rules.select { |rule| rule[:column_names].include?(field) }
if suspects.size > 0
matches[field] ||= []
matches[field] << suspects
matches[field].flatten!
end
end
matches
end
def write_report(assessment, filename)
report = {}
assessment.each do |model, fields|
fields.each do |field, reasons|
display = reasons.map { |r| r[:display_name] }.join(", ")
report[model] ||= []
report[model] << { field: field, comment: "suspected to contain: #{display}" }
end
end
File.open(filename, "w") { |file| file.write(report.to_yaml) }
puts "Assessment written to: #{filename}"
end
def assessment_path
Rails.root.join("active_stash_assessment.yml")
end
def read_report(filename)
YAML.load(assessment_path.read)
end
namespace :active_stash do
desc "assess what data is sensitive"
task :assess => [:environment] do
assessment = models.map { |model|
[model.name, suspected_personal_data(model)]
}
assessment.each do |model, fields|
if fields.size > 0
puts "#{model}:"
fields.each do |field, evidences|
puts "- #{model}.#{field} is suspected to contain: #{evidences.map { |e| e[:display_name] }.join(", ")}"
end
puts
end
end
write_report(assessment, assessment_path)
exit
end
end
---
User:
- :field: name
:comment: 'suspected to contain: names'
- :field: dob
:comment: 'suspected to contain: dates of birth'
- :field: postcode
:comment: 'suspected to contain: postal codes'
# spec/active_stash_audit_spec.rb
require "rails_helper"
def assessment_path
Rails.root.join("active_stash_assessment.yml")
end
def read_report(filename)
YAML.load(assessment_path.read)
end
RSpec.describe "ActiveStash" do
it "protects all sensitive data" do
assessment = read_report(assessment_path)
unprotected = []
assessment.each do |model_name, fields|
model = model_name.constantize
suspected_fields = fields.map { |field| field[:field].to_sym }
unencrypted = suspected_fields.reject { |name| model.encrypted_attributes.include?(name) }
if unencrypted.size > 0
unprotected << { model: model_name, fields: unencrypted }
end
end
if unprotected.any?
reason = "Unprotected sensitive fields:\n\t# #{unprotected.map { |f| "#{f[:model]}: #{f[:fields].join(", ")}" }.join("\n\t# ")}"
pending(reason)
fail
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment