mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 03:41:01 +00:00
Use server-host as source for public links and warn if it is set to localhost (#251)
* Use server-host as source for public links * use config and rm GetURL() * fix: solve import cycle Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
0e8c17e7e8
commit
1a67fc6e99
13 changed files with 48 additions and 98 deletions
|
@ -69,6 +69,12 @@ func server(c *cli.Context) error {
|
|||
)
|
||||
}
|
||||
|
||||
if strings.Contains(c.String("server-host"), "://localhost") {
|
||||
logrus.Warningln(
|
||||
"DRONE_HOST/DRONE_SERVER_HOST/WOODPECKER_HOST/WOODPECKER_SERVER_HOST should probably be publicly accessible (not localhost)",
|
||||
)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(c.String("server-host"), "/") {
|
||||
logrus.Fatalln(
|
||||
"DRONE_HOST/DRONE_SERVER_HOST/WOODPECKER_HOST/WOODPECKER_SERVER_HOST must not have trailing slash",
|
||||
|
@ -224,7 +230,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) {
|
|||
droneserver.Config.Server.Cert = c.String("server-cert")
|
||||
droneserver.Config.Server.Key = c.String("server-key")
|
||||
droneserver.Config.Server.Pass = c.String("agent-secret")
|
||||
droneserver.Config.Server.Host = strings.TrimRight(c.String("server-host"), "/")
|
||||
droneserver.Config.Server.Host = c.String("server-host")
|
||||
droneserver.Config.Server.Port = c.String("server-addr")
|
||||
droneserver.Config.Server.RepoConfig = c.String("repo-config")
|
||||
droneserver.Config.Server.SessionExpires = c.Duration("session-expires")
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/remote/bitbucket/internal"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
@ -54,8 +54,7 @@ func New(client, secret string) remote.Remote {
|
|||
// Login authenticates an account with Bitbucket using the oauth2 protocol. The
|
||||
// Bitbucket account details are returned when the user is successfully authenticated.
|
||||
func (c *config) Login(w http.ResponseWriter, req *http.Request) (*model.User, error) {
|
||||
redirect := httputil.GetURL(req)
|
||||
config := c.newConfig(redirect)
|
||||
config := c.newConfig(server.Config.Server.Host)
|
||||
|
||||
// get the OAuth errors
|
||||
if err := req.FormValue("error"); err != "" {
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/remote/coding/internal"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
|
@ -62,8 +62,6 @@ func New(opts Opts) (remote.Remote, error) {
|
|||
remote.URL = strings.TrimSuffix(opts.URL, "/")
|
||||
}
|
||||
|
||||
// Hack to enable oauth2 access in coding's implementation
|
||||
oauth2.RegisterBrokenAuthHeaderProvider(remote.URL)
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
|
@ -81,7 +79,7 @@ type Coding struct {
|
|||
// Login authenticates the session and returns the
|
||||
// remote user details.
|
||||
func (c *Coding) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) {
|
||||
config := c.newConfig(httputil.GetURL(req))
|
||||
config := c.newConfig(server.Config.Server.Host)
|
||||
|
||||
// get the OAuth errors
|
||||
if err := req.FormValue("error"); err != "" {
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
@ -78,7 +78,6 @@ func NewOauth(opts Opts) (remote.Remote, error) {
|
|||
// Login authenticates an account with Gitea using basic authentication. The
|
||||
// Gitea account details are returned when the user is successfully authenticated.
|
||||
func (c *oauthclient) Login(w http.ResponseWriter, req *http.Request) (*model.User, error) {
|
||||
redirect := httputil.GetURL(req)
|
||||
config := &oauth2.Config{
|
||||
ClientID: c.Client,
|
||||
ClientSecret: c.Secret,
|
||||
|
@ -86,7 +85,7 @@ func (c *oauthclient) Login(w http.ResponseWriter, req *http.Request) (*model.Us
|
|||
AuthURL: fmt.Sprintf(authorizeTokenURL, c.URL),
|
||||
TokenURL: fmt.Sprintf(accessTokenURL, c.URL),
|
||||
},
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", redirect),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.Host),
|
||||
}
|
||||
|
||||
// get the OAuth errors
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"golang.org/x/net/context"
|
||||
|
@ -340,9 +340,9 @@ func (c *client) newConfig(req *http.Request) *oauth2.Config {
|
|||
|
||||
intendedURL := req.URL.Query()["url"]
|
||||
if len(intendedURL) > 0 {
|
||||
redirect = fmt.Sprintf("%s/authorize?url=%s", httputil.GetURL(req), intendedURL[0])
|
||||
redirect = fmt.Sprintf("%s/authorize?url=%s", server.Config.Server.Host, intendedURL[0])
|
||||
} else {
|
||||
redirect = fmt.Sprintf("%s/authorize", httputil.GetURL(req))
|
||||
redirect = fmt.Sprintf("%s/authorize", server.Config.Server.Host)
|
||||
}
|
||||
|
||||
return &oauth2.Config{
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/oauth2"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/remote/gitlab/client"
|
||||
|
@ -121,7 +121,7 @@ func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User,
|
|||
Scope: DefaultScope,
|
||||
AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL),
|
||||
TokenURL: fmt.Sprintf("%s/oauth/token", g.URL),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(req)),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.Host),
|
||||
}
|
||||
|
||||
trans_ := &http.Transport{
|
||||
|
@ -631,7 +631,7 @@ func (g *Gitlab) Oauth2Transport(r *http.Request) *oauth2.Transport {
|
|||
Scope: DefaultScope,
|
||||
AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL),
|
||||
TokenURL: fmt.Sprintf("%s/oauth/token", g.URL),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(r)),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.Host),
|
||||
//settings.Server.Scheme, settings.Server.Hostname),
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/oauth2"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/remote/gitlab3/client"
|
||||
|
@ -121,7 +121,7 @@ func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User,
|
|||
Scope: DefaultScope,
|
||||
AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL),
|
||||
TokenURL: fmt.Sprintf("%s/oauth/token", g.URL),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(req)),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.Host),
|
||||
}
|
||||
|
||||
trans_ := &http.Transport{
|
||||
|
@ -631,7 +631,7 @@ func (g *Gitlab) Oauth2Transport(r *http.Request) *oauth2.Transport {
|
|||
Scope: DefaultScope,
|
||||
AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL),
|
||||
TokenURL: fmt.Sprintf("%s/oauth/token", g.URL),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(r)),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.Host),
|
||||
//settings.Server.Scheme, settings.Server.Hostname),
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
|
|
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
"github.com/woodpecker-ci/woodpecker/cncd/queue"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/store"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
|
@ -309,7 +308,7 @@ func PostApproval(c *gin.Context) {
|
|||
Netrc: netrc,
|
||||
Secs: secs,
|
||||
Regs: regs,
|
||||
Link: httputil.GetURL(c.Request),
|
||||
Link: Config.Server.Host,
|
||||
Yamls: yamls,
|
||||
Envs: envs,
|
||||
}
|
||||
|
@ -518,7 +517,7 @@ func PostBuild(c *gin.Context) {
|
|||
Netrc: netrc,
|
||||
Secs: secs,
|
||||
Regs: regs,
|
||||
Link: httputil.GetURL(c.Request),
|
||||
Link: Config.Server.Host,
|
||||
Yamls: yamls,
|
||||
Envs: buildParams,
|
||||
}
|
||||
|
|
|
@ -15,6 +15,15 @@ type configFetcher struct {
|
|||
build *model.Build
|
||||
}
|
||||
|
||||
func NewConfigFetcher(remote remote.Remote, user *model.User, repo *model.Repo, build *model.Build) *configFetcher {
|
||||
return &configFetcher{
|
||||
remote_: remote,
|
||||
user: user,
|
||||
repo: repo,
|
||||
build: build,
|
||||
}
|
||||
}
|
||||
|
||||
func (cf *configFetcher) Fetch() ([]*remote.FileMeta, error) {
|
||||
for i := 0; i < 5; i++ {
|
||||
select {
|
||||
|
@ -22,7 +31,7 @@ func (cf *configFetcher) Fetch() ([]*remote.FileMeta, error) {
|
|||
// either a file
|
||||
file, fileerr := cf.remote_.File(cf.user, cf.repo, cf.build, cf.repo.Config)
|
||||
if fileerr == nil {
|
||||
return []*remote.FileMeta{&remote.FileMeta{
|
||||
return []*remote.FileMeta{{
|
||||
Name: cf.repo.Config,
|
||||
Data: file,
|
||||
}}, nil
|
||||
|
@ -43,7 +52,7 @@ func (cf *configFetcher) Fetch() ([]*remote.FileMeta, error) {
|
|||
return nil, fileerr
|
||||
}
|
||||
|
||||
return []*remote.FileMeta{&remote.FileMeta{
|
||||
return []*remote.FileMeta{{
|
||||
Name: cf.repo.Config,
|
||||
Data: file,
|
||||
}}, nil
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package server
|
||||
package server_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote/github"
|
||||
"github.com/woodpecker-ci/woodpecker/server"
|
||||
)
|
||||
|
||||
func TestFetchGithub(t *testing.T) {
|
||||
|
@ -14,11 +15,11 @@ func TestFetchGithub(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
configFetcher := &configFetcher{
|
||||
remote_: github,
|
||||
user: &model.User{Token: "xxx"},
|
||||
repo: &model.Repo{Owner: "laszlocph", Name: "drone-multipipeline", Config: ".drone"},
|
||||
build: &model.Build{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"},
|
||||
}
|
||||
configFetcher := server.NewConfigFetcher(
|
||||
github,
|
||||
&model.User{Token: "xxx"},
|
||||
&model.Repo{Owner: "laszlocph", Name: "drone-multipipeline", Config: ".drone"},
|
||||
&model.Build{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"},
|
||||
)
|
||||
configFetcher.Fetch()
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/token"
|
||||
"github.com/woodpecker-ci/woodpecker/store"
|
||||
|
||||
|
@ -257,7 +256,7 @@ func PostHook(c *gin.Context) {
|
|||
Secs: secs,
|
||||
Regs: regs,
|
||||
Envs: envs,
|
||||
Link: httputil.GetURL(c.Request),
|
||||
Link: Config.Server.Host,
|
||||
Yamls: remoteYamlConfigs,
|
||||
}
|
||||
buildItems, err := b.Build()
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/model"
|
||||
"github.com/woodpecker-ci/woodpecker/remote"
|
||||
"github.com/woodpecker-ci/woodpecker/router/middleware/session"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/httputil"
|
||||
"github.com/woodpecker-ci/woodpecker/shared/token"
|
||||
"github.com/woodpecker-ci/woodpecker/store"
|
||||
)
|
||||
|
@ -75,7 +74,7 @@ func PostRepo(c *gin.Context) {
|
|||
|
||||
link := fmt.Sprintf(
|
||||
"%s/hook?access_token=%s",
|
||||
httputil.GetURL(c.Request),
|
||||
Config.Server.Host,
|
||||
sig,
|
||||
)
|
||||
|
||||
|
@ -203,7 +202,7 @@ func DeleteRepo(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
remote.Deactivate(user, repo, httputil.GetURL(c.Request))
|
||||
remote.Deactivate(user, repo, Config.Server.Host)
|
||||
c.JSON(200, repo)
|
||||
}
|
||||
|
||||
|
@ -221,7 +220,7 @@ func RepairRepo(c *gin.Context) {
|
|||
}
|
||||
|
||||
// reconstruct the link
|
||||
host := httputil.GetURL(c.Request)
|
||||
host := Config.Server.Host
|
||||
link := fmt.Sprintf(
|
||||
"%s/hook?access_token=%s",
|
||||
host,
|
||||
|
@ -307,7 +306,7 @@ func MoveRepo(c *gin.Context) {
|
|||
}
|
||||
|
||||
// reconstruct the link
|
||||
host := httputil.GetURL(c.Request)
|
||||
host := Config.Server.Host
|
||||
link := fmt.Sprintf(
|
||||
"%s/hook?access_token=%s",
|
||||
host,
|
||||
|
|
|
@ -38,65 +38,6 @@ func IsHttps(r *http.Request) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// GetScheme is a helper function that evaluates the http.Request
|
||||
// and returns the scheme, HTTP or HTTPS. It is able to detect,
|
||||
// using the X-Forwarded-Proto, if the original request was HTTPS
|
||||
// and routed through a reverse proxy with SSL termination.
|
||||
func GetScheme(r *http.Request) string {
|
||||
switch {
|
||||
case r.URL.Scheme == "https":
|
||||
return "https"
|
||||
case r.TLS != nil:
|
||||
return "https"
|
||||
case strings.HasPrefix(r.Proto, "HTTPS"):
|
||||
return "https"
|
||||
case r.Header.Get("X-Forwarded-Proto") == "https":
|
||||
return "https"
|
||||
default:
|
||||
return "http"
|
||||
}
|
||||
}
|
||||
|
||||
// GetHost is a helper function that evaluates the http.Request
|
||||
// and returns the hostname. It is able to detect, using the
|
||||
// X-Forarded-For header, the original hostname when routed
|
||||
// through a reverse proxy.
|
||||
func GetHost(r *http.Request) string {
|
||||
switch {
|
||||
case len(r.Host) != 0:
|
||||
return r.Host
|
||||
case len(r.URL.Host) != 0:
|
||||
return r.URL.Host
|
||||
case len(r.Header.Get("X-Forwarded-For")) != 0:
|
||||
return r.Header.Get("X-Forwarded-For")
|
||||
case len(r.Header.Get("X-Host")) != 0:
|
||||
return r.Header.Get("X-Host")
|
||||
case len(r.Header.Get("XFF")) != 0:
|
||||
return r.Header.Get("XFF")
|
||||
case len(r.Header.Get("X-Real-IP")) != 0:
|
||||
return r.Header.Get("X-Real-IP")
|
||||
default:
|
||||
return "localhost:8080"
|
||||
}
|
||||
}
|
||||
|
||||
// GetURL is a helper function that evaluates the http.Request
|
||||
// and returns the URL as a string. Only the scheme + hostname
|
||||
// are included; the path is excluded.
|
||||
func GetURL(r *http.Request) string {
|
||||
return GetScheme(r) + "://" + GetHost(r)
|
||||
}
|
||||
|
||||
// GetCookie retrieves and verifies the cookie value.
|
||||
func GetCookie(r *http.Request, name string) (value string) {
|
||||
cookie, err := r.Cookie(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
value = cookie.Value
|
||||
return
|
||||
}
|
||||
|
||||
// SetCookie writes the cookie value.
|
||||
func SetCookie(w http.ResponseWriter, r *http.Request, name, value string) {
|
||||
cookie := http.Cookie{
|
||||
|
|
Loading…
Reference in a new issue