defmodule Mix.Tasks.Stevedore.Verify do
@shortdoc "Verify an image's signatures against a public key"
@moduledoc """
Verify an image's signatures (fetched via the Referrers API / `.sig` tag) against an ECDSA
public key (PEM). Exits non-zero if no signature satisfies the policy.
mix stevedore.verify REF --key path/to/key.pub [--scheme http|https]
"""
use Mix.Task
alias Stevedore.{CLI, Verify}
alias Stevedore.Transport.Parse
@switches [key: :string, scheme: :string]
@impl true
def run(argv) do
{opts, args, _} = OptionParser.parse(argv, switches: @switches)
with [ref] <- args, key_path when is_binary(key_path) <- opts[:key] do
CLI.start_app()
public = File.read!(key_path)
{transport, tref} = CLI.unwrap!(Parse.parse(ref, Keyword.take(opts, [:scheme])))
fetched = CLI.unwrap!(Stevedore.Transport.get_manifest(transport, tref))
verified =
CLI.unwrap!(Verify.image(fetched.digest, %{keys: [public]}, transport: transport))
Mix.shell().info("verified: #{length(verified)} signature(s) accepted")
else
_ -> Mix.raise("usage: mix stevedore.verify REF --key KEY.pub")
end
end
end