Skip to content

Instantly share code, notes, and snippets.

@shenaor
Last active August 8, 2023 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shenaor/4774ecbd654dbe8dad9a68da26b6e8a6 to your computer and use it in GitHub Desktop.
Save shenaor/4774ecbd654dbe8dad9a68da26b6e8a6 to your computer and use it in GitHub Desktop.

Localstack KMS Helpers

Mix.install([
  {:aws, "~> 0.13.3"},
  {:hackney, "~> 1.18"},
  {:kino, "~> 0.10.0"}
])

Aws Client

client =
  AWS.Client.create("chea", "pizza", "us-west-1")
  |> AWS.Client.put_endpoint("localstack:4566")
  |> Map.put(:proto, "http")

Kms manage module

defmodule KmsManage do
  def find(client, alias_name) do
    case list_aliases(client) do
      [] ->
        nil

      {:error, error} ->
        {:error, error}

      aliases ->
        aliases
        |> Enum.find(%{}, fn %{"AliasName" => kms_alias} ->
          kms_alias == alias_name
        end)
        |> Map.get("AliasName")
    end
  end

  def find_or_create_alias(client, alias_name) do
    case find(client, alias_name) do
      nil ->
        create_alias(client, alias_name)

      {:error, error} ->
        {:error, error}

      alias_name ->
        alias_name
    end
  end

  def create_alias(client, alias_name) do
    {:ok, %{"KeyMetadata" => %{"KeyId" => key_id}}, _body} =
      AWS.KMS.create_key(client, %{"Description" => "Key for #{alias_name}"})

    {:ok, _result, _body} =
      AWS.KMS.create_alias(client, %{"AliasName" => alias_name, "TargetKeyId" => key_id})

    alias_name
  end

  def list_aliases(client) do
    case AWS.KMS.list_aliases(client, %{}) do
      {:ok, %{"Aliases" => aliases}, _body} ->
        aliases

      {:error, error} ->
        {:error, error}
    end
  end
end
form =
  Kino.Control.form(
    [
      alias_to_create: Kino.Input.text("Create new alias")
    ],
    submit: "Submit"
  )

form
Kino.listen(form, fn event ->
  KmsManage.find_or_create_alias(client, event.data.alias_to_create)
  list = KmsManage.list_aliases(client)
  Kino.render(Kino.DataTable.new(list))
end)

Form to test encryption

form =
  Kino.Control.form(
    [
      alias_name: Kino.Input.text("Alias Name"),
      payload: Kino.Input.textarea("Payload")
    ],
    submit: "Submit"
  )

form
encrypted = %{}

form
|> Kino.Control.stream()
|> Kino.listen(fn event ->
  {:ok, %{"CiphertextBlob" => encrypted}, _} =
    AWS.KMS.encrypt(client, %{
      "Plaintext" => Base.encode64(event.data.payload),
      "KeyId" => event.data.alias_name
    })

  Kino.render(encrypted)
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment