mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 10:53:34 +00:00
vendor update for CSI 0.3.0
This commit is contained in:
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/BUILD
generated
vendored
@ -26,6 +26,7 @@ go_library(
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/certificates/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/certificate:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/connrotation:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/OWNERS
generated
vendored
@ -1,6 +1,7 @@
|
||||
reviewers:
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- awly
|
||||
approvers:
|
||||
- mikedanese
|
||||
- liggitt
|
||||
|
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/BUILD
generated
vendored
@ -30,6 +30,7 @@ go_library(
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/transport:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/certificate:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/certificate/csr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
86
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go
generated
vendored
86
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/bootstrap/bootstrap.go
generated
vendored
@ -32,13 +32,11 @@ import (
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/transport"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/client-go/util/certificate"
|
||||
"k8s.io/client-go/util/certificate/csr"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultKubeletClientCertificateFile = "kubelet-client.crt"
|
||||
defaultKubeletClientKeyFile = "kubelet-client.key"
|
||||
)
|
||||
const tmpPrivateKeyFile = "kubelet-client.key.tmp"
|
||||
|
||||
// LoadClientCert requests a client cert for kubelet if the kubeconfigPath file does not exist.
|
||||
// The kubeconfig at bootstrapPath is used to request a client certificate from the API server.
|
||||
@ -66,48 +64,46 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string,
|
||||
return fmt.Errorf("unable to create certificates signing request client: %v", err)
|
||||
}
|
||||
|
||||
success := false
|
||||
|
||||
// Get the private key.
|
||||
keyPath, err := filepath.Abs(filepath.Join(certDir, defaultKubeletClientKeyFile))
|
||||
store, err := certificate.NewFileStore("kubelet-client", certDir, certDir, "", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build bootstrap key path: %v", err)
|
||||
}
|
||||
// If we are unable to generate a CSR, we remove our key file and start fresh.
|
||||
// This method is used before enabling client rotation and so we must ensure we
|
||||
// can make forward progress if we crash and exit when a CSR exists but the cert
|
||||
// it is signed for has expired.
|
||||
defer func() {
|
||||
if !success {
|
||||
if err := os.Remove(keyPath); err != nil && !os.IsNotExist(err) {
|
||||
glog.Warningf("Cannot clean up the key file %q: %v", keyPath, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
keyData, _, err := certutil.LoadOrGenerateKeyFile(keyPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to build bootstrap cert store")
|
||||
}
|
||||
|
||||
// Get the cert.
|
||||
certPath, err := filepath.Abs(filepath.Join(certDir, defaultKubeletClientCertificateFile))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build bootstrap client cert path: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if !success {
|
||||
if err := os.Remove(certPath); err != nil && !os.IsNotExist(err) {
|
||||
glog.Warningf("Cannot clean up the cert file %q: %v", certPath, err)
|
||||
var keyData []byte
|
||||
if cert, err := store.Current(); err == nil {
|
||||
if cert.PrivateKey != nil {
|
||||
keyData, err = certutil.MarshalPrivateKeyToPEM(cert.PrivateKey)
|
||||
if err != nil {
|
||||
keyData = nil
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
// Cache the private key in a separate file until CSR succeeds. This has to
|
||||
// be a separate file because store.CurrentPath() points to a symlink
|
||||
// managed by the store.
|
||||
privKeyPath := filepath.Join(certDir, tmpPrivateKeyFile)
|
||||
if !verifyKeyData(keyData) {
|
||||
glog.V(2).Infof("No valid private key and/or certificate found, reusing existing private key or creating a new one")
|
||||
// Note: always call LoadOrGenerateKeyFile so that private key is
|
||||
// reused on next startup if CSR request fails.
|
||||
keyData, _, err = certutil.LoadOrGenerateKeyFile(privKeyPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
certData, err := csr.RequestNodeCertificate(bootstrapClient.CertificateSigningRequests(), keyData, nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := certutil.WriteCert(certPath, certData); err != nil {
|
||||
if _, err := store.Update(certData, keyData); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Remove(privKeyPath); err != nil && !os.IsNotExist(err) {
|
||||
glog.V(2).Infof("failed cleaning up private key file %q: %v", privKeyPath, err)
|
||||
}
|
||||
|
||||
pemPath := store.CurrentPath()
|
||||
|
||||
// Get the CA data from the bootstrap client config.
|
||||
caFile, caData := bootstrapClientConfig.CAFile, []byte{}
|
||||
@ -126,8 +122,8 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string,
|
||||
}},
|
||||
// Define auth based on the obtained client cert.
|
||||
AuthInfos: map[string]*clientcmdapi.AuthInfo{"default-auth": {
|
||||
ClientCertificate: certPath,
|
||||
ClientKey: keyPath,
|
||||
ClientCertificate: pemPath,
|
||||
ClientKey: pemPath,
|
||||
}},
|
||||
// Define a context that connects the auth info and cluster, and set it as the default
|
||||
Contexts: map[string]*clientcmdapi.Context{"default-context": {
|
||||
@ -139,12 +135,7 @@ func LoadClientCert(kubeconfigPath string, bootstrapPath string, certDir string,
|
||||
}
|
||||
|
||||
// Marshal to disk
|
||||
if err := clientcmd.WriteToFile(kubeconfigData, kubeconfigPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
success = true
|
||||
return nil
|
||||
return clientcmd.WriteToFile(kubeconfigData, kubeconfigPath)
|
||||
}
|
||||
|
||||
func loadRESTClientConfig(kubeconfig string) (*restclient.Config, error) {
|
||||
@ -207,3 +198,12 @@ func verifyBootstrapClientConfig(kubeconfigPath string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// verifyKeyData returns true if the provided data appears to be a valid private key.
|
||||
func verifyKeyData(data []byte) bool {
|
||||
if len(data) == 0 {
|
||||
return false
|
||||
}
|
||||
_, err := certutil.ParsePrivateKeyPEM(data)
|
||||
return err == nil
|
||||
}
|
||||
|
179
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go
generated
vendored
179
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport.go
generated
vendored
@ -17,12 +17,10 @@ limitations under the License.
|
||||
package certificate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@ -31,6 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/util/certificate"
|
||||
"k8s.io/client-go/util/connrotation"
|
||||
)
|
||||
|
||||
// UpdateTransport instruments a restconfig with a transport that dynamically uses
|
||||
@ -38,6 +37,8 @@ import (
|
||||
//
|
||||
// The config must not already provide an explicit transport.
|
||||
//
|
||||
// The returned function allows forcefully closing all active connections.
|
||||
//
|
||||
// The returned transport periodically checks the manager to determine if the
|
||||
// certificate has changed. If it has, the transport shuts down all existing client
|
||||
// connections, forcing the client to re-handshake with the server and use the
|
||||
@ -51,87 +52,87 @@ import (
|
||||
//
|
||||
// stopCh should be used to indicate when the transport is unused and doesn't need
|
||||
// to continue checking the manager.
|
||||
func UpdateTransport(stopCh <-chan struct{}, clientConfig *restclient.Config, clientCertificateManager certificate.Manager, exitAfter time.Duration) error {
|
||||
func UpdateTransport(stopCh <-chan struct{}, clientConfig *restclient.Config, clientCertificateManager certificate.Manager, exitAfter time.Duration) (func(), error) {
|
||||
return updateTransport(stopCh, 10*time.Second, clientConfig, clientCertificateManager, exitAfter)
|
||||
}
|
||||
|
||||
// updateTransport is an internal method that exposes how often this method checks that the
|
||||
// client cert has changed.
|
||||
func updateTransport(stopCh <-chan struct{}, period time.Duration, clientConfig *restclient.Config, clientCertificateManager certificate.Manager, exitAfter time.Duration) error {
|
||||
if clientConfig.Transport != nil {
|
||||
return fmt.Errorf("there is already a transport configured")
|
||||
func updateTransport(stopCh <-chan struct{}, period time.Duration, clientConfig *restclient.Config, clientCertificateManager certificate.Manager, exitAfter time.Duration) (func(), error) {
|
||||
if clientConfig.Transport != nil || clientConfig.Dial != nil {
|
||||
return nil, fmt.Errorf("there is already a transport or dialer configured")
|
||||
}
|
||||
|
||||
d := connrotation.NewDialer((&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext)
|
||||
|
||||
tlsConfig, err := restclient.TLSConfigFor(clientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to configure TLS for the rest client: %v", err)
|
||||
return nil, fmt.Errorf("unable to configure TLS for the rest client: %v", err)
|
||||
}
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{}
|
||||
}
|
||||
tlsConfig.Certificates = nil
|
||||
tlsConfig.GetClientCertificate = func(requestInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
cert := clientCertificateManager.Current()
|
||||
if cert == nil {
|
||||
return &tls.Certificate{Certificate: nil}, nil
|
||||
}
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// Custom dialer that will track all connections it creates.
|
||||
t := &connTracker{
|
||||
dialer: &net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second},
|
||||
conns: make(map[*closableConn]struct{}),
|
||||
}
|
||||
|
||||
lastCertAvailable := time.Now()
|
||||
lastCert := clientCertificateManager.Current()
|
||||
go wait.Until(func() {
|
||||
curr := clientCertificateManager.Current()
|
||||
|
||||
if exitAfter > 0 {
|
||||
now := time.Now()
|
||||
if curr == nil {
|
||||
// the certificate has been deleted from disk or is otherwise corrupt
|
||||
if now.After(lastCertAvailable.Add(exitAfter)) {
|
||||
if clientCertificateManager.ServerHealthy() {
|
||||
glog.Fatalf("It has been %s since a valid client cert was found and the server is responsive, exiting.", exitAfter)
|
||||
} else {
|
||||
glog.Errorf("It has been %s since a valid client cert was found, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.", exitAfter)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the certificate is expired
|
||||
if now.After(curr.Leaf.NotAfter) {
|
||||
if clientCertificateManager.ServerHealthy() {
|
||||
glog.Fatalf("The currently active client certificate has expired and the server is responsive, exiting.")
|
||||
} else {
|
||||
glog.Errorf("The currently active client certificate has expired, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.")
|
||||
}
|
||||
}
|
||||
lastCertAvailable = now
|
||||
if clientCertificateManager != nil {
|
||||
tlsConfig.Certificates = nil
|
||||
tlsConfig.GetClientCertificate = func(requestInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
cert := clientCertificateManager.Current()
|
||||
if cert == nil {
|
||||
return &tls.Certificate{Certificate: nil}, nil
|
||||
}
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
if curr == nil || lastCert == curr {
|
||||
// Cert hasn't been rotated.
|
||||
return
|
||||
}
|
||||
lastCert = curr
|
||||
lastCertAvailable := time.Now()
|
||||
lastCert := clientCertificateManager.Current()
|
||||
go wait.Until(func() {
|
||||
curr := clientCertificateManager.Current()
|
||||
|
||||
glog.Infof("certificate rotation detected, shutting down client connections to start using new credentials")
|
||||
// The cert has been rotated. Close all existing connections to force the client
|
||||
// to reperform its TLS handshake with new cert.
|
||||
//
|
||||
// See: https://github.com/kubernetes-incubator/bootkube/pull/663#issuecomment-318506493
|
||||
t.closeAllConns()
|
||||
}, period, stopCh)
|
||||
if exitAfter > 0 {
|
||||
now := time.Now()
|
||||
if curr == nil {
|
||||
// the certificate has been deleted from disk or is otherwise corrupt
|
||||
if now.After(lastCertAvailable.Add(exitAfter)) {
|
||||
if clientCertificateManager.ServerHealthy() {
|
||||
glog.Fatalf("It has been %s since a valid client cert was found and the server is responsive, exiting.", exitAfter)
|
||||
} else {
|
||||
glog.Errorf("It has been %s since a valid client cert was found, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.", exitAfter)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the certificate is expired
|
||||
if now.After(curr.Leaf.NotAfter) {
|
||||
if clientCertificateManager.ServerHealthy() {
|
||||
glog.Fatalf("The currently active client certificate has expired and the server is responsive, exiting.")
|
||||
} else {
|
||||
glog.Errorf("The currently active client certificate has expired, but the server is not responsive. A restart may be necessary to retrieve new initial credentials.")
|
||||
}
|
||||
}
|
||||
lastCertAvailable = now
|
||||
}
|
||||
}
|
||||
|
||||
if curr == nil || lastCert == curr {
|
||||
// Cert hasn't been rotated.
|
||||
return
|
||||
}
|
||||
lastCert = curr
|
||||
|
||||
glog.Infof("certificate rotation detected, shutting down client connections to start using new credentials")
|
||||
// The cert has been rotated. Close all existing connections to force the client
|
||||
// to reperform its TLS handshake with new cert.
|
||||
//
|
||||
// See: https://github.com/kubernetes-incubator/bootkube/pull/663#issuecomment-318506493
|
||||
d.CloseAll()
|
||||
}, period, stopCh)
|
||||
}
|
||||
|
||||
clientConfig.Transport = utilnet.SetTransportDefaults(&http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: tlsConfig,
|
||||
MaxIdleConnsPerHost: 25,
|
||||
DialContext: t.DialContext, // Use custom dialer.
|
||||
DialContext: d.DialContext, // Use custom dialer.
|
||||
})
|
||||
|
||||
// Zero out all existing TLS options since our new transport enforces them.
|
||||
@ -142,60 +143,6 @@ func updateTransport(stopCh <-chan struct{}, period time.Duration, clientConfig
|
||||
clientConfig.CAData = nil
|
||||
clientConfig.CAFile = ""
|
||||
clientConfig.Insecure = false
|
||||
return nil
|
||||
}
|
||||
|
||||
// connTracker is a dialer that tracks all open connections it creates.
|
||||
type connTracker struct {
|
||||
dialer *net.Dialer
|
||||
|
||||
mu sync.Mutex
|
||||
conns map[*closableConn]struct{}
|
||||
}
|
||||
|
||||
// closeAllConns forcibly closes all tracked connections.
|
||||
func (c *connTracker) closeAllConns() {
|
||||
c.mu.Lock()
|
||||
conns := c.conns
|
||||
c.conns = make(map[*closableConn]struct{})
|
||||
c.mu.Unlock()
|
||||
|
||||
for conn := range conns {
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *connTracker) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
conn, err := c.dialer.DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
closable := &closableConn{Conn: conn}
|
||||
|
||||
// Start tracking the connection
|
||||
c.mu.Lock()
|
||||
c.conns[closable] = struct{}{}
|
||||
c.mu.Unlock()
|
||||
|
||||
// When the connection is closed, remove it from the map. This will
|
||||
// be no-op if the connection isn't in the map, e.g. if closeAllConns()
|
||||
// is called.
|
||||
closable.onClose = func() {
|
||||
c.mu.Lock()
|
||||
delete(c.conns, closable)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
return closable, nil
|
||||
}
|
||||
|
||||
type closableConn struct {
|
||||
onClose func()
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (c *closableConn) Close() error {
|
||||
go c.onClose()
|
||||
return c.Conn.Close()
|
||||
|
||||
return d.CloseAll, nil
|
||||
}
|
||||
|
2
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport_test.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/certificate/transport_test.go
generated
vendored
@ -187,7 +187,7 @@ func TestRotateShutsDownConnections(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check for a new cert every 10 milliseconds
|
||||
if err := updateTransport(stop, 10*time.Millisecond, c, m, 0); err != nil {
|
||||
if _, err := updateTransport(stop, 10*time.Millisecond, c, m, 0); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user