github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/security/choria/choria_security.go (about)

     1  // Copyright (c) 2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package choria
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"crypto/ed25519"
    11  	"crypto/sha256"
    12  	"crypto/tls"
    13  	"crypto/x509"
    14  	"encoding/hex"
    15  	"errors"
    16  	"fmt"
    17  	"net/http"
    18  	"net/url"
    19  	"os"
    20  	"regexp"
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/choria-io/go-choria/inter"
    25  	iu "github.com/choria-io/go-choria/internal/util"
    26  	"github.com/choria-io/go-choria/tlssetup"
    27  	"github.com/choria-io/tokens"
    28  	"github.com/sirupsen/logrus"
    29  )
    30  
    31  var (
    32  	callerFormat        = "choria=%s"
    33  	callerIDRe          = regexp.MustCompile(`^[a-z]+=([\w\.\-]+)`)
    34  	errPermissionDenied = errors.New("access denied")
    35  )
    36  
    37  type ChoriaSecurity struct {
    38  	conf *Config
    39  	mu   *sync.Mutex
    40  	log  *logrus.Entry
    41  }
    42  
    43  type Config struct {
    44  	// Identity when not empty will force the identity to be used for validations etc
    45  	Identity string
    46  
    47  	// SeedFile is the file holding the ed25519 seed
    48  	SeedFile string
    49  
    50  	// TokenFile is the file holding the signed JWT file
    51  	TokenFile string
    52  
    53  	// Issuers are Organization issuers that may issue tokens
    54  	Issuers map[string]ed25519.PublicKey
    55  
    56  	// TrustedTokenSigners are keys allowed to sign tokens
    57  	TrustedTokenSigners []ed25519.PublicKey
    58  
    59  	// Is a URL where a remote signer is running
    60  	RemoteSignerURL string
    61  
    62  	// TLSSetup is the shared TLS configuration state between security providers
    63  	TLSConfig *tlssetup.Config
    64  
    65  	// RemoteSigner is the signer used to sign requests using a remote like AAA Service
    66  	RemoteSigner inter.RequestSigner
    67  
    68  	// DisableTLSVerify disables TLS verify in HTTP clients etc
    69  	DisableTLSVerify bool
    70  
    71  	// Certificate is the path to the public certificate
    72  	Certificate string
    73  
    74  	// Key is the path to the private key
    75  	Key string
    76  
    77  	// CA is the path to the Certificate Authority
    78  	CA string
    79  
    80  	// SignedReplies indicates that servers replying should sign their messages
    81  	SignedReplies bool
    82  
    83  	// InitiatedByServer indicates this is a server, it would require trusted signers
    84  	InitiatedByServer bool
    85  }
    86  
    87  func New(opts ...Option) (*ChoriaSecurity, error) {
    88  	s := &ChoriaSecurity{
    89  		conf: &Config{
    90  			SignedReplies: true,
    91  		},
    92  		mu: &sync.Mutex{},
    93  	}
    94  
    95  	for _, opt := range opts {
    96  		err := opt(s)
    97  		if err != nil {
    98  			return nil, err
    99  		}
   100  	}
   101  
   102  	if s.log == nil {
   103  		return nil, fmt.Errorf("logger is required")
   104  	}
   105  
   106  	s.log = s.log.WithFields(logrus.Fields{
   107  		"mTLS":  s.conf.CA != "",
   108  		"token": s.conf.TokenFile,
   109  		"seed":  s.conf.SeedFile,
   110  	})
   111  
   112  	s.log.Infof("Security provider initializing")
   113  
   114  	return s, nil
   115  }
   116  
   117  func (s *ChoriaSecurity) Provider() string {
   118  	return "choria"
   119  }
   120  
   121  func (s *ChoriaSecurity) BackingTechnology() inter.SecurityTechnology {
   122  	return inter.SecurityTechnologyED25519JWT
   123  }
   124  
   125  func (s *ChoriaSecurity) TokenBytes() ([]byte, error) {
   126  	return os.ReadFile(s.conf.TokenFile)
   127  }
   128  
   129  func (s *ChoriaSecurity) Validate() ([]string, bool) {
   130  	var errors []string
   131  
   132  	if s.log == nil {
   133  		errors = append(errors, "logger not given")
   134  	}
   135  
   136  	if s.conf == nil {
   137  		errors = append(errors, "configuration not given")
   138  	} else {
   139  		if s.conf.Identity == "" {
   140  			errors = append(errors, "identity could not be determine automatically via Choria or was not supplied")
   141  		}
   142  
   143  		if s.conf.TokenFile == "" {
   144  			errors = append(errors, "the path to the JWT token is not configured")
   145  		}
   146  
   147  		if s.conf.SeedFile == "" {
   148  			errors = append(errors, "the path to the ed25519 seed is not configured")
   149  		}
   150  
   151  		if s.conf.InitiatedByServer {
   152  			if len(s.conf.TrustedTokenSigners) == 0 && len(s.conf.Issuers) == 0 {
   153  				errors = append(errors, "no trusted token signers or issuers configured")
   154  			}
   155  
   156  			if len(s.conf.TrustedTokenSigners) > 0 && len(s.conf.Issuers) > 0 {
   157  				errors = append(errors, "can only configure one of trusted token signers or issuers")
   158  			}
   159  		}
   160  	}
   161  
   162  	return errors, len(errors) == 0
   163  }
   164  
   165  func (s *ChoriaSecurity) Identity() string {
   166  	// TODO: should load the token and figure it out from there
   167  	// ultimately in this case of identity probably just is a hint
   168  	// only as really this is used to find certs by name in other
   169  	// providers, so maybe this is fine
   170  	return s.conf.Identity
   171  }
   172  
   173  func (s *ChoriaSecurity) CallerName() string {
   174  	// TODO: since this calls identity the same concerns above apply
   175  	return fmt.Sprintf(callerFormat, s.Identity())
   176  }
   177  
   178  func (s *ChoriaSecurity) CallerIdentity(caller string) (string, error) {
   179  	match := callerIDRe.FindStringSubmatch(caller)
   180  
   181  	if match == nil {
   182  		return "", fmt.Errorf("could not find a valid caller identity name in %s", caller)
   183  	}
   184  
   185  	return match[1], nil
   186  }
   187  
   188  func (s *ChoriaSecurity) SignBytes(b []byte) (signature []byte, err error) {
   189  	return iu.Ed25519SignWithSeedFile(s.conf.SeedFile, b)
   190  }
   191  
   192  func (s *ChoriaSecurity) VerifySignatureBytes(dat []byte, sig []byte, public ...[]byte) (should bool, signer string) {
   193  	switch len(public) {
   194  	case 0:
   195  		s.log.Warnf("Received a signature verification request with no public parts")
   196  		return false, ""
   197  	case 1:
   198  		// signature was made by the caller - first in the list of tokens - so it may not be one that requires delegated signatures
   199  		return s.verifyByteSignatureByCaller(dat, sig, public[0])
   200  	case 2:
   201  		// signature was made by a delegation - it's the 2nd signature received. We try load it using all the trusted issuers
   202  		// and, we make sure when it loads that it has delegator permission
   203  		return s.verifyByteSignatureByDelegation(dat, sig, public[0], public[1])
   204  	default:
   205  		s.log.Warnf("Received a signature verification request with %d public parts", len(public))
   206  		return false, ""
   207  	}
   208  }
   209  
   210  func (s *ChoriaSecurity) orgPkForToken(token []byte) (pk ed25519.PublicKey, ou string, err error) {
   211  	uclaims, err := tokens.ParseTokenUnverified(string(token))
   212  	if err != nil {
   213  		return nil, "", err
   214  	}
   215  
   216  	our, ok := uclaims["ou"]
   217  	if !ok {
   218  		return nil, "", fmt.Errorf("no ou found in client token")
   219  	}
   220  
   221  	ous, ok := our.(string)
   222  	if !ok {
   223  		return nil, "", fmt.Errorf("empty ou found in client token")
   224  	}
   225  
   226  	issuer, ok := s.conf.Issuers[ous]
   227  	if !ok {
   228  		s.log.Warnf("No issuer found for %s ou", ous)
   229  		return nil, "", fmt.Errorf("no issuer found for %s ou", ous)
   230  	}
   231  
   232  	return issuer, ous, nil
   233  }
   234  
   235  func (s *ChoriaSecurity) verifyByteSignatureByDelegation(dat []byte, sig []byte, caller []byte, delegate []byte) (bool, string) {
   236  	if len(delegate) == 0 {
   237  		s.log.Warnf("Received an invalid token for signature verification")
   238  		return false, ""
   239  	}
   240  
   241  	purpose := tokens.TokenPurpose(string(delegate))
   242  	// delegate signers must be clients
   243  	if purpose != tokens.ClientIDPurpose {
   244  		s.log.Warnf("Cannot verify byte signatures using a %s token", purpose)
   245  		return false, ""
   246  	}
   247  
   248  	var pk ed25519.PublicKey
   249  	var pks string
   250  	var name string
   251  	var err error
   252  
   253  	checkDelegate := func(signer ed25519.PublicKey, delegate []byte) (pks string, name string, error error) {
   254  		st, err := tokens.ParseClientIDToken(string(delegate), signer, true)
   255  		if err != nil {
   256  			return "", "", fmt.Errorf("could not parse client token: %w", err)
   257  		}
   258  
   259  		// it successfully parsed but now must be a delegator else it's not allowed to sign this data
   260  		if st.Permissions == nil || !st.Permissions.AuthenticationDelegator {
   261  			return "", "", fmt.Errorf("%w: token attempted to sign a request as delegator without required delegator permission: %s", errPermissionDenied, hex.EncodeToString(signer))
   262  		}
   263  
   264  		// this ensures/assumes the caller is always signed by the same signer as the delegator
   265  		ct, err := tokens.ParseClientIDToken(string(caller), signer, true)
   266  		if err != nil {
   267  			return "", "", fmt.Errorf("%w: could not load caller token using the same signer as the delegator: %v", errPermissionDenied, err)
   268  		}
   269  
   270  		if ct.Permissions == nil || !(ct.Permissions.FleetManagement || ct.Permissions.SignedFleetManagement) {
   271  			return "", "", fmt.Errorf("%w: caller token cannot be used without fleet management access: %s: %v", errPermissionDenied, string(caller), err)
   272  		}
   273  
   274  		if st.PublicKey == "" {
   275  			return "", "", fmt.Errorf("%w: no public key set", errPermissionDenied)
   276  		}
   277  
   278  		return st.PublicKey, st.CallerID, nil
   279  	}
   280  
   281  	if len(s.conf.Issuers) > 0 {
   282  		issuer, _, err := s.orgPkForToken(delegate)
   283  		if err != nil {
   284  			s.log.Warnf("Could not get ou from delegate token: %v", err)
   285  			return false, ""
   286  		}
   287  
   288  		pks, name, err = checkDelegate(issuer, delegate)
   289  		if err != nil {
   290  			s.log.Warn(err)
   291  			return false, ""
   292  		}
   293  	} else {
   294  		for _, signer := range s.conf.TrustedTokenSigners {
   295  			s.log.Warnf("Checking using signer %x", signer)
   296  			pks, name, err = checkDelegate(signer, delegate)
   297  			if errors.Is(err, errPermissionDenied) {
   298  				s.log.Warnf(err.Error())
   299  				return false, ""
   300  			} else if err != nil {
   301  				s.log.Warnf(err.Error())
   302  				continue
   303  			} else if err == nil {
   304  				break
   305  			}
   306  		}
   307  	}
   308  
   309  	if pks == "" {
   310  		s.log.Warnf("Signer token %s could not be loaded using %d authorized issuers", string(delegate), len(s.conf.TrustedTokenSigners))
   311  		return false, ""
   312  	}
   313  
   314  	pk, err = hex.DecodeString(pks)
   315  	if err != nil {
   316  		s.log.Warnf("Could not extract public key from token")
   317  		return false, ""
   318  	}
   319  
   320  	ok, err := iu.Ed25519Verify(pk, dat, sig)
   321  	if err != nil {
   322  		s.log.Warnf("Could not verify signature: %v", err)
   323  		return false, ""
   324  	}
   325  
   326  	return ok, name
   327  }
   328  
   329  func (s *ChoriaSecurity) verifyByteSignatureByCaller(dat []byte, sig []byte, token []byte) (bool, string) {
   330  	if len(token) == 0 {
   331  		s.log.Warnf("Received an invalid token for signature verification")
   332  		return false, ""
   333  	}
   334  
   335  	purpose := tokens.TokenPurpose(string(token))
   336  	if purpose != tokens.ServerPurpose && purpose != tokens.ClientIDPurpose {
   337  		s.log.Warnf("Cannot verify byte signatures using a %s token", purpose)
   338  		return false, ""
   339  	}
   340  
   341  	checkClient := func(token []byte, signer ed25519.PublicKey) (pks string, name string, err error) {
   342  		t, err := tokens.ParseClientIDToken(string(token), signer, true)
   343  		if err != nil {
   344  			return "", "", err
   345  		}
   346  
   347  		// it successfully parsed but now must not require delegation
   348  		if t.Permissions != nil && t.Permissions.SignedFleetManagement {
   349  			return "", "", fmt.Errorf("%w: requires authority delegation", errPermissionDenied)
   350  		}
   351  
   352  		if t.Permissions == nil || !t.Permissions.FleetManagement {
   353  			return "", "", fmt.Errorf("%w: does not have fleet management access", errPermissionDenied)
   354  		}
   355  
   356  		if t.PublicKey == "" {
   357  			return "", "", fmt.Errorf("%w: no public key in token", errPermissionDenied)
   358  		}
   359  
   360  		return t.PublicKey, t.CallerID, nil
   361  	}
   362  
   363  	var pk ed25519.PublicKey
   364  	var pks string
   365  	var name string
   366  	var err error
   367  
   368  	if len(s.conf.Issuers) > 0 {
   369  		issuer, ou, err := s.orgPkForToken(token)
   370  		if err != nil {
   371  			s.log.Warnf("Could not get ou from token: %v", err)
   372  			return false, ""
   373  		}
   374  
   375  		if purpose == tokens.ServerPurpose {
   376  			t, err := tokens.ParseServerToken(string(token), issuer)
   377  			if err != nil {
   378  				s.log.Warnf("Could not parse server token using issuer '%s': %v", ou, err)
   379  				return false, ""
   380  			}
   381  
   382  			if t.PublicKey == "" {
   383  				s.log.Warnf("Server token has no public key")
   384  				return false, ""
   385  			}
   386  
   387  			pks = t.PublicKey
   388  			name = t.ChoriaIdentity
   389  		} else {
   390  			pks, name, err = checkClient(token, issuer)
   391  			if err != nil {
   392  				s.log.Warnf("Could not verify signature by caller using issuer '%s': %v", ou, err)
   393  				return false, ""
   394  			}
   395  		}
   396  	} else {
   397  		for _, signer := range s.conf.TrustedTokenSigners {
   398  			if purpose == tokens.ServerPurpose {
   399  				t, err := tokens.ParseServerToken(string(token), signer)
   400  				if err != nil {
   401  					continue
   402  				}
   403  
   404  				if t.PublicKey != "" {
   405  					pks = t.PublicKey
   406  					name = t.ChoriaIdentity
   407  					break
   408  				}
   409  			} else {
   410  				pks, name, err = checkClient(token, signer)
   411  				if errors.Is(err, errPermissionDenied) {
   412  					s.log.Warnf("Could not verify signature by caller: %v", err)
   413  					return false, ""
   414  				} else if err != nil {
   415  					s.log.Warnf("Could not verify signature by caller: %v", err)
   416  					continue
   417  				} else if err == nil {
   418  					break
   419  				}
   420  			}
   421  		}
   422  	}
   423  
   424  	if pks == "" {
   425  		s.log.Warnf("Signer token %s could not be loaded using %d authorized issuers", string(token), len(s.conf.TrustedTokenSigners))
   426  		return false, ""
   427  	}
   428  
   429  	pk, err = hex.DecodeString(pks)
   430  	if err != nil {
   431  		s.log.Warnf("Could not extract public key from token")
   432  		return false, ""
   433  	}
   434  
   435  	ok, err := iu.Ed25519Verify(pk, dat, sig)
   436  	if err != nil {
   437  		s.log.Warnf("Could not verify signature: %v", err)
   438  		return false, ""
   439  	}
   440  
   441  	return ok, name
   442  }
   443  
   444  func (s *ChoriaSecurity) RemoteSignRequest(ctx context.Context, request []byte) (signed []byte, err error) {
   445  	if s.conf.RemoteSigner == nil {
   446  		return nil, fmt.Errorf("remote signing not configured")
   447  	}
   448  
   449  	s.log.Infof("Signing request using %s", s.conf.RemoteSigner.Kind())
   450  	return s.conf.RemoteSigner.Sign(ctx, request, s)
   451  }
   452  
   453  func (s *ChoriaSecurity) RemoteSignerSeedFile() (string, error) {
   454  	return s.conf.SeedFile, nil
   455  }
   456  
   457  func (s *ChoriaSecurity) RemoteSignerToken() ([]byte, error) {
   458  	if s.conf.TokenFile == "" {
   459  		return nil, fmt.Errorf("no token file defined")
   460  	}
   461  
   462  	tb, err := os.ReadFile(s.conf.TokenFile)
   463  	if err != nil {
   464  		return bytes.TrimSpace(tb), fmt.Errorf("could not read token file: %v", err)
   465  	}
   466  
   467  	return tb, err
   468  }
   469  
   470  func (s *ChoriaSecurity) RemoteSignerURL() (*url.URL, error) {
   471  	if s.conf.RemoteSignerURL == "" {
   472  		return nil, fmt.Errorf("no remote url configured")
   473  	}
   474  
   475  	return url.Parse(s.conf.RemoteSignerURL)
   476  }
   477  
   478  func (s *ChoriaSecurity) IsRemoteSigning() bool {
   479  	return s.conf.RemoteSigner != nil
   480  }
   481  
   482  func (s *ChoriaSecurity) ChecksumBytes(data []byte) []byte {
   483  	sum := sha256.Sum256(data)
   484  
   485  	return sum[:]
   486  }
   487  
   488  func (s *ChoriaSecurity) TLSConfig() (*tls.Config, error) {
   489  	tlsc := &tls.Config{
   490  		MinVersion:       tls.VersionTLS12,
   491  		CipherSuites:     s.conf.TLSConfig.CipherSuites,
   492  		CurvePreferences: s.conf.TLSConfig.CurvePreferences,
   493  	}
   494  
   495  	if iu.FileExist(s.conf.Key) && iu.FileExist(s.conf.Certificate) {
   496  		cert, err := tls.LoadX509KeyPair(s.conf.Certificate, s.conf.Key)
   497  		if err != nil {
   498  			err = fmt.Errorf("could not load certificate %s and key %s: %s", s.conf.Certificate, s.conf.Key, err)
   499  			return nil, err
   500  		}
   501  
   502  		cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
   503  		if err != nil {
   504  			err = fmt.Errorf("error parsing certificate: %v", err)
   505  			return nil, err
   506  		}
   507  
   508  		tlsc.Certificates = []tls.Certificate{cert}
   509  	}
   510  
   511  	if iu.FileExist(s.conf.CA) {
   512  		caCert, err := os.ReadFile(s.conf.CA)
   513  		if err != nil {
   514  			return nil, err
   515  		}
   516  
   517  		caCertPool := x509.NewCertPool()
   518  		caCertPool.AppendCertsFromPEM(caCert)
   519  
   520  		tlsc.ClientCAs = caCertPool
   521  		tlsc.RootCAs = caCertPool
   522  	} else {
   523  		// in this security system we are specifically building a system
   524  		// where mTLS is optional, so when we do not have a CA we disable
   525  		// mutual verification
   526  		tlsc.InsecureSkipVerify = true
   527  	}
   528  
   529  	if s.conf.DisableTLSVerify {
   530  		tlsc.InsecureSkipVerify = true
   531  	}
   532  
   533  	return tlsc, nil
   534  }
   535  
   536  func (s *ChoriaSecurity) ClientTLSConfig() (*tls.Config, error) {
   537  	return s.TLSConfig()
   538  }
   539  
   540  func (s *ChoriaSecurity) SSLContext() (*http.Transport, error) {
   541  	tlsConfig, err := s.ClientTLSConfig()
   542  	if err != nil {
   543  		return nil, err
   544  	}
   545  
   546  	transport := &http.Transport{TLSClientConfig: tlsConfig}
   547  
   548  	return transport, nil
   549  }
   550  
   551  func (s *ChoriaSecurity) HTTPClient(secure bool) (*http.Client, error) {
   552  	client := &http.Client{}
   553  
   554  	if secure {
   555  		tlsc, err := s.TLSConfig()
   556  		if err != nil {
   557  			return nil, fmt.Errorf("could not set up HTTP connection: %s", err)
   558  		}
   559  
   560  		client.Transport = &http.Transport{TLSClientConfig: tlsc}
   561  	}
   562  
   563  	return client, nil
   564  }
   565  
   566  func (s *ChoriaSecurity) PublicCert() (*x509.Certificate, error) {
   567  	if s.conf.Key == "" || s.conf.Certificate == "" {
   568  		return nil, fmt.Errorf("no certificates configured")
   569  	}
   570  
   571  	cert, err := tls.LoadX509KeyPair(s.conf.Certificate, s.conf.Key)
   572  	if err != nil {
   573  		err = fmt.Errorf("could not load certificate %s and key %s: %s", s.conf.Certificate, s.conf.Key, err)
   574  		return nil, err
   575  	}
   576  
   577  	cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
   578  	if err != nil {
   579  		err = fmt.Errorf("error parsing certificate: %v", err)
   580  		return nil, err
   581  	}
   582  
   583  	return cert.Leaf, nil
   584  }
   585  
   586  func (s *ChoriaSecurity) PublicCertBytes() ([]byte, error) {
   587  	if s.conf.Key == "" || s.conf.Certificate == "" {
   588  		return nil, fmt.Errorf("no certificates configured")
   589  	}
   590  
   591  	return os.ReadFile(s.conf.Certificate)
   592  }
   593  
   594  func (s *ChoriaSecurity) ShouldAllowCaller(name string, callers ...[]byte) (privileged bool, err error) {
   595  	switch len(callers) {
   596  	case 1:
   597  		return s.shouldAllowCallerUnsigned(name, callers[0])
   598  	case 2:
   599  		return s.shouldAllowSignedCaller(name, callers...)
   600  	default:
   601  		return false, fmt.Errorf("invalid caller data provided")
   602  	}
   603  }
   604  
   605  func (s *ChoriaSecurity) shouldAllowSignedCaller(name string, callers ...[]byte) (privileged bool, err error) {
   606  	if len(callers) != 2 {
   607  		return false, fmt.Errorf("invalid caller data")
   608  	}
   609  
   610  	signerT, err := tokens.ParseClientIDTokenUnverified(string(callers[1]))
   611  	if err != nil {
   612  		return false, fmt.Errorf("invalid signer token: %v", err)
   613  	}
   614  
   615  	if signerT.Permissions == nil || !signerT.Permissions.AuthenticationDelegator {
   616  		return false, fmt.Errorf("signer token does not have delegator permission")
   617  	}
   618  
   619  	callerT, err := tokens.ParseClientIDTokenUnverified(string(callers[0]))
   620  	if err != nil {
   621  		return false, fmt.Errorf("invalid caller token: %v", err)
   622  	}
   623  
   624  	if callerT.Permissions == nil || !(callerT.Permissions.SignedFleetManagement || callerT.Permissions.FleetManagement) {
   625  		return false, fmt.Errorf("caller does not have fleet management access")
   626  	}
   627  
   628  	// we do not check the name, delegators can override, but we log the delegation
   629  	s.log.Infof("Allowing delegator %s to authorize caller %s who holds token %s", signerT.CallerID, name, callerT.CallerID)
   630  
   631  	return true, nil
   632  }
   633  
   634  func (s *ChoriaSecurity) shouldAllowCallerUnsigned(name string, caller []byte) (privileged bool, err error) {
   635  	// will fail for non client tokens
   636  	// we do not verify since was all verified already in sig check
   637  	// TODO: we should think about servers making requests out to choria services or publishing registration data (1740)
   638  	token, err := tokens.ParseClientIDTokenUnverified(string(caller))
   639  	if err != nil {
   640  		return false, err
   641  	}
   642  
   643  	// technically already done in sig verify but cant harm
   644  	if token.Permissions == nil || !(token.Permissions.SignedFleetManagement || token.Permissions.FleetManagement) {
   645  		if token.Permissions.SignedFleetManagement {
   646  			return false, fmt.Errorf("requires signed fleet management access")
   647  		}
   648  		return false, fmt.Errorf("does not have fleet management access")
   649  	}
   650  
   651  	if token.CallerID != name {
   652  		return false, fmt.Errorf("caller name does not match token")
   653  	}
   654  
   655  	return false, nil
   656  }
   657  
   658  func (s *ChoriaSecurity) Enroll(ctx context.Context, wait time.Duration, cb func(digest string, try int)) error {
   659  	return errors.New("the choria security provider does not support enrollment")
   660  }
   661  
   662  func (s *ChoriaSecurity) ShouldSignReplies() bool { return s.conf.SignedReplies }