github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/cloudflare/cfssl/signer/universal/universal.go (about)

     1  // Package universal implements a signer that can do remote or local
     2  package universal
     3  
     4  import (
     5  	"github.com/hellobchain/newcryptosm/http"
     6  	"github.com/hellobchain/newcryptosm/x509"
     7  
     8  	"github.com/hellobchain/third_party/cloudflare/cfssl/certdb"
     9  	"github.com/hellobchain/third_party/cloudflare/cfssl/config"
    10  	cferr "github.com/hellobchain/third_party/cloudflare/cfssl/errors"
    11  	"github.com/hellobchain/third_party/cloudflare/cfssl/info"
    12  	"github.com/hellobchain/third_party/cloudflare/cfssl/signer"
    13  	"github.com/hellobchain/third_party/cloudflare/cfssl/signer/local"
    14  	"github.com/hellobchain/third_party/cloudflare/cfssl/signer/remote"
    15  )
    16  
    17  // Signer represents a universal signer which is both local and remote
    18  // to fulfill the signer.Signer interface.
    19  type Signer struct {
    20  	local  signer.Signer
    21  	remote signer.Signer
    22  	policy *config.Signing
    23  }
    24  
    25  // Root is used to define where the universal signer gets its public
    26  // certificate and private keys for signing.
    27  type Root struct {
    28  	Config      map[string]string
    29  	ForceRemote bool
    30  }
    31  
    32  // a localSignerCheck looks at the Config keys in the Root, and
    33  // decides whether it has enough information to produce a signer.
    34  type localSignerCheck func(root *Root, policy *config.Signing) (signer.Signer, bool, error)
    35  
    36  // fileBackedSigner determines whether a file-backed local signer is supported.
    37  func fileBackedSigner(root *Root, policy *config.Signing) (signer.Signer, bool, error) {
    38  	keyFile := root.Config["key-file"]
    39  	certFile := root.Config["cert-file"]
    40  
    41  	if keyFile == "" {
    42  		return nil, false, nil
    43  	}
    44  
    45  	signer, err := local.NewSignerFromFile(certFile, keyFile, policy)
    46  	return signer, true, err
    47  }
    48  
    49  var localSignerList = []localSignerCheck{
    50  	fileBackedSigner,
    51  }
    52  
    53  // PrependLocalSignerToList prepends signer to the local signer's list
    54  func PrependLocalSignerToList(signer localSignerCheck) {
    55  	localSignerList = append([]localSignerCheck{signer}, localSignerList...)
    56  }
    57  
    58  func newLocalSigner(root Root, policy *config.Signing) (s signer.Signer, err error) {
    59  	// shouldProvide indicates whether the
    60  	// function *should* have produced a key. If
    61  	// it's true, we should use the signer and
    62  	// error returned. Otherwise, keep looking for
    63  	// signers.
    64  	var shouldProvide bool
    65  
    66  	// localSignerList is defined in the
    67  	// universal_signers*.go files. These activate
    68  	// and deactivate signers based on build
    69  	// flags; for example,
    70  	// universal_signers_pkcs11.go contains a list
    71  	// of valid signers when PKCS #11 is turned
    72  	// on.
    73  	for _, possibleSigner := range localSignerList {
    74  		s, shouldProvide, err = possibleSigner(&root, policy)
    75  		if shouldProvide {
    76  			break
    77  		}
    78  	}
    79  
    80  	if s == nil {
    81  		err = cferr.New(cferr.PrivateKeyError, cferr.Unknown)
    82  	}
    83  
    84  	return s, err
    85  }
    86  
    87  func newUniversalSigner(root Root, policy *config.Signing) (*Signer, error) {
    88  	ls, err := newLocalSigner(root, policy)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	rs, err := remote.NewSigner(policy)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	s := &Signer{
    99  		policy: policy,
   100  		local:  ls,
   101  		remote: rs,
   102  	}
   103  	return s, err
   104  }
   105  
   106  // NewSigner generates a new certificate signer from a Root structure.
   107  // This is one of two standard signers: local or remote. If the root
   108  // structure specifies a force remote, then a remote signer is created,
   109  // otherwise either a remote or local signer is generated based on the
   110  // policy. For a local signer, the CertFile and KeyFile need to be
   111  // defined in Root.
   112  func NewSigner(root Root, policy *config.Signing) (signer.Signer, error) {
   113  	if policy == nil {
   114  		policy = &config.Signing{
   115  			Profiles: map[string]*config.SigningProfile{},
   116  			Default:  config.DefaultConfig(),
   117  		}
   118  	}
   119  
   120  	if !policy.Valid() {
   121  		return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
   122  	}
   123  
   124  	var s signer.Signer
   125  	var err error
   126  	if root.ForceRemote {
   127  		s, err = remote.NewSigner(policy)
   128  	} else {
   129  		if policy.NeedsLocalSigner() && policy.NeedsRemoteSigner() {
   130  			s, err = newUniversalSigner(root, policy)
   131  		} else {
   132  			if policy.NeedsLocalSigner() {
   133  				s, err = newLocalSigner(root, policy)
   134  			}
   135  			if policy.NeedsRemoteSigner() {
   136  				s, err = remote.NewSigner(policy)
   137  			}
   138  		}
   139  	}
   140  
   141  	return s, err
   142  }
   143  
   144  // getMatchingProfile returns the SigningProfile that matches the profile passed.
   145  // if an empty profile string is passed it returns the default profile.
   146  func (s *Signer) getMatchingProfile(profile string) (*config.SigningProfile, error) {
   147  	if profile == "" {
   148  		return s.policy.Default, nil
   149  	}
   150  
   151  	for p, signingProfile := range s.policy.Profiles {
   152  		if p == profile {
   153  			return signingProfile, nil
   154  		}
   155  	}
   156  
   157  	return nil, cferr.New(cferr.PolicyError, cferr.UnknownProfile)
   158  }
   159  
   160  // Sign sends a signature request to either the remote or local signer,
   161  // receiving a signed certificate or an error in response.
   162  func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
   163  	profile, err := s.getMatchingProfile(req.Profile)
   164  	if err != nil {
   165  		return cert, err
   166  	}
   167  
   168  	if profile.RemoteServer != "" {
   169  		return s.remote.Sign(req)
   170  	}
   171  	return s.local.Sign(req)
   172  
   173  }
   174  
   175  // Info sends an info request to the remote or local CFSSL server
   176  // receiving an Resp struct or an error in response.
   177  func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
   178  	profile, err := s.getMatchingProfile(req.Profile)
   179  	if err != nil {
   180  		return resp, err
   181  	}
   182  
   183  	if profile.RemoteServer != "" {
   184  		return s.remote.Info(req)
   185  	}
   186  	return s.local.Info(req)
   187  
   188  }
   189  
   190  // SetDBAccessor sets the signer's cert db accessor.
   191  func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
   192  	s.local.SetDBAccessor(dba)
   193  }
   194  
   195  // GetDBAccessor returns the signer's cert db accessor.
   196  func (s *Signer) GetDBAccessor() certdb.Accessor {
   197  	return s.local.GetDBAccessor()
   198  }
   199  
   200  // SetReqModifier sets the function to call to modify the HTTP request prior to sending it
   201  func (s *Signer) SetReqModifier(mod func(*http.Request, []byte)) {
   202  	s.local.SetReqModifier(mod)
   203  	s.remote.SetReqModifier(mod)
   204  }
   205  
   206  // SigAlgo returns the RSA signer's signature algorithm.
   207  func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
   208  	if s.local != nil {
   209  		return s.local.SigAlgo()
   210  	}
   211  
   212  	// currently remote.SigAlgo just returns
   213  	// x509.UnknownSignatureAlgorithm.
   214  	return s.remote.SigAlgo()
   215  }
   216  
   217  // SetPolicy sets the signer's signature policy.
   218  func (s *Signer) SetPolicy(policy *config.Signing) {
   219  	s.policy = policy
   220  }
   221  
   222  // Policy returns the signer's policy.
   223  func (s *Signer) Policy() *config.Signing {
   224  	return s.policy
   225  }