join client CA bundles into the accept path for genericapiserver
This commit is contained in:
@@ -18,6 +18,7 @@ package genericapiserver
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -60,6 +61,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/routes"
|
||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
authenticatorunion "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
||||
@@ -180,7 +182,7 @@ type SecureServingInfo struct {
|
||||
SNICerts map[string]*tls.Certificate
|
||||
|
||||
// ClientCA is the certificate bundle for all the signers that you'll recognize for incoming client certificates
|
||||
ClientCA string
|
||||
ClientCA *x509.CertPool
|
||||
}
|
||||
|
||||
// NewConfig returns a Config struct with the default values
|
||||
@@ -299,17 +301,40 @@ func (c *Config) ApplyInsecureServingOptions(insecureServing *options.ServingOpt
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) ApplyAuthenticationOptions(o *options.BuiltInAuthenticationOptions) *Config {
|
||||
func (c *Config) ApplyAuthenticationOptions(o *options.BuiltInAuthenticationOptions) (*Config, error) {
|
||||
if o == nil || o.PasswordFile == nil {
|
||||
return c
|
||||
return c, nil
|
||||
}
|
||||
|
||||
if o.ClientCert != nil && c.SecureServingInfo != nil {
|
||||
c.SecureServingInfo.ClientCA = o.ClientCert.ClientCA
|
||||
if c.SecureServingInfo != nil {
|
||||
if o.ClientCert != nil && len(o.ClientCert.ClientCA) > 0 {
|
||||
clientCAs, err := certutil.CertsFromFile(o.ClientCert.ClientCA)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load client CA file: %v", err)
|
||||
}
|
||||
if c.SecureServingInfo.ClientCA == nil {
|
||||
c.SecureServingInfo.ClientCA = x509.NewCertPool()
|
||||
}
|
||||
for _, cert := range clientCAs {
|
||||
c.SecureServingInfo.ClientCA.AddCert(cert)
|
||||
}
|
||||
}
|
||||
if o.RequestHeader != nil && len(o.RequestHeader.ClientCAFile) > 0 {
|
||||
clientCAs, err := certutil.CertsFromFile(o.RequestHeader.ClientCAFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load requestheader client CA file: %v", err)
|
||||
}
|
||||
if c.SecureServingInfo.ClientCA == nil {
|
||||
c.SecureServingInfo.ClientCA = x509.NewCertPool()
|
||||
}
|
||||
for _, cert := range clientCAs {
|
||||
c.SecureServingInfo.ClientCA.AddCert(cert)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.SupportsBasicAuth = len(o.PasswordFile.BasicAuthFile) > 0
|
||||
return c
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ApplyOptions applies the run options to the method receiver and returns self
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/validation"
|
||||
|
||||
@@ -69,16 +68,12 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error {
|
||||
secureServer.TLSConfig.Certificates = append(secureServer.TLSConfig.Certificates, *c)
|
||||
}
|
||||
|
||||
if len(s.SecureServingInfo.ClientCA) > 0 {
|
||||
clientCAs, err := certutil.NewPool(s.SecureServingInfo.ClientCA)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
||||
}
|
||||
if s.SecureServingInfo.ClientCA != nil {
|
||||
// Populate PeerCertificates in requests, but don't reject connections without certificates
|
||||
// This allows certificates to be validated by authenticators, while still allowing other auth types
|
||||
secureServer.TLSConfig.ClientAuth = tls.RequestClientCert
|
||||
// Specify allowed CAs for client certificates
|
||||
secureServer.TLSConfig.ClientCAs = clientCAs
|
||||
secureServer.TLSConfig.ClientCAs = s.SecureServingInfo.ClientCA
|
||||
}
|
||||
|
||||
glog.Infof("Serving securely on %s", s.SecureServingInfo.BindAddress)
|
||||
|
||||
@@ -90,7 +90,7 @@ func WriteKey(keyPath string, data []byte) error {
|
||||
// NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file.
|
||||
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
|
||||
func NewPool(filename string) (*x509.CertPool, error) {
|
||||
certs, err := certsFromFile(filename)
|
||||
certs, err := CertsFromFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -101,9 +101,9 @@ func NewPool(filename string) (*x509.CertPool, error) {
|
||||
return pool, nil
|
||||
}
|
||||
|
||||
// certsFromFile returns the x509.Certificates contained in the given PEM-encoded file.
|
||||
// CertsFromFile returns the x509.Certificates contained in the given PEM-encoded file.
|
||||
// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
|
||||
func certsFromFile(file string) ([]*x509.Certificate, error) {
|
||||
func CertsFromFile(file string) ([]*x509.Certificate, error) {
|
||||
if len(file) == 0 {
|
||||
return nil, errors.New("error reading certificates from an empty filename")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user