0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-01-24 21:46:31 +01:00
This commit is contained in:
Excellencedev 2025-12-30 04:38:04 +01:00
parent 4fb498987d
commit efb93b5da1
2 changed files with 122 additions and 1 deletions

View File

@ -3728,12 +3728,31 @@
"git.filemode.submodule": "Submodule",
"actions.general.token_permissions.title": "Action Token Permissions",
"actions.general.token_permissions.desc": "Configure the default permissions for the GITEA_TOKEN running in this repository.",
"actions.general.token_permissions.mode": "Default Token Permissions",
"actions.general.token_permissions.mode.permissive": "Permissive",
"actions.general.token_permissions.mode.permissive.desc": "Read and write permissions for all jobs.",
"actions.general.token_permissions.mode.restricted": "Restricted",
"actions.general.token_permissions.mode.restricted.desc": "Read-only permissions for contents and packages. No other permissions.",
"actions.general.token_permissions.mode.custom": "Custom",
"actions.general.token_permissions.mode.custom.desc": "Configure permissions for each category.",
"actions.general.token_permissions.access_none": "None",
"actions.general.token_permissions.access_read": "Read",
"actions.general.token_permissions.access_write": "Write",
"actions.general.token_permissions.contents": "Contents",
"actions.general.token_permissions.contents.description": "Repository contents, commits, branches, downloads, releases, and merges.",
"actions.general.token_permissions.issues": "Issues",
"actions.general.token_permissions.issues.description": "Issues and related comments, assignees, labels, and milestones.",
"actions.general.token_permissions.pull_requests": "Pull Requests",
"actions.general.token_permissions.pull_requests.description": "Pull requests and related comments, assignees, labels, and milestones.",
"actions.general.token_permissions.wiki": "Wiki",
"actions.general.token_permissions.wiki.description": "Wiki pages and files.",
"actions.general.token_permissions.packages": "Packages",
"actions.general.token_permissions.packages.description": "Packages and container images.",
"actions.general.token_permissions.actions_scope": "Actions",
"actions.general.token_permissions.actions_scope.description": "Interact with workflow runs.",
"actions.general.token_permissions.maximum": "Maximum Token Permissions",
"actions.general.token_permissions.maximum.description": "The maximum permissions tokens are allowed to have. Workflow-specified permissions cannot exceed these limits.",
"actions.general.token_permissions.fork_pr_note": "Note: Pull requests from forks always have read-only permissions.",
"actions.general.token_permissions.max_permissions": "Maximum Permissions",
"actions.general.token_permissions.max_permissions.desc": "Configure better restrictions for the GITEA_TOKEN running in this repository.",
"actions.general.token_permissions.read": "Read",
@ -3750,3 +3769,4 @@
"all_repositories": "All Repositories",
"specific_repositories": "Specific Repositories"
}

View File

@ -10,6 +10,7 @@ import (
"net/http"
"net/url"
"testing"
"time"
actions_model "code.gitea.io/gitea/models/actions"
auth_model "code.gitea.io/gitea/models/auth"
@ -37,11 +38,34 @@ func TestActionsJobTokenAccess(t *testing.T) {
func testActionsJobTokenAccess(u *url.URL, isFork bool) func(t *testing.T) {
return func(t *testing.T) {
task := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: 47})
// Ensure the Actions unit exists for the repository with default permissive mode
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: task.RepoID})
actionsUnit, err := repo.GetUnit(t.Context(), unit_model.TypeActions)
if repo_model.IsErrUnitTypeNotExist(err) {
// Insert Actions unit if it doesn't exist
err = db.Insert(t.Context(), &repo_model.RepoUnit{
RepoID: repo.ID,
Type: unit_model.TypeActions,
Config: &repo_model.ActionsConfig{},
})
require.NoError(t, err)
} else {
require.NoError(t, err)
// Ensure permissive mode for this test
actionsCfg := actionsUnit.ActionsConfig()
actionsCfg.TokenPermissionMode = repo_model.ActionsTokenPermissionModePermissive
actionsCfg.MaxTokenPermissions = nil
actionsUnit.Config = actionsCfg
require.NoError(t, repo_model.UpdateRepoUnit(t.Context(), actionsUnit))
}
require.NoError(t, task.GenerateToken())
task.Status = actions_model.StatusRunning
task.IsForkPullRequest = isFork
err := actions_model.UpdateTask(t.Context(), task, "token_hash", "token_salt", "token_last_eight", "status", "is_fork_pull_request")
err = actions_model.UpdateTask(t.Context(), task, "token_hash", "token_salt", "token_last_eight", "status", "is_fork_pull_request")
require.NoError(t, err)
session := emptyTestSession(t)
context := APITestContext{
Session: session,
@ -413,3 +437,80 @@ func TestActionsCrossRepoAccess(t *testing.T) {
})
})
}
func TestActionsTokenPermissionsWorkflowScenario(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
// Step 1: Create a new repository with Actions enabled
httpContext := NewAPITestContext(t, "user2", "repo-workflow-token-test", auth_model.AccessTokenScopeWriteUser, auth_model.AccessTokenScopeWriteRepository)
t.Run("Create Repository and Test Token Permissions", doAPICreateRepository(httpContext, false, func(t *testing.T, repository structs.Repository) {
// Step 2: Enable Actions unit with Permissive mode (the mode the reviewer set)
err := db.Insert(t.Context(), &repo_model.RepoUnit{
RepoID: repository.ID,
Type: unit_model.TypeActions,
Config: &repo_model.ActionsConfig{
TokenPermissionMode: repo_model.ActionsTokenPermissionModePermissive,
// No MaxTokenPermissions - allows full write access
},
})
require.NoError(t, err)
// Step 3: Create an Actions task (simulates a running workflow)
task := &actions_model.ActionTask{
RepoID: repository.ID,
Status: actions_model.StatusRunning,
IsForkPullRequest: false,
}
require.NoError(t, task.GenerateToken())
require.NoError(t, db.Insert(t.Context(), task))
// Step 4: Use the GITEA_TOKEN to create a file via API (exactly as the reviewer's workflow did)
session := emptyTestSession(t)
testCtx := APITestContext{
Session: session,
Token: task.Token,
Username: "user2",
Reponame: "repo-workflow-token-test",
}
// The create file should succeed with permissive mode
testCtx.ExpectedCode = http.StatusCreated
t.Run("GITEA_TOKEN Create File (Permissive Mode)", doAPICreateFile(testCtx, fmt.Sprintf("test-file-%d.txt", time.Now().Unix()), &structs.CreateFileOptions{
FileOptions: structs.FileOptions{
BranchName: "master",
Message: "test actions token",
},
ContentBase64: base64.StdEncoding.EncodeToString([]byte("Test Content")),
}))
// Verify that the API also works for reading (should always work)
testCtx.ExpectedCode = http.StatusOK
t.Run("GITEA_TOKEN Get Repository", doAPIGetRepository(testCtx, func(t *testing.T, r structs.Repository) {
assert.Equal(t, "repo-workflow-token-test", r.Name)
}))
// Now test with Restricted mode - file creation should fail
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repository.ID})
actionsUnit, err := repo.GetUnit(t.Context(), unit_model.TypeActions)
require.NoError(t, err)
actionsCfg := actionsUnit.ActionsConfig()
actionsCfg.TokenPermissionMode = repo_model.ActionsTokenPermissionModeRestricted
actionsUnit.Config = actionsCfg
require.NoError(t, repo_model.UpdateRepoUnit(t.Context(), actionsUnit))
// Regenerate token to get fresh permissions
require.NoError(t, task.GenerateToken())
task.Status = actions_model.StatusRunning
require.NoError(t, actions_model.UpdateTask(t.Context(), task, "token_hash", "token_salt", "token_last_eight", "status"))
testCtx.Token = task.Token
testCtx.ExpectedCode = http.StatusForbidden
t.Run("GITEA_TOKEN Create File (Restricted Mode - Should Fail)", doAPICreateFile(testCtx, "should-fail.txt", &structs.CreateFileOptions{
FileOptions: structs.FileOptions{
BranchName: "master",
Message: "this should fail",
},
ContentBase64: base64.StdEncoding.EncodeToString([]byte("Should Not Be Created")),
}))
}))
})
}