Skip to content

Commit

Permalink
fix(perm): allow workers with build tokens to access MustRead() for p…
Browse files Browse the repository at this point in the history
…rivate visibility repos (#776)

* fix(perm): allow workers with build tokens to access MustRead() for private visibility repos

* add error

* user -> subject
  • Loading branch information
ecrupper authored Mar 1, 2023
1 parent 32522bb commit 91f607a
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
16 changes: 16 additions & 0 deletions router/middleware/perm/perm.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ func MustWrite() gin.HandlerFunc {
// MustRead ensures the user has admin, write or read access to the repo.
func MustRead() gin.HandlerFunc {
return func(c *gin.Context) {
cl := claims.Retrieve(c)
o := org.Retrieve(c)
r := repo.Retrieve(c)
u := user.Retrieve(c)
Expand All @@ -437,8 +438,23 @@ func MustRead() gin.HandlerFunc {
return
}

// return if request is from worker with build token access
if strings.EqualFold(cl.TokenType, constants.WorkerBuildTokenType) {
b := build.Retrieve(c)
if cl.BuildID == b.GetID() {
return
}

retErr := fmt.Errorf("subject %s does not have 'read' permissions for repo %s", cl.Subject, r.GetFullName())

util.HandleError(c, http.StatusUnauthorized, retErr)

return
}

logger.Debugf("verifying user %s has 'read' permissions for repo %s", u.GetName(), r.GetFullName())

// return if user is platform admin
if u.GetAdmin() {
return
}
Expand Down
82 changes: 82 additions & 0 deletions router/middleware/perm/perm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,88 @@ func TestPerm_MustRead_PlatAdmin(t *testing.T) {
}
}

func TestPerm_MustRead_WorkerBuildToken(t *testing.T) {
// setup types
secret := "superSecret"

tm := &token.Manager{
PrivateKey: "123abc",
SignMethod: jwt.SigningMethodHS256,
UserAccessTokenDuration: time.Minute * 5,
UserRefreshTokenDuration: time.Minute * 30,
}

r := new(library.Repo)
r.SetID(1)
r.SetUserID(1)
r.SetHash("baz")
r.SetOrg("foo")
r.SetName("bar")
r.SetFullName("foo/bar")
r.SetVisibility("private")

b := new(library.Build)
b.SetID(1)
b.SetRepoID(1)
b.SetNumber(1)

mto := &token.MintTokenOpts{
Hostname: "worker",
TokenDuration: time.Minute * 35,
TokenType: constants.WorkerBuildTokenType,
BuildID: 1,
Repo: "foo/bar",
}

tok, _ := tm.MintToken(mto)

// setup context
gin.SetMode(gin.TestMode)

resp := httptest.NewRecorder()
context, engine := gin.CreateTestContext(resp)

// setup database
db, _ := sqlite.NewTest()

defer func() {
db.Sqlite.Exec("delete from builds")
db.Sqlite.Exec("delete from repos;")
_sql, _ := db.Sqlite.DB()
_sql.Close()
}()

_ = db.CreateBuild(b)
_ = db.CreateRepo(r)

context.Request, _ = http.NewRequest(http.MethodGet, "/test/foo/bar/builds/1", nil)
context.Request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", tok))

// setup vela mock server
engine.Use(func(c *gin.Context) { c.Set("secret", secret) })
engine.Use(func(c *gin.Context) { c.Set("token-manager", tm) })
engine.Use(func(c *gin.Context) { database.ToContext(c, db) })
engine.Use(claims.Establish())
engine.Use(user.Establish())
engine.Use(org.Establish())
engine.Use(repo.Establish())
engine.Use(build.Establish())
engine.Use(MustRead())
engine.GET("/test/:org/:repo/builds/:build", func(c *gin.Context) {
c.Status(http.StatusOK)
})

s1 := httptest.NewServer(engine)
defer s1.Close()

// run test
engine.ServeHTTP(context.Writer, context.Request)

if resp.Code != http.StatusOK {
t.Errorf("MustRead returned %v, want %v", resp.Code, http.StatusOK)
}
}

func TestPerm_MustRead_RepoAdmin(t *testing.T) {
// setup types
secret := "superSecret"
Expand Down

0 comments on commit 91f607a

Please sign in to comment.