cloak
cloak copied to clipboard
Support encrypted fields in embedded schemas
See #81 and #83.
Because many databases do not support direct encoding and decoding of embeds, it is often emulated by Ecto by using specific encoding and decoding rules.
For example, PostgreSQL will store embeds on top of JSONB columns, which means types in embedded schemas won’t go through the usual dump->DB->load cycle but rather encode->DB->decode->cast. This means that, when using embedded schemas with databases like PG or MySQL, make sure all of your types can be JSON encoded/decoded correctly. Ecto provides this guarantee for all built-in types.
Some thoughts:
- The values would need to be base64 encrypted in order to encode to JSON
- Ecto needs to call Cloak's
dump
functions in order to trigger the encryption
I have posted a feature request in Ecto's Google group asking for a needed feature to support this: https://groups.google.com/d/msg/elixir-ecto/RbRdj2NFfDI/qsRLz15nAQAJ
I'd love to see this. Just yesterday I tried using encrypted binaries on an embedded schema and then checked my database... not encrypted.
Another option that would work in my case, would be to use an encrypted Map
as the field Ecto
stores the embedded_schema
in. Not sure how that would work with Ecto
needing a map
type though.
This feature is now in Ecto. Just add:
def embed_as(_format), do: :dump
To the Ecto type and it should work in future Ecto versions.
Tested this successfully on our app by decoding/encoding the values with 64 as suggested on the initial comment here:
defmodule MyApp.EncodedBinary do
use Cloak.Ecto.Binary, vault: MyApp.Vault
def embed_as(:json), do: :dump
def dump(nil), do: {:ok, nil}
def dump(value) do
with {:ok, encrypted} <- super(value) do
{:ok, Base.encode64(encrypted)}
end
end
def load(nil), do: {:ok, nil}
def load(value), do: super(Base.decode64!(value))
end