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  }