mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 13:03:02 +12:00
docs: encrypting attributes how-to guide
This commit is contained in:
parent
b000259418
commit
e81ce83d0e
5 changed files with 143 additions and 2 deletions
|
@ -97,7 +97,8 @@ Welcome! Here you will find everything you need to know to get started with and
|
||||||
|
|
||||||
## How-to
|
## How-to
|
||||||
|
|
||||||
- [Optimistic Locking](documentation/how-to/cook-book/preventing-concurrent-writes.livemd)
|
- [Encrypt Attributes](documentation/how-to/encrypt-attributes.livemd)
|
||||||
|
- [Prevent Concurrent Writes](documentation/how-to/prevent-concurrent-writes.livemd)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
3
documentation/assets/livebooks.css
Normal file
3
documentation/assets/livebooks.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.livebook-badge-container + pre {
|
||||||
|
display: none;
|
||||||
|
}
|
134
documentation/how-to/encrypt-attributes.livemd
Normal file
134
documentation/how-to/encrypt-attributes.livemd
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
<!-- livebook:{"persist_outputs":true} -->
|
||||||
|
|
||||||
|
# Encrypt Attributes
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Mix.install([{:ash, "~> 3.0.0-rc"}, {:ash_cloak, "~> 0.1.0-rc"}, {: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"
|
||||||
|
```
|
5
mix.exs
5
mix.exs
|
@ -79,7 +79,8 @@ defmodule Ash.MixProject do
|
||||||
"documentation/topics/security/policies.md",
|
"documentation/topics/security/policies.md",
|
||||||
"documentation/topics/reference/glossary.md",
|
"documentation/topics/reference/glossary.md",
|
||||||
"documentation/topics/reference/expressions.md",
|
"documentation/topics/reference/expressions.md",
|
||||||
"documentation/how-to/preventing-concurrent-writes.livemd",
|
"documentation/how-to/encrypt-attributes.livemd",
|
||||||
|
"documentation/how-to/prevent-concurrent-writes.livemd",
|
||||||
"documentation/dsls/DSL:-Ash.Resource.md",
|
"documentation/dsls/DSL:-Ash.Resource.md",
|
||||||
"documentation/dsls/DSL:-Ash.Domain.md",
|
"documentation/dsls/DSL:-Ash.Domain.md",
|
||||||
"documentation/dsls/DSL:-Ash.Notifier.PubSub.md",
|
"documentation/dsls/DSL:-Ash.Notifier.PubSub.md",
|
||||||
|
@ -111,6 +112,7 @@ defmodule Ash.MixProject do
|
||||||
~r"documentation/dsls"
|
~r"documentation/dsls"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
assets: ["documentation/assets"],
|
||||||
skip_undefined_reference_warnings_on: [
|
skip_undefined_reference_warnings_on: [
|
||||||
"CHANGELOG.md",
|
"CHANGELOG.md",
|
||||||
"documentation/topics/reference/glossary.md",
|
"documentation/topics/reference/glossary.md",
|
||||||
|
@ -132,6 +134,7 @@ defmodule Ash.MixProject do
|
||||||
before_closing_head_tag: fn type ->
|
before_closing_head_tag: fn type ->
|
||||||
if type == :html do
|
if type == :html do
|
||||||
"""
|
"""
|
||||||
|
<link rel="stylesheet" href="assets/livebooks.css">
|
||||||
<script>
|
<script>
|
||||||
if (location.hostname === "hexdocs.pm") {
|
if (location.hostname === "hexdocs.pm") {
|
||||||
var script = document.createElement("script");
|
var script = document.createElement("script");
|
||||||
|
|
Loading…
Reference in a new issue