Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encrypt patron data #628

Merged
merged 7 commits into from
Feb 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# ie `~> 2.5` or `~> 2.6`, not including additional that may be in 2.3
ruby "~> #{File.read('.ruby-version').chomp.split('.').slice(0,3).join('.')}"

gem 'lockbox'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.4'
gem 'webpacker', '~> 4.0'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ GEM
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
lockbox (0.3.1)
loofah (2.4.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
Expand Down Expand Up @@ -651,6 +652,7 @@ DEPENDENCIES
kaminari (~> 1.0)
kithe!
listen (>= 3.0.5, < 3.2)
lockbox
oai (~> 1.0, >= 1.0.1)
pdf-reader (~> 2.2)
pg (>= 0.18, < 2.0)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Some other interesting/complicated sub-systems we've written documentation for:
* [access-granted](https://github.com/chaps-io/access-granted) is used for some very simple authorization/permissions (right now just admins can do some things other logged in staff can not)
* [blacklight](https://github.com/projectblacklight/blacklight) We are currently using Blacklight
for the "end-user-facing" search, although we are using it in a very limited and customized fashion, not including a lot of things the BL generator wanted to include in our app, that we didn't plan on using.
* [lockbox](https://github.com/ankane/lockbox) for encrypting our patron data in Admin::RAndRItem.
For rotating keys should private key need to be changed, see https://github.com/ankane/lockbox/issues/35

### Task to copy a Work from staging to your local dev instance

Expand Down
10 changes: 10 additions & 0 deletions app/lib/scihist_digicoll/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ def self.production?
define_key :aws_access_key_id
define_key :aws_secret_access_key

define_key :lockbox_master_key, default: -> {
# In production, we insist that local_env.yml contain
# a real 64-bit key; if none is defined, we fail at
# deploy time (see config/initializers/lockbox.rb).
#
# However, we do provide a dummy key for dev and test
# environments, which is a string of 64 zeros.
"0" * 64 if Rails.env.test? || Rails.env.development?
}

define_key :aws_region, default: "us-east-1"

# eg "https://digital.sciencehistory.org", or "http://localhost:3000".
Expand Down
15 changes: 13 additions & 2 deletions app/models/admin/r_and_r_item.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# This model is based on the parallel Admin::DigitizationQueueItem.rb.

# "RAndR" is "Rights & Reproductions", and represents requests from specific patrons
# for copies of things in our collection. We sometimes photograph things in response
# to patron request, sometimes they will wind up also being processed for adding
# to Digital Collections, other times not.
#
# This model is based on the parallel Admin::DigitizationQueueItem.rb, both are
# adaptations of former google doc spreadsheet-based processes, and track workflow.
class Admin::RAndRItem < ApplicationRecord

# For more info about how to rotate a leaked Lockbox master key,
# see https://github.com/sciencehistory/scihist_digicoll/issues/629
# and https://github.com/ankane/lockbox/issues/35
encrypts :patron_name, :patron_email

has_many :digitization_queue_item, dependent: :nullify
has_many :queue_item_comments, dependent: :destroy

Expand Down
3 changes: 3 additions & 0 deletions config/initializers/filter_parameter_logging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

Rails.application.config.filter_parameters += [:patron_email]
Rails.application.config.filter_parameters += [:patron_name]
21 changes: 21 additions & 0 deletions config/initializers/lockbox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
lockbox_master_key = ScihistDigicoll::Env.lookup(:lockbox_master_key)

unless lockbox_master_key.present?
raise RuntimeError,
"""

Lockbox master key is missing in production.

We encrypt our patron information using Lockbox.
For encryption to work in production, local_env.yml
must contain a line such as:
lockbox_master_key: #{Lockbox.generate_key}
A key can be generated in the Rails console by running:
\"Lockbox.generate_key\".

More details can be found at https://github.com/ankane/lockbox .

"""
end

Lockbox.master_key = lockbox_master_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddPatronCyphertextToRAndRItems < ActiveRecord::Migration[5.2]
def change
add_column :r_and_r_items, :patron_name_ciphertext, :text
add_column :r_and_r_items, :patron_email_ciphertext, :text

remove_column :r_and_r_items, :patron_name, :string
remove_column :r_and_r_items, :patron_email, :string
end
end
9 changes: 5 additions & 4 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,6 @@ CREATE TABLE public.r_and_r_items (
title character varying,
curator character varying,
collecting_area character varying,
patron_name character varying,
patron_email character varying,
bib_number character varying,
location character varying,
accession_number character varying,
Expand All @@ -365,7 +363,9 @@ CREATE TABLE public.r_and_r_items (
deadline timestamp without time zone,
date_files_sent timestamp without time zone,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
updated_at timestamp without time zone NOT NULL,
patron_name_ciphertext text,
patron_email_ciphertext text
);


Expand Down Expand Up @@ -893,6 +893,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20191016134900'),
('20191112170956'),
('20191210210454'),
('20200131161750');
('20200131161750'),
('20200206194219');


6 changes: 6 additions & 0 deletions spec/controllers/admin/r_and_r_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
expect(Admin::RAndRItem.count).to eq 1
item = Admin::RAndRItem.last
expect(item.title).to eq "Some Item"
# Just by way of making sure the patron and email are indeed
# encrypted in the DB. The length of the encrypted strings
# is arbitrary, but shouldn't change unless e.g. the master_key
# used for our test environment changes first.
expect(item.patron_name_ciphertext.length).to eq 56
expect(item.patron_email_ciphertext.length).to eq 56
end

it "it can show a single item" do
Expand Down