aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorJason Song2023-02-24 15:58:49 +0800
committerGitHub2023-02-24 15:58:49 +0800
commitedf98a2dc30956c8e04b778bb7f1ce55c14ba963 (patch)
tree2d8b7708f76a36c27700ab128082bdb976a0753e /models
parenta6175b01d92a75dcbadbbfc6782a486636fd62a2 (diff)
Require approval to run actions for fork pull request (#22803)
Currently, Gitea will run actions automatically which are triggered by fork pull request. It's a security risk, people can create a PR and modify the workflow yamls to execute a malicious script. So we should require approval for first-time contributors, which is the default strategy of a public repo on GitHub, see [Approving workflow runs from public forks](https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks). Current strategy: - don't need approval if it's not a fork PR; - always need approval if the user is restricted; - don't need approval if the user can write; - don't need approval if the user has been approved before; - otherwise, need approval. https://user-images.githubusercontent.com/9418365/217207121-badf50a8-826c-4425-bef1-d82d1979bc81.mov GitHub has an option for that, you can see that at `/<owner>/<repo>/settings/actions`, and we can support that later. <img width="835" alt="image" src="https://user-images.githubusercontent.com/9418365/217199990-2967e68b-e693-4e59-8186-ab33a1314a16.png"> --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'models')
-rw-r--r--models/actions/run.go12
-rw-r--r--models/actions/run_list.go8
-rw-r--r--models/actions/status.go4
-rw-r--r--models/migrations/migrations.go4
-rw-r--r--models/migrations/v1_20/v244.go22
5 files changed, 43 insertions, 7 deletions
diff --git a/models/actions/run.go b/models/actions/run.go
index 14d191c81..a8d991471 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -32,11 +32,13 @@ type ActionRun struct {
OwnerID int64 `xorm:"index"`
WorkflowID string `xorm:"index"` // the name of workflow file
Index int64 `xorm:"index unique(repo_index)"` // a unique number for each run of a repository
- TriggerUserID int64
- TriggerUser *user_model.User `xorm:"-"`
+ TriggerUserID int64 `xorm:"index"`
+ TriggerUser *user_model.User `xorm:"-"`
Ref string
CommitSHA string
IsForkPullRequest bool
+ NeedApproval bool // may need approval if it's a fork pull request
+ ApprovedBy int64 `xorm:"index"` // who approved
Event webhook_module.HookEventType
EventPayload string `xorm:"LONGTEXT"`
Status Status `xorm:"index"`
@@ -164,10 +166,6 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
}
run.Index = index
- if run.Status.IsUnknown() {
- run.Status = StatusWaiting
- }
-
if err := db.Insert(ctx, run); err != nil {
return err
}
@@ -191,7 +189,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
job.EraseNeeds()
payload, _ := v.Marshal()
status := StatusWaiting
- if len(needs) > 0 {
+ if len(needs) > 0 || run.NeedApproval {
status = StatusBlocked
}
runJobs = append(runJobs, &ActionRunJob{
diff --git a/models/actions/run_list.go b/models/actions/run_list.go
index f9d841722..bc69c6584 100644
--- a/models/actions/run_list.go
+++ b/models/actions/run_list.go
@@ -68,6 +68,8 @@ type FindRunOptions struct {
OwnerID int64
IsClosed util.OptionalBool
WorkflowFileName string
+ TriggerUserID int64
+ Approved bool // not util.OptionalBool, it works only when it's true
}
func (opts FindRunOptions) toConds() builder.Cond {
@@ -89,6 +91,12 @@ func (opts FindRunOptions) toConds() builder.Cond {
if opts.WorkflowFileName != "" {
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowFileName})
}
+ if opts.TriggerUserID > 0 {
+ cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID})
+ }
+ if opts.Approved {
+ cond = cond.And(builder.Gt{"approved_by": 0})
+ }
return cond
}
diff --git a/models/actions/status.go b/models/actions/status.go
index 059cf9bc0..c97578f2a 100644
--- a/models/actions/status.go
+++ b/models/actions/status.go
@@ -82,6 +82,10 @@ func (s Status) IsRunning() bool {
return s == StatusRunning
}
+func (s Status) IsBlocked() bool {
+ return s == StatusBlocked
+}
+
// In returns whether s is one of the given statuses
func (s Status) In(statuses ...Status) bool {
for _, v := range statuses {
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 989a1d6ae..585457e47 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/models/migrations/v1_17"
"code.gitea.io/gitea/models/migrations/v1_18"
"code.gitea.io/gitea/models/migrations/v1_19"
+ "code.gitea.io/gitea/models/migrations/v1_20"
"code.gitea.io/gitea/models/migrations/v1_6"
"code.gitea.io/gitea/models/migrations/v1_7"
"code.gitea.io/gitea/models/migrations/v1_8"
@@ -463,6 +464,9 @@ var migrations = []Migration{
NewMigration("Add exclusive label", v1_19.AddExclusiveLabel),
// Gitea 1.19.0 ends at v244
+
+ // v244 -> v245
+ NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_20/v244.go b/models/migrations/v1_20/v244.go
new file mode 100644
index 000000000..977566ad7
--- /dev/null
+++ b/models/migrations/v1_20/v244.go
@@ -0,0 +1,22 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_20 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddNeedApprovalToActionRun(x *xorm.Engine) error {
+ /*
+ New index: TriggerUserID
+ New fields: NeedApproval, ApprovedBy
+ */
+ type ActionRun struct {
+ TriggerUserID int64 `xorm:"index"`
+ NeedApproval bool // may need approval if it's a fork pull request
+ ApprovedBy int64 `xorm:"index"` // who approved
+ }
+
+ return x.Sync(new(ActionRun))
+}