Packages

Ecto custom type Ecto.Kms to encrypt content in AWS KMS

Current section

Files

Jump to
ecto_kms lib ecto_kms.ex
Raw

lib/ecto_kms.ex

defmodule Ecto.Kms do
@moduledoc """
Custom AWS KMS encrypt field type
When dump to the database data must be encrypted
When load from the database data must be decrypted
"""
alias ExAws.KMS
@behaviour Ecto.Type
@doc false
def type, do: :binary
@doc false
def cast(data), do: {:ok, to_string(data)}
@doc """
Pipe down the incoming string to the AWS KMS service
and returns the encrypted string in case of success.
"""
def dump(data) when is_binary(data) do
with {:ok, encrypted} <- encrypt(data) do
{:ok, encrypted["CiphertextBlob"]}
else
{:error, _} -> {:error, :kms_encryption_failed}
end
end
def dump(_), do: :error
@doc """
Pipe down the data hashed string from database to the
AWS KMS service to be decrypted.
"""
def load(data) when is_binary(data) do
with {:ok, decrypted} <- decrypt(data) do
{:ok, decrypted}
else
{:error, _} -> {:error, :kms_decryption_failed}
end
end
defp encrypt(data) do
data
|> Base.encode64()
|> (&KMS.encrypt(&2, &1)).(encrypt_key())
|> ExAws.request()
end
defp decrypt(data) do
data
|> KMS.decrypt()
|> ExAws.request()
|> decode()
end
defp decode({:error, _}), do: {:error, %{}}
defp decode({:ok, body}), do: Base.decode64(body["Plaintext"])
defp encrypt_key do
Application.get_env(:ecto_kms, :encrypt_key)[:id]
end
end