Skip to content

Commit f3ad015

Browse files
authored
MultiUsers: encrypt API key (#941)
This will make it so that we can safely look up the user by API key without the risk of timing attacks.
1 parent 6b298fd commit f3ad015

13 files changed

+79
-8
lines changed

.env.development

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1-
# use `rails secret` to generate this for production
1+
# you can use `rails secret` to generate this for production
22
SECRET_KEY_BASE=dev_secret
3+
4+
# you can use `rails db:encryption:init` to generate these for production
5+
ENCRYPTION_PRIMARY_KEY=dev_primary_key
6+
ENCRYPTION_DETERMINISTIC_KEY=dev_deterministic_key
7+
ENCRYPTION_KEY_DERIVATION_SALT=dev_derivation_salt

.env.test

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1-
# use `rails secret` to generate this for production
1+
# you can use `rails secret` to generate this for production
22
SECRET_KEY_BASE=test_secret
3+
4+
# you can use `rails db:encryption:init` to generate these for production
5+
ENCRYPTION_PRIMARY_KEY=test_primary_key
6+
ENCRYPTION_DETERMINISTIC_KEY=test_deterministic_key
7+
ENCRYPTION_KEY_DERIVATION_SALT=test_derivation_salt

app.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616
"description": "Secret key used by rails for encryption",
1717
"generator": "secret"
1818
},
19+
"ENCRYPTION_PRIMARY_KEY": {
20+
"description": "Secret key used by rails for encryption",
21+
"generator": "secret"
22+
},
23+
"ENCRYPTION_DETERMINISTIC_KEY": {
24+
"description": "Secret key used by rails for encryption",
25+
"generator": "secret"
26+
},
27+
"ENCRYPTION_KEY_DERIVATION_SALT": {
28+
"description": "Secret key used by rails for encryption",
29+
"generator": "secret"
30+
},
1931
"LOCALE": {
2032
"description": "Specify the translation locale you wish to use",
2133
"value": "en"

app/models/user.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ class User < ApplicationRecord
66
has_secure_password
77
has_secure_token :api_key
88

9+
encrypts :api_key, deterministic: true
10+
911
has_many :feeds, dependent: :delete_all
1012
has_many :groups, dependent: :delete_all
1113

config/application.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,12 @@ class Application < Rails::Application
3939
config.generators.system_tests = nil
4040

4141
config.active_record.belongs_to_required_by_default = false
42+
43+
config.active_record.encryption.primary_key =
44+
ENV.fetch("ENCRYPTION_PRIMARY_KEY")
45+
config.active_record.encryption.deterministic_key =
46+
ENV.fetch("ENCRYPTION_DETERMINISTIC_KEY")
47+
config.active_record.encryption.key_derivation_salt =
48+
ENV.fetch("ENCRYPTION_KEY_DERIVATION_SALT")
4249
end
4350
end

config/initializers/dotenv.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
# frozen_string_literal: true
22

3-
Dotenv.require_keys("SECRET_KEY_BASE")
3+
Dotenv.require_keys(
4+
"SECRET_KEY_BASE",
5+
"ENCRYPTION_PRIMARY_KEY",
6+
"ENCRYPTION_DETERMINISTIC_KEY",
7+
"ENCRYPTION_KEY_DERIVATION_SALT"
8+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
class EncryptAPIKey < ActiveRecord::Migration[7.0]
4+
def change
5+
ActiveRecord::Encryption.config.support_unencrypted_data = true
6+
7+
User.find_each do |user|
8+
user.regenerate_api_key if user.api_key.blank?
9+
user.encrypt
10+
end
11+
12+
ActiveRecord::Encryption.config.support_unencrypted_data = false
13+
14+
change_column_null :users, :api_key, false
15+
add_index :users, :api_key, unique: true
16+
end
17+
end

db/schema.rb

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docker-compose.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ services:
1919
ports:
2020
- 80:8080
2121
environment:
22-
- SECRET_KEY_BASE=YOUR_SECRET_KEY_BASE
22+
- SECRET_KEY_BASE=<your configuration>
23+
- ENCRYPTION_PRIMARY_KEY<your configuration>
24+
- ENCRYPTION_DETERMINISTIC_KEY=<your configuration>
25+
- ENCRYPTION_KEY_DERIVATION_SALT=<your configuration>
2326
- PORT=8080
2427
- DATABASE_URL=postgres://db_user:super_secret_password@postgres:5432/stringer

docs/Heroku.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
git clone [email protected]:stringer-rss/stringer.git
33
cd stringer
44
heroku create
5+
6+
heroku config:set SECRET_KEY_BASE=`openssl rand -hex 64`
7+
heroku config:set ENCRYPTION_PRIMARY_KEY=`openssl rand -hex 64`
8+
heroku config:set ENCRYPTION_DETERMINISTIC_KEY=`openssl rand -hex 64`
9+
heroku config:set ENCRYPTION_KEY_DERIVATION_SALT=`openssl rand -hex 64`
10+
511
git push heroku main
612

713
heroku config:set APP_URL=`heroku apps:info --shell | grep web_url | cut -d= -f2`
8-
heroku config:set SECRET_KEY_BASE=`openssl rand -hex 64`
914

1015
heroku run rake db:migrate
1116
heroku restart

docs/OpenShift.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@ Deploying into OpenShift
3232
chmod +x .openshift/action_hooks/deploy
3333
```
3434

35-
5. Set the SECRET_KEY_BASE as a rhc environment variable by generating it with the command below.
35+
5. Set the environment variables by generating them with the commands below.
3636

3737
```sh
3838
rhc env set SECRET_KEY_BASE="`openssl rand -hex 64`"
39+
rhc env set ENCRYPTION_PRIMARY_KEY="`openssl rand -hex 64`"
40+
rhc env set ENCRYPTION_DETERMINISTIC_KEY="`openssl rand -hex 64`"
41+
rhc env set ENCRYPTION_KEY_DERIVATION_SALT="`openssl rand -hex 64`"
3942
```
4043

4144
6. Configuration of the database server is next. Open the file config/database.yml and add in the configuration for Production as shown below. OpenShift is able to use environment variables to push the information into the application.

docs/VPS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ Stringer uses environment variables to configure the application. Edit these val
9393
echo 'export RACK_ENV="production"' >> $HOME/.bash_profile
9494
echo 'export RAILS_ENV="production"' >> $HOME/.bash_profile
9595
echo "export SECRET_KEY_BASE=`openssl rand -hex 64`" >> $HOME/.bash_profile
96+
echo "export ENCRYPTION_PRIMARY_KEY=`openssl rand -hex 64`" >> $HOME/.bash_profile
97+
echo "export ENCRYPTION_DETERMINISTIC_KEY=`openssl rand -hex 64`" >> $HOME/.bash_profile
98+
echo "export ENCRYPTION_KEY_DERIVATION_SALT=`openssl rand -hex 64`" >> $HOME/.bash_profile
9699
source ~/.bash_profile
97100

98101
Tell stringer to run the database in production mode, using the `postgres` database you created earlier.

docs/docker.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ docker run --detach \
3737
-e PORT=8080 \
3838
-e DATABASE_URL=postgres://postgres:myPassword@stringer-postgres/stringer \
3939
-e SECRET_KEY_BASE=$(openssl rand -hex 64) \
40+
-e ENCRYPTION_PRIMARY_KEY=$(openssl rand -hex 64) \
41+
-e ENCRYPTION_DETERMINISTIC_KEY=$(openssl rand -hex 64) \
42+
-e ENCRYPTION_KEY_DERIVATION_SALT=$(openssl rand -hex 64) \
4043
-e FETCH_FEEDS_CRON="*/5 * * * *" \ # optional
4144
-e CLEANUP_CRON="0 0 * * *" \ # optional
4245
-p 127.0.0.1:8080:8080 \

0 commit comments

Comments
 (0)