Explorar o código

feature: #135 Permissions for logs (#273)

James Read %!s(int64=2) %!d(string=hai) anos
pai
achega
db5de9be97
Modificáronse 3 ficheiros con 51 adicións e 21 borrados
  1. 38 18
      internal/acl/acl.go
  2. 4 0
      internal/config/config.go
  3. 9 3
      internal/grpcapi/grpcApi.go

+ 38 - 18
internal/acl/acl.go

@@ -17,24 +17,51 @@ type AuthenticatedUser struct {
 	acls []string
 }
 
+func logAclNotMatched(cfg *config.Config, aclFunction string, user *AuthenticatedUser, action *config.Action) {
+	if cfg.LogDebugOptions.AclNotMatched {
+		log.WithFields(log.Fields{
+			"User":   user.Username,
+			"Action": action.Title,
+		}).Debugf("%v - No ACLs Matched", aclFunction)
+	}
+}
+
+func logAclMatched(cfg *config.Config, aclFunction string, user *AuthenticatedUser, action *config.Action, acl *config.AccessControlList) {
+	if cfg.LogDebugOptions.AclMatched {
+		log.WithFields(log.Fields{
+			"User":   user.Username,
+			"Action": action.Title,
+			"ACL":    acl.Name,
+		}).Debugf("%v - Matched ACL", aclFunction)
+	}
+}
+
+// IsAllowedLogs checks if a AuthenticatedUser is allowed to view an action's logs
+func IsAllowedLogs(cfg *config.Config, user *AuthenticatedUser, action *config.Action) bool {
+	for _, acl := range getRelevantAcls(cfg, action.Acls, user) {
+		if acl.Permissions.Logs {
+			logAclMatched(cfg, "isAllowedLogs", user, action, acl)
+
+			return true
+		}
+	}
+
+	logAclNotMatched(cfg, "isAllowedLogs", user, action)
+
+	return cfg.DefaultPermissions.Logs
+}
+
 // IsAllowedExec checks if a AuthenticatedUser is allowed to execute an Action
 func IsAllowedExec(cfg *config.Config, user *AuthenticatedUser, action *config.Action) bool {
 	for _, acl := range getRelevantAcls(cfg, action.Acls, user) {
 		if acl.Permissions.Exec {
-			log.WithFields(log.Fields{
-				"User":   user.Username,
-				"Action": action.Title,
-				"ACL":    acl.Name,
-			}).Trace("isAllowedExec - Matched ACL")
+			logAclMatched(cfg, "isAllowedExec", user, action, acl)
 
 			return true
 		}
 	}
 
-	log.WithFields(log.Fields{
-		"User":   user.Username,
-		"Action": action.Title,
-	}).Trace("isAllowedExec - No ACLs matched")
+	logAclNotMatched(cfg, "isAllowedExec", user, action)
 
 	return cfg.DefaultPermissions.Exec
 }
@@ -47,20 +74,13 @@ func IsAllowedView(cfg *config.Config, user *AuthenticatedUser, action *config.A
 
 	for _, acl := range getRelevantAcls(cfg, action.Acls, user) {
 		if acl.Permissions.View {
-			log.WithFields(log.Fields{
-				"User":   user.Username,
-				"Action": action.Title,
-				"ACL":    acl.Name,
-			}).Trace("isAllowedView - Matched ACL")
+			logAclMatched(cfg, "isAllowedView", user, action, acl)
 
 			return true
 		}
 	}
 
-	log.WithFields(log.Fields{
-		"User":   user.Username,
-		"Action": action.Title,
-	}).Trace("isAllowedView - No ACLs matched")
+	logAclNotMatched(cfg, "isAllowedView", user, action)
 
 	return cfg.DefaultPermissions.View
 }

+ 4 - 0
internal/config/config.go

@@ -53,6 +53,7 @@ type EntityFile struct {
 type PermissionsList struct {
 	View bool
 	Exec bool
+	Logs bool
 }
 
 // AccessControlList defines what permissions apply to a user or user group.
@@ -117,6 +118,8 @@ type Config struct {
 type LogDebugOptions struct {
 	SingleFrontendRequests       bool
 	SingleFrontendRequestHeaders bool
+	AclMatched                   bool
+	AclNotMatched                bool
 }
 
 type DashboardComponent struct {
@@ -144,6 +147,7 @@ func DefaultConfig() *Config {
 	config.CheckForUpdates = true
 	config.DefaultPermissions.Exec = true
 	config.DefaultPermissions.View = true
+	config.DefaultPermissions.Logs = true
 	config.AuthJwtClaimUsername = "name"
 	config.AuthJwtClaimUserGroup = "group"
 	config.WebUIDir = "./webui"

+ 9 - 3
internal/grpcapi/grpcApi.go

@@ -227,15 +227,21 @@ func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashb
 }
 
 func (api *oliveTinAPI) GetLogs(ctx ctx.Context, req *pb.GetLogsRequest) (*pb.GetLogsResponse, error) {
+	user := acl.UserFromContext(ctx, cfg)
+
 	ret := &pb.GetLogsResponse{}
 
 	// TODO Limit to 10 entries or something to prevent browser lag.
 
 	for trackingId, logEntry := range api.executor.Logs {
-		pbLogEntry := internalLogEntryToPb(logEntry)
-		pbLogEntry.ExecutionTrackingId = trackingId
+		action := cfg.FindAction(logEntry.ActionTitle)
 
-		ret.Logs = append(ret.Logs, pbLogEntry)
+		if action == nil || acl.IsAllowedLogs(cfg, user, action) {
+			pbLogEntry := internalLogEntryToPb(logEntry)
+			pbLogEntry.ExecutionTrackingId = trackingId
+
+			ret.Logs = append(ret.Logs, pbLogEntry)
+		}
 	}
 
 	sorter := func(i, j int) bool {