mirror of
https://github.com/ash-project/ash.git
synced 2024-09-21 14:03:04 +12:00
134 lines
2.6 KiB
Markdown
134 lines
2.6 KiB
Markdown
<!-- livebook:{"persist_outputs":true} -->
|
|
|
|
# Encrypt Attributes
|
|
|
|
```elixir
|
|
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()
|
|
```
|
|
|
|
## Introduction
|
|
|
|
When dealing with PII 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.
|
|
|
|
## Encrypting attributes
|
|
|
|
1. If you have not yet, follow the getting started guide for `AshCloak` and `Cloak`
|
|
2. Add the `AshCloak` extension to your resource
|
|
3. Configure the attributes that should be encrypted
|
|
4. Add any other additional desired configuration (provided by `AshCloak`)
|
|
|
|
## Examples
|
|
|
|
<!-- livebook:{"disable_formatting":true} -->
|
|
|
|
```elixir
|
|
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
|
|
```
|
|
|
|
<!-- livebook:{"output":true} -->
|
|
|
|
```
|
|
{: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,
|
|
...
|
|
]}
|
|
```
|
|
|
|
## Data is encrypted when modified and is *not displayed* when inspecting.
|
|
|
|
```elixir
|
|
user = Domain.create_user!("111-11-1111")
|
|
```
|
|
|
|
<!-- livebook:{"output":true} -->
|
|
|
|
```
|
|
#User<
|
|
__meta__: #Ecto.Schema.Metadata<:loaded>,
|
|
id: "bc5284fe-294a-485e-8585-06130a4bca4e",
|
|
aggregates: %{},
|
|
calculations: %{},
|
|
...
|
|
>
|
|
```
|
|
|
|
```elixir
|
|
# AshCloak turned ssn into a calculation
|
|
user.ssn
|
|
```
|
|
|
|
<!-- livebook:{"output":true} -->
|
|
|
|
```
|
|
#Ash.NotLoaded<:calculation, field: :ssn>
|
|
```
|
|
|
|
```elixir
|
|
# Load the value to decrypt it on-demand
|
|
Ash.load!(user, :ssn).ssn
|
|
```
|
|
|
|
<!-- livebook:{"output":true} -->
|
|
|
|
```
|
|
"111-11-1111"
|
|
```
|