add encrypted map ecto type for integration credentials
This commit is contained in:
parent
a61abd836c
commit
2fd195e6b3
2 changed files with 63 additions and 0 deletions
21
lib/towerops/ecto_types/encrypted_map.ex
Normal file
21
lib/towerops/ecto_types/encrypted_map.ex
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
defmodule Towerops.Encrypted.Map do
|
||||
@moduledoc """
|
||||
Encrypted map field using Cloak vault.
|
||||
|
||||
Used for storing sensitive configuration like API credentials as encrypted JSON.
|
||||
Data is encrypted at rest using AES-256-GCM.
|
||||
|
||||
## Usage
|
||||
|
||||
field :credentials, Towerops.Encrypted.Map
|
||||
|
||||
## Database Schema
|
||||
|
||||
The database column must be `:binary`:
|
||||
|
||||
add :credentials, :binary
|
||||
|
||||
Note: Atom keys become string keys after decryption.
|
||||
"""
|
||||
use Cloak.Ecto.Map, vault: Towerops.Vault
|
||||
end
|
||||
42
test/towerops/ecto_types/encrypted_map_test.exs
Normal file
42
test/towerops/ecto_types/encrypted_map_test.exs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
defmodule Towerops.Encrypted.MapTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
alias Towerops.Encrypted.Map, as: EncryptedMap
|
||||
|
||||
describe "cast/1" do
|
||||
test "casts a valid map" do
|
||||
assert {:ok, %{"key" => "value"}} = EncryptedMap.cast(%{"key" => "value"})
|
||||
end
|
||||
|
||||
test "casts atom-keyed maps" do
|
||||
assert {:ok, %{key: "value"}} = EncryptedMap.cast(%{key: "value"})
|
||||
end
|
||||
|
||||
test "rejects non-map values" do
|
||||
assert :error = EncryptedMap.cast("not a map")
|
||||
assert :error = EncryptedMap.cast(123)
|
||||
end
|
||||
|
||||
test "casts nil" do
|
||||
assert {:ok, nil} = EncryptedMap.cast(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "dump/1 and load/1 round-trip" do
|
||||
test "encrypts and decrypts a map" do
|
||||
original = %{"api_key" => "secret123", "base_url" => "https://api.preseem.com"}
|
||||
|
||||
assert {:ok, encrypted} = EncryptedMap.dump(original)
|
||||
assert is_binary(encrypted)
|
||||
refute encrypted == Jason.encode!(original)
|
||||
|
||||
assert {:ok, decrypted} = EncryptedMap.load(encrypted)
|
||||
assert decrypted == original
|
||||
end
|
||||
|
||||
test "handles nil values" do
|
||||
assert {:ok, nil} = EncryptedMap.dump(nil)
|
||||
assert {:ok, nil} = EncryptedMap.load(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue