mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-02-24 06:48:07 +08:00
Internal ZTA tests (#2058)
* Tests for GoogleIAP * Tests for Cloudflare * Tests for Cloudflare * Clean up * Applying suggestions * Clean up * Update test/livebook/zta/google_iap_test.exs Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> * Update test/livebook/zta/cloudflare_test.exs Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com> --------- Co-authored-by: Jonatan Kłosko <jonatanklosko@gmail.com>
This commit is contained in:
parent
72d18e5a38
commit
8c3f0bf046
4 changed files with 208 additions and 4 deletions
|
@ -21,7 +21,7 @@ defmodule Livebook.ZTA.Cloudflare do
|
|||
defstruct [:name, :req_options, :identity, :keys]
|
||||
|
||||
def start_link(opts) do
|
||||
identity = identity(opts[:identity][:key])
|
||||
identity = opts[:custom_identity] || identity(opts[:identity][:key])
|
||||
options = [req_options: [url: identity.certs], identity: identity, keys: nil]
|
||||
GenServer.start_link(__MODULE__, options, name: opts[:name])
|
||||
end
|
||||
|
@ -71,7 +71,7 @@ defmodule Livebook.ZTA.Cloudflare do
|
|||
Enum.find_value(keys, :error, fn key ->
|
||||
case JOSE.JWT.verify(key, token) do
|
||||
{true, token, _s} -> {:ok, token}
|
||||
{_, _t, _s} -> nil
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -25,7 +25,7 @@ defmodule Livebook.ZTA.GoogleIAP do
|
|||
defstruct [:name, :req_options, :identity, :keys]
|
||||
|
||||
def start_link(opts) do
|
||||
identity = identity(opts[:identity][:key])
|
||||
identity = opts[:custom_identity] || identity(opts[:identity][:key])
|
||||
options = [req_options: [url: identity.certs], identity: identity, keys: nil]
|
||||
GenServer.start_link(__MODULE__, options, name: opts[:name])
|
||||
end
|
||||
|
@ -74,7 +74,7 @@ defmodule Livebook.ZTA.GoogleIAP do
|
|||
Enum.find_value(keys, :error, fn key ->
|
||||
case JOSE.JWT.verify(key, token) do
|
||||
{true, token, _s} -> {:ok, token}
|
||||
{_, _t, _s} -> nil
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
112
test/livebook/zta/cloudflare_test.exs
Normal file
112
test/livebook/zta/cloudflare_test.exs
Normal file
|
@ -0,0 +1,112 @@
|
|||
defmodule Livebook.ZTA.CloudflareTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Livebook.ZTA.Cloudflare
|
||||
|
||||
@fields [:id, :name, :email]
|
||||
|
||||
setup do
|
||||
bypass = Bypass.open()
|
||||
user_identity = Bypass.open()
|
||||
|
||||
key = %{
|
||||
"kty" => "RSA",
|
||||
"e" => "AQAB",
|
||||
"use" => "sig",
|
||||
"kid" => "bmlyt6y2uWrgWeUh3mENiSkEOR7Np3I8swSjlK98iX0",
|
||||
"alg" => "RS256",
|
||||
"n" =>
|
||||
"qvMgmj7GrjMAKxib9ODcdNyMwhsU1jwjvyAANrCJ5n1UcM82lZ5B3YP13zbPY3vRuufkW_GuA2cEZ8htMGT79kMsPz1cLrwIeUNOdGzncQQvBJVmQgw8NOuflVy5OajvfSe4a5PQmpC6BEp1d-Ix0S4BV2vWJUb0UtHg3bM4GgHTrnhHkSyXfpSZT4SNqnSOtiXiD-7lue52cPlZotkeTR2D4LTVSrsCdp21wGvAxXqnfpRcKYs5EyEmyTQ85zak7nBAReMrAqrRilXej8qTWGGIg1TRILvoCMd3nF5QjcjRCx2JMMHXG4tZNoK4QbEQlsdcd45B1VpE15TwgNTx4Q"
|
||||
}
|
||||
|
||||
token =
|
||||
"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZW1haWwiOiJ0dWthQHBlcmFsdGEuY29tIiwiaWF0IjoxNTE2MjM5MDIyLCJpc3MiOiJsaXZlYm9vayIsImF1ZCI6ImxpdmVib29rd2ViIn0.ZP5LIrkfMHq2p8g3SMgC7RBt7899GeHkP9rzYKM3RvjDCBeYoxpeioLW2sXMT74QyJPxB4JUujRU3shSPIWNAxkjJVaBGwVTqsO_PR34DSx82q45qSkUnkSVXLl-2KgN4BoUUK7dmocP6yzhNQ3XGf6669n5UG69eMZdh9PApZ7GuyRUQ80ubpvakWaIpd9PIaORkptqDWVbyOIk3Z79AMUub0MSG1FpzYByAQoLswob24l2xVo95-aQrdatqLk1sJ43AZ6HLoMxkZkWobYYRMH5w65MkQckJ9NzI3Rk-VOUlg9ePo8OPRnvcGY-OozHXrjdzn2-j03xuP6x1J3Y7Q"
|
||||
|
||||
options = [
|
||||
name: LivebookWeb.ZTA,
|
||||
custom_identity: %{
|
||||
iss: "livebook",
|
||||
key: "livebookweb",
|
||||
certs: "http://localhost:#{bypass.port}",
|
||||
user_identity: "http://localhost:#{user_identity.port}"
|
||||
}
|
||||
]
|
||||
|
||||
Bypass.expect(bypass, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(200, Jason.encode!(%{keys: [key]}))
|
||||
end)
|
||||
|
||||
conn = conn(:get, "/") |> put_req_header("cf-access-jwt-assertion", token)
|
||||
|
||||
{:ok,
|
||||
bypass: bypass, token: token, options: options, user_identity: user_identity, conn: conn}
|
||||
end
|
||||
|
||||
test "returns the user_identity when the user is valid", context do
|
||||
expected_user = %{
|
||||
"user_uuid" => "1234567890",
|
||||
"name" => "Tuka Peralta",
|
||||
"email" => "tuka@peralta.com"
|
||||
}
|
||||
|
||||
Bypass.expect_once(context.user_identity, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(200, Jason.encode!(expected_user))
|
||||
end)
|
||||
|
||||
start_supervised!({Cloudflare, context.options})
|
||||
{_conn, user} = Cloudflare.authenticate(LivebookWeb.ZTA, context.conn, fields: @fields)
|
||||
|
||||
assert %{id: "1234567890", email: "tuka@peralta.com", name: "Tuka Peralta"} = user
|
||||
end
|
||||
|
||||
test "returns nil when the user_identity fails", context do
|
||||
Bypass.expect_once(context.user_identity, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(403, "")
|
||||
end)
|
||||
|
||||
start_supervised!({Cloudflare, context.options})
|
||||
|
||||
assert {_conn, nil} = Cloudflare.authenticate(LivebookWeb.ZTA, context.conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the iss is invalid", %{options: options, conn: conn} do
|
||||
invalid_identity = Map.replace(options[:custom_identity], :iss, "invalid_iss")
|
||||
options = Keyword.put(options, :custom_identity, invalid_identity)
|
||||
start_supervised!({Cloudflare, options})
|
||||
|
||||
assert {_conn, nil} = Cloudflare.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the token is invalid", %{options: options} do
|
||||
conn = conn(:get, "/") |> put_req_header("cf-access-jwt-assertion", "invalid_token")
|
||||
start_supervised!({Cloudflare, options})
|
||||
|
||||
assert {_conn, nil} = Cloudflare.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the assertion is invalid", %{options: options, token: token} do
|
||||
conn = conn(:get, "/") |> put_req_header("invalid_assertion", token)
|
||||
start_supervised!({Cloudflare, options})
|
||||
|
||||
assert {_conn, nil} = Cloudflare.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the key is invalid", %{bypass: bypass, options: options, conn: conn} do
|
||||
Bypass.expect_once(bypass, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(200, Jason.encode!(%{keys: ["invalid_key"]}))
|
||||
end)
|
||||
|
||||
start_supervised!({Cloudflare, options})
|
||||
|
||||
assert {_conn, nil} = Cloudflare.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
end
|
92
test/livebook/zta/google_iap_test.exs
Normal file
92
test/livebook/zta/google_iap_test.exs
Normal file
|
@ -0,0 +1,92 @@
|
|||
defmodule Livebook.ZTA.GoogleIAPTest do
|
||||
use ExUnit.Case, async: true
|
||||
use Plug.Test
|
||||
|
||||
alias Livebook.ZTA.GoogleIAP
|
||||
|
||||
@fields [:id, :name, :email]
|
||||
|
||||
setup do
|
||||
bypass = Bypass.open()
|
||||
|
||||
key = %{
|
||||
"kty" => "RSA",
|
||||
"e" => "AQAB",
|
||||
"use" => "sig",
|
||||
"kid" => "bmlyt6y2uWrgWeUh3mENiSkEOR7Np3I8swSjlK98iX0",
|
||||
"alg" => "RS256",
|
||||
"n" =>
|
||||
"qvMgmj7GrjMAKxib9ODcdNyMwhsU1jwjvyAANrCJ5n1UcM82lZ5B3YP13zbPY3vRuufkW_GuA2cEZ8htMGT79kMsPz1cLrwIeUNOdGzncQQvBJVmQgw8NOuflVy5OajvfSe4a5PQmpC6BEp1d-Ix0S4BV2vWJUb0UtHg3bM4GgHTrnhHkSyXfpSZT4SNqnSOtiXiD-7lue52cPlZotkeTR2D4LTVSrsCdp21wGvAxXqnfpRcKYs5EyEmyTQ85zak7nBAReMrAqrRilXej8qTWGGIg1TRILvoCMd3nF5QjcjRCx2JMMHXG4tZNoK4QbEQlsdcd45B1VpE15TwgNTx4Q"
|
||||
}
|
||||
|
||||
token =
|
||||
"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZW1haWwiOiJ0dWthQHBlcmFsdGEuY29tIiwiaWF0IjoxNTE2MjM5MDIyLCJpc3MiOiJsaXZlYm9vayIsImF1ZCI6ImxpdmVib29rd2ViIn0.ZP5LIrkfMHq2p8g3SMgC7RBt7899GeHkP9rzYKM3RvjDCBeYoxpeioLW2sXMT74QyJPxB4JUujRU3shSPIWNAxkjJVaBGwVTqsO_PR34DSx82q45qSkUnkSVXLl-2KgN4BoUUK7dmocP6yzhNQ3XGf6669n5UG69eMZdh9PApZ7GuyRUQ80ubpvakWaIpd9PIaORkptqDWVbyOIk3Z79AMUub0MSG1FpzYByAQoLswob24l2xVo95-aQrdatqLk1sJ43AZ6HLoMxkZkWobYYRMH5w65MkQckJ9NzI3Rk-VOUlg9ePo8OPRnvcGY-OozHXrjdzn2-j03xuP6x1J3Y7Q"
|
||||
|
||||
options = [
|
||||
name: LivebookWeb.ZTA,
|
||||
custom_identity: %{
|
||||
iss: "livebook",
|
||||
key: "livebookweb",
|
||||
certs: "http://localhost:#{bypass.port}"
|
||||
}
|
||||
]
|
||||
|
||||
Bypass.expect(bypass, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(200, Jason.encode!(%{keys: [key]}))
|
||||
end)
|
||||
|
||||
conn = conn(:get, "/") |> put_req_header("x-goog-iap-jwt-assertion", token)
|
||||
|
||||
{:ok, bypass: bypass, token: token, options: options, conn: conn}
|
||||
end
|
||||
|
||||
test "returns the user when it's valid", %{options: options, conn: conn} do
|
||||
start_supervised!({GoogleIAP, options})
|
||||
{_conn, user} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
assert %{id: "1234567890", email: "tuka@peralta.com"} = user
|
||||
end
|
||||
|
||||
test "returns nil when the iss is invalid", %{options: options, conn: conn} do
|
||||
invalid_identity = Map.replace(options[:custom_identity], :iss, "invalid_iss")
|
||||
options = Keyword.put(options, :custom_identity, invalid_identity)
|
||||
start_supervised!({GoogleIAP, options})
|
||||
|
||||
assert {_conn, nil} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the aud is invalid", %{options: options, conn: conn} do
|
||||
invalid_identity = Map.replace(options[:custom_identity], :key, "invalid_aud")
|
||||
options = Keyword.put(options, :custom_identity, invalid_identity)
|
||||
start_supervised!({GoogleIAP, options})
|
||||
|
||||
assert {_conn, nil} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the token is invalid", %{options: options} do
|
||||
conn = conn(:get, "/") |> put_req_header("x-goog-iap-jwt-assertion", "invalid_token")
|
||||
start_supervised!({GoogleIAP, options})
|
||||
|
||||
assert {_conn, nil} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the assertion is invalid", %{options: options, token: token} do
|
||||
conn = conn(:get, "/") |> put_req_header("invalid_assertion", token)
|
||||
start_supervised!({GoogleIAP, options})
|
||||
|
||||
assert {_conn, nil} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
|
||||
test "returns nil when the key is invalid", %{bypass: bypass, options: options, conn: conn} do
|
||||
Bypass.expect_once(bypass, fn conn ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(200, Jason.encode!(%{keys: ["invalid_key"]}))
|
||||
end)
|
||||
|
||||
start_supervised!({GoogleIAP, options})
|
||||
|
||||
assert {_conn, nil} = GoogleIAP.authenticate(LivebookWeb.ZTA, conn, fields: @fields)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue