Add Burrow Authentik admin directory sync
This commit is contained in:
parent
1ff8270a01
commit
bb05bd9014
5 changed files with 484 additions and 11 deletions
249
Scripts/authentik-sync-burrow-directory.sh
Normal file
249
Scripts/authentik-sync-burrow-directory.sh
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
authentik_url="${AUTHENTIK_URL:-https://auth.burrow.net}"
|
||||
bootstrap_token="${AUTHENTIK_BOOTSTRAP_TOKEN:-}"
|
||||
directory_json="${AUTHENTIK_BURROW_DIRECTORY_JSON:-[]}"
|
||||
users_group="${AUTHENTIK_BURROW_USERS_GROUP:-burrow-users}"
|
||||
admins_group="${AUTHENTIK_BURROW_ADMINS_GROUP:-burrow-admins}"
|
||||
forgejo_application_slug="${AUTHENTIK_FORGEJO_APPLICATION_SLUG:-}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: Scripts/authentik-sync-burrow-directory.sh
|
||||
|
||||
Required environment:
|
||||
AUTHENTIK_BOOTSTRAP_TOKEN
|
||||
AUTHENTIK_BURROW_DIRECTORY_JSON
|
||||
|
||||
Optional environment:
|
||||
AUTHENTIK_URL
|
||||
AUTHENTIK_BURROW_USERS_GROUP
|
||||
AUTHENTIK_BURROW_ADMINS_GROUP
|
||||
AUTHENTIK_FORGEJO_APPLICATION_SLUG
|
||||
EOF
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "$bootstrap_token" ]]; then
|
||||
echo "error: AUTHENTIK_BOOTSTRAP_TOKEN is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$directory_json" | jq -e 'type == "array"' >/dev/null; then
|
||||
echo "error: AUTHENTIK_BURROW_DIRECTORY_JSON must be a JSON array" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
api() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local data="${3:-}"
|
||||
|
||||
if [[ -n "$data" ]]; then
|
||||
curl -fsS \
|
||||
-X "$method" \
|
||||
-H "Authorization: Bearer ${bootstrap_token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data" \
|
||||
"${authentik_url}${path}"
|
||||
else
|
||||
curl -fsS \
|
||||
-X "$method" \
|
||||
-H "Authorization: Bearer ${bootstrap_token}" \
|
||||
"${authentik_url}${path}"
|
||||
fi
|
||||
}
|
||||
|
||||
wait_for_authentik() {
|
||||
for _ in $(seq 1 90); do
|
||||
if curl -fsS "${authentik_url}/-/health/ready/" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "error: Authentik did not become ready at ${authentik_url}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
lookup_group_pk() {
|
||||
local group_name="$1"
|
||||
|
||||
api GET "/api/v3/core/groups/?page_size=200&search=${group_name}" \
|
||||
| jq -r --arg name "$group_name" '.results[]? | select(.name == $name) | .pk // empty' \
|
||||
| head -n1
|
||||
}
|
||||
|
||||
ensure_group() {
|
||||
local group_name="$1"
|
||||
local payload group_pk
|
||||
|
||||
payload="$(
|
||||
jq -cn \
|
||||
--arg name "$group_name" \
|
||||
'{name: $name}'
|
||||
)"
|
||||
|
||||
group_pk="$(lookup_group_pk "$group_name")"
|
||||
if [[ -n "$group_pk" ]]; then
|
||||
api PATCH "/api/v3/core/groups/${group_pk}/" "$payload" >/dev/null
|
||||
else
|
||||
group_pk="$(
|
||||
api POST "/api/v3/core/groups/" "$payload" \
|
||||
| jq -r '.pk // empty'
|
||||
)"
|
||||
fi
|
||||
|
||||
if [[ -z "$group_pk" ]]; then
|
||||
echo "error: could not create Authentik group ${group_name}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$group_pk"
|
||||
}
|
||||
|
||||
lookup_user_pk() {
|
||||
local username="$1"
|
||||
|
||||
api GET "/api/v3/core/users/?page_size=200&search=${username}" \
|
||||
| jq -r --arg username "$username" '.results[]? | select(.username == $username) | .pk // empty' \
|
||||
| head -n1
|
||||
}
|
||||
|
||||
ensure_user() {
|
||||
local user_spec="$1"
|
||||
local username name email is_admin groups_json effective_groups_json group_name
|
||||
local group_pks_json payload user_pk
|
||||
|
||||
username="$(printf '%s\n' "$user_spec" | jq -r '.username')"
|
||||
name="$(printf '%s\n' "$user_spec" | jq -r '.name')"
|
||||
email="$(printf '%s\n' "$user_spec" | jq -r '.email')"
|
||||
is_admin="$(printf '%s\n' "$user_spec" | jq -r '.isAdmin // false')"
|
||||
groups_json="$(printf '%s\n' "$user_spec" | jq -c '.groups // []')"
|
||||
|
||||
if [[ -z "$username" || "$username" == "null" || -z "$email" || "$email" == "null" ]]; then
|
||||
echo "error: each Burrow Authentik user requires username and email" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
effective_groups_json="$(
|
||||
printf '%s\n' "$groups_json" \
|
||||
| jq -c --arg users_group "$users_group" --arg admins_group "$admins_group" --argjson is_admin "$is_admin" '
|
||||
. + [$users_group] + (if $is_admin then [$admins_group] else [] end) | unique
|
||||
'
|
||||
)"
|
||||
|
||||
group_pks_json='[]'
|
||||
while IFS= read -r group_name; do
|
||||
group_pk="$(ensure_group "$group_name")"
|
||||
group_pks_json="$(
|
||||
jq -cn \
|
||||
--argjson current "$group_pks_json" \
|
||||
--arg next "$group_pk" \
|
||||
'$current + [$next]'
|
||||
)"
|
||||
done < <(printf '%s\n' "$effective_groups_json" | jq -r '.[]')
|
||||
|
||||
payload="$(
|
||||
jq -cn \
|
||||
--arg username "$username" \
|
||||
--arg name "$name" \
|
||||
--arg email "$email" \
|
||||
--argjson groups "$group_pks_json" \
|
||||
'{
|
||||
username: $username,
|
||||
name: $name,
|
||||
email: $email,
|
||||
is_active: true,
|
||||
path: "users",
|
||||
groups: $groups
|
||||
}'
|
||||
)"
|
||||
|
||||
user_pk="$(lookup_user_pk "$username")"
|
||||
if [[ -n "$user_pk" ]]; then
|
||||
api PATCH "/api/v3/core/users/${user_pk}/" "$payload" >/dev/null
|
||||
else
|
||||
user_pk="$(
|
||||
api POST "/api/v3/core/users/" "$payload" \
|
||||
| jq -r '.pk // empty'
|
||||
)"
|
||||
fi
|
||||
|
||||
if [[ -z "$user_pk" ]]; then
|
||||
echo "error: could not create Authentik user ${username}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
lookup_application_pk() {
|
||||
local slug="$1"
|
||||
|
||||
api GET "/api/v3/core/applications/?page_size=200" \
|
||||
| jq -r --arg slug "$slug" '.results[]? | select(.slug == $slug) | .pk // empty' \
|
||||
| head -n1
|
||||
}
|
||||
|
||||
ensure_application_group_binding() {
|
||||
local application_slug="$1"
|
||||
local group_name="$2"
|
||||
local application_pk group_pk existing payload binding_pk
|
||||
|
||||
application_pk="$(lookup_application_pk "$application_slug")"
|
||||
if [[ -z "$application_pk" ]]; then
|
||||
echo "warning: could not resolve Authentik application ${application_slug}; skipping application group binding" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
group_pk="$(lookup_group_pk "$group_name")"
|
||||
if [[ -z "$group_pk" ]]; then
|
||||
echo "error: could not resolve Authentik group ${group_name}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
existing="$(
|
||||
api GET "/api/v3/policies/bindings/?page_size=200&target=${application_pk}" \
|
||||
| jq -c --arg group_pk "$group_pk" '.results[]? | select(.group == $group_pk)' \
|
||||
| head -n1
|
||||
)"
|
||||
|
||||
payload="$(
|
||||
jq -cn \
|
||||
--arg target "$application_pk" \
|
||||
--arg group "$group_pk" \
|
||||
'{
|
||||
group: $group,
|
||||
target: $target,
|
||||
negate: false,
|
||||
enabled: true,
|
||||
order: 100,
|
||||
timeout: 30,
|
||||
failure_result: false
|
||||
}'
|
||||
)"
|
||||
|
||||
if [[ -n "$existing" ]]; then
|
||||
binding_pk="$(printf '%s\n' "$existing" | jq -r '.pk')"
|
||||
api PATCH "/api/v3/policies/bindings/${binding_pk}/" "$payload" >/dev/null
|
||||
else
|
||||
api POST "/api/v3/policies/bindings/" "$payload" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
wait_for_authentik
|
||||
ensure_group "$users_group" >/dev/null
|
||||
ensure_group "$admins_group" >/dev/null
|
||||
|
||||
while IFS= read -r user_spec; do
|
||||
ensure_user "$user_spec"
|
||||
done < <(printf '%s\n' "$directory_json" | jq -c '.[]')
|
||||
|
||||
if [[ -n "$forgejo_application_slug" ]]; then
|
||||
ensure_application_group_binding "$forgejo_application_slug" "$users_group"
|
||||
fi
|
||||
|
||||
echo "Synced Burrow Authentik directory."
|
||||
|
|
@ -74,6 +74,41 @@ api() {
|
|||
fi
|
||||
}
|
||||
|
||||
api_with_status() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local data="${3:-}"
|
||||
local response_file status
|
||||
|
||||
response_file="$(mktemp)"
|
||||
trap 'rm -f "$response_file"' RETURN
|
||||
|
||||
if [[ -n "$data" ]]; then
|
||||
status="$(
|
||||
curl -sS \
|
||||
-o "$response_file" \
|
||||
-w '%{http_code}' \
|
||||
-X "$method" \
|
||||
-H "Authorization: Bearer ${bootstrap_token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data" \
|
||||
"${authentik_url}${path}"
|
||||
)"
|
||||
else
|
||||
status="$(
|
||||
curl -sS \
|
||||
-o "$response_file" \
|
||||
-w '%{http_code}' \
|
||||
-X "$method" \
|
||||
-H "Authorization: Bearer ${bootstrap_token}" \
|
||||
"${authentik_url}${path}"
|
||||
)"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$status"
|
||||
cat "$response_file"
|
||||
}
|
||||
|
||||
wait_for_authentik() {
|
||||
for _ in $(seq 1 90); do
|
||||
if curl -fsS "${authentik_url}/-/health/ready/" >/dev/null 2>&1; then
|
||||
|
|
@ -106,7 +141,6 @@ signing_key="$(printf '%s\n' "$template_provider" | jq -r '.signing_key')"
|
|||
provider_payload="$(
|
||||
jq -n \
|
||||
--arg name "$provider_name" \
|
||||
--arg slug "$application_slug" \
|
||||
--arg authorization_flow "$authorization_flow" \
|
||||
--arg invalidation_flow "$invalidation_flow" \
|
||||
--arg client_id "$client_id" \
|
||||
|
|
@ -116,7 +150,6 @@ provider_payload="$(
|
|||
--argjson redirect_uris "$redirect_uris_json" \
|
||||
'{
|
||||
name: $name,
|
||||
slug: $slug,
|
||||
authorization_flow: $authorization_flow,
|
||||
invalidation_flow: $invalidation_flow,
|
||||
client_type: "confidential",
|
||||
|
|
@ -172,18 +205,32 @@ application_payload="$(
|
|||
)"
|
||||
|
||||
existing_application="$(
|
||||
api GET "/api/v3/core/applications/?slug=${application_slug}" \
|
||||
| jq -c '.results[]? | select(.slug != null)' \
|
||||
api GET "/api/v3/core/applications/?page_size=200" \
|
||||
| jq -c --arg slug "$application_slug" '.results[]? | select(.slug == $slug)' \
|
||||
| head -n1
|
||||
)"
|
||||
|
||||
if [[ -n "$existing_application" ]]; then
|
||||
application_pk="$(printf '%s\n' "$existing_application" | jq -r '.pk')"
|
||||
else
|
||||
application_pk="$(
|
||||
api POST "/api/v3/core/applications/" "$application_payload" \
|
||||
| jq -r '.pk // empty'
|
||||
create_application_result="$(
|
||||
api_with_status POST "/api/v3/core/applications/" "$application_payload"
|
||||
)"
|
||||
create_application_status="$(printf '%s\n' "$create_application_result" | sed -n '1p')"
|
||||
create_application_body="$(printf '%s\n' "$create_application_result" | sed '1d')"
|
||||
|
||||
if [[ "$create_application_status" =~ ^20[01]$ ]]; then
|
||||
application_pk="$(printf '%s\n' "$create_application_body" | jq -r '.pk // empty')"
|
||||
elif [[ "$create_application_status" == "400" ]] && printf '%s\n' "$create_application_body" | jq -e '
|
||||
(.slug // [] | index("Application with this slug already exists.")) != null
|
||||
or (.provider // [] | index("Application with this provider already exists.")) != null
|
||||
' >/dev/null; then
|
||||
application_pk="existing-duplicate"
|
||||
else
|
||||
printf '%s\n' "$create_application_body" >&2
|
||||
echo "error: could not reconcile Authentik application ${application_slug}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${application_pk:-}" ]]; then
|
||||
|
|
|
|||
|
|
@ -91,6 +91,22 @@
|
|||
headscaleClientSecretFile = config.age.secrets.burrowHeadscaleOidcClientSecret.path;
|
||||
googleClientIDFile = config.age.secrets.burrowAuthentikGoogleClientId.path;
|
||||
googleClientSecretFile = config.age.secrets.burrowAuthentikGoogleClientSecret.path;
|
||||
bootstrapUsers = [
|
||||
{
|
||||
username = "contact";
|
||||
name = "Burrow";
|
||||
email = "contact@burrow.net";
|
||||
sourceEmail = "net.burrow@gmail.com";
|
||||
isAdmin = true;
|
||||
}
|
||||
{
|
||||
username = "conrad";
|
||||
name = "Conrad Kramer";
|
||||
email = "conrad@burrow.net";
|
||||
sourceEmail = "ckrames1234@gmail.com";
|
||||
isAdmin = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.burrow.headscale = {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ let
|
|||
blueprintFile = "${blueprintDir}/burrow-authentik.yaml";
|
||||
postgresVolume = "burrow-authentik-postgresql:/var/lib/postgresql/data";
|
||||
dataVolume = "burrow-authentik-data:/data";
|
||||
directorySyncScript = ../../Scripts/authentik-sync-burrow-directory.sh;
|
||||
forgejoOidcSyncScript = ../../Scripts/authentik-sync-forgejo-oidc.sh;
|
||||
googleSourceSyncScript = ../../Scripts/authentik-sync-google-source.sh;
|
||||
authentikBlueprint = pkgs.writeText "burrow-authentik-blueprint.yaml" ''
|
||||
|
|
@ -31,6 +32,19 @@ let
|
|||
"email_verified": True,
|
||||
}
|
||||
|
||||
- model: authentik_providers_oauth2.scopemapping
|
||||
id: burrow-oidc-groups
|
||||
identifiers:
|
||||
name: Burrow OIDC Groups
|
||||
attrs:
|
||||
name: Burrow OIDC Groups
|
||||
scope_name: groups
|
||||
description: Group membership mapping for Burrow
|
||||
expression: |
|
||||
return {
|
||||
"groups": [group.name for group in request.user.ak_groups.all()],
|
||||
}
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: burrow-oidc-provider-ts
|
||||
identifiers:
|
||||
|
|
@ -50,6 +64,7 @@ let
|
|||
property_mappings:
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-openid]]
|
||||
- !KeyOf burrow-oidc-email
|
||||
- !KeyOf burrow-oidc-groups
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-profile]]
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
|
||||
|
|
@ -159,6 +174,54 @@ in
|
|||
default = "redirect";
|
||||
description = "Identification-stage behavior for the Google Authentik source.";
|
||||
};
|
||||
|
||||
userGroupName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "burrow-users";
|
||||
description = "Authentik group granted baseline Burrow access.";
|
||||
};
|
||||
|
||||
adminGroupName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "burrow-admins";
|
||||
description = "Authentik group granted Burrow administrator access.";
|
||||
};
|
||||
|
||||
bootstrapUsers = lib.mkOption {
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
username = lib.mkOption {
|
||||
type = str;
|
||||
description = "Authentik username.";
|
||||
};
|
||||
name = lib.mkOption {
|
||||
type = str;
|
||||
description = "Display name for the user.";
|
||||
};
|
||||
email = lib.mkOption {
|
||||
type = str;
|
||||
description = "Canonical email stored in Authentik.";
|
||||
};
|
||||
sourceEmail = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "External Google account email that should map onto this Authentik user.";
|
||||
};
|
||||
groups = lib.mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = "Additional Authentik groups for this user.";
|
||||
};
|
||||
isAdmin = lib.mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = "Whether this user should be in the Burrow admin group.";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [ ];
|
||||
description = "Declarative Burrow users to create in Authentik.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
|
@ -295,6 +358,16 @@ EOF
|
|||
];
|
||||
};
|
||||
|
||||
systemd.services.podman-burrow-authentik-server.restartTriggers = [
|
||||
blueprintFile
|
||||
envFile
|
||||
];
|
||||
|
||||
systemd.services.podman-burrow-authentik-worker.restartTriggers = [
|
||||
blueprintFile
|
||||
envFile
|
||||
];
|
||||
|
||||
systemd.services.burrow-authentik-ready = {
|
||||
description = "Wait for Burrow Authentik to become ready";
|
||||
after = [ "podman-burrow-authentik-server.service" ];
|
||||
|
|
@ -366,11 +439,66 @@ EOF
|
|||
export AUTHENTIK_GOOGLE_USER_MATCHING_MODE=email_link
|
||||
export AUTHENTIK_GOOGLE_CLIENT_ID="$(tr -d '\r\n' < ${lib.escapeShellArg cfg.googleClientIDFile})"
|
||||
export AUTHENTIK_GOOGLE_CLIENT_SECRET="$(tr -d '\r\n' < ${lib.escapeShellArg cfg.googleClientSecretFile})"
|
||||
export AUTHENTIK_GOOGLE_ACCOUNT_MAP_JSON='${builtins.toJSON (map (user: {
|
||||
source_email = user.sourceEmail;
|
||||
username = user.username;
|
||||
email = user.email;
|
||||
name = user.name;
|
||||
}) (lib.filter (user: user.sourceEmail != null) cfg.bootstrapUsers))}'
|
||||
|
||||
${pkgs.bash}/bin/bash ${googleSourceSyncScript}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.burrow-authentik-directory = lib.mkIf (cfg.bootstrapUsers != [ ]) {
|
||||
description = "Reconcile Burrow Authentik users and groups";
|
||||
after =
|
||||
[
|
||||
"burrow-authentik-ready.service"
|
||||
"network-online.target"
|
||||
]
|
||||
++ lib.optionals (cfg.forgejoClientSecretFile != null) [ "burrow-authentik-forgejo-oidc.service" ];
|
||||
wants =
|
||||
[
|
||||
"burrow-authentik-ready.service"
|
||||
"network-online.target"
|
||||
]
|
||||
++ lib.optionals (cfg.forgejoClientSecretFile != null) [ "burrow-authentik-forgejo-oidc.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = [
|
||||
directorySyncScript
|
||||
cfg.envFile
|
||||
];
|
||||
path = [
|
||||
pkgs.bash
|
||||
pkgs.coreutils
|
||||
pkgs.curl
|
||||
pkgs.jq
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
set -a
|
||||
source ${lib.escapeShellArg cfg.envFile}
|
||||
set +a
|
||||
|
||||
export AUTHENTIK_URL=https://${cfg.domain}
|
||||
export AUTHENTIK_BURROW_USERS_GROUP=${lib.escapeShellArg cfg.userGroupName}
|
||||
export AUTHENTIK_BURROW_ADMINS_GROUP=${lib.escapeShellArg cfg.adminGroupName}
|
||||
export AUTHENTIK_FORGEJO_APPLICATION_SLUG=${lib.escapeShellArg cfg.forgejoProviderSlug}
|
||||
export AUTHENTIK_BURROW_DIRECTORY_JSON='${builtins.toJSON (map (user: {
|
||||
inherit (user) username name email isAdmin;
|
||||
groups = user.groups;
|
||||
}) cfg.bootstrapUsers)}'
|
||||
|
||||
${pkgs.bash}/bin/bash ${directorySyncScript}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.burrow-authentik-forgejo-oidc = lib.mkIf (cfg.forgejoClientSecretFile != null) {
|
||||
description = "Reconcile the Burrow Authentik Forgejo OIDC application";
|
||||
after = [
|
||||
|
|
|
|||
|
|
@ -92,6 +92,35 @@ in
|
|||
description = "OpenID Connect discovery URL for the Forgejo login source.";
|
||||
};
|
||||
|
||||
oidcScopes = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
"groups"
|
||||
];
|
||||
description = "OIDC scopes requested from Authentik.";
|
||||
};
|
||||
|
||||
oidcGroupClaimName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "groups";
|
||||
description = "OIDC claim name that carries group membership.";
|
||||
};
|
||||
|
||||
oidcAdminGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "burrow-admins";
|
||||
description = "OIDC group that should grant Forgejo admin access.";
|
||||
};
|
||||
|
||||
oidcRestrictedGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "burrow-users";
|
||||
description = "OIDC group that is required to log into Forgejo.";
|
||||
};
|
||||
|
||||
authorizedKeys = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [ ];
|
||||
|
|
@ -339,6 +368,10 @@ in
|
|||
--arg client_id ${lib.escapeShellArg cfg.oidcClientId} \
|
||||
--arg client_secret "$oidc_secret" \
|
||||
--arg discovery_url ${lib.escapeShellArg cfg.oidcDiscoveryUrl} \
|
||||
--argjson scopes '${builtins.toJSON cfg.oidcScopes}' \
|
||||
--arg group_claim_name ${lib.escapeShellArg cfg.oidcGroupClaimName} \
|
||||
--arg admin_group ${lib.escapeShellArg cfg.oidcAdminGroup} \
|
||||
--arg restricted_group ${lib.escapeShellArg cfg.oidcRestrictedGroup} \
|
||||
'{
|
||||
Provider: "openidConnect",
|
||||
ClientID: $client_id,
|
||||
|
|
@ -346,15 +379,15 @@ in
|
|||
OpenIDConnectAutoDiscoveryURL: $discovery_url,
|
||||
CustomURLMapping: null,
|
||||
IconURL: "",
|
||||
Scopes: ["openid", "profile", "email"],
|
||||
Scopes: $scopes,
|
||||
AttributeSSHPublicKey: "",
|
||||
RequiredClaimName: "",
|
||||
RequiredClaimValue: "",
|
||||
GroupClaimName: "",
|
||||
AdminGroup: "",
|
||||
GroupClaimName: $group_claim_name,
|
||||
AdminGroup: $admin_group,
|
||||
GroupTeamMap: "",
|
||||
GroupTeamMapRemoval: false,
|
||||
RestrictedGroup: ""
|
||||
RestrictedGroup: $restricted_group
|
||||
}')"
|
||||
|
||||
${pkgs.postgresql}/bin/psql -v ON_ERROR_STOP=1 \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue