1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
package spiffebundle
import (
"sort"
"sync"
"github.com/spiffe/go-spiffe/v2/bundle/jwtbundle"
"github.com/spiffe/go-spiffe/v2/bundle/x509bundle"
"github.com/spiffe/go-spiffe/v2/spiffeid"
)
// Set is a set of bundles, keyed by trust domain.
type Set struct {
mtx sync.RWMutex
bundles map[spiffeid.TrustDomain]*Bundle
}
// NewSet creates a new set initialized with the given bundles.
func NewSet(bundles ...*Bundle) *Set {
bundlesMap := make(map[spiffeid.TrustDomain]*Bundle)
for _, b := range bundles {
if b != nil {
bundlesMap[b.trustDomain] = b
}
}
return &Set{
bundles: bundlesMap,
}
}
// Add adds a new bundle into the set. If a bundle already exists for the
// trust domain, the existing bundle is replaced.
func (s *Set) Add(bundle *Bundle) {
s.mtx.Lock()
defer s.mtx.Unlock()
if bundle != nil {
s.bundles[bundle.trustDomain] = bundle
}
}
// Remove removes the bundle for the given trust domain.
func (s *Set) Remove(trustDomain spiffeid.TrustDomain) {
s.mtx.Lock()
defer s.mtx.Unlock()
delete(s.bundles, trustDomain)
}
// Has returns true if there is a bundle for the given trust domain.
func (s *Set) Has(trustDomain spiffeid.TrustDomain) bool {
s.mtx.RLock()
defer s.mtx.RUnlock()
_, ok := s.bundles[trustDomain]
return ok
}
// Get returns a bundle for the given trust domain. If the bundle is in the set
// it is returned and the boolean is true. Otherwise, the returned value is
// nil and the boolean is false.
func (s *Set) Get(trustDomain spiffeid.TrustDomain) (*Bundle, bool) {
s.mtx.RLock()
defer s.mtx.RUnlock()
bundle, ok := s.bundles[trustDomain]
return bundle, ok
}
// Bundles returns the bundles in the set sorted by trust domain.
func (s *Set) Bundles() []*Bundle {
s.mtx.RLock()
defer s.mtx.RUnlock()
out := make([]*Bundle, 0, len(s.bundles))
for _, bundle := range s.bundles {
out = append(out, bundle)
}
sort.Slice(out, func(a, b int) bool {
return out[a].TrustDomain().Compare(out[b].TrustDomain()) < 0
})
return out
}
// Len returns the number of bundles in the set.
func (s *Set) Len() int {
s.mtx.RLock()
defer s.mtx.RUnlock()
return len(s.bundles)
}
// GetBundleForTrustDomain returns the SPIFFE bundle for the given trust
// domain. It implements the Source interface.
func (s *Set) GetBundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*Bundle, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
bundle, ok := s.bundles[trustDomain]
if !ok {
return nil, spiffebundleErr.New("no SPIFFE bundle for trust domain %q", trustDomain)
}
return bundle, nil
}
// GetX509BundleForTrustDomain returns the X.509 bundle for the given trust
// domain. It implements the x509bundle.Source interface.
func (s *Set) GetX509BundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*x509bundle.Bundle, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
bundle, ok := s.bundles[trustDomain]
if !ok {
return nil, spiffebundleErr.New("no X.509 bundle for trust domain %q", trustDomain)
}
return bundle.X509Bundle(), nil
}
// GetJWTBundleForTrustDomain returns the JWT bundle for the given trust
// domain. It implements the jwtbundle.Source interface.
func (s *Set) GetJWTBundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*jwtbundle.Bundle, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
bundle, ok := s.bundles[trustDomain]
if !ok {
return nil, spiffebundleErr.New("no JWT bundle for trust domain %q", trustDomain)
}
return bundle.JWTBundle(), nil
}
|