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:
Cristine Guadelupe 2023-07-12 16:45:45 +02:00 committed by GitHub
parent 72d18e5a38
commit 8c3f0bf046
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 208 additions and 4 deletions

View file

@ -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

View file

@ -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

View 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

View 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