github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/frontman/rulecleanup_windows.go (about)

     1  // +build windows
     2  
     3  package frontman
     4  
     5  import (
     6  	"strings"
     7  )
     8  
     9  type ruleCleanup interface {
    10  	mapIpsetToRule(ipsetName string, filterName, criteriaName string)
    11  	deleteRulesForIpset(wrapDriver WrapDriver, ipsetName string) error
    12  	deleteRuleForIpsetByPrefix(wrapDriver WrapDriver, prefix string) error
    13  	deleteRuleFromIpsetMap(filterName, criteriaName string)
    14  	getRulesForIpset(ipsetName string) []*filterRulePair
    15  }
    16  
    17  type ruleCleaner struct {
    18  	ipsetToRule map[string][]*filterRulePair
    19  }
    20  
    21  type filterRulePair struct {
    22  	filterName   string
    23  	ruleCriteria string
    24  }
    25  
    26  func newRuleCleanup() ruleCleanup {
    27  	return &ruleCleaner{
    28  		ipsetToRule: make(map[string][]*filterRulePair),
    29  	}
    30  }
    31  
    32  // We keep a map of ipset name to rules. This is a safeguard to ensure that rules are deleted.
    33  // Normally, during policy update, rules and ipsets are deleted explicitly and all works well.
    34  // There are some instances though (Discovery Mode) where criteria name strings use in deletion
    35  // do not align with criteria name strings used during addition. This will result in rules
    36  // stranded in our driver, which is really bad for multiple reasons.
    37  // Since deletion of ipsets is more orderly than deletion of rules by criteria name, and since
    38  // the rules that are subject to being stranded are all so far associated with an ephemeral ipset,
    39  // we can use the deletion of an ipset to trigger a cleanup of all rules associated with it.
    40  
    41  func (r *ruleCleaner) mapIpsetToRule(ipsetName string, filterName, criteriaName string) {
    42  	r.ipsetToRule[ipsetName] = append(r.ipsetToRule[ipsetName], &filterRulePair{filterName: filterName, ruleCriteria: criteriaName})
    43  }
    44  
    45  func (r *ruleCleaner) deleteRulesForIpset(wrapDriver WrapDriver, ipsetName string) error {
    46  	for _, frpair := range r.ipsetToRule[ipsetName] {
    47  		// In recent changes, these rule are already gone, so don't log an error if this fails.
    48  		wrapDriver.DeleteFilterCriteria(frpair.filterName, frpair.ruleCriteria) //nolint
    49  	}
    50  	delete(r.ipsetToRule, ipsetName)
    51  	return nil
    52  }
    53  
    54  func (r *ruleCleaner) deleteRuleForIpsetByPrefix(wrapDriver WrapDriver, prefix string) error {
    55  
    56  	ipsets, err := wrapDriver.ListIpsets()
    57  	if err != nil {
    58  		return err
    59  	}
    60  	for _, ipsetName := range ipsets {
    61  		if strings.HasPrefix(ipsetName, prefix) {
    62  			if err := r.deleteRulesForIpset(wrapDriver, ipsetName); err != nil {
    63  				return err
    64  			}
    65  		}
    66  	}
    67  	return nil
    68  }
    69  
    70  func (r *ruleCleaner) deleteRuleFromIpsetMap(filterName, criteriaName string) {
    71  	// quadratic for now, optimize later if we need to
    72  	for ipsetName, frpairs := range r.ipsetToRule {
    73  		for i, frpair := range frpairs {
    74  			if frpair.filterName == filterName && frpair.ruleCriteria == criteriaName {
    75  				// delete pair from slice
    76  				frpairs[i] = frpairs[len(frpairs)-1]
    77  				r.ipsetToRule[ipsetName] = frpairs[:len(frpairs)-1]
    78  				// rule can be mapped from multiple ipsets, so continue our outer loop
    79  				break
    80  			}
    81  		}
    82  	}
    83  }
    84  
    85  func (r *ruleCleaner) getRulesForIpset(ipsetName string) []*filterRulePair {
    86  	frpairs := r.ipsetToRule[ipsetName]
    87  	result := make([]*filterRulePair, len(frpairs))
    88  	copy(result, frpairs)
    89  	return result
    90  }