Skip to content

Commit

Permalink
Added option to disable webhooks (go-gitea#13176)
Browse files Browse the repository at this point in the history
* 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: 07df661
Related: go-gitea#13176 (review)
Author-Change-Id: IB#1105174

* Parameter description fixed

Parameter description fixed.

Fixes: 07df661
Related: go-gitea#13176 (review)
Author-Change-Id: IB#1105174
  • Loading branch information
pboguslawski committed Feb 11, 2021
1 parent ac70163 commit 7d7007d
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 25 deletions.
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ var (
MinPasswordLength int
ImportLocalPaths bool
DisableGitHooks bool
DisableWebhooks bool
OnlyAllowPushIfGiteaEnvironmentSet bool
PasswordComplexity []string
PasswordHashAlgo string
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions modules/templates/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down
30 changes: 20 additions & 10 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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).
Expand Down Expand Up @@ -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).
Expand Down
26 changes: 17 additions & 9 deletions routers/routes/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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).
Expand Down
4 changes: 4 additions & 0 deletions services/webhook/deliver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions services/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
8 changes: 5 additions & 3 deletions templates/admin/navbar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
<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>
Expand Down
2 changes: 2 additions & 0 deletions templates/org/settings/navbar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 2 additions & 0 deletions templates/repo/settings/nav.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
8 changes: 5 additions & 3 deletions templates/repo/settings/navbar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
{{.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"}}
Expand Down

0 comments on commit 7d7007d

Please sign in to comment.