mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Interrupt WaitForCertificate if desired kubelet serving cert changes
This commit is contained in:
parent
8ae998ceb6
commit
739a75fc32
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package renewal
|
package renewal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
@ -97,7 +98,10 @@ func (r *APIRenewer) Renew(cfg *certutil.Config) (*x509.Certificate, crypto.Sign
|
|||||||
|
|
||||||
fmt.Printf("[certs] Certificate request %q created\n", req.Name)
|
fmt.Printf("[certs] Certificate request %q created\n", req.Name)
|
||||||
|
|
||||||
certData, err := csrutil.WaitForCertificate(r.client.CertificateSigningRequests(), req, watchTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), watchTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
certData, err := csrutil.WaitForCertificate(ctx, r.client.CertificateSigningRequests(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "certificate failed to appear")
|
return nil, nil, errors.Wrap(err, "certificate failed to appear")
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,11 @@ func requestNodeCertificate(client certificatesv1beta1.CertificateSigningRequest
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return csr.WaitForCertificate(client, req, 3600*time.Second)
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3600*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return csr.WaitForCertificate(ctx, client, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This digest should include all the relevant pieces of the CSR we care about.
|
// This digest should include all the relevant pieces of the CSR we care about.
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package certificate
|
package certificate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
cryptorand "crypto/rand"
|
cryptorand "crypto/rand"
|
||||||
@ -148,9 +149,13 @@ type CSRClientFunc func(current *tls.Certificate) (certificatesclient.Certificat
|
|||||||
func (e *NoCertKeyError) Error() string { return string(*e) }
|
func (e *NoCertKeyError) Error() string { return string(*e) }
|
||||||
|
|
||||||
type manager struct {
|
type manager struct {
|
||||||
getTemplate func() *x509.CertificateRequest
|
getTemplate func() *x509.CertificateRequest
|
||||||
lastRequestLock sync.Mutex
|
|
||||||
lastRequest *x509.CertificateRequest
|
// lastRequestLock guards lastRequestCancel and lastRequest
|
||||||
|
lastRequestLock sync.Mutex
|
||||||
|
lastRequestCancel context.CancelFunc
|
||||||
|
lastRequest *x509.CertificateRequest
|
||||||
|
|
||||||
dynamicTemplate bool
|
dynamicTemplate bool
|
||||||
usages []certificates.KeyUsage
|
usages []certificates.KeyUsage
|
||||||
forceRotation bool
|
forceRotation bool
|
||||||
@ -261,7 +266,8 @@ func (m *manager) Start() {
|
|||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
// unblock when deadline expires
|
// unblock when deadline expires
|
||||||
case <-templateChanged:
|
case <-templateChanged:
|
||||||
if reflect.DeepEqual(m.getLastRequest(), m.getTemplate()) {
|
_, lastRequestTemplate := m.getLastRequest()
|
||||||
|
if reflect.DeepEqual(lastRequestTemplate, m.getTemplate()) {
|
||||||
// if the template now matches what we last requested, restart the rotation deadline loop
|
// if the template now matches what we last requested, restart the rotation deadline loop
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -289,10 +295,19 @@ func (m *manager) Start() {
|
|||||||
if m.dynamicTemplate {
|
if m.dynamicTemplate {
|
||||||
go wait.Until(func() {
|
go wait.Until(func() {
|
||||||
// check if the current template matches what we last requested
|
// check if the current template matches what we last requested
|
||||||
if !m.certSatisfiesTemplate() && !reflect.DeepEqual(m.getLastRequest(), m.getTemplate()) {
|
lastRequestCancel, lastRequestTemplate := m.getLastRequest()
|
||||||
|
|
||||||
|
if !m.certSatisfiesTemplate() && !reflect.DeepEqual(lastRequestTemplate, m.getTemplate()) {
|
||||||
// if the template is different, queue up an interrupt of the rotation deadline loop.
|
// if the template is different, queue up an interrupt of the rotation deadline loop.
|
||||||
// if we've requested a CSR that matches the new template by the time the interrupt is handled, the interrupt is disregarded.
|
// if we've requested a CSR that matches the new template by the time the interrupt is handled, the interrupt is disregarded.
|
||||||
templateChanged <- struct{}{}
|
if lastRequestCancel != nil {
|
||||||
|
// if we're currently waiting on a submitted request that no longer matches what we want, stop waiting
|
||||||
|
lastRequestCancel()
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case templateChanged <- struct{}{}:
|
||||||
|
case <-m.stopCh:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, time.Second, m.stopCh)
|
}, time.Second, m.stopCh)
|
||||||
}
|
}
|
||||||
@ -386,12 +401,15 @@ func (m *manager) rotateCerts() (bool, error) {
|
|||||||
return false, m.updateServerError(err)
|
return false, m.updateServerError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), certificateWaitTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
// Once we've successfully submitted a CSR for this template, record that we did so
|
// Once we've successfully submitted a CSR for this template, record that we did so
|
||||||
m.setLastRequest(template)
|
m.setLastRequest(cancel, template)
|
||||||
|
|
||||||
// Wait for the certificate to be signed. This interface and internal timout
|
// Wait for the certificate to be signed. This interface and internal timout
|
||||||
// is a remainder after the old design using raw watch wrapped with backoff.
|
// is a remainder after the old design using raw watch wrapped with backoff.
|
||||||
crtPEM, err := csr.WaitForCertificate(client, req, certificateWaitTimeout)
|
crtPEM, err := csr.WaitForCertificate(ctx, client, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("Certificate request was not signed: %v", err))
|
utilruntime.HandleError(fmt.Errorf("Certificate request was not signed: %v", err))
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -561,14 +579,15 @@ func (m *manager) generateCSR() (template *x509.CertificateRequest, csrPEM []byt
|
|||||||
return template, csrPEM, keyPEM, privateKey, nil
|
return template, csrPEM, keyPEM, privateKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *manager) getLastRequest() *x509.CertificateRequest {
|
func (m *manager) getLastRequest() (context.CancelFunc, *x509.CertificateRequest) {
|
||||||
m.lastRequestLock.Lock()
|
m.lastRequestLock.Lock()
|
||||||
defer m.lastRequestLock.Unlock()
|
defer m.lastRequestLock.Unlock()
|
||||||
return m.lastRequest
|
return m.lastRequestCancel, m.lastRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *manager) setLastRequest(r *x509.CertificateRequest) {
|
func (m *manager) setLastRequest(cancel context.CancelFunc, r *x509.CertificateRequest) {
|
||||||
m.lastRequestLock.Lock()
|
m.lastRequestLock.Lock()
|
||||||
defer m.lastRequestLock.Unlock()
|
defer m.lastRequestLock.Unlock()
|
||||||
|
m.lastRequestCancel = cancel
|
||||||
m.lastRequest = r
|
m.lastRequest = r
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func RequestCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WaitForCertificate waits for a certificate to be issued until timeout, or returns an error.
|
// WaitForCertificate waits for a certificate to be issued until timeout, or returns an error.
|
||||||
func WaitForCertificate(client certificatesclient.CertificateSigningRequestInterface, req *certificates.CertificateSigningRequest, timeout time.Duration) (certData []byte, err error) {
|
func WaitForCertificate(ctx context.Context, client certificatesclient.CertificateSigningRequestInterface, req *certificates.CertificateSigningRequest) (certData []byte, err error) {
|
||||||
fieldSelector := fields.OneTermEqualSelector("metadata.name", req.Name).String()
|
fieldSelector := fields.OneTermEqualSelector("metadata.name", req.Name).String()
|
||||||
lw := &cache.ListWatch{
|
lw := &cache.ListWatch{
|
||||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||||
@ -94,8 +94,6 @@ func WaitForCertificate(client certificatesclient.CertificateSigningRequestInter
|
|||||||
return client.Watch(options)
|
return client.Watch(options)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout)
|
|
||||||
defer cancel()
|
|
||||||
event, err := watchtools.UntilWithSync(
|
event, err := watchtools.UntilWithSync(
|
||||||
ctx,
|
ctx,
|
||||||
lw,
|
lw,
|
||||||
|
Loading…
Reference in New Issue
Block a user