forked from juanfont/headscale
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow use of the preferred_username OIDC claim
Previously, Headscale would only use the `email` OIDC claim to set the Headscale user. In certain cases (self-hosted SSO), it may be useful to instead use the `preferred_username` to set the Headscale username. This also closes juanfont#938. This adds a config setting to use this claim instead. The OIDC docs have been updated to include this entry as well. In addition, this adds an Authelia OIDC example to the docs. Added OIDC claim integration tests. Updated the MockOIDC wrapper to take an environment variable that lets you set the username/email claims to return. Added two integration tests, TestOIDCEmailGrant and TestOIDCUsernameGrant, which check the username by checking the FQDN of clients. Updated the HTML template shown after OIDC login to show whatever username is used, based on the Headscale settings.
- Loading branch information
Showing
8 changed files
with
467 additions
and
21 deletions.
There are no files selected for viewing
65 changes: 65 additions & 0 deletions
65
.github/workflows/test-integration-v2-TestOIDCEmailGrant.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go | ||
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/ | ||
|
||
name: Integration Test v2 - TestOIDCEmailGrant | ||
|
||
on: [pull_request] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
TestOIDCEmailGrant: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 2 | ||
|
||
- uses: DeterminateSystems/nix-installer-action@main | ||
- uses: DeterminateSystems/magic-nix-cache-action@main | ||
- uses: satackey/action-docker-layer-caching@main | ||
continue-on-error: true | ||
|
||
- name: Get changed files | ||
id: changed-files | ||
uses: tj-actions/changed-files@v34 | ||
with: | ||
files: | | ||
*.nix | ||
go.* | ||
**/*.go | ||
integration_test/ | ||
config-example.yaml | ||
- name: Run TestOIDCEmailGrant | ||
if: steps.changed-files.outputs.any_changed == 'true' | ||
run: | | ||
nix develop --command -- docker run \ | ||
--tty --rm \ | ||
--volume ~/.cache/hs-integration-go:/go \ | ||
--name headscale-test-suite \ | ||
--volume $PWD:$PWD -w $PWD/integration \ | ||
--volume /var/run/docker.sock:/var/run/docker.sock \ | ||
--volume $PWD/control_logs:/tmp/control \ | ||
golang:1 \ | ||
go run gotest.tools/gotestsum@latest -- ./... \ | ||
-tags ts2019 \ | ||
-failfast \ | ||
-timeout 120m \ | ||
-parallel 1 \ | ||
-run "^TestOIDCEmailGrant$" | ||
- uses: actions/upload-artifact@v3 | ||
if: always() && steps.changed-files.outputs.any_changed == 'true' | ||
with: | ||
name: logs | ||
path: "control_logs/*.log" | ||
|
||
- uses: actions/upload-artifact@v3 | ||
if: always() && steps.changed-files.outputs.any_changed == 'true' | ||
with: | ||
name: pprof | ||
path: "control_logs/*.pprof.tar" |
65 changes: 65 additions & 0 deletions
65
.github/workflows/test-integration-v2-TestOIDCUsernameGrant.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# DO NOT EDIT, generated with cmd/gh-action-integration-generator/main.go | ||
# To regenerate, run "go generate" in cmd/gh-action-integration-generator/ | ||
|
||
name: Integration Test v2 - TestOIDCUsernameGrant | ||
|
||
on: [pull_request] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
TestOIDCUsernameGrant: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 2 | ||
|
||
- uses: DeterminateSystems/nix-installer-action@main | ||
- uses: DeterminateSystems/magic-nix-cache-action@main | ||
- uses: satackey/action-docker-layer-caching@main | ||
continue-on-error: true | ||
|
||
- name: Get changed files | ||
id: changed-files | ||
uses: tj-actions/changed-files@v34 | ||
with: | ||
files: | | ||
*.nix | ||
go.* | ||
**/*.go | ||
integration_test/ | ||
config-example.yaml | ||
- name: Run TestOIDCUsernameGrant | ||
if: steps.changed-files.outputs.any_changed == 'true' | ||
run: | | ||
nix develop --command -- docker run \ | ||
--tty --rm \ | ||
--volume ~/.cache/hs-integration-go:/go \ | ||
--name headscale-test-suite \ | ||
--volume $PWD:$PWD -w $PWD/integration \ | ||
--volume /var/run/docker.sock:/var/run/docker.sock \ | ||
--volume $PWD/control_logs:/tmp/control \ | ||
golang:1 \ | ||
go run gotest.tools/gotestsum@latest -- ./... \ | ||
-tags ts2019 \ | ||
-failfast \ | ||
-timeout 120m \ | ||
-parallel 1 \ | ||
-run "^TestOIDCUsernameGrant$" | ||
- uses: actions/upload-artifact@v3 | ||
if: always() && steps.changed-files.outputs.any_changed == 'true' | ||
with: | ||
name: logs | ||
path: "control_logs/*.log" | ||
|
||
- uses: actions/upload-artifact@v3 | ||
if: always() && steps.changed-files.outputs.any_changed == 'true' | ||
with: | ||
name: pprof | ||
path: "control_logs/*.pprof.tar" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -304,6 +304,16 @@ unix_socket_permission: "0770" | |
# allowed_users: | ||
# - [email protected] | ||
# | ||
# # By default, Headscale will use the OIDC email address claim to determine the username. | ||
# # OIDC also returns a `preferred_username` claim. | ||
# # | ||
# # If `use_username_claim` is set to `true`, then the `preferred_username` claim will | ||
# # be used instead to set the Headscale username. | ||
# # If `use_username_claim` is set to `false`, then the `email` claim will be used | ||
# # to derive the Headscale username (as modified by the `strip_email_domain` entry). | ||
# | ||
# use_username_claim: false | ||
# | ||
# # If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed. | ||
# # This will transform `[email protected]` to the user `first-name.last-name` | ||
# # If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,16 @@ oidc: | |
allowed_users: | ||
- [email protected] | ||
|
||
# By default, Headscale will use the OIDC email address claim to determine the username. | ||
# OIDC also returns a `preferred_username` claim. | ||
# | ||
# If `use_username_claim` is set to `true`, then the `preferred_username` claim will | ||
# be used instead to set the Headscale username. | ||
# If `use_username_claim` is set to `false`, then the `email` claim will be used | ||
# to derive the Headscale username (as modified by the `strip_email_domain` entry). | ||
|
||
use_username_claim: false | ||
|
||
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed. | ||
# This will transform `[email protected]` to the user `first-name.last-name` | ||
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following | ||
|
@@ -170,3 +180,48 @@ oidc: | |
``` | ||
|
||
You can also use `allowed_domains` and `allowed_users` to restrict the users who can authenticate. | ||
|
||
## Authelia Example | ||
|
||
In order to integrate Headscale with your Authelia instance, you need to generate a client secret add your Headscale instance as a client. | ||
|
||
First, generate a client secret. If you are running Authelia inside docker, prepend `docker-compose exec <authelia_container_name>` before these commands: | ||
|
||
```shell | ||
authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 | ||
``` | ||
|
||
This will return two strings, a "Random Password" which you will fill into Headscale, and a "Digest" you will fill into Authelia. | ||
|
||
In your Authelia configuration, add Headscale under the client section: | ||
|
||
```yaml | ||
clients: | ||
- id: headscale | ||
description: Headscale | ||
secret: "DIGEST_STRING_FROM_ABOVE" | ||
public: false | ||
authorization_policy: two_factor | ||
redirect_uris: | ||
- https://your.headscale.domain/oidc/callback | ||
scopes: | ||
- openid | ||
- profile | ||
- groups | ||
``` | ||
|
||
In your Headscale `config.yaml`, edit the config under `oidc`, filling in the `client_id` to match the `id` line in the Authelia config and filling in `client_secret` from the "Random Password" output. | ||
You may want to tune the `expiry`, `only_start_if_oidc_available`, and other entries. The following are only the required entries. | ||
|
||
```yaml | ||
oidc: | ||
issuer: "https://your.authelia.domain" | ||
client_id: "headscale" | ||
client_secret: "RANDOM_PASSWORD_STRING_FROM_ABOVE" | ||
scope: ["openid", "profile", "email", "groups"] | ||
allowed_groups: | ||
- authelia_groups_you_want_to_limit | ||
``` | ||
|
||
In particular, you may want to set `use_username_claim: true` to use Authelia's `preferred_username` grant to set Headscale usernames. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.