From 20b84a1aeeee27b291b58822b224560b335db78c Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Fri, 29 Mar 2024 14:36:48 +0100 Subject: [PATCH] Add flag to only access public repositories on GitHub (#3566) --- cmd/server/flags.go | 6 ++++++ cmd/server/setup.go | 1 + docs/docs/30-administration/11-forges/20-github.md | 6 ++++++ server/forge/github/github.go | 12 +++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/server/flags.go b/cmd/server/flags.go index 152070ba5..dd7eefe52 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -340,6 +340,12 @@ var flags = append([]cli.Flag{ Usage: "github pull requests use merge ref", Value: true, }, + &cli.BoolFlag{ + EnvVars: []string{"WOODPECKER_GITHUB_PUBLIC_ONLY"}, + Name: "github-public-only", + Usage: "github tokens should only get access to public repos", + Value: false, + }, &cli.BoolFlag{ EnvVars: []string{"WOODPECKER_GITHUB_SKIP_VERIFY"}, Name: "github-skip-verify", diff --git a/cmd/server/setup.go b/cmd/server/setup.go index fa3bba2d8..be63d5c32 100644 --- a/cmd/server/setup.go +++ b/cmd/server/setup.go @@ -200,6 +200,7 @@ func setupGitHub(c *cli.Context) (forge.Forge, error) { Secret: c.String("github-secret"), SkipVerify: c.Bool("github-skip-verify"), MergeRef: c.Bool("github-merge-ref"), + OnlyPublic: c.Bool("github-public-only"), } log.Trace().Msgf("forge (github) opts: %#v", opts) return github.New(opts) diff --git a/docs/docs/30-administration/11-forges/20-github.md b/docs/docs/30-administration/11-forges/20-github.md index f3656f8fd..338e555fd 100644 --- a/docs/docs/30-administration/11-forges/20-github.md +++ b/docs/docs/30-administration/11-forges/20-github.md @@ -81,3 +81,9 @@ Read the value for `WOODPECKER_GITHUB_SECRET` from the specified filepath. > Default: `false` Configure if SSL verification should be skipped. + +### `WOODPECKER_GITHUB_PUBLIC_ONLY` + +> Default: `false` + +Configures the GitHub OAuth client to only obtain a token that can manage public repositories. diff --git a/server/forge/github/github.go b/server/forge/github/github.go index 278b91401..d48fec314 100644 --- a/server/forge/github/github.go +++ b/server/forge/github/github.go @@ -51,6 +51,7 @@ type Opts struct { Secret string // GitHub oauth client secret. SkipVerify bool // Skip ssl verification. MergeRef bool // Clone pull requests using the merge ref. + OnlyPublic bool // Only obtain OAuth tokens with access to public repos. } // New returns a Forge implementation that integrates with a GitHub Cloud or @@ -63,6 +64,7 @@ func New(opts Opts) (forge.Forge, error) { Secret: opts.Secret, SkipVerify: opts.SkipVerify, MergeRef: opts.MergeRef, + OnlyPublic: opts.OnlyPublic, } if opts.URL != defaultURL { r.url = strings.TrimSuffix(opts.URL, "/") @@ -79,6 +81,7 @@ type client struct { Secret string SkipVerify bool MergeRef bool + OnlyPublic bool } // Name returns the string name of this driver @@ -405,10 +408,17 @@ func (c *client) newContext(ctx context.Context) context.Context { // helper function to return the GitHub oauth2 config func (c *client) newConfig() *oauth2.Config { + scopes := []string{"user:email", "read:org"} + if c.OnlyPublic { + scopes = append(scopes, []string{"admin:repo_hook", "repo:status"}...) + } else { + scopes = append(scopes, "repo") + } + return &oauth2.Config{ ClientID: c.Client, ClientSecret: c.Secret, - Scopes: []string{"repo", "user:email", "read:org"}, + Scopes: scopes, Endpoint: oauth2.Endpoint{ AuthURL: fmt.Sprintf("%s/login/oauth/authorize", c.url), TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.url),