defmodule Mix.Tasks.Stevedore.Sign do @shortdoc "Sign an image and attach the signature as a referrer" @moduledoc """ Sign an image with an ECDSA private key (PEM) and attach the cosign-compatible signature to it via the Referrers API. mix stevedore.sign REF --key path/to/key.pem [--scheme http|https] """ use Mix.Task alias Stevedore.{CLI, Referrers, Sign} 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() key = %{private: File.read!(key_path)} {transport, tref} = CLI.unwrap!(Parse.parse(ref, Keyword.take(opts, [:scheme]))) fetched = CLI.unwrap!(Stevedore.Transport.get_manifest(transport, tref)) signature = CLI.unwrap!(Sign.sigstore(fetched.digest, key, subject_size: byte_size(fetched.raw))) digest = CLI.unwrap!(Referrers.attach(transport, fetched.digest, signature)) Mix.shell().info("attached signature #{digest}") else _ -> Mix.raise("usage: mix stevedore.sign REF --key KEY.pem") end end end