github.com/greenpau/go-authcrunch@v1.1.4/pkg/acl/acl.go (about) 1 // Copyright 2022 Paul Greenberg greenpau@outlook.com 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package acl 16 17 import ( 18 "context" 19 "go.uber.org/zap" 20 ) 21 22 // AccessList is a collection of access list rules. 23 type AccessList struct { 24 config []*RuleConfiguration 25 rules []aclRule 26 logger *zap.Logger 27 defaultAllow bool 28 } 29 30 // NewAccessList returns an instance of AccessList. 31 func NewAccessList() *AccessList { 32 return &AccessList{ 33 rules: []aclRule{}, 34 } 35 } 36 37 // GetRules returns configured ACL rules. 38 func (acl *AccessList) GetRules() []*RuleConfiguration { 39 return acl.config 40 } 41 42 // SetDefaultAllowAction sets default allow for the AccessList, 43 // i.e. the AccessList fails open. 44 func (acl *AccessList) SetDefaultAllowAction() { 45 acl.defaultAllow = true 46 } 47 48 // SetLogger adds a logger to AccessList. 49 func (acl *AccessList) SetLogger(logger *zap.Logger) { 50 acl.logger = logger 51 } 52 53 // AddRules adds multiple rules to AccessList. 54 func (acl *AccessList) AddRules(ctx context.Context, cfgs []*RuleConfiguration) error { 55 for _, cfg := range cfgs { 56 if err := acl.AddRule(ctx, cfg); err != nil { 57 return err 58 } 59 } 60 return nil 61 } 62 63 // AddRule adds a rule to AccessList. 64 func (acl *AccessList) AddRule(ctx context.Context, cfg *RuleConfiguration) error { 65 rule, err := newACLRule(ctx, len(acl.rules), cfg, acl.logger) 66 if err != nil { 67 return err 68 } 69 acl.config = append(acl.config, cfg) 70 acl.rules = append(acl.rules, rule) 71 return nil 72 } 73 74 // AsMap returns acl configuration as map. 75 func (acl *AccessList) AsMap() map[string]interface{} { 76 m := make(map[string]interface{}) 77 rules := []map[string]interface{}{} 78 for _, rule := range acl.rules { 79 ruleConfig := rule.getConfig(context.Background()) 80 rules = append(rules, ruleConfig.AsMap()) 81 } 82 if len(rules) > 0 { 83 m["rules"] = rules 84 } 85 m["count"] = len(rules) 86 return m 87 } 88 89 // Allow takes in client identity and metadata and returns an error when 90 // denied access. 91 func (acl *AccessList) Allow(ctx context.Context, data map[string]interface{}) bool { 92 var grantAccess bool 93 for _, rule := range acl.rules { 94 v := rule.eval(ctx, data) 95 switch v { 96 case ruleVerdictAllowStop: 97 return true 98 case ruleVerdictAllow: 99 grantAccess = true 100 case ruleVerdictDenyStop: 101 return false 102 case ruleVerdictDeny: 103 return false 104 } 105 } 106 if grantAccess || acl.defaultAllow { 107 return true 108 } 109 return false 110 } 111 112 // GetFieldDataType return data type for a particular data field. 113 func GetFieldDataType(s string) (string, string) { 114 k := s 115 dt := dataTypeUnknown 116 if v, exists := inputDataAliases[s]; exists { 117 if vdt, exists := inputDataTypes[v]; exists { 118 dt = vdt 119 k = v 120 } 121 } else { 122 if sdt, exists := inputDataTypes[s]; exists { 123 dt = sdt 124 } 125 } 126 switch dt { 127 case dataTypeListStr: 128 return k, "list_str" 129 case dataTypeStr: 130 return k, "str" 131 } 132 return k, "" 133 }