Skip to content

Commit 91f607a

Browse files
authored
fix(perm): allow workers with build tokens to access MustRead() for private visibility repos (#776)
* fix(perm): allow workers with build tokens to access MustRead() for private visibility repos * add error * user -> subject
1 parent 32522bb commit 91f607a

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

router/middleware/perm/perm.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ func MustWrite() gin.HandlerFunc {
417417
// MustRead ensures the user has admin, write or read access to the repo.
418418
func MustRead() gin.HandlerFunc {
419419
return func(c *gin.Context) {
420+
cl := claims.Retrieve(c)
420421
o := org.Retrieve(c)
421422
r := repo.Retrieve(c)
422423
u := user.Retrieve(c)
@@ -437,8 +438,23 @@ func MustRead() gin.HandlerFunc {
437438
return
438439
}
439440

441+
// return if request is from worker with build token access
442+
if strings.EqualFold(cl.TokenType, constants.WorkerBuildTokenType) {
443+
b := build.Retrieve(c)
444+
if cl.BuildID == b.GetID() {
445+
return
446+
}
447+
448+
retErr := fmt.Errorf("subject %s does not have 'read' permissions for repo %s", cl.Subject, r.GetFullName())
449+
450+
util.HandleError(c, http.StatusUnauthorized, retErr)
451+
452+
return
453+
}
454+
440455
logger.Debugf("verifying user %s has 'read' permissions for repo %s", u.GetName(), r.GetFullName())
441456

457+
// return if user is platform admin
442458
if u.GetAdmin() {
443459
return
444460
}

router/middleware/perm/perm_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,88 @@ func TestPerm_MustRead_PlatAdmin(t *testing.T) {
17191719
}
17201720
}
17211721

1722+
func TestPerm_MustRead_WorkerBuildToken(t *testing.T) {
1723+
// setup types
1724+
secret := "superSecret"
1725+
1726+
tm := &token.Manager{
1727+
PrivateKey: "123abc",
1728+
SignMethod: jwt.SigningMethodHS256,
1729+
UserAccessTokenDuration: time.Minute * 5,
1730+
UserRefreshTokenDuration: time.Minute * 30,
1731+
}
1732+
1733+
r := new(library.Repo)
1734+
r.SetID(1)
1735+
r.SetUserID(1)
1736+
r.SetHash("baz")
1737+
r.SetOrg("foo")
1738+
r.SetName("bar")
1739+
r.SetFullName("foo/bar")
1740+
r.SetVisibility("private")
1741+
1742+
b := new(library.Build)
1743+
b.SetID(1)
1744+
b.SetRepoID(1)
1745+
b.SetNumber(1)
1746+
1747+
mto := &token.MintTokenOpts{
1748+
Hostname: "worker",
1749+
TokenDuration: time.Minute * 35,
1750+
TokenType: constants.WorkerBuildTokenType,
1751+
BuildID: 1,
1752+
Repo: "foo/bar",
1753+
}
1754+
1755+
tok, _ := tm.MintToken(mto)
1756+
1757+
// setup context
1758+
gin.SetMode(gin.TestMode)
1759+
1760+
resp := httptest.NewRecorder()
1761+
context, engine := gin.CreateTestContext(resp)
1762+
1763+
// setup database
1764+
db, _ := sqlite.NewTest()
1765+
1766+
defer func() {
1767+
db.Sqlite.Exec("delete from builds")
1768+
db.Sqlite.Exec("delete from repos;")
1769+
_sql, _ := db.Sqlite.DB()
1770+
_sql.Close()
1771+
}()
1772+
1773+
_ = db.CreateBuild(b)
1774+
_ = db.CreateRepo(r)
1775+
1776+
context.Request, _ = http.NewRequest(http.MethodGet, "/test/foo/bar/builds/1", nil)
1777+
context.Request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", tok))
1778+
1779+
// setup vela mock server
1780+
engine.Use(func(c *gin.Context) { c.Set("secret", secret) })
1781+
engine.Use(func(c *gin.Context) { c.Set("token-manager", tm) })
1782+
engine.Use(func(c *gin.Context) { database.ToContext(c, db) })
1783+
engine.Use(claims.Establish())
1784+
engine.Use(user.Establish())
1785+
engine.Use(org.Establish())
1786+
engine.Use(repo.Establish())
1787+
engine.Use(build.Establish())
1788+
engine.Use(MustRead())
1789+
engine.GET("/test/:org/:repo/builds/:build", func(c *gin.Context) {
1790+
c.Status(http.StatusOK)
1791+
})
1792+
1793+
s1 := httptest.NewServer(engine)
1794+
defer s1.Close()
1795+
1796+
// run test
1797+
engine.ServeHTTP(context.Writer, context.Request)
1798+
1799+
if resp.Code != http.StatusOK {
1800+
t.Errorf("MustRead returned %v, want %v", resp.Code, http.StatusOK)
1801+
}
1802+
}
1803+
17221804
func TestPerm_MustRead_RepoAdmin(t *testing.T) {
17231805
// setup types
17241806
secret := "superSecret"

0 commit comments

Comments
 (0)