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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
// Package universal implements a signer that can do remote or local
package universal
import (
"crypto/x509"
"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/config"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/info"
"github.com/cloudflare/cfssl/signer"
"github.com/cloudflare/cfssl/signer/local"
"github.com/cloudflare/cfssl/signer/remote"
)
// Signer represents a universal signer which is both local and remote
// to fulfill the signer.Signer interface.
type Signer struct {
local signer.Signer
remote signer.Signer
policy *config.Signing
}
// Root is used to define where the universal signer gets its public
// certificate and private keys for signing.
type Root struct {
Config map[string]string
ForceRemote bool
}
// a localSignerCheck looks at the Config keys in the Root, and
// decides whether it has enough information to produce a signer.
type localSignerCheck func(root *Root, policy *config.Signing) (signer.Signer, bool, error)
// fileBackedSigner determines whether a file-backed local signer is supported.
func fileBackedSigner(root *Root, policy *config.Signing) (signer.Signer, bool, error) {
keyFile := root.Config["key-file"]
certFile := root.Config["cert-file"]
if keyFile == "" {
return nil, false, nil
}
signer, err := local.NewSignerFromFile(certFile, keyFile, policy)
return signer, true, err
}
var localSignerList = []localSignerCheck{
fileBackedSigner,
}
func newLocalSigner(root Root, policy *config.Signing) (s signer.Signer, err error) {
// shouldProvide indicates whether the
// function *should* have produced a key. If
// it's true, we should use the signer and
// error returned. Otherwise, keep looking for
// signers.
var shouldProvide bool
// localSignerList is defined in the
// universal_signers*.go files. These activate
// and deactivate signers based on build
// flags; for example,
// universal_signers_pkcs11.go contains a list
// of valid signers when PKCS #11 is turned
// on.
for _, possibleSigner := range localSignerList {
s, shouldProvide, err = possibleSigner(&root, policy)
if shouldProvide {
break
}
}
if s == nil {
err = cferr.New(cferr.PrivateKeyError, cferr.Unknown)
}
return s, err
}
func newUniversalSigner(root Root, policy *config.Signing) (*Signer, error) {
ls, err := newLocalSigner(root, policy)
if err != nil {
return nil, err
}
rs, err := remote.NewSigner(policy)
if err != nil {
return nil, err
}
s := &Signer{
policy: policy,
local: ls,
remote: rs,
}
return s, err
}
// NewSigner generates a new certificate signer from a Root structure.
// This is one of two standard signers: local or remote. If the root
// structure specifies a force remote, then a remote signer is created,
// otherwise either a remote or local signer is generated based on the
// policy. For a local signer, the CertFile and KeyFile need to be
// defined in Root.
func NewSigner(root Root, policy *config.Signing) (signer.Signer, error) {
if policy == nil {
policy = &config.Signing{
Profiles: map[string]*config.SigningProfile{},
Default: config.DefaultConfig(),
}
}
if !policy.Valid() {
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
}
var s signer.Signer
var err error
if root.ForceRemote {
s, err = remote.NewSigner(policy)
} else {
if policy.NeedsLocalSigner() && policy.NeedsRemoteSigner() {
s, err = newUniversalSigner(root, policy)
} else {
if policy.NeedsLocalSigner() {
s, err = newLocalSigner(root, policy)
}
if policy.NeedsRemoteSigner() {
s, err = remote.NewSigner(policy)
}
}
}
return s, err
}
// getMatchingProfile returns the SigningProfile that matches the profile passed.
// if an empty profile string is passed it returns the default profile.
func (s *Signer) getMatchingProfile(profile string) (*config.SigningProfile, error) {
if profile == "" {
return s.policy.Default, nil
}
for p, signingProfile := range s.policy.Profiles {
if p == profile {
return signingProfile, nil
}
}
return nil, cferr.New(cferr.PolicyError, cferr.UnknownProfile)
}
// Sign sends a signature request to either the remote or local signer,
// receiving a signed certificate or an error in response.
func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
profile, err := s.getMatchingProfile(req.Profile)
if err != nil {
return cert, err
}
if profile.RemoteServer != "" {
return s.remote.Sign(req)
}
return s.local.Sign(req)
}
// Info sends an info request to the remote or local CFSSL server
// receiving an Resp struct or an error in response.
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
profile, err := s.getMatchingProfile(req.Profile)
if err != nil {
return resp, err
}
if profile.RemoteServer != "" {
return s.remote.Info(req)
}
return s.local.Info(req)
}
// SetDBAccessor sets the signer's cert db accessor.
func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
s.local.SetDBAccessor(dba)
s.remote.SetDBAccessor(dba)
}
// SigAlgo returns the RSA signer's signature algorithm.
func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
if s.local != nil {
return s.local.SigAlgo()
}
// currently remote.SigAlgo just returns
// x509.UnknownSignatureAlgorithm.
return s.remote.SigAlgo()
}
// SetPolicy sets the signer's signature policy.
func (s *Signer) SetPolicy(policy *config.Signing) {
s.policy = policy
}
// Policy returns the signer's policy.
func (s *Signer) Policy() *config.Signing {
return s.policy
}
|