ca: move SignCertificate to CAManager
To reduce the scope of Server, and keep all the CA logic together
This commit is contained in:
parent
a0320169fe
commit
c2e85f25d4
|
@ -109,11 +109,18 @@ type AutoConfigBackend interface {
|
|||
CreateACLToken(template *structs.ACLToken) (*structs.ACLToken, error)
|
||||
DatacenterJoinAddresses(segment string) ([]string, error)
|
||||
ForwardRPC(method string, info structs.RPCInfo, reply interface{}) (bool, error)
|
||||
|
||||
GetCARoots() (*structs.IndexedCARoots, error)
|
||||
SignCertificate(csr *x509.CertificateRequest, id connect.CertURI) (*structs.IssuedCert, error)
|
||||
}
|
||||
|
||||
type autoConfigBackend struct {
|
||||
*Server
|
||||
}
|
||||
|
||||
func (b autoConfigBackend) SignCertificate(csr *x509.CertificateRequest, id connect.CertURI) (*structs.IssuedCert, error) {
|
||||
return b.Server.caManager.SignCertificate(csr, id)
|
||||
}
|
||||
|
||||
// AutoConfig endpoint is used for cluster auto configuration operations
|
||||
type AutoConfig struct {
|
||||
// currently AutoConfig does not support pushing down any configuration that would be reloadable on the servers
|
||||
|
|
|
@ -192,7 +192,7 @@ func (s *ConnectCA) Sign(
|
|||
}
|
||||
}
|
||||
|
||||
cert, err := s.srv.SignCertificate(csr, spiffeID)
|
||||
cert, err := s.srv.caManager.SignCertificate(csr, spiffeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -492,7 +492,6 @@ func (c *FSM) applyConnectCALeafOperation(buf []byte, index uint64) interface{}
|
|||
switch req.Op {
|
||||
case structs.CALeafOpIncrementIndex:
|
||||
// Use current index as the new value as well as the value to write at.
|
||||
// TODO(banks) do we even use this op any more?
|
||||
if err := c.state.CALeafSetIndex(index, index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ const (
|
|||
type caServerDelegate interface {
|
||||
ca.ConsulProviderStateDelegate
|
||||
IsLeader() bool
|
||||
ApplyCALeafRequest() (uint64, error)
|
||||
|
||||
forwardDC(method, dc string, args interface{}, reply interface{}) error
|
||||
generateCASignRequest(csr string) *structs.CASignRequest
|
||||
|
@ -48,6 +49,8 @@ type CAManager struct {
|
|||
delegate caServerDelegate
|
||||
serverConf *Config
|
||||
logger hclog.Logger
|
||||
// rate limiter to use when signing leaf certificates
|
||||
caLeafLimiter connectSignRateLimiter
|
||||
|
||||
providerLock sync.RWMutex
|
||||
// provider is the current CA provider in use for Connect. This is
|
||||
|
@ -82,6 +85,29 @@ func (c *caDelegateWithState) ApplyCARequest(req *structs.CARequest) (interface{
|
|||
return c.Server.raftApplyMsgpack(structs.ConnectCARequestType, req)
|
||||
}
|
||||
|
||||
func (c *caDelegateWithState) ApplyCALeafRequest() (uint64, error) {
|
||||
// TODO(banks): when we implement IssuedCerts table we can use the insert to
|
||||
// that as the raft index to return in response.
|
||||
//
|
||||
// UPDATE(mkeeler): The original implementation relied on updating the CAConfig
|
||||
// and using its index as the ModifyIndex for certs. This was buggy. The long
|
||||
// term goal is still to insert some metadata into raft about the certificates
|
||||
// and use that raft index for the ModifyIndex. This is a partial step in that
|
||||
// direction except that we only are setting an index and not storing the
|
||||
// metadata.
|
||||
req := structs.CALeafRequest{
|
||||
Op: structs.CALeafOpIncrementIndex,
|
||||
Datacenter: c.Server.config.Datacenter,
|
||||
}
|
||||
resp, err := c.Server.raftApplyMsgpack(structs.ConnectCALeafRequestType|structs.IgnoreUnknownTypeFlag, &req)
|
||||
|
||||
modIdx, ok := resp.(uint64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("Invalid response from updating the leaf cert index")
|
||||
}
|
||||
return modIdx, err
|
||||
}
|
||||
|
||||
func (c *caDelegateWithState) generateCASignRequest(csr string) *structs.CASignRequest {
|
||||
return &structs.CASignRequest{
|
||||
Datacenter: c.Server.config.PrimaryDatacenter,
|
||||
|
|
|
@ -62,6 +62,10 @@ func (m *mockCAServerDelegate) CheckServers(datacenter string, fn func(*metadata
|
|||
})
|
||||
}
|
||||
|
||||
func (m *mockCAServerDelegate) ApplyCALeafRequest() (uint64, error) {
|
||||
return 3, nil
|
||||
}
|
||||
|
||||
// ApplyCARequest mirrors FSM.applyConnectCAOperation because that functionality
|
||||
// is not exported.
|
||||
func (m *mockCAServerDelegate) ApplyCARequest(req *structs.CARequest) (interface{}, error) {
|
||||
|
|
|
@ -878,7 +878,7 @@ func (s *Server) setupRPC() error {
|
|||
authz = &disabledAuthorizer{}
|
||||
}
|
||||
// now register with the insecure RPC server
|
||||
s.insecureRPCServer.Register(NewAutoConfig(s.config, s.tlsConfigurator, s, authz))
|
||||
s.insecureRPCServer.Register(NewAutoConfig(s.config, s.tlsConfigurator, autoConfigBackend{Server: s}, authz))
|
||||
|
||||
ln, err := net.ListenTCP("tcp", s.config.RPCAddr)
|
||||
if err != nil {
|
||||
|
@ -1456,6 +1456,7 @@ func (s *Server) isReadyForConsistentReads() bool {
|
|||
}
|
||||
|
||||
// CreateACLToken will create an ACL token from the given template
|
||||
// TODO: move to autoConfigBackend
|
||||
func (s *Server) CreateACLToken(template *structs.ACLToken) (*structs.ACLToken, error) {
|
||||
// we have to require local tokens or else it would require having these servers use a token with acl:write to make a
|
||||
// token create RPC to the servers in the primary DC.
|
||||
|
@ -1504,6 +1505,7 @@ func (s *Server) CreateACLToken(template *structs.ACLToken) (*structs.ACLToken,
|
|||
|
||||
// DatacenterJoinAddresses will return all the strings suitable for usage in
|
||||
// retry join operations to connect to the the LAN or LAN segment gossip pool.
|
||||
// TODO: move to autoConfigBackend
|
||||
func (s *Server) DatacenterJoinAddresses(segment string) ([]string, error) {
|
||||
members, err := s.LANSegmentMembers(segment)
|
||||
if err != nil {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/hashicorp/consul/lib/semaphore"
|
||||
)
|
||||
|
||||
// TODO: move to leader_connect_ca.go
|
||||
type connectSignRateLimiter struct {
|
||||
// csrRateLimiter limits the rate of signing new certs if configured. Lazily
|
||||
// initialized from current config to support dynamic changes.
|
||||
|
@ -70,7 +71,8 @@ func (l *connectSignRateLimiter) getCSRRateLimiterWithLimit(limit rate.Limit) *r
|
|||
return l.csrRateLimiter
|
||||
}
|
||||
|
||||
// GetCARoots will retrieve
|
||||
// GetCARoots will retrieve CARoots
|
||||
// TODO: move to autoConfigBackend
|
||||
func (s *Server) GetCARoots() (*structs.IndexedCARoots, error) {
|
||||
return s.getCARoots(nil, s.fsm.State())
|
||||
}
|
||||
|
@ -138,9 +140,9 @@ func (s *Server) getCARoots(ws memdb.WatchSet, state *state.Store) (*structs.Ind
|
|||
return indexedRoots, nil
|
||||
}
|
||||
|
||||
// TODO: Move this off Server. This is only called by RPC endpoints.
|
||||
func (s *Server) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.CertURI) (*structs.IssuedCert, error) {
|
||||
provider, caRoot := s.caManager.getCAProvider()
|
||||
// TODO: Move this to leader_connect_ca.go
|
||||
func (c *CAManager) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.CertURI) (*structs.IssuedCert, error) {
|
||||
provider, caRoot := c.getCAProvider()
|
||||
if provider == nil {
|
||||
return nil, fmt.Errorf("CA is uninitialized and unable to sign certificates yet: provider is nil")
|
||||
} else if caRoot == nil {
|
||||
|
@ -148,7 +150,7 @@ func (s *Server) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.
|
|||
}
|
||||
|
||||
// Verify that the CSR entity is in the cluster's trust domain
|
||||
state := s.fsm.State()
|
||||
state := c.delegate.State()
|
||||
_, config, err := state.CAConfig(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -198,7 +200,7 @@ func (s *Server) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.
|
|||
return nil, err
|
||||
}
|
||||
if commonCfg.CSRMaxPerSecond > 0 {
|
||||
lim := s.caLeafLimiter.getCSRRateLimiterWithLimit(rate.Limit(commonCfg.CSRMaxPerSecond))
|
||||
lim := c.caLeafLimiter.getCSRRateLimiterWithLimit(rate.Limit(commonCfg.CSRMaxPerSecond))
|
||||
// Wait up to the small threshold we allow for a token.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), csrLimitWait)
|
||||
defer cancel()
|
||||
|
@ -206,13 +208,13 @@ func (s *Server) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.
|
|||
return nil, ErrRateLimited
|
||||
}
|
||||
} else if commonCfg.CSRMaxConcurrent > 0 {
|
||||
s.caLeafLimiter.csrConcurrencyLimiter.SetSize(int64(commonCfg.CSRMaxConcurrent))
|
||||
c.caLeafLimiter.csrConcurrencyLimiter.SetSize(int64(commonCfg.CSRMaxConcurrent))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), csrLimitWait)
|
||||
defer cancel()
|
||||
if err := s.caLeafLimiter.csrConcurrencyLimiter.Acquire(ctx); err != nil {
|
||||
if err := c.caLeafLimiter.csrConcurrencyLimiter.Acquire(ctx); err != nil {
|
||||
return nil, ErrRateLimited
|
||||
}
|
||||
defer s.caLeafLimiter.csrConcurrencyLimiter.Release()
|
||||
defer c.caLeafLimiter.csrConcurrencyLimiter.Release()
|
||||
}
|
||||
|
||||
connect.HackSANExtensionForCSR(csr)
|
||||
|
@ -245,30 +247,11 @@ func (s *Server) SignCertificate(csr *x509.CertificateRequest, spiffeID connect.
|
|||
pem = pem + ca.EnsureTrailingNewline(inter)
|
||||
}
|
||||
|
||||
// TODO(banks): when we implement IssuedCerts table we can use the insert to
|
||||
// that as the raft index to return in response.
|
||||
//
|
||||
// UPDATE(mkeeler): The original implementation relied on updating the CAConfig
|
||||
// and using its index as the ModifyIndex for certs. This was buggy. The long
|
||||
// term goal is still to insert some metadata into raft about the certificates
|
||||
// and use that raft index for the ModifyIndex. This is a partial step in that
|
||||
// direction except that we only are setting an index and not storing the
|
||||
// metadata.
|
||||
req := structs.CALeafRequest{
|
||||
Op: structs.CALeafOpIncrementIndex,
|
||||
Datacenter: s.config.Datacenter,
|
||||
}
|
||||
|
||||
resp, err := s.raftApply(structs.ConnectCALeafRequestType|structs.IgnoreUnknownTypeFlag, &req)
|
||||
modIdx, err := c.delegate.ApplyCALeafRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modIdx, ok := resp.(uint64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Invalid response from updating the leaf cert index")
|
||||
}
|
||||
|
||||
cert, err := connect.ParseCert(pem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in New Issue