mirror of
https://github.com/harness/drone.git
synced 2025-05-12 06:59:54 +08:00
hooks are protected with signed sha
This commit is contained in:
parent
64cc684295
commit
6fcae7d80a
@ -1,8 +1,10 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TokenUser = "u"
|
TokenUser = "u"
|
||||||
TokenSess = "s"
|
TokenSess = "s"
|
||||||
|
TokenHook = "h"
|
||||||
|
TokenAgent = "a"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
|
@ -64,6 +64,12 @@ func push(t *bolt.Tx, bucket, index, value []byte) error {
|
|||||||
if err != nil && err != ErrKeyNotFound {
|
if err != nil && err != ErrKeyNotFound {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// we shouldn't add a key that already exists
|
||||||
|
for _, key := range keys {
|
||||||
|
if bytes.Equal(key, value) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
keys = append(keys, value)
|
keys = append(keys, value)
|
||||||
return update(t, bucket, index, &keys)
|
return update(t, bucket, index, &keys)
|
||||||
}
|
}
|
||||||
|
2
drone.go
2
drone.go
@ -42,12 +42,12 @@ func main() {
|
|||||||
api.Use(server.SetRemote(remote))
|
api.Use(server.SetRemote(remote))
|
||||||
api.Use(server.SetQueue(queue.New()))
|
api.Use(server.SetQueue(queue.New()))
|
||||||
api.Use(server.SetSettings(settings))
|
api.Use(server.SetSettings(settings))
|
||||||
|
api.Use(server.SetSession(session))
|
||||||
api.Use(server.SetUser(session))
|
api.Use(server.SetUser(session))
|
||||||
|
|
||||||
user := api.Group("/user")
|
user := api.Group("/user")
|
||||||
{
|
{
|
||||||
user.Use(server.MustUser())
|
user.Use(server.MustUser())
|
||||||
user.Use(server.SetSession(session))
|
|
||||||
|
|
||||||
user.GET("", server.GetUserCurr)
|
user.GET("", server.GetUserCurr)
|
||||||
user.PATCH("", server.PutUserCurr)
|
user.PATCH("", server.PutUserCurr)
|
||||||
|
@ -172,7 +172,7 @@ func GetHook(client *github.Client, owner, name, url string) (*github.Hook, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
if hook.Config["url"] == url {
|
if strings.HasPrefix(hook.Config["url"].(string), url) {
|
||||||
return &hook, nil
|
return &hook, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,6 +255,9 @@ func DeleteKey(client *github.Client, owner, name, title string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if k == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
_, err = client.Repositories.DeleteKey(owner, name, *k.ID)
|
_, err = client.Repositories.DeleteKey(owner, name, *k.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ func PostHook(c *gin.Context) {
|
|||||||
remote := ToRemote(c)
|
remote := ToRemote(c)
|
||||||
store := ToDatastore(c)
|
store := ToDatastore(c)
|
||||||
queue_ := ToQueue(c)
|
queue_ := ToQueue(c)
|
||||||
|
sess := ToSession(c)
|
||||||
|
|
||||||
hook, err := remote.Hook(c.Request)
|
hook, err := remote.Hook(c.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -38,6 +39,14 @@ func PostHook(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the token and verify the hook is authorized
|
||||||
|
token := sess.GetLogin(c.Request)
|
||||||
|
if token == nil || token.Label != hook.Repo.FullName {
|
||||||
|
log.Errorf("invalid token sent with hook.")
|
||||||
|
c.AbortWithStatus(403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// a build may be skipped if the text [CI SKIP]
|
// a build may be skipped if the text [CI SKIP]
|
||||||
// is found inside the commit message
|
// is found inside the commit message
|
||||||
if hook.Commit != nil && strings.Contains(hook.Commit.Message, "[CI SKIP]") {
|
if hook.Commit != nil && strings.Contains(hook.Commit.Message, "[CI SKIP]") {
|
||||||
|
@ -166,15 +166,11 @@ func DeleteRepo(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
func PostRepo(c *gin.Context) {
|
func PostRepo(c *gin.Context) {
|
||||||
user := ToUser(c)
|
user := ToUser(c)
|
||||||
|
sess := ToSession(c)
|
||||||
store := ToDatastore(c)
|
store := ToDatastore(c)
|
||||||
owner := c.Params.ByName("owner")
|
owner := c.Params.ByName("owner")
|
||||||
name := c.Params.ByName("name")
|
name := c.Params.ByName("name")
|
||||||
|
|
||||||
link := fmt.Sprintf(
|
|
||||||
"%s/api/hook",
|
|
||||||
httputil.GetURL(c.Request),
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(bradrydzewski) verify repo not exists
|
// TODO(bradrydzewski) verify repo not exists
|
||||||
|
|
||||||
// get the repository and user permissions
|
// get the repository and user permissions
|
||||||
@ -194,6 +190,21 @@ func PostRepo(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token := &common.Token{}
|
||||||
|
token.Kind = common.TokenHook
|
||||||
|
token.Label = r.FullName
|
||||||
|
tokenstr, err := sess.GenerateToken(token)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
link := fmt.Sprintf(
|
||||||
|
"%s/api/hook?access_token=%s",
|
||||||
|
httputil.GetURL(c.Request),
|
||||||
|
tokenstr,
|
||||||
|
)
|
||||||
|
|
||||||
// set the repository owner to the
|
// set the repository owner to the
|
||||||
// currently authenticated user.
|
// currently authenticated user.
|
||||||
r.User = &common.Owner{Login: user.Login}
|
r.User = &common.Owner{Login: user.Login}
|
||||||
|
@ -125,7 +125,7 @@ func SetUser(s session.Session) gin.HandlerFunc {
|
|||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
ds := ToDatastore(c)
|
ds := ToDatastore(c)
|
||||||
token := s.GetLogin(c.Request)
|
token := s.GetLogin(c.Request)
|
||||||
if token == nil {
|
if token == nil || len(token.Login) == 0 {
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -137,7 +137,8 @@ func SetUser(s session.Session) gin.HandlerFunc {
|
|||||||
|
|
||||||
// if session token we can proceed, otherwise
|
// if session token we can proceed, otherwise
|
||||||
// we should validate the token hasn't been revoked
|
// we should validate the token hasn't been revoked
|
||||||
if token.Kind == common.TokenSess {
|
switch token.Kind {
|
||||||
|
case common.TokenSess:
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/drone/drone/common"
|
"github.com/drone/drone/common"
|
||||||
"github.com/drone/drone/settings"
|
"github.com/drone/drone/settings"
|
||||||
"github.com/gorilla/securecookie"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Session interface {
|
type Session interface {
|
||||||
@ -22,12 +21,8 @@ type session struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(s *settings.Session) Session {
|
func New(s *settings.Session) Session {
|
||||||
// TODO (bradrydzewski) hook up the Session.Expires
|
|
||||||
secret := []byte(s.Secret)
|
secret := []byte(s.Secret)
|
||||||
expire := time.Hour * 72
|
expire := time.Hour * 72
|
||||||
if len(secret) == 0 {
|
|
||||||
securecookie.GenerateRandomKey(32)
|
|
||||||
}
|
|
||||||
return &session{
|
return &session{
|
||||||
secret: secret,
|
secret: secret,
|
||||||
expire: expire,
|
expire: expire,
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import "github.com/BurntSushi/toml"
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Service represents the configuration details required
|
// Service represents the configuration details required
|
||||||
// to connect to the revision control system (ie GitHub, Bitbucket)
|
// to connect to the revision control system (ie GitHub, Bitbucket)
|
||||||
@ -108,7 +106,7 @@ type Settings struct {
|
|||||||
func Parse(path string) (*Settings, error) {
|
func Parse(path string) (*Settings, error) {
|
||||||
s := &Settings{}
|
s := &Settings{}
|
||||||
_, err := toml.DecodeFile(path, s)
|
_, err := toml.DecodeFile(path, s)
|
||||||
return s, err
|
return applyDefaults(s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseString parses the Drone settings string and unmarshals
|
// ParseString parses the Drone settings string and unmarshals
|
||||||
@ -116,5 +114,18 @@ func Parse(path string) (*Settings, error) {
|
|||||||
func ParseString(data string) (*Settings, error) {
|
func ParseString(data string) (*Settings, error) {
|
||||||
s := &Settings{}
|
s := &Settings{}
|
||||||
_, err := toml.Decode(data, s)
|
_, err := toml.Decode(data, s)
|
||||||
return s, err
|
return applyDefaults(s), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyDefaults(s *Settings) *Settings {
|
||||||
|
if s.Session == nil {
|
||||||
|
s.Session = &Session{}
|
||||||
|
}
|
||||||
|
// if no session token is provided we can
|
||||||
|
// instead use the client secret to sign
|
||||||
|
// our sessions and tokens.
|
||||||
|
if len(s.Session.Secret) == 0 {
|
||||||
|
s.Session.Secret = s.Service.OAuth.Secret
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user