vendor: Update vendor logic

This commit is contained in:
Clayton Coleman 2020-04-08 14:34:43 -04:00
parent c6ac5cbc87
commit 4ca64b85f0
No known key found for this signature in database
GPG key ID: 3D16906B4F1C5CB3
1540 changed files with 265304 additions and 91616 deletions

View file

@ -0,0 +1,71 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package x509
import (
"crypto/x509"
"fmt"
"k8s.io/client-go/util/cert"
)
// StaticVerifierFn is a VerifyOptionFunc that always returns the same value. This allows verify options that cannot change.
func StaticVerifierFn(opts x509.VerifyOptions) VerifyOptionFunc {
return func() (x509.VerifyOptions, bool) {
return opts, true
}
}
// NewStaticVerifierFromFile creates a new verification func from a file. It reads the content and then fails.
// It will return a nil function if you pass an empty CA file.
func NewStaticVerifierFromFile(clientCA string) (VerifyOptionFunc, error) {
if len(clientCA) == 0 {
return nil, nil
}
// Wrap with an x509 verifier
var err error
opts := DefaultVerifyOptions()
opts.Roots, err = cert.NewPool(clientCA)
if err != nil {
return nil, fmt.Errorf("error loading certs from %s: %v", clientCA, err)
}
return StaticVerifierFn(opts), nil
}
// StringSliceProvider is a way to get a string slice value. It is heavily used for authentication headers among other places.
type StringSliceProvider interface {
// Value returns the current string slice. Callers should never mutate the returned value.
Value() []string
}
// StringSliceProviderFunc is a function that matches the StringSliceProvider interface
type StringSliceProviderFunc func() []string
// Value returns the current string slice. Callers should never mutate the returned value.
func (d StringSliceProviderFunc) Value() []string {
return d()
}
// StaticStringSlice a StringSliceProvider that returns a fixed value
type StaticStringSlice []string
// Value returns the current string slice. Callers should never mutate the returned value.
func (s StaticStringSlice) Value() []string {
return s
}

View file

@ -23,16 +23,24 @@ import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
)
var clientCertificateExpirationHistogram = prometheus.NewHistogram(
prometheus.HistogramOpts{
/*
* By default, the following metric is defined as falling under
* ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes)
*
* Promoting the stability level of the metric is a responsibility of the component owner, since it
* involves explicitly acknowledging support for the metric across multiple releases, in accordance with
* the metric stability policy.
*/
var clientCertificateExpirationHistogram = metrics.NewHistogram(
&metrics.HistogramOpts{
Namespace: "apiserver",
Subsystem: "client",
Name: "certificate_expiration_seconds",
@ -53,11 +61,12 @@ var clientCertificateExpirationHistogram = prometheus.NewHistogram(
(6 * 30 * 24 * time.Hour).Seconds(),
(12 * 30 * 24 * time.Hour).Seconds(),
},
StabilityLevel: metrics.ALPHA,
},
)
func init() {
prometheus.MustRegister(clientCertificateExpirationHistogram)
legacyregistry.MustRegister(clientCertificateExpirationHistogram)
}
// UserConversion defines an interface for extracting user info from a client certificate chain
@ -73,16 +82,28 @@ func (f UserConversionFunc) User(chain []*x509.Certificate) (*authenticator.Resp
return f(chain)
}
// VerifyOptionFunc is function which provides a shallow copy of the VerifyOptions to the authenticator. This allows
// for cases where the options (particularly the CAs) can change. If the bool is false, then the returned VerifyOptions
// are ignored and the authenticator will express "no opinion". This allows a clear signal for cases where a CertPool
// is eventually expected, but not currently present.
type VerifyOptionFunc func() (x509.VerifyOptions, bool)
// Authenticator implements request.Authenticator by extracting user info from verified client certificates
type Authenticator struct {
opts x509.VerifyOptions
user UserConversion
verifyOptionsFn VerifyOptionFunc
user UserConversion
}
// New returns a request.Authenticator that verifies client certificates using the provided
// VerifyOptions, and converts valid certificate chains into user.Info using the provided UserConversion
func New(opts x509.VerifyOptions, user UserConversion) *Authenticator {
return &Authenticator{opts, user}
return NewDynamic(StaticVerifierFn(opts), user)
}
// NewDynamic returns a request.Authenticator that verifies client certificates using the provided
// VerifyOptionFunc (which may be dynamic), and converts valid certificate chains into user.Info using the provided UserConversion
func NewDynamic(verifyOptionsFn VerifyOptionFunc, user UserConversion) *Authenticator {
return &Authenticator{verifyOptionsFn, user}
}
// AuthenticateRequest authenticates the request using presented client certificates
@ -92,7 +113,11 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.R
}
// Use intermediates, if provided
optsCopy := a.opts
optsCopy, ok := a.verifyOptionsFn()
// if there are intentionally no verify options, then we cannot authenticate this request
if !ok {
return nil, false, nil
}
if optsCopy.Intermediates == nil && len(req.TLS.PeerCertificates) > 1 {
optsCopy.Intermediates = x509.NewCertPool()
for _, intermediate := range req.TLS.PeerCertificates[1:] {
@ -124,17 +149,23 @@ func (a *Authenticator) AuthenticateRequest(req *http.Request) (*authenticator.R
// Verifier implements request.Authenticator by verifying a client cert on the request, then delegating to the wrapped auth
type Verifier struct {
opts x509.VerifyOptions
auth authenticator.Request
verifyOptionsFn VerifyOptionFunc
auth authenticator.Request
// allowedCommonNames contains the common names which a verified certificate is allowed to have.
// If empty, all verified certificates are allowed.
allowedCommonNames sets.String
allowedCommonNames StringSliceProvider
}
// NewVerifier create a request.Authenticator by verifying a client cert on the request, then delegating to the wrapped auth
func NewVerifier(opts x509.VerifyOptions, auth authenticator.Request, allowedCommonNames sets.String) authenticator.Request {
return &Verifier{opts, auth, allowedCommonNames}
return NewDynamicCAVerifier(StaticVerifierFn(opts), auth, StaticStringSlice(allowedCommonNames.List()))
}
// NewDynamicCAVerifier create a request.Authenticator by verifying a client cert on the request, then delegating to the wrapped auth
// TODO make the allowedCommonNames dynamic
func NewDynamicCAVerifier(verifyOptionsFn VerifyOptionFunc, auth authenticator.Request, allowedCommonNames StringSliceProvider) authenticator.Request {
return &Verifier{verifyOptionsFn, auth, allowedCommonNames}
}
// AuthenticateRequest verifies the presented client certificate, then delegates to the wrapped auth
@ -144,7 +175,11 @@ func (a *Verifier) AuthenticateRequest(req *http.Request) (*authenticator.Respon
}
// Use intermediates, if provided
optsCopy := a.opts
optsCopy, ok := a.verifyOptionsFn()
// if there are intentionally no verify options, then we cannot authenticate this request
if !ok {
return nil, false, nil
}
if optsCopy.Intermediates == nil && len(req.TLS.PeerCertificates) > 1 {
optsCopy.Intermediates = x509.NewCertPool()
for _, intermediate := range req.TLS.PeerCertificates[1:] {
@ -163,12 +198,14 @@ func (a *Verifier) AuthenticateRequest(req *http.Request) (*authenticator.Respon
func (a *Verifier) verifySubject(subject pkix.Name) error {
// No CN restrictions
if len(a.allowedCommonNames) == 0 {
if len(a.allowedCommonNames.Value()) == 0 {
return nil
}
// Enforce CN restrictions
if a.allowedCommonNames.Has(subject.CommonName) {
return nil
for _, allowedCommonName := range a.allowedCommonNames.Value() {
if allowedCommonName == subject.CommonName {
return nil
}
}
return fmt.Errorf("x509: subject with cn=%s is not in the allowed list", subject.CommonName)
}