mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-30 08:06:52 +02:00
Merge pull request #1181 from Bugagazavr/clone-mode
Added clone mode for gitlab, use token mode as default
This commit is contained in:
commit
c9a62fc73c
@ -31,6 +31,7 @@ This section lists all connection options used in the connection string format.
|
||||
* `open=false` allows users to self-register. Defaults to false for security reasons.
|
||||
* `orgs=drone,docker` restricts access to these GitLab organizations. **Optional**
|
||||
* `skip_verify=false` skip ca verification if self-signed certificate. Defaults to false for security reasons.
|
||||
* `clone_mode=token` a strategy for clone authorization, by default use repo token, but can be changed to `oauth` ( This is not secure, because your user token, with full access to your gitlab account will be written to .netrc, and it can be read by all who have access to project builds )
|
||||
|
||||
## Gitlab registration
|
||||
|
||||
|
12
pkg/hash/hash.go
Normal file
12
pkg/hash/hash.go
Normal file
@ -0,0 +1,12 @@
|
||||
package hash
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func New(text, salt string) string {
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(text + salt))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
@ -170,7 +170,7 @@ func (g *GitHub) Script(u *common.User, r *common.Repo, b *common.Build) ([]byte
|
||||
|
||||
// Netrc returns a .netrc file that can be used to clone
|
||||
// private repositories from a remote system.
|
||||
func (g *GitHub) Netrc(u *common.User) (*common.Netrc, error) {
|
||||
func (g *GitHub) Netrc(u *common.User, r *common.Repo) (*common.Netrc, error) {
|
||||
url_, err := url.Parse(g.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client"
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/hashicorp/golang-lru"
|
||||
"github.com/drone/drone/pkg/hash"
|
||||
"github.com/drone/drone/pkg/oauth2"
|
||||
"github.com/drone/drone/pkg/remote"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
@ -26,6 +27,7 @@ type Gitlab struct {
|
||||
Client string
|
||||
Secret string
|
||||
AllowedOrgs []string
|
||||
CloneMode string
|
||||
Open bool
|
||||
PrivateMode bool
|
||||
SkipVerify bool
|
||||
@ -54,6 +56,13 @@ func NewDriver(config string) (remote.Remote, error) {
|
||||
gitlab.SkipVerify, _ = strconv.ParseBool(params.Get("skip_verify"))
|
||||
gitlab.Open, _ = strconv.ParseBool(params.Get("open"))
|
||||
|
||||
switch params.Get("clone_mode") {
|
||||
case "oauth":
|
||||
gitlab.CloneMode = "oauth"
|
||||
default:
|
||||
gitlab.CloneMode = "token"
|
||||
}
|
||||
|
||||
// this is a temp workaround
|
||||
gitlab.Search, _ = strconv.ParseBool(params.Get("search"))
|
||||
|
||||
@ -64,8 +73,8 @@ func NewDriver(config string) (remote.Remote, error) {
|
||||
return &gitlab, err
|
||||
}
|
||||
|
||||
func (r *Gitlab) Login(token, secret string) (*common.User, error) {
|
||||
client := NewClient(r.URL, token, r.SkipVerify)
|
||||
func (g *Gitlab) Login(token, secret string) (*common.User, error) {
|
||||
client := NewClient(g.URL, token, g.SkipVerify)
|
||||
var login, err = client.CurrentUser()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -79,20 +88,20 @@ func (r *Gitlab) Login(token, secret string) (*common.User, error) {
|
||||
if strings.HasPrefix(login.AvatarUrl, "http") {
|
||||
user.Avatar = login.AvatarUrl
|
||||
} else {
|
||||
user.Avatar = r.URL + "/" + login.AvatarUrl
|
||||
user.Avatar = g.URL + "/" + login.AvatarUrl
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// Orgs fetches the organizations for the given user.
|
||||
func (r *Gitlab) Orgs(u *common.User) ([]string, error) {
|
||||
func (g *Gitlab) Orgs(u *common.User) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Repo fetches the named repository from the remote system.
|
||||
func (r *Gitlab) Repo(u *common.User, owner, name string) (*common.Repo, error) {
|
||||
client := NewClient(r.URL, u.Token, r.SkipVerify)
|
||||
id, err := GetProjectId(r, client, owner, name)
|
||||
func (g *Gitlab) Repo(u *common.User, owner, name string) (*common.Repo, error) {
|
||||
client := NewClient(g.URL, u.Token, g.SkipVerify)
|
||||
id, err := GetProjectId(g, client, owner, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -113,7 +122,7 @@ func (r *Gitlab) Repo(u *common.User, owner, name string) (*common.Repo, error)
|
||||
repo.Branch = repo_.DefaultBranch
|
||||
}
|
||||
|
||||
if r.PrivateMode {
|
||||
if g.PrivateMode {
|
||||
repo.Private = true
|
||||
} else {
|
||||
repo.Private = !repo_.Public
|
||||
@ -123,15 +132,15 @@ func (r *Gitlab) Repo(u *common.User, owner, name string) (*common.Repo, error)
|
||||
}
|
||||
|
||||
// Perm fetches the named repository from the remote system.
|
||||
func (r *Gitlab) Perm(u *common.User, owner, name string) (*common.Perm, error) {
|
||||
func (g *Gitlab) Perm(u *common.User, owner, name string) (*common.Perm, error) {
|
||||
key := fmt.Sprintf("%s/%s/%s", u.Login, owner, name)
|
||||
val, ok := r.cache.Get(key)
|
||||
val, ok := g.cache.Get(key)
|
||||
if ok {
|
||||
return val.(*common.Perm), nil
|
||||
}
|
||||
|
||||
client := NewClient(r.URL, u.Token, r.SkipVerify)
|
||||
id, err := GetProjectId(r, client, owner, name)
|
||||
client := NewClient(g.URL, u.Token, g.SkipVerify)
|
||||
id, err := GetProjectId(g, client, owner, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -144,15 +153,15 @@ func (r *Gitlab) Perm(u *common.User, owner, name string) (*common.Perm, error)
|
||||
m.Admin = IsAdmin(repo)
|
||||
m.Pull = IsRead(repo)
|
||||
m.Push = IsWrite(repo)
|
||||
r.cache.Add(key, m)
|
||||
g.cache.Add(key, m)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// GetScript fetches the build script (.drone.yml) from the remote
|
||||
// repository and returns in string format.
|
||||
func (r *Gitlab) Script(user *common.User, repo *common.Repo, build *common.Build) ([]byte, error) {
|
||||
var client = NewClient(r.URL, user.Token, r.SkipVerify)
|
||||
id, err := GetProjectId(r, client, repo.Owner, repo.Name)
|
||||
func (g *Gitlab) Script(user *common.User, repo *common.Repo, build *common.Build) ([]byte, error) {
|
||||
var client = NewClient(g.URL, user.Token, g.SkipVerify)
|
||||
id, err := GetProjectId(g, client, repo.Owner, repo.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -163,29 +172,36 @@ func (r *Gitlab) Script(user *common.User, repo *common.Repo, build *common.Buil
|
||||
// NOTE Currently gitlab doesn't support status for commits and events,
|
||||
// also if we want get MR status in gitlab we need implement a special plugin for gitlab,
|
||||
// gitlab uses API to fetch build status on client side. But for now we skip this.
|
||||
func (r *Gitlab) Status(u *common.User, repo *common.Repo, b *common.Build) error {
|
||||
func (g *Gitlab) Status(u *common.User, repo *common.Repo, b *common.Build) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Netrc returns a .netrc file that can be used to clone
|
||||
// private repositories from a remote system.
|
||||
func (r *Gitlab) Netrc(u *common.User) (*common.Netrc, error) {
|
||||
url_, err := url.Parse(r.URL)
|
||||
func (g *Gitlab) Netrc(u *common.User, r *common.Repo) (*common.Netrc, error) {
|
||||
url_, err := url.Parse(g.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
netrc := &common.Netrc{}
|
||||
|
||||
switch g.CloneMode {
|
||||
case "oauth":
|
||||
netrc.Login = "oauth2"
|
||||
netrc.Password = u.Token
|
||||
case "token":
|
||||
netrc.Login = "drone-ci-token"
|
||||
netrc.Password = hash.New(r.FullName, r.Hash)
|
||||
}
|
||||
netrc.Machine = url_.Host
|
||||
return netrc, nil
|
||||
}
|
||||
|
||||
// Activate activates a repository by adding a Post-commit hook and
|
||||
// a Public Deploy key, if applicable.
|
||||
func (r *Gitlab) Activate(user *common.User, repo *common.Repo, k *common.Keypair, link string) error {
|
||||
var client = NewClient(r.URL, user.Token, r.SkipVerify)
|
||||
id, err := GetProjectId(r, client, repo.Owner, repo.Name)
|
||||
func (g *Gitlab) Activate(user *common.User, repo *common.Repo, k *common.Keypair, link string) error {
|
||||
var client = NewClient(g.URL, user.Token, g.SkipVerify)
|
||||
id, err := GetProjectId(g, client, repo.Owner, repo.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -197,7 +213,7 @@ func (r *Gitlab) Activate(user *common.User, repo *common.Repo, k *common.Keypai
|
||||
|
||||
droneUrl := fmt.Sprintf("%s://%s", uri.Scheme, uri.Host)
|
||||
droneToken := uri.Query().Get("access_token")
|
||||
ssl_verify := strconv.FormatBool(!r.SkipVerify)
|
||||
ssl_verify := strconv.FormatBool(!g.SkipVerify)
|
||||
|
||||
return client.AddDroneService(id, map[string]string{
|
||||
"token": droneToken,
|
||||
@ -208,9 +224,9 @@ func (r *Gitlab) Activate(user *common.User, repo *common.Repo, k *common.Keypai
|
||||
|
||||
// Deactivate removes a repository by removing all the post-commit hooks
|
||||
// which are equal to link and removing the SSH deploy key.
|
||||
func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) error {
|
||||
var client = NewClient(r.URL, user.Token, r.SkipVerify)
|
||||
id, err := GetProjectId(r, client, repo.Owner, repo.Name)
|
||||
func (g *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) error {
|
||||
var client = NewClient(g.URL, user.Token, g.SkipVerify)
|
||||
id, err := GetProjectId(g, client, repo.Owner, repo.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -220,7 +236,7 @@ func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) e
|
||||
|
||||
// ParseHook parses the post-commit hook from the Request body
|
||||
// and returns the required data in a standard format.
|
||||
func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) {
|
||||
func (g *Gitlab) Hook(req *http.Request) (*common.Hook, error) {
|
||||
defer req.Body.Close()
|
||||
var payload, _ = ioutil.ReadAll(req.Body)
|
||||
var parsed, err = gogitlab.ParseHook(payload)
|
||||
@ -341,16 +357,16 @@ func (g *Gitlab) Oauth2Transport(r *http.Request) *oauth2.Transport {
|
||||
}
|
||||
|
||||
// Accessor method, to allowed remote organizations field.
|
||||
func (r *Gitlab) GetOrgs() []string {
|
||||
return r.AllowedOrgs
|
||||
func (g *Gitlab) GetOrgs() []string {
|
||||
return g.AllowedOrgs
|
||||
}
|
||||
|
||||
// Accessor method, to open field.
|
||||
func (r *Gitlab) GetOpen() bool {
|
||||
return r.Open
|
||||
func (g *Gitlab) GetOpen() bool {
|
||||
return g.Open
|
||||
}
|
||||
|
||||
// return default scope for GitHub
|
||||
func (r *Gitlab) Scope() string {
|
||||
func (g *Gitlab) Scope() string {
|
||||
return DefaultScope
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ type Remote interface {
|
||||
|
||||
// Netrc returns a .netrc file that can be used to clone
|
||||
// private repositories from a remote system.
|
||||
Netrc(u *types.User) (*types.Netrc, error)
|
||||
Netrc(u *types.User, r *types.Repo) (*types.Netrc, error)
|
||||
|
||||
// Activate activates a repository by creating the post-commit hook and
|
||||
// adding the SSH deploy key, if applicable.
|
||||
|
@ -166,7 +166,7 @@ func RunBuild(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
netrc, err := remote.Netrc(user)
|
||||
netrc, err := remote.Netrc(user, repo)
|
||||
if err != nil {
|
||||
c.Fail(500, err)
|
||||
return
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/drone/drone/pkg/hash"
|
||||
)
|
||||
|
||||
// RedirectSha accepts a request to retvie a redirect
|
||||
@ -78,7 +80,7 @@ func GetPullRequest(c *gin.Context) {
|
||||
repo := ToRepo(c)
|
||||
|
||||
// get the token and verify the hook is authorized
|
||||
if c.Request.FormValue("access_token") != hash(repo.FullName, repo.Hash) {
|
||||
if c.Request.FormValue("access_token") != hash.New(repo.FullName, repo.Hash) {
|
||||
c.AbortWithStatus(403)
|
||||
return
|
||||
}
|
||||
@ -117,7 +119,7 @@ func GetCommit(c *gin.Context) {
|
||||
sha := c.Params.ByName("sha")
|
||||
|
||||
// get the token and verify the hook is authorized
|
||||
if c.Request.FormValue("access_token") != hash(repo.FullName, repo.Hash) {
|
||||
if c.Request.FormValue("access_token") != hash.New(repo.FullName, repo.Hash) {
|
||||
c.AbortWithStatus(403)
|
||||
return
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus"
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin"
|
||||
"github.com/drone/drone/pkg/hash"
|
||||
"github.com/drone/drone/pkg/queue"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
"github.com/drone/drone/pkg/yaml"
|
||||
@ -56,7 +57,7 @@ func PostHook(c *gin.Context) {
|
||||
}
|
||||
|
||||
// get the token and verify the hook is authorized
|
||||
if c.Request.FormValue("access_token") != hash(repo.FullName, repo.Hash) {
|
||||
if c.Request.FormValue("access_token") != hash.New(repo.FullName, repo.Hash) {
|
||||
log.Errorf("invalid token sent with hook.")
|
||||
c.AbortWithStatus(403)
|
||||
return
|
||||
@ -128,7 +129,7 @@ func PostHook(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
netrc, err := remote.Netrc(user)
|
||||
netrc, err := remote.Netrc(user, repo)
|
||||
if err != nil {
|
||||
log.Errorf("failure to generate netrc for %s. %s", repo.FullName, err)
|
||||
c.Fail(500, err)
|
||||
|
@ -1,14 +1,13 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin"
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin/binding"
|
||||
|
||||
"github.com/drone/drone/pkg/hash"
|
||||
"github.com/drone/drone/pkg/remote"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
"github.com/drone/drone/pkg/utils/httputil"
|
||||
@ -209,7 +208,7 @@ func PostRepo(c *gin.Context) {
|
||||
link := fmt.Sprintf(
|
||||
"%s/api/hook?access_token=%s",
|
||||
httputil.GetURL(c.Request),
|
||||
hash(r.FullName, r.Hash),
|
||||
hash.New(r.FullName, r.Hash),
|
||||
)
|
||||
|
||||
// generate an RSA key and add to the repo
|
||||
@ -316,9 +315,3 @@ func perms(remote remote.Remote, u *common.User, r *common.Repo) *common.Perm {
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func hash(text, salt string) string {
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(text + salt))
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user