Skip to content

Commit 93977bc

Browse files
authored
Encrypt teacher invitation email address (#368)
## Status Related to: RaspberryPiFoundation/digital-editor-issues#159 ## What's changed? This PR ensures that the `email_address` field on the `teacher_invitations` table is encrypted. We can't currently avoid storing this PII in the editor-api database (as we need to use the email adress to send the invitation email) but this change helps mitigate the risk of someone getting access to the production database. We haven't sent any teacher invitation emails in production yet, so we don't need to worry about migrating or encrypting any existing data. ## Steps to perform before deploying to production We need to set the following ENV variables on non-local environments: ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT Rails provides a command, `bin/rails db:encryption:init` to generate suitable values for these, but any long non-guessable strings should be fine.
2 parents f82f10f + 2e36b80 commit 93977bc

File tree

5 files changed

+23
-0
lines changed

5 files changed

+23
-0
lines changed

.circleci/config.yml

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ jobs:
2828
POSTGRES_USER: choco
2929
POSTGRES_HOST: "127.0.0.1"
3030
RAILS_ENV: test
31+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: primary-key
32+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: deterministic-key
33+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: derivation-salt
3134
steps:
3235
- checkout
3336
- browser-tools/install-firefox

.env.example

+5
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,8 @@ HOST_URL=http://localhost:3009
3131
EDITOR_PUBLIC_URL=http://localhost:3012
3232

3333
PROFILE_API_KEY=test # This has to match the value set in Profile (https://github.com/RaspberryPiFoundation/profile/blob/ca10a4f360b6fe2b04be76264e03283054126b0f/.env.example#L45).
34+
35+
# Run bin/rails db:encryption:init to generate values for these if you need to encrypt securely locally.
36+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=primary-key
37+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=deterministic-key
38+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=derivation-salt

app/models/teacher_invitation.rb

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class TeacherInvitation < ApplicationRecord
88
format: { with: EmailValidator.regexp, message: I18n.t('validations.invitation.email_address') }
99
validate :school_is_verified
1010
after_create_commit :send_invitation_email
11+
encrypts :email_address
1112

1213
generates_token_for :teacher_invitation, expires_in: 30.days do
1314
email_address

config/initializers/encryption.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
Rails.application.configure do
4+
config.active_record.encryption.primary_key = ENV.fetch('ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY')
5+
config.active_record.encryption.deterministic_key = ENV.fetch('ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY')
6+
config.active_record.encryption.key_derivation_salt = ENV.fetch('ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT')
7+
end

spec/models/teacher_invitation_spec.rb

+7
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,11 @@
6464

6565
expect(invitation.school_name).to eq('school-name')
6666
end
67+
68+
it 'non-deterministically encrypts the email_address' do
69+
school = create(:verified_school)
70+
described_class.create!(email_address: '[email protected]', school:)
71+
72+
expect(described_class.find_by(email_address: '[email protected]')).to be_nil
73+
end
6774
end

0 commit comments

Comments
 (0)