| package spiffebundle | |
| import ( | |
| "fmt" | |
| "sort" | |
| "sync" | |
| "github.com/spiffe/go-spiffe/v2/bundle/jwtbundle" | |
| "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" | |
| "github.com/spiffe/go-spiffe/v2/exp/bundle/witbundle" | |
| "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, wrapSpiffebundleErr(fmt.Errorf("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, wrapSpiffebundleErr(fmt.Errorf("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, wrapSpiffebundleErr(fmt.Errorf("no JWT bundle for trust domain %q", trustDomain)) | |
| } | |
| return bundle.JWTBundle(), nil | |
| } | |
| // GetWITBundleForTrustDomain returns the WIT bundle for the given trust | |
| // domain. It implements the witbundle.Source interface. | |
| func (s *Set) GetWITBundleForTrustDomain(trustDomain spiffeid.TrustDomain) (*witbundle.Bundle, error) { | |
| s.mtx.RLock() | |
| defer s.mtx.RUnlock() | |
| bundle, ok := s.bundles[trustDomain] | |
| if !ok { | |
| return nil, wrapSpiffebundleErr(fmt.Errorf("no WIT bundle for trust domain %q", trustDomain)) | |
| } | |
| return bundle.WITBundle(), nil | |
| } |