func (b *Bundle) Empty() bool {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	return len(b.x509Authorities) == 0 && len(b.jwtAuthorities) == 0
}
Empty returns true if the bundle has no X.509 and JWT authorities.
package spiffebundle
import (
	"crypto"
	"crypto/x509"
	"encoding/json"
	"io"
	"io/ioutil"
	"sync"
	"time"
	"github.com/spiffe/go-spiffe/v2/bundle/jwtbundle"
	"github.com/spiffe/go-spiffe/v2/bundle/x509bundle"
	"github.com/spiffe/go-spiffe/v2/internal/jwtutil"
	"github.com/spiffe/go-spiffe/v2/internal/x509util"
	"github.com/spiffe/go-spiffe/v2/spiffeid"
	"github.com/zeebo/errs"
	"gopkg.in/square/go-jose.v2"
)
const (
	x509SVIDUse = "x509-svid"
	jwtSVIDUse  = "jwt-svid"
)
var (
	spiffebundleErr = errs.Class("spiffebundle")
)
type bundleDoc struct {
	jose.JSONWebKeySet
	SequenceNumber *uint64 `json:"spiffe_sequence,omitempty"`
	RefreshHint    *int64  `json:"spiffe_refresh_hint,omitempty"`
}
type Bundle struct {
	trustDomain spiffeid.TrustDomain
	mtx             sync.RWMutex
	refreshHint     *time.Duration
	sequenceNumber  *uint64
	jwtAuthorities  map[string]crypto.PublicKey
	x509Authorities []*x509.Certificate
}
func New(trustDomain spiffeid.TrustDomain) *Bundle {
	return &Bundle{
		trustDomain:    trustDomain,
		jwtAuthorities: make(map[string]crypto.PublicKey),
	}
}
func Load(trustDomain spiffeid.TrustDomain, path string) (*Bundle, error) {
	bundleBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, spiffebundleErr.New("unable to read SPIFFE bundle: %w", err)
	}
	return Parse(trustDomain, bundleBytes)
}
func Read(trustDomain spiffeid.TrustDomain, r io.Reader) (*Bundle, error) {
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, spiffebundleErr.New("unable to read: %v", err)
	}
	return Parse(trustDomain, b)
}
func Parse(trustDomain spiffeid.TrustDomain, bundleBytes []byte) (*Bundle, error) {
	jwks := &bundleDoc{}
	if err := json.Unmarshal(bundleBytes, jwks); err != nil {
		return nil, spiffebundleErr.New("unable to parse JWKS: %v", err)
	}
	bundle := New(trustDomain)
	if jwks.RefreshHint != nil {
		bundle.SetRefreshHint(time.Second * time.Duration(*jwks.RefreshHint))
	}
	if jwks.SequenceNumber != nil {
		bundle.SetSequenceNumber(*jwks.SequenceNumber)
	}
	if jwks.Keys == nil {
		return nil, spiffebundleErr.New("no authorities found")
	}
	for i, key := range jwks.Keys {
		switch key.Use {
		case x509SVIDUse:
			if len(key.Certificates) != 1 {
				return nil, spiffebundleErr.New("expected a single certificate in %s entry %d; got %d", x509SVIDUse, i, len(key.Certificates))
			}
			bundle.AddX509Authority(key.Certificates[0])
		case jwtSVIDUse:
			if err := bundle.AddJWTAuthority(key.KeyID, key.Key); err != nil {
				return nil, spiffebundleErr.New("error adding authority %d of JWKS: %v", i, errs.Unwrap(err))
			}
		}
	}
	return bundle, nil
}
func FromX509Bundle(x509Bundle *x509bundle.Bundle) *Bundle {
	bundle := New(x509Bundle.TrustDomain())
	bundle.x509Authorities = x509Bundle.X509Authorities()
	return bundle
}
func FromJWTBundle(jwtBundle *jwtbundle.Bundle) *Bundle {
	bundle := New(jwtBundle.TrustDomain())
	bundle.jwtAuthorities = jwtBundle.JWTAuthorities()
	return bundle
}
func FromX509Authorities(trustDomain spiffeid.TrustDomain, x509Authorities []*x509.Certificate) *Bundle {
	bundle := New(trustDomain)
	bundle.x509Authorities = x509util.CopyX509Authorities(x509Authorities)
	return bundle
}
func FromJWTAuthorities(trustDomain spiffeid.TrustDomain, jwtAuthorities map[string]crypto.PublicKey) *Bundle {
	bundle := New(trustDomain)
	bundle.jwtAuthorities = jwtutil.CopyJWTAuthorities(jwtAuthorities)
	return bundle
}
func (b *Bundle) TrustDomain() spiffeid.TrustDomain {
	return b.trustDomain
}
func (b *Bundle) X509Authorities() []*x509.Certificate {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	return x509util.CopyX509Authorities(b.x509Authorities)
}
func (b *Bundle) AddX509Authority(x509Authority *x509.Certificate) {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	for _, r := range b.x509Authorities {
		if r.Equal(x509Authority) {
			return
		}
	}
	b.x509Authorities = append(b.x509Authorities, x509Authority)
}
func (b *Bundle) RemoveX509Authority(x509Authority *x509.Certificate) {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	for i, r := range b.x509Authorities {
		if r.Equal(x509Authority) {
			b.x509Authorities = append(b.x509Authorities[:i], b.x509Authorities[i+1:]...)
			return
		}
	}
}
func (b *Bundle) HasX509Authority(x509Authority *x509.Certificate) bool {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	for _, r := range b.x509Authorities {
		if r.Equal(x509Authority) {
			return true
		}
	}
	return false
}
func (b *Bundle) SetX509Authorities(authorities []*x509.Certificate) {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	b.x509Authorities = x509util.CopyX509Authorities(authorities)
}
func (b *Bundle) JWTAuthorities() map[string]crypto.PublicKey {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	return jwtutil.CopyJWTAuthorities(b.jwtAuthorities)
}
func (b *Bundle) FindJWTAuthority(keyID string) (crypto.PublicKey, bool) {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	jwtAuthority, ok := b.jwtAuthorities[keyID]
	return jwtAuthority, ok
}
func (b *Bundle) HasJWTAuthority(keyID string) bool {
	b.mtx.RLock()
	defer b.mtx.RUnlock()
	_, ok := b.jwtAuthorities[keyID]
	return ok
}
func (b *Bundle) AddJWTAuthority(keyID string, jwtAuthority crypto.PublicKey) error {
	if keyID == "" {
		return spiffebundleErr.New("keyID cannot be empty")
	}
	b.mtx.Lock()
	defer b.mtx.Unlock()
	b.jwtAuthorities[keyID] = jwtAuthority
	return nil
}
func (b *Bundle) RemoveJWTAuthority(keyID string) {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	delete(b.jwtAuthorities, keyID)
}
func (b *Bundle) SetJWTAuthorities(jwtAuthorities map[string]crypto.PublicKey) {
	b.mtx.Lock()
	defer b.mtx.Unlock()
	b.jwtAuthorities = jwtutil.CopyJWTAuthorities(jwtAuthorities)
}