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

Support for key rotation, new key API #28

Open
meteficha opened this issue Dec 18, 2014 · 0 comments
Open

Support for key rotation, new key API #28

meteficha opened this issue Dec 18, 2014 · 0 comments

Comments

@meteficha
Copy link
Member

Currently there are two options available to clientsession users:

  1. Use the same key forever and ever. Easy to do, convenient for users (who won't get their sessions invalidated due to key changes), but not a security best practice.
  2. Rotate keys periodically. Completely manual at this point (I don't think anyone ever implemented this on their own), invalidates all sessions at once (no support for more than one key simultaneously).

The goal is to remove both drawbacks from option 2 above:

  • Automatic key rotation implemented by the library: harder, see below.
  • Support for more than one key: this one should be easy, but does require a change in API.

The biggest problem in automatic key rotation is propagating the new key to all frontend servers. Of course this is trivial if you have only one server. Here's a simple solution, just to point out that the problem is solvable without much engineering:

  • A new key gets generated a X time before new sessions start to get encrypted by it. (By whom, you may ask: a simple solution would be "by clientsession users themselves", and the only small problem is not creating a bunch of new keys, which is solvable by manually increasing key ids and using DB uniqueness constraints.)
  • The new key, together with all valid old keys, is saved on the database.
  • All clientsession servers periodically update their keyring from the one at the database.
  • After said X time have passed, all servers are assumed to have gotten the new keyring and the new key starts to be used. Old ones that are at most Y time old still are accepted.

In order to sanely implement these features, we could make a big revamp of the key API. Currently it sucks and everyone knows it. Here's the idea:

-- Not shown: a better way of generating keys.

-- | A collection of 'Key's used for encoding and decoding sessions.
data Keyring = 
  Keyring
    { activeKey :: Key 
      -- ^ The key that should be used when encoding sessions.
    , otherValidKeys :: [Key]
      -- ^ Other keys that may be used when decoding sessions.
      -- Doesn't include the active key.
    } deriving (...)

-- | A keyring backend, responsible for updating the keyring whenever
-- necessary.
newtype KeyringBackend =
  KeyringBackend
    { fetchKeyring :: IO Keyring }

-- | Trivial keyring backend: uses a single key, never rotates it.  
-- Same behavior as `clientsession` up to version 0.9.
trivialKeyringBackend :: Key -> KeyringBackend
trivialKeyringBackend = return . flip Keyring []

-- | Keyring backend that fetches the `Key` from the given environment
-- variable.  If the environment variable doesn't exist, a new key is
-- generated and printed to stdout.
envKeyringBackend :: Text -> IO KeyringBackend
envKeyringBackend = ...

-- | Keyring backend that fetches the `Key` from the given file.
-- If the file doesn't exist, a new key is generated and saved.
-- Even though rotating keys would be possible using a file,
-- synchronizing the file between frontend servers is not trivial
-- so this feature is not implemented here.
simpleFileKeyringBackend :: FilePath -> IO KeyringBackend
simpleFileKeyringBackend = ...

This would allow us to create a clientsession-persistent package with a keyring backend that encodes the process I've outlined above. The end result being that users of persistent, including the Yesod scaffold, would get a one-liner that does the right thing without any hassle, while still allowing users the flexibility of using other processes for key rotation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant