-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
OIDC provider #33945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
scubbo
wants to merge
31
commits into
go-gitea:main
Choose a base branch
from
scubbo:oidc-provider
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
OIDC provider #33945
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
3a16680
Refactor token signing method in OAuth2 service
sorenisanerd 31e8ad3
feat: Add basic permissions support for actions
sorenisanerd 8271be5
Extract {base_,}{sha,ref} and EventName logic
sorenisanerd 724e138
feat: Add OIDC provider for actions
sorenisanerd fc80a8a
Copy Permissions struct actions_model
sorenisanerd e192676
*looks at a calendar*
sorenisanerd 69ce797
Merge remote-tracking branch 'origin/main' into oidc-provider
sorenisanerd 66dca88
Merge branch 'main' into oidc-provider
scubbo 747dcc1
Add Migration with updated name
scubbo 32e618a
Remove old (inconsistently-named) migration
scubbo 647bdf5
Update Copyright dates
scubbo 0625616
Lint-fix
scubbo f66c4b9
More lintfixes
scubbo 3cde888
Move `permissions.go` to `modules/actions`
scubbo 6395824
Merge remote-tracking branch 'origin/main' into oidc-provider
scubbo 828e2d5
Correction to package-name for migration
scubbo 3ac43c6
Merge branch 'main' into oidc-provider
scubbo 74ace80
Merge branch 'main' into oidc-provider
scubbo 8221de2
Add required models/actions/permissions file
scubbo 50c2a21
Use personal tag of act
scubbo 95c31fb
Remove routers/api/actions/runner/utils
scubbo 8f02684
Use appropriate type for RefType
scubbo 236745d
Merge branch 'main' into oidc-provider
scubbo c028254
Use renamed oauth2_provider for signing token
scubbo d77b250
Reformatting
scubbo f014369
Use gitea/act
scubbo f952190
PR comments
scubbo 7b98be8
Reverting Copyright date updates
scubbo 702f640
Move OIDC API into subfolder
scubbo c477e0e
Merge branch 'main' into oidc-provider
scubbo 7094798
Merge remote-tracking branch 'origin/main' into oidc-provider
scubbo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
// Copyright 2025 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package actions | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
type Permission int | ||
|
||
const ( | ||
PermissionUnspecified Permission = iota | ||
PermissionNone | ||
PermissionRead | ||
PermissionWrite | ||
) | ||
|
||
// Per https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idpermissions | ||
type Permissions struct { | ||
Actions Permission `yaml:"actions"` | ||
Checks Permission `yaml:"checks"` | ||
Contents Permission `yaml:"contents"` | ||
Deployments Permission `yaml:"deployments"` | ||
IDToken Permission `yaml:"id-token"` | ||
Issues Permission `yaml:"issues"` | ||
Discussions Permission `yaml:"discussions"` | ||
Packages Permission `yaml:"packages"` | ||
Pages Permission `yaml:"pages"` | ||
PullRequests Permission `yaml:"pull-requests"` | ||
RepositoryProjects Permission `yaml:"repository-projects"` | ||
SecurityEvents Permission `yaml:"security-events"` | ||
Statuses Permission `yaml:"statuses"` | ||
} | ||
|
||
// WorkflowPermissions parses a workflow and returns | ||
// a Permissions struct representing the permissions set | ||
// at the workflow (i.e. file) level | ||
func WorkflowPermissions(contents []byte) (Permissions, error) { | ||
p := struct { | ||
Permissions Permissions `yaml:"permissions"` | ||
}{} | ||
err := yaml.Unmarshal(contents, &p) | ||
return p.Permissions, err | ||
} | ||
|
||
// Given the contents of a workflow, JobPermissions | ||
// returns a Permissions object representing the permissions | ||
// of THE FIRST job in the file. | ||
func JobPermissions(contents []byte) (Permissions, error) { | ||
p := struct { | ||
Jobs []struct { | ||
Permissions Permissions `yaml:"permissions"` | ||
} `yaml:"jobs"` | ||
}{} | ||
err := yaml.Unmarshal(contents, &p) | ||
if len(p.Jobs) > 0 { | ||
return p.Jobs[0].Permissions, err | ||
} | ||
return Permissions{}, errors.New("no jobs detected in workflow") | ||
} | ||
|
||
func (p *Permission) UnmarshalYAML(unmarshal func(any) error) error { | ||
var data string | ||
if err := unmarshal(&data); err != nil { | ||
return err | ||
} | ||
|
||
switch data { | ||
case "none": | ||
*p = PermissionNone | ||
case "read": | ||
*p = PermissionRead | ||
case "write": | ||
*p = PermissionWrite | ||
default: | ||
return fmt.Errorf("invalid permission: %s", data) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// DefaultAccessPermissive is the default "permissive" set granted to actions on repositories | ||
// per https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token | ||
// That page also lists a "metadata" permission that I can't find mentioned anywhere else. | ||
// However, it seems to always have "read" permission, so it doesn't really matter. | ||
// Interestingly, it doesn't list "Discussions", so we assume "write" for permissive and "none" for restricted. | ||
var DefaultAccessPermissive = Permissions{ | ||
Actions: PermissionWrite, | ||
Checks: PermissionWrite, | ||
Contents: PermissionWrite, | ||
Deployments: PermissionWrite, | ||
IDToken: PermissionNone, | ||
Issues: PermissionWrite, | ||
Discussions: PermissionWrite, | ||
Packages: PermissionWrite, | ||
Pages: PermissionWrite, | ||
PullRequests: PermissionWrite, | ||
RepositoryProjects: PermissionWrite, | ||
SecurityEvents: PermissionWrite, | ||
Statuses: PermissionWrite, | ||
} | ||
|
||
// DefaultAccessRestricted is the default "restrictive" set granted. See docs for | ||
// DefaultAccessPermissive above. | ||
// | ||
// This is not currently used, since Gitea does not have a permissive/restricted setting. | ||
var DefaultAccessRestricted = Permissions{ | ||
Actions: PermissionNone, | ||
Checks: PermissionNone, | ||
Contents: PermissionWrite, | ||
Deployments: PermissionNone, | ||
IDToken: PermissionNone, | ||
Issues: PermissionNone, | ||
Discussions: PermissionNone, | ||
Packages: PermissionRead, | ||
Pages: PermissionNone, | ||
PullRequests: PermissionNone, | ||
RepositoryProjects: PermissionNone, | ||
SecurityEvents: PermissionNone, | ||
Statuses: PermissionNone, | ||
} | ||
|
||
var ReadAllPermissions = Permissions{ | ||
Actions: PermissionRead, | ||
Checks: PermissionRead, | ||
Contents: PermissionRead, | ||
Deployments: PermissionRead, | ||
IDToken: PermissionRead, | ||
Issues: PermissionRead, | ||
Discussions: PermissionRead, | ||
Packages: PermissionRead, | ||
Pages: PermissionRead, | ||
PullRequests: PermissionRead, | ||
RepositoryProjects: PermissionRead, | ||
SecurityEvents: PermissionRead, | ||
Statuses: PermissionRead, | ||
} | ||
|
||
var WriteAllPermissions = Permissions{ | ||
Actions: PermissionWrite, | ||
Checks: PermissionWrite, | ||
Contents: PermissionWrite, | ||
Deployments: PermissionWrite, | ||
IDToken: PermissionWrite, | ||
Issues: PermissionWrite, | ||
Discussions: PermissionWrite, | ||
Packages: PermissionWrite, | ||
Pages: PermissionWrite, | ||
PullRequests: PermissionWrite, | ||
RepositoryProjects: PermissionWrite, | ||
SecurityEvents: PermissionWrite, | ||
Statuses: PermissionWrite, | ||
} | ||
|
||
// FromYAML takes a yaml.Node representing a permissions | ||
// definition and parses it into a Permissions struct | ||
func (p *Permissions) FromYAML(rawPermissions *yaml.Node) error { | ||
switch rawPermissions.Kind { | ||
case yaml.ScalarNode: | ||
var val string | ||
err := rawPermissions.Decode(&val) | ||
if err != nil { | ||
return err | ||
} | ||
if val == "read-all" { | ||
*p = ReadAllPermissions | ||
} | ||
if val == "write-all" { | ||
*p = WriteAllPermissions | ||
} | ||
return fmt.Errorf("unexpected `permissions` value: %v", rawPermissions) | ||
case yaml.MappingNode: | ||
var perms Permissions | ||
err := rawPermissions.Decode(&perms) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
case 0: | ||
*p = Permissions{} | ||
return nil | ||
default: | ||
return fmt.Errorf("invalid permissions value: %v", rawPermissions) | ||
} | ||
} | ||
|
||
func merge[T comparable](a, b T) T { | ||
var zero T | ||
if a == zero { | ||
return b | ||
} | ||
return a | ||
} | ||
|
||
// Merge merges two Permission values | ||
// | ||
// Already set values take precedence over `other`. | ||
// I.e. you want to call jobLevel.Permissions.Merge(topLevel.Permissions) | ||
func (p *Permissions) Merge(other Permissions) { | ||
p.Actions = merge(p.Actions, other.Actions) | ||
p.Checks = merge(p.Checks, other.Checks) | ||
p.Contents = merge(p.Contents, other.Contents) | ||
p.Deployments = merge(p.Deployments, other.Deployments) | ||
p.IDToken = merge(p.IDToken, other.IDToken) | ||
p.Issues = merge(p.Issues, other.Issues) | ||
p.Discussions = merge(p.Discussions, other.Discussions) | ||
p.Packages = merge(p.Packages, other.Packages) | ||
p.Pages = merge(p.Pages, other.Pages) | ||
p.PullRequests = merge(p.PullRequests, other.PullRequests) | ||
p.RepositoryProjects = merge(p.RepositoryProjects, other.RepositoryProjects) | ||
p.SecurityEvents = merge(p.SecurityEvents, other.SecurityEvents) | ||
p.Statuses = merge(p.Statuses, other.Statuses) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.