mirror of
https://github.com/gogs/gogs.git
synced 2025-12-20 23:30:00 +01:00
Check deploy keys when Gogs is run with Service.RequireSignInView=true (#4078)
* Check deploy keys when Gogs is run with require_sign_in_view Check if the deploy key can access to a repository. A deploy key doesn't represent an gogs user, so in a site with Service.RequireSignInView activated we should give read access only in the repositories where this deploy key is in use. In other case, a deploy service or system using an active deploy key can get read access to all the repositories in a Gogs service. * Refactoring: Comments starts in a new line * Minor change in a comment * Code cleaning. Replace spaces with tabs
This commit is contained in:
70
cmd/serve.go
70
cmd/serve.go
@@ -41,6 +41,7 @@ var CmdServ = cli.Command{
|
|||||||
|
|
||||||
func setup(logPath string) {
|
func setup(logPath string) {
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
|
setting.NewService()
|
||||||
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
|
||||||
|
|
||||||
models.LoadConfigs()
|
models.LoadConfigs()
|
||||||
@@ -61,6 +62,37 @@ func parseCmd(cmd string) (string, string) {
|
|||||||
return ss[0], strings.Replace(ss[1], "'/", "'", 1)
|
return ss[0], strings.Replace(ss[1], "'/", "'", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getKey(cmdKey string) *models.PublicKey {
|
||||||
|
keys := strings.Split(cmdKey, "-")
|
||||||
|
if len(keys) != 2 {
|
||||||
|
fail("Key ID format error", "Invalid key argument: %s", cmdKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
|
||||||
|
if err != nil {
|
||||||
|
fail("Invalid key ID", "Invalid key ID[%s]: %v", cmdKey, err)
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkDeployKey(key *models.PublicKey, repo *models.Repository) {
|
||||||
|
// Check if this deploy key belongs to current repository.
|
||||||
|
if !models.HasDeployKey(key.ID, repo.ID) {
|
||||||
|
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update deploy key activity.
|
||||||
|
deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
fail("Internal error", "GetDeployKey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
deployKey.Updated = time.Now()
|
||||||
|
if err = models.UpdateDeployKey(deployKey); err != nil {
|
||||||
|
fail("Internal error", "UpdateDeployKey: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
allowedCommands = map[string]models.AccessMode{
|
allowedCommands = map[string]models.AccessMode{
|
||||||
"git-upload-pack": models.ACCESS_MODE_READ,
|
"git-upload-pack": models.ACCESS_MODE_READ,
|
||||||
@@ -199,38 +231,15 @@ func runServ(c *cli.Context) error {
|
|||||||
keyID int64
|
keyID int64
|
||||||
user *models.User
|
user *models.User
|
||||||
)
|
)
|
||||||
|
key := getKey(c.Args()[0])
|
||||||
|
keyID = key.ID
|
||||||
if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
|
if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate {
|
||||||
keys := strings.Split(c.Args()[0], "-")
|
|
||||||
if len(keys) != 2 {
|
|
||||||
fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
|
|
||||||
if err != nil {
|
|
||||||
fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
|
|
||||||
}
|
|
||||||
keyID = key.ID
|
|
||||||
|
|
||||||
// Check deploy key or user key.
|
// Check deploy key or user key.
|
||||||
if key.Type == models.KEY_TYPE_DEPLOY {
|
if key.Type == models.KEY_TYPE_DEPLOY {
|
||||||
if key.Mode < requestedMode {
|
if key.Mode < requestedMode {
|
||||||
fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
|
fail("Key permission denied", "Cannot push with deployment key: %d", key.ID)
|
||||||
}
|
}
|
||||||
// Check if this deploy key belongs to current repository.
|
checkDeployKey(key, repo)
|
||||||
if !models.HasDeployKey(key.ID, repo.ID) {
|
|
||||||
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update deploy key activity.
|
|
||||||
deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.ID)
|
|
||||||
if err != nil {
|
|
||||||
fail("Internal error", "GetDeployKey: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
deployKey.Updated = time.Now()
|
|
||||||
if err = models.UpdateDeployKey(deployKey); err != nil {
|
|
||||||
fail("Internal error", "UpdateDeployKey: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
user, err = models.GetUserByKeyID(key.ID)
|
user, err = models.GetUserByKeyID(key.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -250,6 +259,15 @@ func runServ(c *cli.Context) error {
|
|||||||
user.Name, requestedMode, repoPath)
|
user.Name, requestedMode, repoPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// if public and read ...
|
||||||
|
// Check if the key can access to the repository in case of it is a deploy key (a deploy keys != user key).
|
||||||
|
// A deploy key doesn't represent a signed in user, so in a site with Service.RequireSignInView activated
|
||||||
|
// we should give read access only in repositories where this deploy key is in use. In other case, a server
|
||||||
|
// or system using an active deploy key can get read access to all the repositories in a Gogs service.
|
||||||
|
if key.Type == models.KEY_TYPE_DEPLOY && setting.Service.RequireSignInView {
|
||||||
|
checkDeployKey(key, repo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := gouuid.NewV4().String()
|
uuid := gouuid.NewV4().String()
|
||||||
|
|||||||
@@ -806,6 +806,10 @@ func newWebhookService() {
|
|||||||
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
|
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewService() {
|
||||||
|
newService()
|
||||||
|
}
|
||||||
|
|
||||||
func NewServices() {
|
func NewServices() {
|
||||||
newService()
|
newService()
|
||||||
newLogService()
|
newLogService()
|
||||||
|
|||||||
Reference in New Issue
Block a user