Skip to content

Instantly share code, notes, and snippets.

@bforchhammer
Last active December 6, 2019 16:06
Show Gist options
  • Save bforchhammer/b2a22caef43e7426e041f94a6655b552 to your computer and use it in GitHub Desktop.
Save bforchhammer/b2a22caef43e7426e041f94a6655b552 to your computer and use it in GitHub Desktop.
Exec authentication provider for k8s elixir library
defmodule K8sAuth.Exec do
@moduledoc false
alias K8sAuth.Exec
alias K8s.Conn.RequestOptions
@behaviour K8s.Conn.Auth
defstruct [:command, :env, :args]
@type t :: %__MODULE__{
command: String.t(),
env: list(%{name: String.t(), value: String.t()}),
args: list(String.t())
}
@impl true
def create(%{"exec" => config}, _) do
%{
"command" => command,
"args" => args,
"env" => env
} = config
%__MODULE__{
command: command,
env: format_env(env),
args: args
}
end
def create(_, _), do: nil
defp format_env(env) when is_list(env), do: Enum.into(env, %{}, &format_env/1)
defp format_env(%{"name" => key, "value" => value}), do: {key, value}
defimpl RequestOptions, for: __MODULE__ do
@doc "Generates HTTP Authorization options for auth-provider authentication"
@spec generate(Exec.t()) :: RequestOptions.generate_t()
def generate(%Exec{} = provider) do
case Exec.generate_token(provider) do
{:ok, token} ->
{
:ok,
%RequestOptions{
headers: [{"Authorization", "Bearer #{token}"}],
ssl_options: []
}
}
error ->
error
end
end
end
@doc """
"Generate" a token using the `exec` config in kube config.
"""
@spec generate_token(t) ::
{:ok, binary} | {:error, binary | atom, {:exec_fail, binary}}
def generate_token(config) do
with {cmd_response, 0} <- System.cmd(config.command, config.args, env: config.env),
{:ok, data} <- Jason.decode(cmd_response),
{:ok, token} when not is_nil(token) <- parse_cmd_response(data) do
{:ok, token}
else
{cmd_response, err_code}
when is_binary(cmd_response) and is_integer(err_code) ->
{:error, {:exec_fail, cmd_response}}
error ->
error
end
end
defp parse_cmd_response(%{"kind" => "ExecCredential", "status" => %{"token" => token}}),
do: {:ok, token}
# TODO: support clientKeyData and clientCertificateData
defp parse_cmd_response(_), do: {:error, {:exec_fail, "Unsupported ExecCredential"}}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment