Mix.install([{:ash, "~> 3.0"}, {:ash_cloak, "~> 0.1.0"}, {:cloak, "~> 1.1"}],
consolidate_protocols: false
)
Application.put_env(:my_app, MyApp.Vault,
ciphers: [
default: {
Cloak.Ciphers.AES.GCM,
tag: "AES.GCM.V1",
key: Base.decode64!("ETpvtowVAL7JmcxfqJ+XVQWzKrt1ynAkC0vT7AxfyNU="),
iv_length: 12
}
]
)
defmodule MyApp.Vault do
use Cloak.Vault, otp_app: :my_app
end
MyApp.Vault.start_link()When dealing with PII(Personally Identifiable Information) or other sensitive data, we often want to encrypt this data, and control access to the decrypted values.
To do this in Ash, we do that with AshCloak. See the getting started guide in AshCloak for installation instructions.
- If you have not yet, follow the getting started guide for
AshCloakandCloak - Add the
AshCloakextension to your resource - Configure the attributes that should be encrypted
- Add any other additional desired configuration (provided by
AshCloak)
defmodule User do
use Ash.Resource,
domain: Domain,
data_layer: Ash.DataLayer.Ets,
extensions: [AshCloak]
cloak do
vault MyApp.Vault
attributes [:ssn]
end
attributes do
uuid_primary_key :id
attribute :ssn, :string, allow_nil?: false
end
actions do
defaults [:read, create: [:ssn], update: [:ssn]]
end
end
defmodule Domain do
use Ash.Domain,
validate_config_inclusion?: false
resources do
resource User do
define(:create_user, action: :create, args: [:ssn])
define(:update_user, action: :update, args: [:ssn])
define(:list_users, action: :read)
end
end
end{:module, Domain, <<70, 79, 82, 49, 0, 1, 255, ...>>,
[
Ash.Domain.Dsl.Resources.Resource,
Ash.Domain.Dsl.Resources.Options,
Ash.Domain.Dsl,
%{opts: [], entities: [...]},
Ash.Domain.Dsl,
Ash.Domain.Dsl.Resources.Options,
...
]}
user = Domain.create_user!("111-11-1111")#User<
__meta__: #Ecto.Schema.Metadata<:loaded>,
id: "bc5284fe-294a-485e-8585-06130a4bca4e",
aggregates: %{},
calculations: %{},
...
>
# AshCloak turned ssn into a calculation
user.ssn#Ash.NotLoaded<:calculation, field: :ssn>
# Load the value to decrypt it on-demand
Ash.load!(user, :ssn).ssn"111-11-1111"