diff --git a/modules/setting/reverseproxy.go b/modules/setting/reverseproxy.go new file mode 100644 index 0000000000000..82abd762dea78 --- /dev/null +++ b/modules/setting/reverseproxy.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +var ReverseProxyAuth = struct { + Enabled bool + EnableReverseProxyAuthAPI bool + EnableReverseProxyAutoRegister bool + EnableReverseProxyEmail bool + EnableReverseProxyFullName bool + ReverseProxyAuthUser string + ReverseProxyAuthEmail string + ReverseProxyAuthFullName string + ReverseProxyLimit int + ReverseProxyTrustedProxies []string +}{} + +func loadReverseProxyAuthFrom(rootCfg ConfigProvider) { + serviceSec := rootCfg.Section("service") + + ReverseProxyAuth.Enabled = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() + ReverseProxyAuth.EnableReverseProxyAuthAPI = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool() + ReverseProxyAuth.EnableReverseProxyAutoRegister = serviceSec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() + ReverseProxyAuth.EnableReverseProxyEmail = serviceSec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool() + ReverseProxyAuth.EnableReverseProxyFullName = serviceSec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool() + + securitySec := rootCfg.Section("security") + ReverseProxyAuth.ReverseProxyAuthUser = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER") + ReverseProxyAuth.ReverseProxyAuthEmail = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_EMAIL").MustString("X-WEBAUTH-EMAIL") + ReverseProxyAuth.ReverseProxyAuthFullName = securitySec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME") + + ReverseProxyAuth.ReverseProxyLimit = securitySec.Key("REVERSE_PROXY_LIMIT").MustInt(1) + ReverseProxyAuth.ReverseProxyTrustedProxies = securitySec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",") + if len(ReverseProxyAuth.ReverseProxyTrustedProxies) == 0 { + ReverseProxyAuth.ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"} + } +} diff --git a/modules/setting/security.go b/modules/setting/security.go index 3d12fcf8d9fdd..a1d2a953cc53f 100644 --- a/modules/setting/security.go +++ b/modules/setting/security.go @@ -15,16 +15,12 @@ import ( var ( // Security settings - InstallLock bool - SecretKey string - InternalToken string // internal access token - LogInRememberDays int - CookieRememberName string - ReverseProxyAuthUser string - ReverseProxyAuthEmail string - ReverseProxyAuthFullName string - ReverseProxyLimit int - ReverseProxyTrustedProxies []string + InstallLock bool + SecretKey string + InternalToken string // internal access token + LogInRememberDays int + CookieRememberName string + MinPasswordLength int ImportLocalPaths bool DisableGitHooks bool @@ -114,16 +110,6 @@ func loadSecurityFrom(rootCfg ConfigProvider) { CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").MustString("gitea_incredible") - ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER") - ReverseProxyAuthEmail = sec.Key("REVERSE_PROXY_AUTHENTICATION_EMAIL").MustString("X-WEBAUTH-EMAIL") - ReverseProxyAuthFullName = sec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME") - - ReverseProxyLimit = sec.Key("REVERSE_PROXY_LIMIT").MustInt(1) - ReverseProxyTrustedProxies = sec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",") - if len(ReverseProxyTrustedProxies) == 0 { - ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"} - } - MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(8) ImportLocalPaths = sec.Key("IMPORT_LOCAL_PATHS").MustBool(false) DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(true) diff --git a/modules/setting/service.go b/modules/setting/service.go index 3ea1501236dfd..de3c3a7cca818 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -45,11 +45,6 @@ var Service = struct { RequireSignInView bool EnableNotifyMail bool EnableBasicAuth bool - EnableReverseProxyAuth bool - EnableReverseProxyAuthAPI bool - EnableReverseProxyAutoRegister bool - EnableReverseProxyEmail bool - EnableReverseProxyFullName bool EnableCaptcha bool RequireCaptchaForLogin bool RequireExternalRegistrationCaptcha bool @@ -157,11 +152,7 @@ func loadServiceFrom(rootCfg ConfigProvider) { Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true) Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true) - Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() - Service.EnableReverseProxyAuthAPI = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool() - Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() - Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool() - Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool() + Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false) Service.RequireCaptchaForLogin = sec.Key("REQUIRE_CAPTCHA_FOR_LOGIN").MustBool(false) Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index c93d199b1b639..6e35ed3ea662c 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -203,6 +203,7 @@ func LoadSettings() { loadDBSetting(CfgProvider) loadServiceFrom(CfgProvider) + loadReverseProxyAuthFrom(CfgProvider) loadOAuth2ClientFrom(CfgProvider) loadCacheFrom(CfgProvider) loadSessionFrom(CfgProvider) @@ -223,6 +224,7 @@ func LoadSettings() { func LoadSettingsForInstall() { loadDBSetting(CfgProvider) loadServiceFrom(CfgProvider) + loadReverseProxyAuthFrom(CfgProvider) loadMailerFrom(CfgProvider) } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index e3b17f9a04f2d..ffcceb9589a78 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3196,7 +3196,16 @@ config.repo_root_path = Repository Root Path config.lfs_root_path = LFS Root Path config.log_file_root_path = Log Path config.script_type = Script Type -config.reverse_auth_user = Reverse Authentication User +config.reverse_proxy_auth_config = Reverse Proxy Authentication Configuration +config.reverse_proxy_auth_user = Authentication User +config.reverse_proxy_auth_email = Authentication Email +config.reverse_proxy_auth_fullname = Authentication Fullname +config.reverse_proxy_auth_limit = Authentication Limit +config.reverse_proxy_auth_trusted_proxies = Authentication Trusted Proxies +config.reverse_proxy_auth_enable_api = Enable Authentication API +config.reverse_proxy_auth_enable_autoregister = Enable Authentication Auto Register +config.reverse_proxy_auth_enable_email = Enable Authentication Email +config.reverse_proxy_auth_enable_fullname = Enable Authentication Fullname config.ssh_config = SSH Configuration config.ssh_enabled = Enabled diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 0f42e8f59ebb7..8a04c3ff7f37e 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -75,7 +75,7 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) { } func verifyAuth(r *web.Router, authMethods []auth.Method) { - if setting.Service.EnableReverseProxyAuth { + if setting.ReverseProxyAuth.Enabled { authMethods = append(authMethods, &auth.ReverseProxy{}) } authGroup := auth.NewGroup(authMethods...) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 5aa8ad44e5e3d..fb6c4b39e796a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -331,7 +331,7 @@ func reqExploreSignIn() func(ctx *context.APIContext) { func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if ctx.IsSigned && setting.Service.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName { + if ctx.IsSigned && setting.ReverseProxyAuth.EnableReverseProxyAuthAPI && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName { return } if !ctx.IsBasicAuth { @@ -700,7 +700,7 @@ func buildAuthGroup() *auth.Group { &auth.HTTPSign{}, &auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API ) - if setting.Service.EnableReverseProxyAuthAPI { + if setting.ReverseProxyAuth.EnableReverseProxyAuthAPI { group.Add(&auth.ReverseProxy{}) } diff --git a/routers/common/middleware.go b/routers/common/middleware.go index 51e42d87a0b9e..bd96ae1819884 100644 --- a/routers/common/middleware.go +++ b/routers/common/middleware.go @@ -60,11 +60,11 @@ func ProtocolMiddlewares() (handlers []any) { }) }) - if setting.ReverseProxyLimit > 0 { + if setting.ReverseProxyAuth.ReverseProxyLimit > 0 { opt := proxy.NewForwardedHeadersOptions(). - WithForwardLimit(setting.ReverseProxyLimit). + WithForwardLimit(setting.ReverseProxyAuth.ReverseProxyLimit). ClearTrustedProxies() - for _, n := range setting.ReverseProxyTrustedProxies { + for _, n := range setting.ReverseProxyAuth.ReverseProxyTrustedProxies { if !strings.Contains(n, "/") { opt.AddTrustedProxy(n) } else { diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 2ae93e9cacc9b..15b0f25d71549 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -136,9 +136,8 @@ func Config(ctx *context.Context) { ctx.Data["CustomRootPath"] = setting.CustomPath ctx.Data["LogRootPath"] = setting.Log.RootPath ctx.Data["ScriptType"] = setting.ScriptType - ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser - ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail + ctx.Data["ReverseProxyAuth"] = setting.ReverseProxyAuth ctx.Data["SSH"] = setting.SSH ctx.Data["LFS"] = setting.LFS diff --git a/routers/web/web.go b/routers/web/web.go index af46c36fe7d2b..ef16a568d4461 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -102,7 +102,7 @@ func buildAuthGroup() *auth_service.Group { group.Add(&auth_service.OAuth2{}) // FIXME: this should be removed and only applied in download and oauth related routers group.Add(&auth_service.Basic{}) // FIXME: this should be removed and only applied in download and git/lfs routers - if setting.Service.EnableReverseProxyAuth { + if setting.ReverseProxyAuth.Enabled { group.Add(&auth_service.ReverseProxy{}) // reverseproxy should before Session, otherwise the header will be ignored if user has login } group.Add(&auth_service.Session{}) diff --git a/services/auth/reverseproxy.go b/services/auth/reverseproxy.go index 36b4ef68f42f4..17bac1caad9f8 100644 --- a/services/auth/reverseproxy.go +++ b/services/auth/reverseproxy.go @@ -28,13 +28,13 @@ const ReverseProxyMethodName = "reverse_proxy" // ReverseProxy implements the Auth interface, but actually relies on // a reverse proxy for authentication of users. // On successful authentication the proxy is expected to populate the username in the -// "setting.ReverseProxyAuthUser" header. Optionally it can also populate the email of the +// "setting.ReverseProxyAuth.ReverseProxyAuthUser" header. Optionally it can also populate the email of the // user in the "setting.ReverseProxyAuthEmail" header. type ReverseProxy struct{} -// getUserName extracts the username from the "setting.ReverseProxyAuthUser" header +// getUserName extracts the username from the "setting.ReverseProxyAuth.ReverseProxyAuthUser" header func (r *ReverseProxy) getUserName(req *http.Request) string { - return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthUser)) + return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuth.ReverseProxyAuthUser)) } // Name represents the name of auth method @@ -42,11 +42,11 @@ func (r *ReverseProxy) Name() string { return ReverseProxyMethodName } -// getUserFromAuthUser extracts the username from the "setting.ReverseProxyAuthUser" header +// getUserFromAuthUser extracts the username from the "setting.ReverseProxyAuth.ReverseProxyAuthUser" header // of the request and returns the corresponding user object for that name. // Verification of header data is not performed as it should have already been done by // the reverse proxy. -// If a username is available in the "setting.ReverseProxyAuthUser" header an existing +// If a username is available in the "setting.ReverseProxyAuth.ReverseProxyAuthUser" header an existing // user object is returned (populated with username or email found in header). // Returns nil if header is empty. func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) (*user_model.User, error) { @@ -69,7 +69,7 @@ func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) (*user_model.User, // getEmail extracts the email from the "setting.ReverseProxyAuthEmail" header func (r *ReverseProxy) getEmail(req *http.Request) string { - return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthEmail)) + return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuth.ReverseProxyAuthEmail)) } // getUserFromAuthEmail extracts the username from the "setting.ReverseProxyAuthEmail" header @@ -80,7 +80,7 @@ func (r *ReverseProxy) getEmail(req *http.Request) string { // user object is returned (populated with the email found in header). // Returns nil if header is empty or if "setting.EnableReverseProxyEmail" is disabled. func (r *ReverseProxy) getUserFromAuthEmail(req *http.Request) *user_model.User { - if !setting.Service.EnableReverseProxyEmail { + if !setting.ReverseProxyAuth.EnableReverseProxyEmail { return nil } email := r.getEmail(req) @@ -130,7 +130,7 @@ func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store Da // isAutoRegisterAllowed checks if EnableReverseProxyAutoRegister setting is true func (r *ReverseProxy) isAutoRegisterAllowed() bool { - return setting.Service.EnableReverseProxyAutoRegister + return setting.ReverseProxyAuth.EnableReverseProxyAutoRegister } // newUser creates a new user object for the purpose of automatic registration @@ -142,16 +142,16 @@ func (r *ReverseProxy) newUser(req *http.Request) *user_model.User { } email := gouuid.New().String() + "@localhost" - if setting.Service.EnableReverseProxyEmail { - webAuthEmail := req.Header.Get(setting.ReverseProxyAuthEmail) + if setting.ReverseProxyAuth.EnableReverseProxyEmail { + webAuthEmail := req.Header.Get(setting.ReverseProxyAuth.ReverseProxyAuthEmail) if len(webAuthEmail) > 0 { email = webAuthEmail } } var fullname string - if setting.Service.EnableReverseProxyFullName { - fullname = req.Header.Get(setting.ReverseProxyAuthFullName) + if setting.ReverseProxyAuth.EnableReverseProxyFullName { + fullname = req.Header.Get(setting.ReverseProxyAuth.ReverseProxyAuthFullName) } user := &user_model.User{ diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 87f18192a6f59..85e53b012de93 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -44,8 +44,6 @@