lib/openagents/deployments/secret_resolver/environment.ex

58e6347eeb72 · 1 KB

defmodule OpenAgents.Deployments.SecretResolver.Environment do
  @moduledoc """
  Resolves deployment secrets from the host process environment.

  The variable name is derived from the repository, the environment, and the
  reference, so one environment's binding cannot read another's value even when
  both declare the same reference name:

      OPENAGENTS_DEPLOY__<REPOSITORY>__<ENVIRONMENT>__<REFERENCE>

  This resolver exists because the first delivery phase runs against a fake
  provider, and a fake provider still has to prove the secret boundary. A hosted
  resolver replaces this module without changing any caller.
  """

  @behaviour OpenAgents.Deployments.SecretResolver

  alias OpenAgents.Deployments.Environment

  @impl true
  def resolve(%Environment{} = environment, references) do
    Enum.reduce_while(references, {:ok, %{}}, fn reference, {:ok, resolved} ->
      case System.get_env(variable_name(environment, reference)) do
        nil -> {:halt, {:error, {:missing_secret_reference, reference}}}
        value -> {:cont, {:ok, Map.put(resolved, reference, value)}}
      end
    end)
  end

  @doc "The host variable one environment's reference resolves from."
  @spec variable_name(Environment.t(), String.t()) :: String.t()
  def variable_name(%Environment{} = environment, reference) when is_binary(reference) do
    repository = environment.repository_id |> to_string() |> String.replace("-", "")

    "OPENAGENTS_DEPLOY__#{String.upcase(repository)}__#{upcase_segment(environment.name)}__#{reference}"
  end

  defp upcase_segment(value), do: value |> String.replace("-", "_") |> String.upcase()
end