From 07df6614dc84cdd2e9f39c57577fa1062bd70012 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Fri, 16 Oct 2020 16:51:45 +0200 Subject: [PATCH] Added option to disable web hooks This mod introduces DISABLE_WEB_HOOKS parameter in [security] section of app.ini (by default set to false). If set to true it disables web hooks feature. Any existing undelivered web hook tasks will be cancelled. Any existing web hook definitions will be left untouched in db but its delivery tasks will be ignored. Author-Change-Id: IB#1105130 --- custom/conf/app.example.ini | 2 ++ .../doc/advanced/config-cheat-sheet.en-us.md | 1 + modules/setting/setting.go | 2 ++ modules/templates/helper.go | 3 ++ modules/webhook/deliver.go | 4 +++ modules/webhook/webhook.go | 5 ++++ routers/api/v1/api.go | 30 ++++++++++++------- routers/routes/routes.go | 26 ++++++++++------ templates/admin/navbar.tmpl | 2 ++ templates/org/settings/navbar.tmpl | 2 ++ templates/repo/settings/nav.tmpl | 2 ++ templates/repo/settings/navbar.tmpl | 2 ++ 12 files changed, 62 insertions(+), 19 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index dc273ced8005..9f5f6118ad76 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -541,6 +541,8 @@ IMPORT_LOCAL_PATHS = false ; It also enables them to access other resources available to the user on the operating system that is running the Gitea instance and perform arbitrary actions in the name of the Gitea OS user. ; WARNING: This maybe harmful to you website or your operating system. DISABLE_GIT_HOOKS = true +; Set to false to disable web hooks feature. +DISABLE_WEB_HOOKS = false ; Set to false to allow pushes to gitea repositories despite having an incomplete environment - NOT RECOMMENDED ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = true ;Comma separated list of character classes required to pass minimum complexity. diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 9e61a25f3360..fb044e9fbcd5 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -400,6 +400,7 @@ relation to port exhaustion. It also enables them to access other resources available to the user on the operating system that is running the Gitea instance and perform arbitrary actions in the name of the Gitea OS user. This maybe harmful to you website or your operating system. +- `DISABLE_WEB_HOOKS`: **false**: Set to `true` to disable web hooks feature. - `ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET`: **true**: Set to `false` to allow local users to push to gitea-repositories without setting up the Gitea environment. This is not recommended and if you want local users to push to gitea repositories you should set the environment appropriately. - `IMPORT_LOCAL_PATHS`: **false**: Set to `false` to prevent all users (including admin) from importing local path on server. - `INTERNAL_TOKEN`: **\**: Secret used to validate communication within Gitea binary. diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 7ae8bb352de1..1ff0b2ec7967 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -152,6 +152,7 @@ var ( MinPasswordLength int ImportLocalPaths bool DisableGitHooks bool + DisableWebHooks bool OnlyAllowPushIfGiteaEnvironmentSet bool PasswordComplexity []string PasswordHashAlgo string @@ -770,6 +771,7 @@ func NewContext() { MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(6) ImportLocalPaths = sec.Key("IMPORT_LOCAL_PATHS").MustBool(false) DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(true) + DisableWebHooks = sec.Key("DISABLE_WEB_HOOKS").MustBool(false) OnlyAllowPushIfGiteaEnvironmentSet = sec.Key("ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET").MustBool(true) PasswordHashAlgo = sec.Key("PASSWORD_HASH_ALGO").MustString("argon2") CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true) diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 63be27d98735..7b49b6798ada 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -225,6 +225,9 @@ func NewFuncMap() []template.FuncMap { "DisableGitHooks": func() bool { return setting.DisableGitHooks }, + "DisableWebHooks": func() bool { + return setting.DisableWebHooks + }, "DisableImportLocal": func() bool { return !setting.ImportLocalPaths }, diff --git a/modules/webhook/deliver.go b/modules/webhook/deliver.go index c29fcb6fa9e4..dbca2e6376d1 100644 --- a/modules/webhook/deliver.go +++ b/modules/webhook/deliver.go @@ -141,6 +141,10 @@ func Deliver(t *models.HookTask) error { } }() + if setting.DisableWebHooks { + return fmt.Errorf("Sending webhook skipped (web hooks disabled): [%d]", t.ID) + } + resp, err := webhookHTTPClient.Do(req) if err != nil { t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err) diff --git a/modules/webhook/webhook.go b/modules/webhook/webhook.go index 2ef150210e71..9b2d472730f0 100644 --- a/modules/webhook/webhook.go +++ b/modules/webhook/webhook.go @@ -68,6 +68,11 @@ func checkBranch(w *models.Webhook, branch string) bool { } func prepareWebhook(w *models.Webhook, repo *models.Repository, event models.HookEventType, p api.Payloader) error { + // Skip sending if web hooks are disabled. + if setting.DisableWebHooks { + return nil + } + for _, e := range w.EventCheckers() { if event == e.Type { if !e.Has() { diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index acd97648bf9b..efa68daac1ae 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -374,6 +374,16 @@ func reqGitHook() macaron.Handler { } } +// reqWebHooksEnabled requires web hooks to be enabled by admin. +func reqWebHooksEnabled() macaron.Handler { + return func(ctx *context.APIContext) { + if setting.DisableWebHooks { + ctx.Error(http.StatusForbidden, "", "web hooks disabled by administrator") + return + } + } +} + func orgAssignment(args ...bool) macaron.Handler { var ( assignOrg bool @@ -646,6 +656,14 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("/notifications"). Get(reqToken(), notify.ListRepoNotifications). Put(reqToken(), notify.ReadRepoNotifications) + m.Group("/hooks/git", func() { + m.Combo("").Get(repo.ListGitHooks) + m.Group("/:id", func() { + m.Combo("").Get(repo.GetGitHook). + Patch(bind(api.EditGitHookOption{}), repo.EditGitHook). + Delete(repo.DeleteGitHook) + }) + }, reqToken(), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true)) m.Group("/hooks", func() { m.Combo("").Get(repo.ListHooks). Post(bind(api.CreateHookOption{}), repo.CreateHook) @@ -655,15 +673,7 @@ func RegisterRoutes(m *macaron.Macaron) { Delete(repo.DeleteHook) m.Post("/tests", context.RepoRef(), repo.TestHook) }) - m.Group("/git", func() { - m.Combo("").Get(repo.ListGitHooks) - m.Group("/:id", func() { - m.Combo("").Get(repo.GetGitHook). - Patch(bind(api.EditGitHookOption{}), repo.EditGitHook). - Delete(repo.DeleteGitHook) - }) - }, reqGitHook(), context.ReferencesGitRepo(true)) - }, reqToken(), reqAdmin()) + }, reqToken(), reqAdmin(), reqWebHooksEnabled()) m.Group("/collaborators", func() { m.Get("", reqAnyRepoReader(), repo.ListCollaborators) m.Combo("/:collaborator").Get(reqAnyRepoReader(), repo.IsCollaborator). @@ -914,7 +924,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("/:id").Get(org.GetHook). Patch(bind(api.EditHookOption{}), org.EditHook). Delete(org.DeleteHook) - }, reqToken(), reqOrgOwnership()) + }, reqToken(), reqOrgOwnership(), reqWebHooksEnabled()) }, orgAssignment(true)) m.Group("/teams/:teamid", func() { m.Combo("").Get(org.GetTeam). diff --git a/routers/routes/routes.go b/routers/routes/routes.go index adda91985763..c3ade35d6a99 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -331,6 +331,14 @@ func RegisterRoutes(m *macaron.Macaron) { } } + // webHooksEnabled requires web hooks to be enabled by admin. + webHooksEnabled := func(ctx *context.Context) { + if setting.DisableWebHooks { + ctx.Error(403) + return + } + } + m.Use(user.GetNotificationCount) m.Use(func(ctx *context.Context) { ctx.Data["UnitWikiGlobalDisabled"] = models.UnitTypeWiki.UnitGlobalDisabled() @@ -550,7 +558,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) - }) + }, webHooksEnabled) m.Group("/auths", func() { m.Get("", admin.Authentications) @@ -655,7 +663,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) - }) + }, webHooksEnabled) m.Group("/labels", func() { m.Get("", org.RetrieveLabels, org.Labels) @@ -708,6 +716,12 @@ func RegisterRoutes(m *macaron.Macaron) { Post(bindIgnErr(auth.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo.SettingsProtectedBranchPost) }, repo.MustBeNotEmpty) + m.Group("/hooks/git", func() { + m.Get("", repo.GitHooks) + m.Combo("/:name").Get(repo.GitHooksEdit). + Post(repo.GitHooksEditPost) + }, context.GitHookService()) + m.Group("/hooks", func() { m.Get("", repo.Webhooks) m.Post("/delete", repo.DeleteWebhook) @@ -732,13 +746,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/matrix/:id", bindIgnErr(auth.NewMatrixHookForm{}), repo.MatrixHooksEditPost) m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost) m.Post("/feishu/:id", bindIgnErr(auth.NewFeishuHookForm{}), repo.FeishuHooksEditPost) - - m.Group("/git", func() { - m.Get("", repo.GitHooks) - m.Combo("/:name").Get(repo.GitHooksEdit). - Post(repo.GitHooksEditPost) - }, context.GitHookService()) - }) + }, webHooksEnabled) m.Group("/keys", func() { m.Combo("").Get(repo.DeployKeys). diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index 6d81d7557f60..f4c862bd223c 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -11,12 +11,14 @@ {{.i18n.Tr "admin.repositories"}} + {{if not DisableWebHooks}} {{.i18n.Tr "admin.hooks"}} {{.i18n.Tr "admin.systemhooks"}} + {{end}} {{.i18n.Tr "admin.authentication"}} diff --git a/templates/org/settings/navbar.tmpl b/templates/org/settings/navbar.tmpl index 63114b056ed4..99e0162daa75 100644 --- a/templates/org/settings/navbar.tmpl +++ b/templates/org/settings/navbar.tmpl @@ -4,9 +4,11 @@ {{.i18n.Tr "org.settings.options"}} + {{if not DisableWebHooks}} {{.i18n.Tr "repo.settings.hooks"}} + {{end}} {{.i18n.Tr "repo.labels"}} diff --git a/templates/repo/settings/nav.tmpl b/templates/repo/settings/nav.tmpl index 5cc77e1dc91c..ad8c86fe4f69 100644 --- a/templates/repo/settings/nav.tmpl +++ b/templates/repo/settings/nav.tmpl @@ -5,7 +5,9 @@
  • {{.i18n.Tr "repo.settings.options"}}
  • {{.i18n.Tr "repo.settings.collaboration"}}
  • {{.i18n.Tr "repo.settings.branches"}}
  • + {{if not DisableWebHooks}}
  • {{.i18n.Tr "repo.settings.hooks"}}
  • + {{end}} {{if or .SignedUser.AllowGitHook .SignedUser.IsAdmin}}
  • {{.i18n.Tr "repo.settings.githooks"}}
  • {{end}} diff --git a/templates/repo/settings/navbar.tmpl b/templates/repo/settings/navbar.tmpl index abd6e285dc3e..09699d515c01 100644 --- a/templates/repo/settings/navbar.tmpl +++ b/templates/repo/settings/navbar.tmpl @@ -10,9 +10,11 @@ {{.i18n.Tr "repo.settings.branches"}} {{end}} + {{if not DisableWebHooks}} {{.i18n.Tr "repo.settings.hooks"}} + {{end}} {{if .SignedUser.CanEditGitHook}} {{.i18n.Tr "repo.settings.githooks"}}