github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/policy/localcopy/repository.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package localcopy 19 20 import ( 21 "fmt" 22 "strings" 23 "sync" 24 25 "github.com/mysteriumnetwork/node/identity" 26 "github.com/mysteriumnetwork/node/market" 27 ) 28 29 type listItem struct { 30 policy market.AccessPolicy 31 rules market.AccessPolicyRuleSet 32 } 33 34 // Repository represents async policy fetcher from TrustOracle 35 type Repository struct { 36 lock sync.RWMutex 37 items []listItem 38 } 39 40 // NewRepository create instance of policy repository 41 func NewRepository() *Repository { 42 return &Repository{ 43 items: make([]listItem, 0), 44 } 45 } 46 47 // SetPolicyRules set policy and it's items to repository 48 func (r *Repository) SetPolicyRules(policy market.AccessPolicy, policyRules market.AccessPolicyRuleSet) { 49 r.lock.Lock() 50 defer r.lock.Unlock() 51 52 item, err := r.findItemFor(policy) 53 if err != nil { 54 r.items = append(r.items, listItem{ 55 policy: policy, 56 rules: policyRules, 57 }) 58 } else { 59 item.rules = policyRules 60 } 61 } 62 63 // Policies list policies in repository 64 func (r *Repository) Policies() []market.AccessPolicy { 65 r.lock.RLock() 66 defer r.lock.RUnlock() 67 68 policies := make([]market.AccessPolicy, 0) 69 for _, item := range r.items { 70 policies = append(policies, item.policy) 71 } 72 73 return policies 74 } 75 76 // RulesForPolicy gives items of given polic 77 func (r *Repository) RulesForPolicy(policy market.AccessPolicy) (market.AccessPolicyRuleSet, error) { 78 r.lock.RLock() 79 defer r.lock.RUnlock() 80 81 item, err := r.findItemFor(policy) 82 if err != nil { 83 return market.AccessPolicyRuleSet{}, err 84 } 85 86 return item.rules, nil 87 } 88 89 // RulesForPolicies gives list of items of given policies 90 func (r *Repository) RulesForPolicies(policies []market.AccessPolicy) ([]market.AccessPolicyRuleSet, error) { 91 r.lock.RLock() 92 defer r.lock.RUnlock() 93 94 policiesRules := make([]market.AccessPolicyRuleSet, len(policies)) 95 for i, policy := range policies { 96 item, err := r.findItemFor(policy) 97 if err != nil { 98 return []market.AccessPolicyRuleSet{}, fmt.Errorf("unknown policy: %s", policy) 99 } 100 policiesRules[i] = item.rules 101 } 102 103 return policiesRules, nil 104 } 105 106 // Rules gives list of items all policies 107 func (r *Repository) Rules() []market.AccessPolicyRuleSet { 108 r.lock.RLock() 109 defer r.lock.RUnlock() 110 111 policiesRules := make([]market.AccessPolicyRuleSet, 0) 112 for _, item := range r.items { 113 policiesRules = append(policiesRules, item.rules) 114 } 115 116 return policiesRules 117 } 118 119 // IsIdentityAllowed returns flag if given identity should be allowed by rules 120 func (r *Repository) IsIdentityAllowed(identity identity.Identity) bool { 121 r.lock.RLock() 122 defer r.lock.RUnlock() 123 124 isAllowedByDefault := true 125 for _, item := range r.items { 126 for _, rule := range item.rules.Allow { 127 if rule.Type == market.AccessPolicyTypeIdentity { 128 isAllowedByDefault = false 129 if identity.Address == rule.Value { 130 return true 131 } 132 } 133 } 134 } 135 136 return isAllowedByDefault 137 } 138 139 // HasDNSRules returns flag if any DNS rules are applied 140 func (r *Repository) HasDNSRules() bool { 141 r.lock.RLock() 142 defer r.lock.RUnlock() 143 144 for _, item := range r.items { 145 for _, rule := range item.rules.Allow { 146 if rule.Type == market.AccessPolicyTypeDNSZone { 147 return true 148 } 149 if rule.Type == market.AccessPolicyTypeDNSHostname { 150 return true 151 } 152 } 153 } 154 155 return false 156 } 157 158 // IsHostAllowed returns flag if given FQDN host should be allowed by rules 159 func (r *Repository) IsHostAllowed(host string) bool { 160 r.lock.RLock() 161 defer r.lock.RUnlock() 162 163 isAllowedByDefault := true 164 for _, item := range r.items { 165 for _, rule := range item.rules.Allow { 166 if rule.Type == market.AccessPolicyTypeDNSZone { 167 isAllowedByDefault = false 168 if strings.HasSuffix(host, rule.Value) { 169 return true 170 } 171 } 172 if rule.Type == market.AccessPolicyTypeDNSHostname { 173 isAllowedByDefault = false 174 if host == rule.Value { 175 return true 176 } 177 } 178 } 179 } 180 181 return isAllowedByDefault 182 } 183 184 func (r *Repository) findItemFor(policy market.AccessPolicy) (*listItem, error) { 185 for i, item := range r.items { 186 if item.policy == policy { 187 return &r.items[i], nil 188 } 189 } 190 return nil, fmt.Errorf("unknown policy: %s", policy) 191 }