signature: drop unecessary round trip over user
We already got the key.
This commit is contained in:
parent
bc79bd0edf
commit
51642a90c5
6 changed files with 22 additions and 64 deletions
|
@ -9,24 +9,11 @@ defmodule Pleroma.Signature do
|
||||||
alias Pleroma.User.SigningKey
|
alias Pleroma.User.SigningKey
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
def key_id_to_actor_id(key_id) do
|
|
||||||
case SigningKey.key_id_to_ap_id(key_id) do
|
|
||||||
nil ->
|
|
||||||
# hm, we SHOULD have gotten this in the pipeline before we hit here!
|
|
||||||
Logger.error("Could not figure out who owns the key #{key_id}")
|
|
||||||
{:error, :key_owner_not_found}
|
|
||||||
|
|
||||||
key ->
|
|
||||||
{:ok, key}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def fetch_public_key(conn) do
|
def fetch_public_key(conn) do
|
||||||
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
||||||
{:ok, %SigningKey{}} <- SigningKey.get_or_fetch_by_key_id(kid),
|
{:ok, %SigningKey{} = sk} <- SigningKey.get_or_fetch_by_key_id(kid),
|
||||||
{:ok, actor_id} <- key_id_to_actor_id(kid),
|
{:ok, decoded_key} <- SigningKey.public_key_decoded(sk) do
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, decoded_key}
|
||||||
{:ok, public_key}
|
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
{:error, e}
|
{:error, e}
|
||||||
|
@ -35,10 +22,10 @@ def fetch_public_key(conn) do
|
||||||
|
|
||||||
def refetch_public_key(conn) do
|
def refetch_public_key(conn) do
|
||||||
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
|
||||||
{:ok, %SigningKey{}} <- SigningKey.get_or_fetch_by_key_id(kid),
|
# TODO: force a refetch of stale keys (perhaps with a backoff time based on updated_at)
|
||||||
{:ok, actor_id} <- key_id_to_actor_id(kid),
|
{:ok, %SigningKey{} = sk} <- SigningKey.get_or_fetch_by_key_id(kid),
|
||||||
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
|
{:ok, decoded_key} <- SigningKey.public_key_decoded(sk) do
|
||||||
{:ok, public_key}
|
{:ok, decoded_key}
|
||||||
else
|
else
|
||||||
e ->
|
e ->
|
||||||
{:error, e}
|
{:error, e}
|
||||||
|
|
|
@ -2068,17 +2068,6 @@ defp create_service_actor(uri, nickname) do
|
||||||
|
|
||||||
defdelegate public_key(user), to: SigningKey
|
defdelegate public_key(user), to: SigningKey
|
||||||
|
|
||||||
def get_public_key_for_ap_id(ap_id) do
|
|
||||||
with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
|
|
||||||
{:ok, public_key} <- SigningKey.public_key(user) do
|
|
||||||
{:ok, public_key}
|
|
||||||
else
|
|
||||||
e ->
|
|
||||||
Logger.error("Could not get public key for #{ap_id}.\n#{inspect(e)}")
|
|
||||||
{:error, e}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc "Gets or fetch a user by uri or nickname."
|
@doc "Gets or fetch a user by uri or nickname."
|
||||||
@spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
|
@spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
|
||||||
def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
|
def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)
|
||||||
|
|
|
@ -115,24 +115,18 @@ def private_pem_to_public_pem(private_pem) do
|
||||||
{:ok, :public_key.pem_encode([public_key])}
|
{:ok, :public_key.pem_encode([public_key])}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec public_key(User.t()) :: {:ok, binary()} | {:error, String.t()}
|
@spec public_key(__MODULE__) :: {:ok, binary()} | {:error, String.t()}
|
||||||
@doc """
|
@doc """
|
||||||
Given a user, return the public key for that user in binary format.
|
Return public key data in binary format.
|
||||||
"""
|
"""
|
||||||
def public_key(%User{} = user) do
|
def public_key_decoded(%__MODULE__{public_key: public_key_pem}) do
|
||||||
case Repo.preload(user, :signing_key) do
|
decoded =
|
||||||
%User{signing_key: %__MODULE__{public_key: public_key_pem}} ->
|
public_key_pem
|
||||||
key =
|
|> :public_key.pem_decode()
|
||||||
public_key_pem
|
|> hd()
|
||||||
|> :public_key.pem_decode()
|
|> :public_key.pem_entry_decode()
|
||||||
|> hd()
|
|
||||||
|> :public_key.pem_entry_decode()
|
|
||||||
|
|
||||||
{:ok, key}
|
{:ok, decoded}
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:error, "key not found"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def public_key(_), do: {:error, "key not found"}
|
def public_key(_), do: {:error, "key not found"}
|
||||||
|
|
|
@ -8,8 +8,8 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
||||||
|
|
||||||
use Pleroma.Web, :verified_routes
|
use Pleroma.Web, :verified_routes
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Signature
|
|
||||||
alias Pleroma.Instances
|
alias Pleroma.Instances
|
||||||
|
alias Pleroma.User.SigningKey
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||||
|
@ -140,15 +140,17 @@ defp maybe_require_signature(conn), do: conn
|
||||||
|
|
||||||
defp signature_host(conn) do
|
defp signature_host(conn) do
|
||||||
with {:key_id, %{"keyId" => kid}} <- {:key_id, HTTPSignatures.signature_for_conn(conn)},
|
with {:key_id, %{"keyId" => kid}} <- {:key_id, HTTPSignatures.signature_for_conn(conn)},
|
||||||
{:actor_id, {:ok, actor_id}} <- {:actor_id, Signature.key_id_to_actor_id(kid)} do
|
{:actor_id, actor_id, _} when actor_id != nil <-
|
||||||
|
{:actor_id, SigningKey.key_id_to_ap_id(kid), kid} do
|
||||||
actor_id
|
actor_id
|
||||||
else
|
else
|
||||||
{:key_id, e} ->
|
{:key_id, e} ->
|
||||||
Logger.error("Failed to extract key_id from signature: #{inspect(e)}")
|
Logger.error("Failed to extract key_id from signature: #{inspect(e)}")
|
||||||
nil
|
nil
|
||||||
|
|
||||||
{:actor_id, e} ->
|
{:actor_id, _, kid} ->
|
||||||
Logger.error("Failed to extract actor_id from signature: #{inspect(e)}")
|
# SigningKeys SHOULD have been fetched before this gets called!
|
||||||
|
Logger.error("Failed to extract actor_id from signature: signing key #{kid} not known")
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -114,16 +114,6 @@ test "it returns signature headers" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "key_id_to_actor_id/1" do
|
|
||||||
test "it reverses the key id to actor id" do
|
|
||||||
user =
|
|
||||||
insert(:user)
|
|
||||||
|> with_signing_key()
|
|
||||||
|
|
||||||
assert Signature.key_id_to_actor_id(user.signing_key.key_id) == {:ok, user.ap_id}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "signed_date" do
|
describe "signed_date" do
|
||||||
test "it returns formatted current date" do
|
test "it returns formatted current date" do
|
||||||
with_mock(NaiveDateTime, utc_now: fn -> ~N[2019-08-23 18:11:24.822233] end) do
|
with_mock(NaiveDateTime, utc_now: fn -> ~N[2019-08-23 18:11:24.822233] end) do
|
||||||
|
|
|
@ -1820,10 +1820,6 @@ test "unsuggests a user" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get_public_key_for_ap_id fetches a user that's not in the db" do
|
|
||||||
assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "per-user rich-text filtering" do
|
describe "per-user rich-text filtering" do
|
||||||
test "html_filter_policy returns default policies, when rich-text is enabled" do
|
test "html_filter_policy returns default policies, when rich-text is enabled" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
Loading…
Reference in a new issue