Add a detailed Google Workspace setup guide and other docs (#2876)

- Added google workspace docs at `/kb/authenticate/google`
- Updated in-product Provider creation form with more details and a link
to docs
- Fixed bg-color for unauthenticated layouts

---------

Co-authored-by: Brian Manifold <bmanifold@gmail.com>
This commit is contained in:
Jamil
2023-12-12 23:16:11 -08:00
committed by GitHub
parent 75d90d7372
commit 33bcbbee45
31 changed files with 640 additions and 240 deletions

View File

@@ -1100,4 +1100,39 @@ defmodule Web.CoreComponents do
def translate_errors(errors, field) when is_list(errors) do
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
end
@doc """
This component is meant to be used for step by step instructions
ex.
<.step>
<:title>Step 1. Do Something</:title>
<:content>
Here are instructions for step 1...
</:content>
</.step>
<.step>
<:title>Step 2. Do Another Thing</:title>
<:content>
Here are instructions for step 2...
</:content>
</.step>
"""
slot :title, required: true
slot :content, required: true
def step(assigns) do
~H"""
<div class="mb-6">
<h2 class="mb-2 text-2xl tracking-tight font-bold text-neutral-900">
<%= render_slot(@title) %>
</h2>
<div class="px-4">
<%= render_slot(@content) %>
</div>
</div>
"""
end
end

View File

@@ -32,7 +32,7 @@
>
</script>
</head>
<body class="">
<body class="bg-neutral-50">
<%= @inner_content %>
</body>
</html>

View File

@@ -14,7 +14,7 @@ defmodule Web.PageComponents do
def section(assigns) do
~H"""
<div class="mb-12 bg-white overflow-hidden shadow mx-5 rounded border px-6 pb-6">
<div class="mb-6 bg-white overflow-hidden shadow mx-5 rounded border px-6 pb-6">
<.header>
<:title>
<%= render_slot(@title) %>

View File

@@ -3,7 +3,7 @@ defmodule Web.HomeHTML do
def home(assigns) do
~H"""
<section class="bg-neutral-50">
<section>
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto lg:py-0">
<.logo />

View File

@@ -3,117 +3,227 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.Components do
def provider_form(assigns) do
~H"""
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-12">
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
Step 1. Enable Admin SDK API
</h2>
Visit the following link to enable the Admin SDK API for your Google Workspace account:
<a
href="https://console.cloud.google.com/apis/library/admin.googleapis.com"
class={link_style()}
target="_blank"
>
https://console.cloud.google.com/apis/library/admin.googleapis.com
</a>
</div>
<.step>
<:title>Step 1. Create a new project in Google Cloud</:title>
<:content>
Visit the following link to create a new project to use for this integration:
<a
href="https://console.cloud.google.com/projectcreate"
class={link_style()}
target="_blank"
>
https://console.cloud.google.com/projectcreate
</a>
</:content>
</.step>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
Step 2. Configure OAuth consent screen
</h2>
<p class="mb-4">
Ensure the following scopes are added to the OAuth client:
</p>
<.code_block
:for={
{name, scope} <- [
openid: "openid",
email: "email",
profile: "profile",
orgunit: "https://www.googleapis.com/auth/admin.directory.orgunit.readonly",
group: "https://www.googleapis.com/auth/admin.directory.group.readonly",
user: "https://www.googleapis.com/auth/admin.directory.user.readonly"
]
}
id={"scope-#{name}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= scope %></.code_block>
</div>
<.step>
<:title>Step 2. Enable Admin SDK API</:title>
<:content>
Visit the following link to enable the Admin SDK API for the project you just created:
<a
href="https://console.cloud.google.com/apis/library/admin.googleapis.com"
class={link_style()}
target="_blank"
>
https://console.cloud.google.com/apis/library/admin.googleapis.com
</a>
</:content>
</.step>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
Step 3: Create OAuth client
</h2>
<p class="mb-4">
Ensure the OAuth client has following redirect URLs configured:
</p>
<.code_block
:for={
{type, redirect_url} <- [
sign_in: url(~p"/#{@account.id}/sign_in/providers/#{@id}/handle_callback"),
connect:
url(
~p"/#{@account.id}/settings/identity_providers/google_workspace/#{@id}/handle_callback"
)
]
}
id={"redirect_url-#{type}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= redirect_url %></.code_block>
</div>
<.step>
<:title>Step 3. Configure OAuth consent screen</:title>
<:content>
<p class="mb-4">
Visit the following link to configure the OAuth consent screen:
<a
href="https://console.cloud.google.com/apis/credentials/consent"
class={link_style()}
target="_blank"
>
https://console.cloud.google.com/apis/credentials/consent
</a>
</p>
<p class="mb-4">
Select <strong>Internal</strong> for the user type and click <strong>CREATE</strong>.
</p>
<p class="mb-4">
On the next page, use the following values:
</p>
<ul class="ml-4 mb-4 list-disc list-inside">
<li>
<strong>App name</strong>: Firezone
</li>
<li>
<strong>User support email</strong>: Your email address
</li>
<li>
<strong>App logo</strong>:
<.link
href="https://www.firezone.dev/images/gco-oauth-screen-logo.png"
class={link_style()}
>
Download here
</.link>
</li>
<li>
<strong>Application home page</strong>:
<.link href="https://www.firezone.dev" class={link_style()}>
https://www.firezone.dev
</.link>
</li>
<li>
<strong>Application privacy policy link</strong>:
<.link href="https://www.firezone.dev/privacy-policy" class={link_style()}>
https://www.firezone.dev/privacy-policy
</.link>
</li>
<li>
<strong>Application terms of service link</strong>:
<.link href="https://www.firezone.dev/terms" class={link_style()}>
https://www.firezone.dev/terms
</.link>
</li>
<li>
<strong>Authorized domains</strong>:
<code class="px-1 py-0.5 text-sm bg-neutral-600 text-white">firezone.dev</code>
</li>
</ul>
<p class="mb-4">
Click <strong>SAVE AND CONTINUE</strong>.
</p>
</:content>
</.step>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
Step 4. Configure client
</h2>
<.step>
<:title>Step 4. Configure scopes</:title>
<:content>
<p class="mb-4">
Click <strong>ADD OR REMOVE SCOPES</strong> and ensure the following scopes are added:
</p>
<.code_block
id="oauth-scopes"
class="w-full text-xs mb-4 whitespace-pre-line rounded"
phx-no-format
><%= scopes() %></.code_block>
<p class="mb-4">
Then click <strong>UPDATE</strong>.
</p>
</:content>
</.step>
<.base_error form={@form} field={:base} />
<.step>
<:title>Step 5: Create client credentials</:title>
<:content>
<p class="mb-4">
Go to the client credentials section and click <strong>CREATE CREDENTIALS</strong>
to create new OAuth credentials.
</p>
<p class="mb-4">
Select <strong>OAuth client ID</strong>
and then select <strong>Web application</strong>.
</p>
<p class="mb-4">
Use the following values on the next screen:
</p>
<ul class="ml-4 mb-4 list-disc list-inside">
<li>
<strong>Name</strong>: Firezone OAuth Client
</li>
<li>
<strong>Authorized redirect URIs</strong>:
<p class="mt-4">
<.code_block
:for={
{type, redirect_url} <- [
sign_in: url(~p"/#{@account.id}/sign_in/providers/#{@id}/handle_callback"),
connect:
url(
~p"/#{@account.id}/settings/identity_providers/google_workspace/#{@id}/handle_callback"
)
]
}
id={"redirect_url-#{type}"}
class="w-full mb-4 text-xs whitespace-nowrap rounded"
phx-no-format
><%= redirect_url %></.code_block>
</p>
</li>
</ul>
<p class="mb-4">
Click <strong>CREATE</strong>. Copy the <strong>Client ID</strong>
and <strong>Client secret</strong>
values from the next screen.
</p>
</:content>
</.step>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div>
<.input
label="Name"
autocomplete="off"
field={@form[:name]}
placeholder="Name this identity provider"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A friendly name for this identity provider. This will be displayed to end-users.
</p>
<.step>
<:title>Step 6. Configure Firezone</:title>
<:content>
<.base_error form={@form} field={:base} />
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div>
<.input
label="Name"
autocomplete="off"
field={@form[:name]}
placeholder="Name this identity provider"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A friendly name for this identity provider. This will be displayed to end-users.
</p>
</div>
<.inputs_for :let={adapter_config_form} field={@form[:adapter_config]}>
<div>
<.input
label="Client ID"
autocomplete="off"
field={adapter_config_form[:client_id]}
required
/>
<p class="mt-2 text-xs text-neutral-500">
The Client ID from the previous step.
</p>
</div>
<div>
<.input
label="Client secret"
autocomplete="off"
field={adapter_config_form[:client_secret]}
required
/>
<p class="mt-2 text-xs text-neutral-500">
The Client secret from the previous step.
</p>
</div>
</.inputs_for>
</div>
<.inputs_for :let={adapter_config_form} field={@form[:adapter_config]}>
<div>
<.input
label="Client ID"
autocomplete="off"
field={adapter_config_form[:client_id]}
required
/>
</div>
<div>
<.input
label="Client secret"
autocomplete="off"
field={adapter_config_form[:client_secret]}
required
/>
</div>
</.inputs_for>
</div>
<.submit_button>
Connect Identity Provider
</.submit_button>
</div>
<.submit_button>
Connect Identity Provider
</.submit_button>
</:content>
</.step>
</.form>
</div>
"""
end
def scopes do
"""
openid
profile
email
https://www.googleapis.com/auth/admin.directory.orgunit.readonly
https://www.googleapis.com/auth/admin.directory.group.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly
"""
end
end

View File

@@ -39,6 +39,11 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.New do
<:title>
Add a new Google Workspace Identity Provider
</:title>
<:help>
For a more detailed guide on setting up Firezone with Google Workspace, please <.link class={
link_style()
}>refer to our documentation</.link>.
</:help>
<:content>
<.provider_form account={@account} id={@id} form={@form} />
</:content>

View File

@@ -48,13 +48,6 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.Show do
>
Enable Identity Provider
</.button>
<.button
:if={is_nil(@provider.disabled_at)}
phx-click="disable"
data-confirm="Are you sure want to disable this provider? All authorizations will be revoked and actors won't be able to use it to access Firezone."
>
Disable Identity Provider
</.button>
<% end %>
</:action>
<:action :if={is_nil(@provider.deleted_at)}>
@@ -104,6 +97,15 @@ defmodule Web.Settings.IdentityProviders.GoogleWorkspace.Show do
<.danger_zone :if={is_nil(@provider.deleted_at)}>
<:action>
<.button
:if={is_nil(@provider.disabled_at)}
style="warning"
phx-click="disable"
icon="hero-no-symbol"
data-confirm="Are you sure want to disable this provider? Users will no longer be able to sign in with this provider and user / group sync will be paused."
>
Disable Identity Provider
</.button>
<.delete_button
data-confirm="Are you sure want to delete this provider along with all related data?"
phx-click="delete"

View File

@@ -3,116 +3,115 @@ defmodule Web.Settings.IdentityProviders.OpenIDConnect.Components do
def provider_form(assigns) do
~H"""
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-16">
<div class="max-w-2xl px-4 py-8 mx-auto lg:py-12">
<.form for={@form} phx-change={:change} phx-submit={:submit}>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
Step 1. Create OAuth app in your identity provider
</h2>
Please make sure that following scopes are added to the OAuth application: <.code_block
:for={scope <- [:openid, :email, :profile]}
id={"scope-#{scope}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= scope %></.code_block> Please make sure that OAuth client has following redirect URL's whitelisted: <.code_block
:for={
{type, redirect_url} <- [
sign_in: url(~p"/#{@account.id}/sign_in/providers/#{@id}/handle_callback"),
connect:
url(
~p"/#{@account.id}/settings/identity_providers/openid_connect/#{@id}/handle_callback"
)
]
}
id={"redirect_url-#{type}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= redirect_url %></.code_block>
</div>
<.step>
<:title>Step 1. Create OAuth app in your identity provider</:title>
<:content>
Please make sure that following scopes are added to the OAuth application: <.code_block
:for={scope <- [:openid, :email, :profile]}
id={"scope-#{scope}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= scope %></.code_block> Please make sure that OAuth client has following redirect URL's whitelisted: <.code_block
:for={
{type, redirect_url} <- [
sign_in: url(~p"/#{@account.id}/sign_in/providers/#{@id}/handle_callback"),
connect:
url(
~p"/#{@account.id}/settings/identity_providers/openid_connect/#{@id}/handle_callback"
)
]
}
id={"redirect_url-#{type}"}
class="w-full mb-4 whitespace-nowrap rounded"
phx-no-format
><%= redirect_url %></.code_block>
</:content>
</.step>
<div class="mb-4">
<h2 class="mb-4 text-xl font-bold text-neutral-900">
2. Configure client
</h2>
<.step>
<:title>Step 2. Configure client</:title>
<:content>
<.base_error form={@form} field={:base} />
<.base_error form={@form} field={:base} />
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div>
<.input
label="Name"
autocomplete="off"
field={@form[:name]}
placeholder="Name this identity provider"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A friendly name for this identity provider. This will be displayed to end-users.
</p>
</div>
<div class="grid gap-4 mb-4 sm:grid-cols-1 sm:gap-6 sm:mb-6">
<div>
<.input
label="Name"
autocomplete="off"
field={@form[:name]}
placeholder="Name this identity provider"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A friendly name for this identity provider. This will be displayed to end-users.
</p>
<.inputs_for :let={adapter_config_form} field={@form[:adapter_config]}>
<div>
<.input
label="Response Type"
field={adapter_config_form[:response_type]}
placeholder="code"
value="code"
disabled
/>
<p class="mt-2 text-xs text-neutral-500">
Firezone currently only supports <code>code</code> flows.
</p>
</div>
<div>
<.input
label="Scopes"
autocomplete="off"
field={adapter_config_form[:scope]}
placeholder="OpenID Connect scopes to request"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A space-delimited list of scopes to request from your identity provider. In most cases you shouldn't need to change this.
</p>
</div>
<div>
<.input
label="Client ID"
autocomplete="off"
field={adapter_config_form[:client_id]}
placeholder="Client ID from your IdP"
required
/>
</div>
<div>
<.input
label="Client secret"
autocomplete="off"
field={adapter_config_form[:client_secret]}
placeholder="Client Secret from your IdP"
required
/>
</div>
<div>
<.input
label="Discovery URL"
field={adapter_config_form[:discovery_document_uri]}
placeholder=".well-known URL for your IdP"
required
/>
</div>
</.inputs_for>
</div>
<.inputs_for :let={adapter_config_form} field={@form[:adapter_config]}>
<div>
<.input
label="Response Type"
field={adapter_config_form[:response_type]}
placeholder="code"
value="code"
disabled
/>
<p class="mt-2 text-xs text-neutral-500">
Firezone currently only supports <code>code</code> flows.
</p>
</div>
<div>
<.input
label="Scopes"
autocomplete="off"
field={adapter_config_form[:scope]}
placeholder="OpenID Connect scopes to request"
required
/>
<p class="mt-2 text-xs text-neutral-500">
A space-delimited list of scopes to request from your identity provider. In most cases you shouldn't need to change this.
</p>
</div>
<div>
<.input
label="Client ID"
autocomplete="off"
field={adapter_config_form[:client_id]}
placeholder="Client ID from your IdP"
required
/>
</div>
<div>
<.input
label="Client secret"
autocomplete="off"
field={adapter_config_form[:client_secret]}
placeholder="Client Secret from your IdP"
required
/>
</div>
<div>
<.input
label="Discovery URL"
field={adapter_config_form[:discovery_document_uri]}
placeholder=".well-known URL for your IdP"
required
/>
</div>
</.inputs_for>
</div>
<.submit_button>
Connect Identity Provider
</.submit_button>
</div>
<.submit_button>
Connect Identity Provider
</.submit_button>
</:content>
</.step>
</.form>
</div>
"""

View File

@@ -40,7 +40,7 @@ defmodule Web.SignIn do
def render(assigns) do
~H"""
<section class="bg-neutral-50">
<section>
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto lg:py-0">
<.logo />

View File

@@ -31,7 +31,7 @@ defmodule Web.SignIn.Email do
def render(assigns) do
~H"""
<section class="bg-neutral-50">
<section>
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto lg:py-0">
<.logo />

View File

@@ -63,7 +63,7 @@ defmodule Web.SignUp do
def render(assigns) do
~H"""
<section class="bg-neutral-50">
<section>
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto lg:py-0">
<.logo />

View File

@@ -43,6 +43,19 @@ defmodule Web.Sites.NewToken do
<:title>
Deploy a new Gateway
</:title>
<:help>
Gateways require outbound access to <code
class="text-sm bg-neutral-600 text-white px-1 py-0.5 rounded"
phx-no-format
>api.firezone.dev:443</code> only. <strong>No inbound firewall rules</strong>
are required or recommended.
</:help>
<:help>
<.link
href="http://www.firezone.dev/kb/deploy/gateways?utm_source=product"
class="text-accent-500 hover:underline"
>Read the gateway deployment guide for more detailed instructions</.link>.
</:help>
<:content>
<div class="py-8 px-4 mx-auto max-w-2xl lg:py-16">
<div class="text-xl mb-4">