fix getting started to generate IdpManagerConfig on external IdP

This commit is contained in:
jnfrati
2026-06-12 18:06:12 +02:00
parent 8e05834384
commit f74d66c9ad
3 changed files with 83 additions and 1 deletions

View File

@@ -635,6 +635,19 @@ load_setup_env() {
return 0
}
render_setup_env_idp_manager_vars() {
local var
[[ -n "${NETBIRD_MGMT_IDP:-}" ]] && printf '%s=%q\n' "NETBIRD_MGMT_IDP" "$NETBIRD_MGMT_IDP"
[[ -n "${NETBIRD_MGMT_IDP_SIGNKEY_REFRESH:-}" ]] && printf '%s=%q\n' "NETBIRD_MGMT_IDP_SIGNKEY_REFRESH" "$NETBIRD_MGMT_IDP_SIGNKEY_REFRESH"
[[ -n "${NETBIRD_IDP_MGMT_CLIENT_ID:-}" ]] && printf '%s=%q\n' "NETBIRD_IDP_MGMT_CLIENT_ID" "$NETBIRD_IDP_MGMT_CLIENT_ID"
[[ -n "${NETBIRD_IDP_MGMT_CLIENT_SECRET:-}" ]] && printf '%s=%q\n' "NETBIRD_IDP_MGMT_CLIENT_SECRET" "$NETBIRD_IDP_MGMT_CLIENT_SECRET"
for var in ${!NETBIRD_IDP_MGMT_EXTRA_*}; do
printf '%s=%q\n' "$var" "${!var}"
done
return 0
}
write_setup_env() {
if [[ "$NON_INTERACTIVE" == "true" ]]; then
persist_generated_secrets
@@ -695,8 +708,12 @@ NETBIRD_DATASTORE_ENC_KEY="$DATASTORE_ENCRYPTION_KEY"
# IdP management API for user/group sync (external IdP only), see
# https://docs.netbird.io/selfhosted/identity-providers:
#NETBIRD_MGMT_IDP=""
#NETBIRD_MGMT_IDP_SIGNKEY_REFRESH="false"
#NETBIRD_IDP_MGMT_CLIENT_ID=""
#NETBIRD_IDP_MGMT_CLIENT_SECRET=""
# Extra IdP-manager settings (provider-specific), for example:
#NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT=""
$(render_setup_env_idp_manager_vars)
# Docker image overrides:
#DASHBOARD_IMAGE=""
#NETBIRD_SERVER_IMAGE=""
@@ -1450,6 +1467,7 @@ render_management_json() {
mgmt_oidc_endpoint="$AUTH_OIDC_ENDPOINT"
mgmt_signkey_refresh="false"
fi
mgmt_signkey_refresh="${NETBIRD_MGMT_IDP_SIGNKEY_REFRESH:-$mgmt_signkey_refresh}"
local trusted_proxies="[]"
if [[ "$REVERSE_PROXY_TYPE" == "0" ]]; then
@@ -1500,6 +1518,25 @@ EOF
return 0
}
render_idp_manager_extra_config() {
local extra_config="{}"
local var key value
# Extract extra config from all env prefixed with NETBIRD_IDP_MGMT_EXTRA_.
# Preserve configure.sh's snake-case to CamelCase conversion so existing setup.env files keep working.
for var in ${!NETBIRD_IDP_MGMT_EXTRA_*}; do
key=$(
echo "${var#NETBIRD_IDP_MGMT_EXTRA_}" | awk -F "_" \
'{for (i=1; i<=NF; i++) {output=output substr($i,1,1) tolower(substr($i,2))} print output}'
)
value="${!var}"
extra_config=$(jq -c --arg k "$key" --arg v "$value" '.[$k] = $v' <<<"$extra_config")
done
printf '%s' "$extra_config"
return 0
}
render_management_json_idp_section() {
if [[ "$IDP_MODE" == "embedded" ]]; then
cat <<EOF
@@ -1575,7 +1612,8 @@ EOF
"ClientID": "$NETBIRD_IDP_MGMT_CLIENT_ID",
"ClientSecret": "$NETBIRD_IDP_MGMT_CLIENT_SECRET",
"GrantType": "client_credentials"
}
},
"ExtraConfig": $(render_idp_manager_extra_config)
}
EOF
fi

View File

@@ -51,8 +51,15 @@ NETBIRD_TOKEN_SOURCE="accessToken"
# IdP management API for user/group sync (optional)
# eg. zitadel, auth0, azure, keycloak
#NETBIRD_MGMT_IDP=""
# Enable IdP signing-key refresh when required by your provider (e.g. Zitadel)
#NETBIRD_MGMT_IDP_SIGNKEY_REFRESH="false"
#NETBIRD_IDP_MGMT_CLIENT_ID=""
#NETBIRD_IDP_MGMT_CLIENT_SECRET=""
# Provider-specific IdP-manager settings (converted to ExtraConfig CamelCase keys)
# e.g. Keycloak AdminEndpoint, Zitadel ManagementEndpoint, PocketID ApiToken
#NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT=""
#NETBIRD_IDP_MGMT_EXTRA_MANAGEMENT_ENDPOINT=""
#NETBIRD_IDP_MGMT_EXTRA_API_TOKEN=""
# -------------------------------------------
# Reverse proxy

View File

@@ -156,6 +156,30 @@ NETBIRD_AUTH_CLIENT_ID="netbird"
NETBIRD_REVERSE_PROXY_TYPE="5"
EOF
run_case split-external-keycloak-extra-config docker-compose.yml management.json dashboard.env <<EOF
NETBIRD_DOMAIN="netbird.example.org"
NETBIRD_IDP_MODE="external"
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="file://$OIDC_FIXTURE"
NETBIRD_AUTH_CLIENT_ID="netbird"
NETBIRD_REVERSE_PROXY_TYPE="5"
NETBIRD_MGMT_IDP="keycloak"
NETBIRD_IDP_MGMT_CLIENT_ID="netbird-backend"
NETBIRD_IDP_MGMT_CLIENT_SECRET="backend-secret"
NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT="https://idp.example.org/admin/realms/netbird"
NETBIRD_MGMT_IDP_SIGNKEY_REFRESH="true"
EOF
run_case split-external-keycloak-no-extra-config docker-compose.yml management.json dashboard.env <<EOF
NETBIRD_DOMAIN="netbird.example.org"
NETBIRD_IDP_MODE="external"
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="file://$OIDC_FIXTURE"
NETBIRD_AUTH_CLIENT_ID="netbird"
NETBIRD_REVERSE_PROXY_TYPE="5"
NETBIRD_MGMT_IDP="keycloak"
NETBIRD_IDP_MGMT_CLIENT_ID="netbird-backend"
NETBIRD_IDP_MGMT_CLIENT_SECRET="backend-secret"
EOF
# Invalid combination must fail: combined + external IdP
echo "--- case: combined-external-rejected"
REJECT_DIR="$WORK_DIR/combined-external-rejected"
@@ -174,6 +198,19 @@ if (cd "$REJECT_DIR" && bash "$GETTING_STARTED" --non-interactive --render-only
fi
# Spot-check rendered content
SPLIT_KEYCLOAK_EXTRA="$WORK_DIR/split-external-keycloak-extra-config"
if [[ -f "$SPLIT_KEYCLOAK_EXTRA/management.json" ]]; then
[[ $(jq -r '.IdpManagerConfig.ManagerType' "$SPLIT_KEYCLOAK_EXTRA/management.json") == "keycloak" ]] || { echo "FAIL: IdP manager type mismatch"; FAILURES=$((FAILURES + 1)); }
[[ $(jq -r '.IdpManagerConfig.ClientConfig.ClientID' "$SPLIT_KEYCLOAK_EXTRA/management.json") == "netbird-backend" ]] || { echo "FAIL: IdP manager client ID mismatch"; FAILURES=$((FAILURES + 1)); }
[[ $(jq -r '.IdpManagerConfig.ExtraConfig.AdminEndpoint' "$SPLIT_KEYCLOAK_EXTRA/management.json") == "https://idp.example.org/admin/realms/netbird" ]] || { echo "FAIL: IdP manager ExtraConfig.AdminEndpoint missing"; FAILURES=$((FAILURES + 1)); }
[[ $(jq -r '.HttpConfig.IdpSignKeyRefreshEnabled' "$SPLIT_KEYCLOAK_EXTRA/management.json") == "true" ]] || { echo "FAIL: IdP sign-key refresh env not honored"; FAILURES=$((FAILURES + 1)); }
fi
SPLIT_KEYCLOAK_NO_EXTRA="$WORK_DIR/split-external-keycloak-no-extra-config"
if [[ -f "$SPLIT_KEYCLOAK_NO_EXTRA/management.json" ]]; then
[[ $(jq -c '.IdpManagerConfig.ExtraConfig // {}' "$SPLIT_KEYCLOAK_NO_EXTRA/management.json") == "{}" ]] || { echo "FAIL: IdP manager ExtraConfig should be empty without EXTRA vars"; FAILURES=$((FAILURES + 1)); }
fi
SPLIT_EXT="$WORK_DIR/split-external-nginx-postgres"
if [[ -f "$SPLIT_EXT/management.json" ]]; then
[[ $(jq -r '.HttpConfig.AuthIssuer' "$SPLIT_EXT/management.json") == "https://idp.example.org/realms/netbird" ]] || { echo "FAIL: external AuthIssuer mismatch"; FAILURES=$((FAILURES + 1)); }