| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- package acl
- import (
- "context"
- config "github.com/OliveTin/OliveTin/internal/config"
- log "github.com/sirupsen/logrus"
- "golang.org/x/exp/slices"
- "google.golang.org/grpc/metadata"
- )
- // User respresents a person.
- type AuthenticatedUser struct {
- Username string
- Usergroup string
- acls []string
- }
- // 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,
- }).Debug("isAllowedExec - Matched ACL")
- return true
- }
- }
- log.WithFields(log.Fields{
- "User": user.Username,
- "Action": action.Title,
- }).Debug("isAllowedExec - No ACLs matched")
- return cfg.DefaultPermissions.Exec
- }
- // IsAllowedView checks if a User is allowed to view an Action
- func IsAllowedView(cfg *config.Config, user *AuthenticatedUser, action *config.Action) bool {
- 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,
- }).Debug("isAllowedView - Matched ACL")
- return true
- }
- }
- log.WithFields(log.Fields{
- "User": user.Username,
- "Action": action.Title,
- }).Debug("isAllowedView - No ACLs matched")
- return cfg.DefaultPermissions.View
- }
- func getMetdataKeyOrEmpty(md metadata.MD, key string) string {
- mdValues := md.Get(key)
- if len(mdValues) > 0 {
- return mdValues[0]
- }
- return ""
- }
- // UserFromContext tries to find a user from a grpc context
- func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser {
- md, ok := metadata.FromIncomingContext(ctx)
- ret := &AuthenticatedUser{}
- if ok {
- ret.Username = getMetdataKeyOrEmpty(md, "username")
- ret.Usergroup = getMetdataKeyOrEmpty(md, "usergroup")
- }
- buildUserAcls(cfg, ret)
- log.WithFields(log.Fields{
- "username": ret.Username,
- "usergroup": ret.Usergroup,
- }).Infof("UserFromContext")
- return ret
- }
- func buildUserAcls(cfg *config.Config, user *AuthenticatedUser) {
- for _, acl := range cfg.AccessControlLists {
- if slices.Contains(acl.MatchUsernames, user.Username) {
- user.acls = append(user.acls, acl.Name)
- continue
- }
- if slices.Contains(acl.MatchUsergroups, user.Usergroup) {
- user.acls = append(user.acls, acl.Name)
- continue
- }
- }
- }
- func isACLRelevant(cfg *config.Config, actionAcls []string, acl config.AccessControlList, user *AuthenticatedUser) bool {
- if !slices.Contains(user.acls, acl.Name) {
- return false
- }
- if acl.AddToEveryAction {
- return true
- }
- if slices.Contains(actionAcls, acl.Name) {
- return true
- }
- return false
- }
- func getRelevantAcls(cfg *config.Config, actionAcls []string, user *AuthenticatedUser) []*config.AccessControlList {
- var ret []*config.AccessControlList
- for _, acl := range cfg.AccessControlLists {
- if isACLRelevant(cfg, actionAcls, acl, user) {
- ret = append(ret, &acl)
- }
- }
- return ret
- }
|