]> source.dussan.org Git - gitea.git/commitdiff
Added option to disable webhooks (#13176)
authorPaweł Bogusławski <pawel.boguslawski@ib.pl>
Thu, 11 Feb 2021 17:34:34 +0000 (18:34 +0100)
committerGitHub <noreply@github.com>
Thu, 11 Feb 2021 17:34:34 +0000 (12:34 -0500)
* 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

* Webhook spelling fixed

Webhook spelling fixed.

Fixes: 07df6614dc84cdd2e9f39c57577fa1062bd70012
Related: https://github.com/go-gitea/gitea/pull/13176#pullrequestreview-510868421
Author-Change-Id: IB#1105174

* Parameter description fixed

Parameter description fixed.

Fixes: 07df6614dc84cdd2e9f39c57577fa1062bd70012
Related: https://github.com/go-gitea/gitea/pull/13176#pullrequestreview-514086107
Author-Change-Id: IB#1105174

12 files changed:
custom/conf/app.example.ini
docs/content/doc/advanced/config-cheat-sheet.en-us.md
modules/setting/setting.go
modules/templates/helper.go
routers/api/v1/api.go
routers/routes/web.go
services/webhook/deliver.go
services/webhook/webhook.go
templates/admin/navbar.tmpl
templates/org/settings/navbar.tmpl
templates/repo/settings/nav.tmpl
templates/repo/settings/navbar.tmpl

index cec7e4255a20f6ce80cc1732608270ccf7513ffa..747173b5ae47e96496b3935841ad459de6f431f6 100644 (file)
@@ -556,6 +556,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 true to disable webhooks feature.
+DISABLE_WEBHOOKS = 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.
index 9b5c4cbf2df7cd67f699b29772bf1dd18ad72342..b65f59ce0c5c2037f84ec7c7524219f28422e49e 100644 (file)
@@ -396,6 +396,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_WEBHOOKS`: **false**: Set to `true` to disable webhooks 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`: **\<random at every install if no uri set\>**: Secret used to validate communication within Gitea binary.
index dd38f5be45dd2557dd68f2ef246c4b70c39a6cd6..54ddb6937c0b1d6680e486384032caf8ac411eed 100644 (file)
@@ -156,6 +156,7 @@ var (
        MinPasswordLength                  int
        ImportLocalPaths                   bool
        DisableGitHooks                    bool
+       DisableWebhooks                    bool
        OnlyAllowPushIfGiteaEnvironmentSet bool
        PasswordComplexity                 []string
        PasswordHashAlgo                   string
@@ -801,6 +802,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_WEBHOOKS").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)
index b8e4f5d5055ed2dc8c5c9fc3cc46ffa8e2ca83f0..00ccd49cb401c1078f98075a6dd35a18e7b8d8e7 100644 (file)
@@ -229,6 +229,9 @@ func NewFuncMap() []template.FuncMap {
                "DisableGitHooks": func() bool {
                        return setting.DisableGitHooks
                },
+               "DisableWebhooks": func() bool {
+                       return setting.DisableWebhooks
+               },
                "DisableImportLocal": func() bool {
                        return !setting.ImportLocalPaths
                },
index 85c4e4d5bfa0e13a2a1f4f4e45c5d988afba4c3e..855e44b65bf5839629d2ba75f7bbbcff7d59900f 100644 (file)
@@ -383,6 +383,16 @@ func reqGitHook() func(ctx *context.APIContext) {
        }
 }
 
+// reqWebhooksEnabled requires webhooks to be enabled by admin.
+func reqWebhooksEnabled() func(ctx *context.APIContext) {
+       return func(ctx *context.APIContext) {
+               if setting.DisableWebhooks {
+                       ctx.Error(http.StatusForbidden, "", "webhooks disabled by administrator")
+                       return
+               }
+       }
+}
+
 func orgAssignment(args ...bool) func(ctx *context.APIContext) {
        var (
                assignOrg  bool
@@ -703,6 +713,14 @@ func Routes() *web.Route {
                                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)
@@ -712,15 +730,7 @@ func Routes() *web.Route {
                                                        Delete(repo.DeleteHook)
                                                m.Post("/tests", context.RepoRefForAPI, 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).
@@ -984,7 +994,7 @@ func Routes() *web.Route {
                                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).
index 2f28e567f9f4f6f929f184cf0ad3482bf87e7a6a..389e050376e907ae4414702b63dd024346714c56 100644 (file)
@@ -248,6 +248,14 @@ func RegisterRoutes(m *web.Route) {
                }
        }
 
+       // webhooksEnabled requires webhooks to be enabled by admin.
+       webhooksEnabled := func(ctx *context.Context) {
+               if setting.DisableWebhooks {
+                       ctx.Error(403)
+                       return
+               }
+       }
+
        // FIXME: not all routes need go through same middleware.
        // Especially some AJAX requests, we can reduce middleware number to improve performance.
        // Routers.
@@ -446,7 +454,7 @@ func RegisterRoutes(m *web.Route) {
                        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("/{configType:default-hooks|system-hooks}", func() {
                        m.Get("/{type}/new", repo.WebhooksNew)
@@ -568,7 +576,7 @@ func RegisterRoutes(m *web.Route) {
                                        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)
@@ -621,6 +629,12 @@ func RegisterRoutes(m *web.Route) {
                                        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)
@@ -645,13 +659,7 @@ func RegisterRoutes(m *web.Route) {
                                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).
index 44c1a18b6c8af6983821b831c42ba90ad5e4d036..8ac7d8c1924678f1ea2e702d4152f3b3418bbe05 100644 (file)
@@ -141,6 +141,10 @@ func Deliver(t *models.HookTask) error {
                }
        }()
 
+       if setting.DisableWebhooks {
+               return fmt.Errorf("Webhook task skipped (webhooks disabled): [%d]", t.ID)
+       }
+
        resp, err := webhookHTTPClient.Do(req)
        if err != nil {
                t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err)
index 7b6bc555f73ea56fd7fc270abdf203b13c773a68..87f28a5cdc179172adf7e9589a7fcf596c62e27b 100644 (file)
@@ -120,6 +120,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 webhooks are disabled.
+       if setting.DisableWebhooks {
+               return nil
+       }
+
        for _, e := range w.EventCheckers() {
                if event == e.Type {
                        if !e.Has() {
index 953076d808d8e77efde04fa4dbb0cd56b05f1028..c656d0619b339c2a7e0a73a34e0da7706eb04ad8 100644 (file)
                <a class="{{if .PageIsAdminRepositories}}active{{end}} item" href="{{AppSubUrl}}/admin/repos">
                        {{.i18n.Tr "admin.repositories"}}
                </a>
-               <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
-                       {{.i18n.Tr "admin.hooks"}}
-               </a>
+               {{if not DisableWebhooks}}
+                       <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
+                               {{.i18n.Tr "admin.hooks"}}
+                       </a>
+               {{end}}
                <a class="{{if .PageIsAdminAuthentications}}active{{end}} item" href="{{AppSubUrl}}/admin/auths">
                        {{.i18n.Tr "admin.authentication"}}
                </a>
index 63114b056ed4201a418fca90fe723707c149fc40..b4edbb077f52a2f15a852c1dc5076212c1f24cd6 100644 (file)
@@ -4,9 +4,11 @@
                <a class="{{if .PageIsSettingsOptions}}active{{end}} item" href="{{.OrgLink}}/settings">
                        {{.i18n.Tr "org.settings.options"}}
                </a>
+               {{if not DisableWebhooks}}
                <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.OrgLink}}/settings/hooks">
                        {{.i18n.Tr "repo.settings.hooks"}}
                </a>
+               {{end}}
                <a class="{{if .PageIsOrgSettingsLabels}}active{{end}} item" href="{{.OrgLink}}/settings/labels">
                        {{.i18n.Tr "repo.labels"}}
                </a>
index 5cc77e1dc91ca2a43264edf1889d15bec3c451bc..4b89ece34918df6fa7bf7f9189e6cdefade33682 100644 (file)
@@ -5,7 +5,9 @@
                        <li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="{{.RepoLink}}/settings">{{.i18n.Tr "repo.settings.options"}}</a></li>
                        <li {{if .PageIsSettingsCollaboration}}class="current"{{end}}><a href="{{.RepoLink}}/settings/collaboration">{{.i18n.Tr "repo.settings.collaboration"}}</a></li>
                        <li {{if .PageIsSettingsBranches}}class="current"{{end}}><a href="{{.RepoLink}}/settings/branches">{{.i18n.Tr "repo.settings.branches"}}</a></li>
+                       {{if not DisableWebhooks}}
                        <li {{if .PageIsSettingsHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks">{{.i18n.Tr "repo.settings.hooks"}}</a></li>
+                       {{end}}
                        {{if or .SignedUser.AllowGitHook .SignedUser.IsAdmin}}
                                <li {{if .PageIsSettingsGitHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks/git">{{.i18n.Tr "repo.settings.githooks"}}</a></li>
                        {{end}}
index 1aba5de7313bc11ef6b9402b2347f3da3e1eeafa..501c3c4630a40547559c9bb45e75225c4905bace 100644 (file)
                                {{.i18n.Tr "repo.settings.branches"}}
                        </a>
                {{end}}
-               <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks">
-                       {{.i18n.Tr "repo.settings.hooks"}}
-               </a>
+               {{if not DisableWebhooks}}
+                       <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks">
+                               {{.i18n.Tr "repo.settings.hooks"}}
+                       </a>
+               {{end}}
                {{if .SignedUser.CanEditGitHook}}
                        <a class="{{if .PageIsSettingsGitHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks/git">
                                {{.i18n.Tr "repo.settings.githooks"}}