From 5527d9bf86936eb8f52403d047268137c91188d6 Mon Sep 17 00:00:00 2001 From: Anbraten <6918444+anbraten@users.noreply.github.com> Date: Wed, 15 May 2024 15:45:08 +0200 Subject: [PATCH] Cleanup server env settings (#3670) Co-authored-by: Robert Kaussow Co-authored-by: Robert Kaussow --- .gitpod.yml | 7 +++-- cmd/server/flags.go | 30 +++++++++++-------- cmd/server/server.go | 4 +-- docs/docs/20-usage/15-terminology/index.md | 1 + docs/docs/91-migrations.md | 2 ++ .../bitbucketdatacenter.go | 10 ++++++- server/forge/gitea/gitea.go | 18 +++++------ server/forge/github/github.go | 10 ++++++- server/forge/gitlab/gitlab.go | 10 ++++++- server/forge/setup/setup.go | 14 ++++----- server/model/forge.go | 1 + server/services/setup.go | 2 +- 12 files changed, 70 insertions(+), 39 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index e1a42ef1d..b99e67542 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,6 +4,7 @@ tasks: WOODPECKER_OPEN: true WOODPECKER_ADMIN: woodpecker WOODPECKER_HOST: http://host.docker.internal:8000 + WOODPECKER_EXPERT_WEBHOOK_HOST: http://host.docker.internal:8000 WOODPECKER_AGENT_SECRET: '1234' WOODPECKER_GITEA: true WOODPECKER_DEV_WWW_PROXY: http://localhost:8010 @@ -20,9 +21,9 @@ tasks: grep "WOODPECKER_GITEA_URL=" .env \ && sed "s,^WOODPECKER_GITEA_URL=.*,WOODPECKER_GITEA_URL=$(gp url 3000)," .env \ || echo WOODPECKER_GITEA_URL=$(gp url 3000) >> .env - grep "WOODPECKER_DEV_OAUTH_HOST=" .env \ - && sed "s,^WOODPECKER_DEV_OAUTH_HOST=.*,WOODPECKER_DEV_OAUTH_HOST=$(gp url 8000)," .env \ - || echo WOODPECKER_DEV_OAUTH_HOST=$(gp url 8000) >> .env + grep "WOODPECKER_HOST=" .env \ + && sed "s,^WOODPECKER_HOST=.*,WOODPECKER_HOST=$(gp url 8000)," .env \ + || echo WOODPECKER_HOST=$(gp url 8000) >> .env gp sync-await gitea gp sync-done woodpecker-server go run go.woodpecker-ci.org/woodpecker/v2/cmd/server diff --git a/cmd/server/flags.go b/cmd/server/flags.go index b10a3a3b7..d2141457e 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -38,12 +38,7 @@ var flags = append([]cli.Flag{ &cli.StringFlag{ EnvVars: []string{"WOODPECKER_HOST"}, Name: "server-host", - Usage: "server fully qualified url (://[/])", - }, - &cli.StringFlag{ - EnvVars: []string{"WOODPECKER_WEBHOOK_HOST"}, - Name: "server-webhook-host", - Usage: "server fully qualified url for forge's Webhooks (://[/])", + Usage: "server fully qualified url. Format: ://[/]", }, &cli.StringFlag{ EnvVars: []string{"WOODPECKER_SERVER_ADDR"}, @@ -330,6 +325,11 @@ var flags = append([]cli.Flag{ Usage: "skip ssl verification", EnvVars: []string{"WOODPECKER_FORGE_SKIP_VERIFY", "WOODPECKER_GITHUB_SKIP_VERIFY", "WOODPECKER_GITLAB_SKIP_VERIFY", "WOODPECKER_GITEA_SKIP_VERIFY", "WOODPECKER_BITBUCKET_SKIP_VERIFY"}, }, + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_EXPERT_FORGE_OAUTH_HOST", "WOODPECKER_DEV_GITEA_OAUTH_URL"}, // TODO: remove WOODPECKER_DEV_GITEA_OAUTH_URL in next major release + Name: "forge-oauth-host", + Usage: "!!!for experts!!! fully qualified public forge url. Use it if your forge url WOODPECKER_FORGE_URL or WOODPECKER_GITEA_URL, ... isn't a public url. Format: ://[/]", + }, // // Addon // @@ -366,11 +366,6 @@ var flags = append([]cli.Flag{ Name: "gitea", Usage: "gitea driver is enabled", }, - &cli.StringFlag{ - EnvVars: []string{"WOODPECKER_DEV_GITEA_OAUTH_URL"}, - Name: "gitea-oauth-server", - Usage: "user-facing gitea server url for oauth", - }, // // Bitbucket // @@ -416,10 +411,19 @@ var flags = append([]cli.Flag{ Usage: "serve the website by using a proxy (used for development)", Hidden: true, }, + // + // expert flags + // + &cli.StringFlag{ + EnvVars: []string{"WOODPECKER_EXPERT_WEBHOOK_HOST", "WOODPECKER_WEBHOOK_HOST"}, // TODO: remove WOODPECKER_WEBHOOK_HOST in next major release + Name: "server-webhook-host", + Usage: "!!!for experts!!! fully qualified woodpecker server url called by forge's webhooks. Format: ://[/]", + }, + // TODO: remove in next major release &cli.StringFlag{ EnvVars: []string{"WOODPECKER_DEV_OAUTH_HOST"}, - Name: "server-dev-oauth-host", - Usage: "server fully qualified url (://[/]) used for oauth redirect (used for development)", + Name: "server-dev-oauth-host-deprecated", + Usage: "DEPRECATED: use WOODPECKER_EXPERT_FORGE_OAUTH_HOST instead\nfully qualified url used for oauth redirects. Format: ://[/]", Value: "", Hidden: true, }, diff --git a/cmd/server/server.go b/cmd/server/server.go index 39ddc2580..bc5a8b2c6 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -317,8 +317,8 @@ func setupEvilGlobals(c *cli.Context, s store.Store) error { } else { server.Config.Server.WebhookHost = serverHost } - if c.IsSet("server-dev-oauth-host") { - server.Config.Server.OAuthHost = c.String("server-dev-oauth-host") + if c.IsSet("server-dev-oauth-host-deprecated") { + server.Config.Server.OAuthHost = c.String("server-dev-oauth-host-deprecated") } else { server.Config.Server.OAuthHost = serverHost } diff --git a/docs/docs/20-usage/15-terminology/index.md b/docs/docs/20-usage/15-terminology/index.md index d2bc5bdc0..5e9d8e5de 100644 --- a/docs/docs/20-usage/15-terminology/index.md +++ b/docs/docs/20-usage/15-terminology/index.md @@ -50,6 +50,7 @@ Sometimes there are multiple terms that can be used to describe something. This - Environment variables `*_LINK` should be called `*_URL`. In the code use `URL()` instead of `Link()` - Use the term **pipelines** instead of the previous **builds** - Use the term **steps** instead of the previous **jobs** +- Use the prefix `WOODPECKER_EXPERT_` for advanced environment variables that are normally not required to be set by users diff --git a/docs/docs/91-migrations.md b/docs/docs/91-migrations.md index 6ad8f7b13..02c7cd08f 100644 --- a/docs/docs/91-migrations.md +++ b/docs/docs/91-migrations.md @@ -12,6 +12,8 @@ Some versions need some changes to the server configuration or the pipeline conf - Deprecated alternative names for secrets, use `environment` with `from_secret` - Deprecated slice definition for env vars - Deprecated `environment` filter, use `when.evaluate` +- Use `WOODPECKER_EXPERT_FORGE_OAUTH_HOST` instead of `WOODPECKER_DEV_GITEA_OAUTH_URL` or `WOODPECKER_DEV_OAUTH_HOST` +- Deprecated `WOODPECKER_WEBHOOK_HOST` in favor of `WOODPECKER_EXPERT_WEBHOOK_HOST` ## 2.0.0 diff --git a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go index 126a5d6b6..c2dad10aa 100644 --- a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go +++ b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go @@ -43,6 +43,7 @@ type Opts struct { Password string // Git machine account password. ClientID string // OAuth 2.0 client id ClientSecret string // OAuth 2.0 client secret + OAuthHost string // OAuth 2.0 host } type client struct { @@ -50,6 +51,7 @@ type client struct { urlAPI string clientID string clientSecret string + oauthHost string username string password string } @@ -62,6 +64,7 @@ func New(opts Opts) (forge.Forge, error) { urlAPI: fmt.Sprintf("%s/rest", opts.URL), clientID: opts.ClientID, clientSecret: opts.ClientSecret, + oauthHost: opts.OAuthHost, username: opts.Username, password: opts.Password, } @@ -608,11 +611,16 @@ func (c *client) Org(_ context.Context, _ *model.User, owner string) (*model.Org } func (c *client) newOAuth2Config() *oauth2.Config { + publicOAuthURL := c.oauthHost + if publicOAuthURL == "" { + publicOAuthURL = c.urlAPI + } + return &oauth2.Config{ ClientID: c.clientID, ClientSecret: c.clientSecret, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("%s/oauth2/latest/authorize", c.urlAPI), + AuthURL: fmt.Sprintf("%s/oauth2/latest/authorize", publicOAuthURL), TokenURL: fmt.Sprintf("%s/oauth2/latest/token", c.urlAPI), }, Scopes: []string{string(bb.PermissionRepoRead), string(bb.PermissionRepoWrite), string(bb.PermissionRepoAdmin)}, diff --git a/server/forge/gitea/gitea.go b/server/forge/gitea/gitea.go index c16463d81..e0d82c506 100644 --- a/server/forge/gitea/gitea.go +++ b/server/forge/gitea/gitea.go @@ -50,9 +50,9 @@ const ( type Gitea struct { url string - oauth2URL string ClientID string ClientSecret string + OAuthHost string SkipVerify bool pageSize int } @@ -60,24 +60,20 @@ type Gitea struct { // Opts defines configuration options. type Opts struct { URL string // Gitea server url. - OAuth2URL string // User-facing Gitea server url for OAuth2. Client string // OAuth2 Client ID Secret string // OAuth2 Client Secret + OAuthHost string // OAuth2 Host SkipVerify bool // Skip ssl verification. } // New returns a Forge implementation that integrates with Gitea, // an open source Git service written in Go. See https://gitea.io/ func New(opts Opts) (forge.Forge, error) { - if opts.OAuth2URL == "" { - opts.OAuth2URL = opts.URL - } - return &Gitea{ url: opts.URL, - oauth2URL: opts.OAuth2URL, ClientID: opts.Client, ClientSecret: opts.Secret, + OAuthHost: opts.OAuthHost, SkipVerify: opts.SkipVerify, }, nil } @@ -93,12 +89,16 @@ func (c *Gitea) URL() string { } func (c *Gitea) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) { + publicOAuthURL := c.OAuthHost + if publicOAuthURL == "" { + publicOAuthURL = c.url + } return &oauth2.Config{ ClientID: c.ClientID, ClientSecret: c.ClientSecret, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf(authorizeTokenURL, c.oauth2URL), - TokenURL: fmt.Sprintf(accessTokenURL, c.oauth2URL), + AuthURL: fmt.Sprintf(authorizeTokenURL, publicOAuthURL), + TokenURL: fmt.Sprintf(accessTokenURL, c.url), }, RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), }, diff --git a/server/forge/github/github.go b/server/forge/github/github.go index 42bb74a17..6b3646ebd 100644 --- a/server/forge/github/github.go +++ b/server/forge/github/github.go @@ -52,6 +52,7 @@ type Opts struct { 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. + OAuthHost string // Public url for oauth if different from url. } // New returns a Forge implementation that integrates with a GitHub Cloud or @@ -62,6 +63,7 @@ func New(opts Opts) (forge.Forge, error) { url: defaultURL, Client: opts.Client, Secret: opts.Secret, + oAuthHost: opts.OAuthHost, SkipVerify: opts.SkipVerify, MergeRef: opts.MergeRef, OnlyPublic: opts.OnlyPublic, @@ -82,6 +84,7 @@ type client struct { SkipVerify bool MergeRef bool OnlyPublic bool + oAuthHost string } // Name returns the string name of this driver. @@ -415,12 +418,17 @@ func (c *client) newConfig() *oauth2.Config { scopes = append(scopes, "repo") } + publicOAuthURL := c.oAuthHost + if publicOAuthURL == "" { + publicOAuthURL = c.url + } + return &oauth2.Config{ ClientID: c.Client, ClientSecret: c.Secret, Scopes: scopes, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("%s/login/oauth/authorize", c.url), + AuthURL: fmt.Sprintf("%s/login/oauth/authorize", publicOAuthURL), TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.url), }, RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index 2c3c342fc..27cd50cb7 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -51,6 +51,7 @@ type Opts struct { ClientID string // Oauth2 client id. ClientSecret string // Oauth2 client secret. SkipVerify bool // Skip ssl verification. + OAuthHost string // Public url for oauth if different from url. } // Gitlab implements "Forge" interface. @@ -61,6 +62,7 @@ type GitLab struct { SkipVerify bool HideArchives bool Search bool + oAuthHost string } // New returns a Forge implementation that integrates with Gitlab, an open @@ -70,6 +72,7 @@ func New(opts Opts) (forge.Forge, error) { url: opts.URL, ClientID: opts.ClientID, ClientSecret: opts.ClientSecret, + oAuthHost: opts.OAuthHost, SkipVerify: opts.SkipVerify, HideArchives: true, }, nil @@ -86,11 +89,16 @@ func (g *GitLab) URL() string { } func (g *GitLab) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) { + publicOAuthURL := g.oAuthHost + if publicOAuthURL == "" { + publicOAuthURL = g.url + } + return &oauth2.Config{ ClientID: g.ClientID, ClientSecret: g.ClientSecret, Endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("%s/oauth/authorize", g.url), + AuthURL: fmt.Sprintf("%s/oauth/authorize", publicOAuthURL), TokenURL: fmt.Sprintf("%s/oauth/token", g.url), }, Scopes: []string{defaultScope}, diff --git a/server/forge/setup/setup.go b/server/forge/setup/setup.go index d5ce8f742..824a580f7 100644 --- a/server/forge/setup/setup.go +++ b/server/forge/setup/setup.go @@ -46,22 +46,17 @@ func setupBitbucket(forge *model.Forge) (forge.Forge, error) { } func setupGitea(forge *model.Forge) (forge.Forge, error) { - server, err := url.Parse(forge.URL) + serverURL, err := url.Parse(forge.URL) if err != nil { return nil, err } - oauthURL, ok := forge.AdditionalOptions["oauth-server"].(string) - if !ok { - return nil, fmt.Errorf("missing oauth-server") - } - opts := gitea.Opts{ - URL: strings.TrimRight(server.String(), "/"), + URL: strings.TrimRight(serverURL.String(), "/"), Client: forge.Client, Secret: forge.ClientSecret, SkipVerify: forge.SkipVerify, - OAuth2URL: oauthURL, + OAuthHost: forge.OAuthHost, } if len(opts.URL) == 0 { return nil, fmt.Errorf("WOODPECKER_GITEA_URL must be set") @@ -76,6 +71,7 @@ func setupGitLab(forge *model.Forge) (forge.Forge, error) { ClientID: forge.Client, ClientSecret: forge.ClientSecret, SkipVerify: forge.SkipVerify, + OAuthHost: forge.OAuthHost, }) } @@ -97,6 +93,7 @@ func setupGitHub(forge *model.Forge) (forge.Forge, error) { SkipVerify: forge.SkipVerify, MergeRef: mergeRef, OnlyPublic: publicOnly, + OAuthHost: forge.OAuthHost, } log.Trace().Msgf("Forge (github) opts: %#v", opts) return github.New(opts) @@ -118,6 +115,7 @@ func setupBitbucketDatacenter(forge *model.Forge) (forge.Forge, error) { ClientSecret: forge.ClientSecret, Username: gitUsername, Password: gitPassword, + OAuthHost: forge.OAuthHost, } log.Trace().Msgf("Forge (bitbucketdatacenter) opts: %#v", opts) return bitbucketdatacenter.New(opts) diff --git a/server/model/forge.go b/server/model/forge.go index 8190fc34d..2d670e6d5 100644 --- a/server/model/forge.go +++ b/server/model/forge.go @@ -32,5 +32,6 @@ type Forge struct { Client string `xorm:"VARCHAR(250)"` ClientSecret string `xorm:"VARCHAR(250)"` SkipVerify bool `xorm:"bool"` + OAuthHost string `xorm:"VARCHAR(250) 'oauth_host'"` // public url for oauth if different from url AdditionalOptions map[string]any `xorm:"json"` } diff --git a/server/services/setup.go b/server/services/setup.go index 57dd1f94b..8baed83c9 100644 --- a/server/services/setup.go +++ b/server/services/setup.go @@ -118,6 +118,7 @@ func setupForgeService(c *cli.Context, _store store.Store) error { _forge.ClientSecret = c.String("forge-oauth-secret") _forge.URL = c.String("forge-url") _forge.SkipVerify = c.Bool("forge-skip-verify") + _forge.OAuthHost = c.String("forge-oauth-host") switch { case c.String("addon-forge") != "": @@ -137,7 +138,6 @@ func setupForgeService(c *cli.Context, _store store.Store) error { } case c.Bool("gitea"): _forge.Type = model.ForgeTypeGitea - _forge.AdditionalOptions["oauth-server"] = c.String("gitea-oauth-server") if _forge.URL == "" { _forge.URL = "https://try.gitea.com" }