diff --git a/deepfence_server/auth/policy.csv b/deepfence_server/auth/policy.csv index 64967beccd..7b32bed286 100644 --- a/deepfence_server/auth/policy.csv +++ b/deepfence_server/auth/policy.csv @@ -1,9 +1,9 @@ -p, admin, standard-user, delete -p, admin, standard-user, write -p, admin, standard-user, read -p, standard-user, standard-user, write -p, standard-user, standard-user, read -p, read-only-user, standard-user, read +p, admin, user, delete +p, admin, user, write +p, admin, user, read +p, standard-user, user, write +p, standard-user, user, read +p, read-only-user, user, read p, admin, all-users, write p, admin, all-users, read @@ -14,8 +14,16 @@ p, admin, scan, stop p, standard-user, scan, start p, standard-user, scan, stop -p, admin, scan_report, delete -p, admin, scan_report, mask -p, admin, scan_report, unmask -p, standard-user, scan_report, mask -p, standard-user, scan_report, unmask \ No newline at end of file +p, admin, scan-report, delete +p, admin, scan-report, mask +p, admin, scan-report, unmask +p, admin, scan-report, ingest +p, standard-user, scan-report, mask +p, standard-user, scan-report, unmask +p, standard-user, scan-report, ingest + +p, admin, agent-report, ingest +p, standard-user, agent-report, ingest + +p, admin, cloud-report, ingest +p, standard-user, cloud-report, ingest \ No newline at end of file diff --git a/deepfence_server/handler/user.go b/deepfence_server/handler/user.go index fef38dc839..358ba6e91a 100644 --- a/deepfence_server/handler/user.go +++ b/deepfence_server/handler/user.go @@ -193,7 +193,7 @@ func (h *Handler) GetUserFromJWT(requestContext context.Context) (*model.User, i func (h *Handler) getIntFieldFromJwtClaim(claims map[string]interface{}, key string) (int64, error) { val, ok := claims[key] if !ok { - return 0, errors.New("cannot parse jwt") + return 0, errors.New(fmt.Sprintf("key %s not found in JWT claims", key)) } number, err := utils.InterfaceToInt(val) if err != nil { @@ -206,7 +206,7 @@ func (h *Handler) getIntFieldFromJwtClaim(claims map[string]interface{}, key str func (h *Handler) getStringFieldFromJwtClaim(claims map[string]interface{}, key string) (string, error) { val, ok := claims[key] if !ok { - return "", errors.New("cannot parse jwt") + return "", errors.New(fmt.Sprintf("key %s not found in JWT claims", key)) } return fmt.Sprintf("%v", val), nil } diff --git a/deepfence_server/router/router.go b/deepfence_server/router/router.go index c1ea655ee5..e6c7c63b7a 100644 --- a/deepfence_server/router/router.go +++ b/deepfence_server/router/router.go @@ -15,6 +15,26 @@ import ( "github.com/twmb/franz-go/pkg/kgo" ) +const ( + // API RBAC permissions + + PermissionRead = "read" + PermissionWrite = "write" + PermissionDelete = "delete" + PermissionIngest = "ingest" + PermissionStart = "start" + PermissionStop = "stop" + + // API RBAC Resources + + ResourceUser = "user" + ResourceAllUsers = "all-users" + ResourceAgentReport = "agent-report" + ResourceCloudReport = "cloud-report" + ResourceScanReport = "scan-report" + ResourceScan = "scan" +) + func SetupRoutes(r *chi.Mux, serverPort string, jwtSecret []byte, serveOpenapiDocs bool, ingestC chan *kgo.Record) error { // JWT tokenAuth := jwtauth.New("HS256", jwtSecret, nil) @@ -87,20 +107,20 @@ func SetupRoutes(r *chi.Mux, serverPort string, jwtSecret []byte, serveOpenapiDo openApiDocs.AddUserOperations() // current user r.Route("/user", func(r chi.Router) { - r.Get("/", dfHandler.AuthHandler("user", "read", dfHandler.GetUser)) - r.Put("/", dfHandler.AuthHandler("user", "write", dfHandler.UpdateUser)) - r.Delete("/", dfHandler.AuthHandler("user", "delete", dfHandler.DeleteUser)) + r.Get("/", dfHandler.AuthHandler(ResourceUser, PermissionRead, dfHandler.GetUser)) + r.Put("/", dfHandler.AuthHandler(ResourceUser, PermissionWrite, dfHandler.UpdateUser)) + r.Delete("/", dfHandler.AuthHandler(ResourceUser, PermissionDelete, dfHandler.DeleteUser)) }) r.Route("/api-token", func(r chi.Router) { - r.Get("/", dfHandler.AuthHandler("user", "read", dfHandler.GetApiTokens)) + r.Get("/", dfHandler.AuthHandler(ResourceUser, PermissionRead, dfHandler.GetApiTokens)) }) // manage other users r.Route("/users/{userId}", func(r chi.Router) { - r.Get("/", dfHandler.AuthHandler("all-users", "read", dfHandler.GetUser)) - r.Put("/", dfHandler.AuthHandler("all-users", "write", dfHandler.UpdateUser)) - r.Delete("/", dfHandler.AuthHandler("all-users", "delete", dfHandler.DeleteUser)) + r.Get("/", dfHandler.AuthHandler(ResourceAllUsers, PermissionRead, dfHandler.GetUser)) + r.Put("/", dfHandler.AuthHandler(ResourceAllUsers, PermissionWrite, dfHandler.UpdateUser)) + r.Delete("/", dfHandler.AuthHandler(ResourceAllUsers, PermissionDelete, dfHandler.DeleteUser)) }) openApiDocs.AddGraphOperations() @@ -111,27 +131,27 @@ func SetupRoutes(r *chi.Mux, serverPort string, jwtSecret []byte, serveOpenapiDo openApiDocs.AddIngestersOperations() r.Route("/ingest", func(r chi.Router) { - r.Post("/report", dfHandler.IngestAgentReport) - r.Post("/cloud-resources", dfHandler.IngestCloudResourcesReportHandler) + r.Post("/report", dfHandler.AuthHandler(ResourceAgentReport, PermissionIngest, dfHandler.IngestAgentReport)) + r.Post("/cloud-resources", dfHandler.AuthHandler(ResourceCloudReport, PermissionIngest, dfHandler.IngestCloudResourcesReportHandler)) // below api's write to kafka - r.Post("/cves", dfHandler.IngestCVEReportHandler) - r.Post("/secrets", dfHandler.IngestSecretReportHandler) - r.Post("/compliance", dfHandler.IngestComplianceReportHandler) - r.Post("/cloud-compliance", dfHandler.IngestCloudComplianceReportHandler) + r.Post("/cves", dfHandler.AuthHandler(ResourceScanReport, PermissionIngest, dfHandler.IngestCVEReportHandler)) + r.Post("/secrets", dfHandler.AuthHandler(ResourceScanReport, PermissionIngest, dfHandler.IngestSecretReportHandler)) + r.Post("/compliance", dfHandler.AuthHandler(ResourceScanReport, PermissionIngest, dfHandler.IngestComplianceReportHandler)) + r.Post("/cloud-compliance", dfHandler.AuthHandler(ResourceScanReport, PermissionIngest, dfHandler.IngestCloudComplianceReportHandler)) }) openApiDocs.AddScansOperations() r.Route("/scan/start", func(r chi.Router) { - r.Get("/vulnerability", dfHandler.AuthHandler("scan", "start", dfHandler.StartVulnerabilityScanHandler)) - r.Get("/secret", dfHandler.AuthHandler("scan", "start", dfHandler.StartSecretScanHandler)) - r.Get("/compliance", dfHandler.AuthHandler("scan", "start", dfHandler.StartComplianceScanHandler)) - r.Get("/malware", dfHandler.AuthHandler("scan", "start", dfHandler.StartMalwareScanHandler)) + r.Post("/vulnerability", dfHandler.AuthHandler(ResourceScan, PermissionStart, dfHandler.StartVulnerabilityScanHandler)) + r.Post("/secret", dfHandler.AuthHandler(ResourceScan, PermissionStart, dfHandler.StartSecretScanHandler)) + r.Post("/compliance", dfHandler.AuthHandler(ResourceScan, PermissionStart, dfHandler.StartComplianceScanHandler)) + r.Post("/malware", dfHandler.AuthHandler(ResourceScan, PermissionStart, dfHandler.StartMalwareScanHandler)) }) r.Route("/scan/stop", func(r chi.Router) { - r.Get("/vulnerability", dfHandler.AuthHandler("scan", "stop", dfHandler.StopVulnerabilityScanHandler)) - r.Get("/secret", dfHandler.AuthHandler("scan", "stop", dfHandler.StopSecretScanHandler)) - r.Get("/compliance", dfHandler.AuthHandler("scan", "stop", dfHandler.StopComplianceScanHandler)) - r.Get("/malware", dfHandler.AuthHandler("scan", "stop", dfHandler.StopMalwareScanHandler)) + r.Post("/vulnerability", dfHandler.AuthHandler(ResourceScan, PermissionStop, dfHandler.StopVulnerabilityScanHandler)) + r.Post("/secret", dfHandler.AuthHandler(ResourceScan, PermissionStop, dfHandler.StopSecretScanHandler)) + r.Post("/compliance", dfHandler.AuthHandler(ResourceScan, PermissionStop, dfHandler.StopComplianceScanHandler)) + r.Post("/malware", dfHandler.AuthHandler(ResourceScan, PermissionStop, dfHandler.StopMalwareScanHandler)) }) })