msakrejda / attr_vault

Simple at-rest encryption with key rotation for Sequel models

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JSON config is unwieldy

msakrejda opened this issue · comments

I would have loved many config vars instead of one but I understand why it is that way.
The fact it is an array of json elements in a config var seems odd to me.

Not sure if more practical:

# List of IDs
ATTR_VAULT_IDS=123,234,456
# Values 
ATTR_VAULT_SECRET_123=456
ATTR_VAULT_CREATED_AT_123=timestamp
ATTR_VAULT_SECRET_234=123
ATTR_VAULT_CREATED_AT_234=timestamp
#...

@ys so the keyring has to be JSON right now, but that doesn't mean it has to be that way in your env. You could certainly set config vars as you've outlined and then just define your attr_vault class as:

class Foo < Sequel::Model
  vault_keyring ENV.fetch('ATTR_VAULT_IDS').split(',').map do |id|
    { id: id,
      created_at: ENV.fetch("ATTR_VAULT_CREATED_AT_#{id}"),
      value: ENV.fetch("ATTR_VAULT_SECRET_#{id}") }
  end.to_json
  vault_attr :foo
end

Or just stick that in a helper somewhere so you don't have to repeat it. I definitely don't want to have AttrVault start reading env vars directly--that's a little too magical. Maybe I could support a global config for the vault keyring, but that addresses kind of a different issue. Thoughts?

I've simplified the config a bit in master, so I'll close this for now. Let me know if you have other suggestions. The new syntax allows omitting created_at if using numeric ids, and also allows you to specify a hash rather than an array of keys:

before:

[ { "id": "<some-uuid>", "created_at": "2009-02...", "value": "abcd..." },
  { "id": "<other-uuid>", "created_at": "2014-03...", "value": "defg..." } ]

after:

[ { "id": 1, "value": "abcd..." },
  { "id": 2, "value": "defg..." } ]

or simply

{ "1": "abcd...", "2": "defg..." }

I'll restore some uuid key tests (I've changed them to use integer keys for now) and add a mechanism to migrate from a uuid key column to an integer key column before I make a release.

Actually an in-band migration mechanism is probably overkill: you can easily migrate via something like

  • Add a new_key_id column
  • Rename the existing key_id column to old_key_id
  • Run the following update, filling in the key id mapping based on your keyring's created_at dates for its keys:
WITH key_map(new_key_id, old_key_id) AS (
  VALUES
    (1, 'some-uuid'),
    (2, 'other-uuid')
)
UPDATE
  my_table
SET
  my_table.new_key_id = key_map.new_key_id
FROM
  key_map
WHERE
  my_table.old_key_id = key_map.old_key_id
  • Rename new_key_id to key_id
  • Drop the old_key_id colum

I'll flesh this out and add it to the docs.

Thanks a lot.
This looks in fact easier already:)

I've committed updated docs to master.