Merge pull request #6190 from liggitt/client_cert_auth
Add client cert authentication
This commit is contained in:
@@ -19,18 +19,61 @@ package apiserver
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/request/x509"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/token/tokenfile"
|
||||
)
|
||||
|
||||
// NewAuthenticatorFromTokenFile returns an authenticator.Request or an error
|
||||
func NewAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Request, error) {
|
||||
var authenticator authenticator.Request
|
||||
if len(tokenAuthFile) != 0 {
|
||||
tokenAuthenticator, err := tokenfile.NewCSV(tokenAuthFile)
|
||||
// NewAuthenticator returns an authenticator.Request or an error
|
||||
func NewAuthenticator(clientCAFile string, tokenFile string) (authenticator.Request, error) {
|
||||
authenticators := []authenticator.Request{}
|
||||
|
||||
if len(clientCAFile) > 0 {
|
||||
certAuth, err := newAuthenticatorFromClientCAFile(clientCAFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authenticator = bearertoken.New(tokenAuthenticator)
|
||||
authenticators = append(authenticators, certAuth)
|
||||
}
|
||||
return authenticator, nil
|
||||
|
||||
if len(tokenFile) > 0 {
|
||||
tokenAuth, err := newAuthenticatorFromTokenFile(tokenFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authenticators = append(authenticators, tokenAuth)
|
||||
}
|
||||
|
||||
if len(authenticators) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if len(authenticators) == 1 {
|
||||
return authenticators[1], nil
|
||||
}
|
||||
return union.New(authenticators...), nil
|
||||
|
||||
}
|
||||
|
||||
// newAuthenticatorFromTokenFile returns an authenticator.Request or an error
|
||||
func newAuthenticatorFromTokenFile(tokenAuthFile string) (authenticator.Request, error) {
|
||||
tokenAuthenticator, err := tokenfile.NewCSV(tokenAuthFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bearertoken.New(tokenAuthenticator), nil
|
||||
}
|
||||
|
||||
// newAuthenticatorFromClientCAFile returns an authenticator.Request or an error
|
||||
func newAuthenticatorFromClientCAFile(clientCAFile string) (authenticator.Request, error) {
|
||||
roots, err := util.CertPoolFromFile(clientCAFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := x509.DefaultVerifyOptions()
|
||||
opts.Roots = roots
|
||||
|
||||
return x509.New(opts, x509.CommonNameUserConversion), nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
@@ -97,3 +98,65 @@ func GenerateSelfSignedCert(host, certPath, keyPath string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CertPoolFromFile 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 CertPoolFromFile(filename string) (*x509.CertPool, error) {
|
||||
certs, err := certificatesFromFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pool := x509.NewCertPool()
|
||||
for _, cert := range certs {
|
||||
pool.AddCert(cert)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
|
||||
// certificatesFromFile 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 certificatesFromFile(file string) ([]*x509.Certificate, error) {
|
||||
if len(file) == 0 {
|
||||
return nil, errors.New("error reading certificates from an empty filename")
|
||||
}
|
||||
pemBlock, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs, err := certsFromPEM(pemBlock)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading %s: %s", file, err)
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
// certsFromPEM returns the x509.Certificates contained in the given PEM-encoded byte array
|
||||
// Returns an error if a certificate could not be parsed, or if the data does not contain any certificates
|
||||
func certsFromPEM(pemCerts []byte) ([]*x509.Certificate, error) {
|
||||
ok := false
|
||||
certs := []*x509.Certificate{}
|
||||
for len(pemCerts) > 0 {
|
||||
var block *pem.Block
|
||||
block, pemCerts = pem.Decode(pemCerts)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
// Only use PEM "CERTIFICATE" blocks without extra headers
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return certs, err
|
||||
}
|
||||
|
||||
certs = append(certs, cert)
|
||||
ok = true
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return certs, errors.New("could not read any certificates")
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user