Skip to content

Commit

Permalink
Simple RBAC solution for the admin API
Browse files Browse the repository at this point in the history
  • Loading branch information
jbygdell committed Nov 4, 2024
1 parent bc01890 commit a5e1882
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 67 deletions.
43 changes: 32 additions & 11 deletions sda/cmd/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,16 @@ func setup(config *config.Config) *http.Server {
r.GET("/ready", readinessResponse)
r.GET("/files", getFiles)
// admin endpoints below here
if len(config.API.Admins) > 0 {
r.POST("/file/ingest", isAdmin(), ingestFile) // start ingestion of a file
r.POST("/file/accession", isAdmin(), setAccession) // assign accession ID to a file
r.POST("/dataset/create", isAdmin(), createDataset) // maps a set of files to a dataset
r.POST("/dataset/release/*dataset", isAdmin(), releaseDataset) // Releases a dataset to be accessible
r.POST("/c4gh-keys/add", isAdmin(), addC4ghHash) // Adds a key hash to the database
r.GET("/users", isAdmin(), listActiveUsers) // Lists all users
r.GET("/users/:username/files", isAdmin(), listUserFiles) // Lists all unmapped files for a user
if len(config.API.RBAC.Admin) > 0 || len(config.API.RBAC.Helpdesk) > 0 {
r.POST("/file/ingest", rbac([]string{"admin", "helpdesk"}), ingestFile) // start ingestion of a file
r.POST("/file/accession", rbac([]string{"admin", "helpdesk"}), setAccession) // assign accession ID to a file
r.POST("/dataset/create", rbac([]string{"admin", "helpdesk"}), createDataset) // maps a set of files to a dataset
r.POST("/dataset/release/*dataset", rbac([]string{"admin", "helpdesk"}), releaseDataset) // Releases a dataset to be accessible
r.GET("/users", rbac([]string{"admin", "helpdesk"}), listActiveUsers) // Lists all users
r.GET("/users/:username/files", rbac([]string{"admin", "helpdesk"}), listUserFiles) // Lists all unmapped files for a user
}
if len(config.API.RBAC.Admin) > 0 {
r.POST("/c4gh-keys/add", rbac([]string{"admin"}), addC4ghHash) // Adds a key hash to the database
}

cfg := &tls.Config{MinVersion: tls.VersionTLS12}
Expand Down Expand Up @@ -195,7 +197,7 @@ func getFiles(c *gin.Context) {
c.JSON(200, files)
}

func isAdmin() gin.HandlerFunc {
func rbac(roles []string) gin.HandlerFunc {
return func(c *gin.Context) {
token, err := auth.Authenticate(c.Request)
if err != nil {
Expand All @@ -204,8 +206,27 @@ func isAdmin() gin.HandlerFunc {

return
}
if !slices.Contains(Conf.API.Admins, token.Subject()) {
log.Debugf("%s is not an admin", token.Subject())

authorized := false
for _, role := range roles {
switch {
case role == "admin":
if slices.Contains(Conf.API.RBAC.Admin, token.Subject()) {
authorized = true

break
}
case role == "helpdesk":
if slices.Contains(Conf.API.RBAC.Helpdesk, token.Subject()) {
authorized = true

break
}
}
}

if !authorized {
log.Debugf("%s is not in the list of allowed users", token.Subject())
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "not authorized"})

return
Expand Down
Loading

0 comments on commit a5e1882

Please sign in to comment.