github.com/DerekStrickland/consul@v1.4.5/agent/consul/filter.go (about)

     1  package consul
     2  
     3  import (
     4  	"github.com/hashicorp/consul/acl"
     5  	"github.com/hashicorp/consul/agent/structs"
     6  )
     7  
     8  type dirEntFilter struct {
     9  	authorizer acl.Authorizer
    10  	ent        structs.DirEntries
    11  }
    12  
    13  func (d *dirEntFilter) Len() int {
    14  	return len(d.ent)
    15  }
    16  func (d *dirEntFilter) Filter(i int) bool {
    17  	return !d.authorizer.KeyRead(d.ent[i].Key)
    18  }
    19  func (d *dirEntFilter) Move(dst, src, span int) {
    20  	copy(d.ent[dst:dst+span], d.ent[src:src+span])
    21  }
    22  
    23  // FilterDirEnt is used to filter a list of directory entries
    24  // by applying an ACL policy
    25  func FilterDirEnt(authorizer acl.Authorizer, ent structs.DirEntries) structs.DirEntries {
    26  	df := dirEntFilter{authorizer: authorizer, ent: ent}
    27  	return ent[:FilterEntries(&df)]
    28  }
    29  
    30  type keyFilter struct {
    31  	authorizer acl.Authorizer
    32  	keys       []string
    33  }
    34  
    35  func (k *keyFilter) Len() int {
    36  	return len(k.keys)
    37  }
    38  func (k *keyFilter) Filter(i int) bool {
    39  	return !k.authorizer.KeyRead(k.keys[i])
    40  }
    41  
    42  func (k *keyFilter) Move(dst, src, span int) {
    43  	copy(k.keys[dst:dst+span], k.keys[src:src+span])
    44  }
    45  
    46  // FilterKeys is used to filter a list of keys by
    47  // applying an ACL policy
    48  func FilterKeys(authorizer acl.Authorizer, keys []string) []string {
    49  	kf := keyFilter{authorizer: authorizer, keys: keys}
    50  	return keys[:FilterEntries(&kf)]
    51  }
    52  
    53  type txnResultsFilter struct {
    54  	authorizer acl.Authorizer
    55  	results    structs.TxnResults
    56  }
    57  
    58  func (t *txnResultsFilter) Len() int {
    59  	return len(t.results)
    60  }
    61  
    62  func (t *txnResultsFilter) Filter(i int) bool {
    63  	result := t.results[i]
    64  	switch {
    65  	case result.KV != nil:
    66  		return !t.authorizer.KeyRead(result.KV.Key)
    67  	case result.Node != nil:
    68  		return !t.authorizer.NodeRead(result.Node.Node)
    69  	case result.Service != nil:
    70  		return !t.authorizer.ServiceRead(result.Service.Service)
    71  	case result.Check != nil:
    72  		if result.Check.ServiceName != "" {
    73  			return !t.authorizer.ServiceRead(result.Check.ServiceName)
    74  		}
    75  		return !t.authorizer.NodeRead(result.Check.Node)
    76  	}
    77  	return false
    78  }
    79  
    80  func (t *txnResultsFilter) Move(dst, src, span int) {
    81  	copy(t.results[dst:dst+span], t.results[src:src+span])
    82  }
    83  
    84  // FilterTxnResults is used to filter a list of transaction results by
    85  // applying an ACL policy.
    86  func FilterTxnResults(authorizer acl.Authorizer, results structs.TxnResults) structs.TxnResults {
    87  	rf := txnResultsFilter{authorizer: authorizer, results: results}
    88  	return results[:FilterEntries(&rf)]
    89  }
    90  
    91  // Filter interface is used with FilterEntries to do an
    92  // in-place filter of a slice.
    93  type Filter interface {
    94  	Len() int
    95  	Filter(int) bool
    96  	Move(dst, src, span int)
    97  }
    98  
    99  // FilterEntries is used to do an inplace filter of
   100  // a slice. This has cost proportional to the list length.
   101  func FilterEntries(f Filter) int {
   102  	// Compact the list
   103  	dst := 0
   104  	src := 0
   105  	n := f.Len()
   106  	for dst < n {
   107  		for src < n && f.Filter(src) {
   108  			src++
   109  		}
   110  		if src == n {
   111  			break
   112  		}
   113  		end := src + 1
   114  		for end < n && !f.Filter(end) {
   115  			end++
   116  		}
   117  		span := end - src
   118  		if span > 0 {
   119  			f.Move(dst, src, span)
   120  			dst += span
   121  			src += span
   122  		}
   123  	}
   124  
   125  	// Return the size of the slice
   126  	return dst
   127  }