mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
Add LocalAuthDisabled option to embedded IdP configuration This adds the ability to disable local (email/password) authentication when using the embedded Dex identity provider. When disabled, users can only authenticate via external identity providers (Google, OIDC, etc.). This simplifies user login when there is only one external IdP configured. The login page will redirect directly to the IdP login page. Key changes: Added LocalAuthDisabled field to EmbeddedIdPConfig Added methods to check and toggle local auth: IsLocalAuthEnabled, HasNonLocalConnectors, DisableLocalAuth, EnableLocalAuth Validation prevents disabling local auth if no external connectors are configured Existing local users are preserved when disabled and can login again when re-enabled Operations are idempotent (disabling already disabled is a no-op)
103 lines
3.3 KiB
Go
103 lines
3.3 KiB
Go
package instance
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/gorilla/mux"
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
nbinstance "github.com/netbirdio/netbird/management/server/instance"
|
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
|
"github.com/netbirdio/netbird/shared/management/http/util"
|
|
)
|
|
|
|
// handler handles the instance setup HTTP endpoints
|
|
type handler struct {
|
|
instanceManager nbinstance.Manager
|
|
}
|
|
|
|
// AddEndpoints registers the instance setup endpoints.
|
|
// These endpoints bypass authentication for initial setup.
|
|
func AddEndpoints(instanceManager nbinstance.Manager, router *mux.Router) {
|
|
h := &handler{
|
|
instanceManager: instanceManager,
|
|
}
|
|
|
|
router.HandleFunc("/instance", h.getInstanceStatus).Methods("GET", "OPTIONS")
|
|
router.HandleFunc("/setup", h.setup).Methods("POST", "OPTIONS")
|
|
}
|
|
|
|
// AddVersionEndpoint registers the authenticated version endpoint.
|
|
func AddVersionEndpoint(instanceManager nbinstance.Manager, router *mux.Router) {
|
|
h := &handler{
|
|
instanceManager: instanceManager,
|
|
}
|
|
|
|
router.HandleFunc("/instance/version", h.getVersionInfo).Methods("GET", "OPTIONS")
|
|
}
|
|
|
|
// getInstanceStatus returns the instance status including whether setup is required.
|
|
// This endpoint is unauthenticated.
|
|
func (h *handler) getInstanceStatus(w http.ResponseWriter, r *http.Request) {
|
|
setupRequired, err := h.instanceManager.IsSetupRequired(r.Context())
|
|
if err != nil {
|
|
log.WithContext(r.Context()).Errorf("failed to check setup status: %v", err)
|
|
util.WriteErrorResponse("failed to check instance status", http.StatusInternalServerError, w)
|
|
return
|
|
}
|
|
log.WithContext(r.Context()).Infof("instance setup status: %v", setupRequired)
|
|
util.WriteJSONObject(r.Context(), w, api.InstanceStatus{
|
|
SetupRequired: setupRequired,
|
|
})
|
|
}
|
|
|
|
// setup creates the initial admin user for the instance.
|
|
// This endpoint is unauthenticated but only works when setup is required.
|
|
func (h *handler) setup(w http.ResponseWriter, r *http.Request) {
|
|
var req api.SetupRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
util.WriteErrorResponse("invalid request body", http.StatusBadRequest, w)
|
|
return
|
|
}
|
|
|
|
userData, err := h.instanceManager.CreateOwnerUser(r.Context(), req.Email, req.Password, req.Name)
|
|
if err != nil {
|
|
util.WriteError(r.Context(), err, w)
|
|
return
|
|
}
|
|
|
|
log.WithContext(r.Context()).Infof("instance setup completed: created user %s", req.Email)
|
|
|
|
util.WriteJSONObject(r.Context(), w, api.SetupResponse{
|
|
UserId: userData.ID,
|
|
Email: userData.Email,
|
|
})
|
|
}
|
|
|
|
// getVersionInfo returns version information for NetBird components.
|
|
// This endpoint requires authentication.
|
|
func (h *handler) getVersionInfo(w http.ResponseWriter, r *http.Request) {
|
|
versionInfo, err := h.instanceManager.GetVersionInfo(r.Context())
|
|
if err != nil {
|
|
log.WithContext(r.Context()).Errorf("failed to get version info: %v", err)
|
|
util.WriteErrorResponse("failed to get version info", http.StatusInternalServerError, w)
|
|
return
|
|
}
|
|
|
|
resp := api.InstanceVersionInfo{
|
|
ManagementCurrentVersion: versionInfo.CurrentVersion,
|
|
ManagementUpdateAvailable: versionInfo.ManagementUpdateAvailable,
|
|
}
|
|
|
|
if versionInfo.DashboardVersion != "" {
|
|
resp.DashboardAvailableVersion = &versionInfo.DashboardVersion
|
|
}
|
|
|
|
if versionInfo.ManagementVersion != "" {
|
|
resp.ManagementAvailableVersion = &versionInfo.ManagementVersion
|
|
}
|
|
|
|
util.WriteJSONObject(r.Context(), w, resp)
|
|
}
|