mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-02-22 07:03:28 +00:00
kubelet: Fix nil panic in podcertificatemanager
If the the PCR that kubelet created gets deleted before it is issued, a nil panic will be thrown while composing the error message.
This commit is contained in:
@@ -481,7 +481,7 @@ func (m *IssuingManager) handleProjection(ctx context.Context, key projectionKey
|
||||
// remember creating the PCR, then we must be in case 2. Return to
|
||||
// credStateInitial so we create a new PCR.
|
||||
rec.curState = &credStateInitial{}
|
||||
return fmt.Errorf("PodCertificateRequest %q appears to have been deleted", pcr.ObjectMeta.Namespace+"/"+pcr.ObjectMeta.Name)
|
||||
return fmt.Errorf("PodCertificateRequest %q appears to have been deleted", key.Namespace+"/"+state.pcrName)
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("while getting PodCertificateRequest %q: %w", key.Namespace+"/"+state.pcrName, err)
|
||||
}
|
||||
|
||||
@@ -178,6 +178,117 @@ func TestTransitionInitialToWait(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPCRDeletedWhileWaiting(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(ktesting.Init(t))
|
||||
defer cancel()
|
||||
|
||||
kc := fake.NewClientset()
|
||||
clock := testclock.NewFakeClock(mustRFC3339(t, "2010-01-01T00:00:00Z"))
|
||||
|
||||
signerName := "foo.com/signer"
|
||||
|
||||
pcrStore := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
pcrLister := certlistersv1beta1.NewPodCertificateRequestLister(pcrStore)
|
||||
|
||||
nodeStore := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
nodeLister := corelistersv1.NewNodeLister(nodeStore)
|
||||
node1 := &corev1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "node1",
|
||||
UID: "node1-uid",
|
||||
},
|
||||
}
|
||||
if err := nodeStore.Add(node1); err != nil {
|
||||
t.Fatalf("Unexpected error adding node: %v", err)
|
||||
}
|
||||
|
||||
workloadSA, err := kc.CoreV1().ServiceAccounts("ns1").Create(ctx, &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "ns1",
|
||||
Name: "workload",
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error creating workload serviceaccount: %v", err)
|
||||
}
|
||||
|
||||
node1PodManager := &FakeSynchronousPodManager{
|
||||
pods: []*corev1.Pod{},
|
||||
}
|
||||
|
||||
workloadPod := &corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "ns1",
|
||||
Name: "workload",
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
ServiceAccountName: workloadSA.ObjectMeta.Name,
|
||||
NodeName: "node1",
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "main",
|
||||
Image: "notarealimage",
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "certificate",
|
||||
MountPath: "/run/foo-cert",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "certificate",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
PodCertificate: &corev1.PodCertificateProjection{
|
||||
SignerName: signerName,
|
||||
KeyType: "ED25519",
|
||||
CredentialBundlePath: "creds.pem",
|
||||
MaxExpirationSeconds: ptr.To[int32](86400), // Defaulting doesn't work with a fake client.
|
||||
UserAnnotations: map[string]string{"test.domain/foo": "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
node1PodManager.pods = append(node1PodManager.pods, workloadPod)
|
||||
|
||||
node1PodCertificateManager := &IssuingManager{
|
||||
kc: kc,
|
||||
podManager: node1PodManager,
|
||||
pcrLister: pcrLister,
|
||||
nodeLister: nodeLister,
|
||||
nodeName: types.NodeName("node1"),
|
||||
clock: clock,
|
||||
credStore: map[projectionKey]*projectionRecord{},
|
||||
}
|
||||
|
||||
// Step the handling state machine by one step. We should now be in wait state.
|
||||
if err := node1PodCertificateManager.handleProjection(ctx, projectionKey{workloadPod.ObjectMeta.Namespace, workloadPod.ObjectMeta.Name, string(workloadPod.ObjectMeta.UID), "certificate", 0}); err != nil {
|
||||
t.Fatalf("Unexpected error while running handleProjection: %v", err)
|
||||
}
|
||||
|
||||
// Clear all PCRs and advance time past assumeDeletedThreshold.
|
||||
if err := kc.CertificatesV1beta1().PodCertificateRequests("ns1").DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil {
|
||||
t.Fatalf("Unexpected error while deleting all PCRs in ns1: %v", err)
|
||||
}
|
||||
clock.Step(assumeDeletedThreshold + 1*time.Minute)
|
||||
|
||||
// Calling handleProjection again should return an error, *not* nil panic.
|
||||
err = node1PodCertificateManager.handleProjection(ctx, projectionKey{workloadPod.ObjectMeta.Namespace, workloadPod.ObjectMeta.Name, string(workloadPod.ObjectMeta.UID), "certificate", 0})
|
||||
if err == nil { // EQUALS nil
|
||||
t.Fatalf("Got no error from handleProjection, but wanted an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFullFlow(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(ktesting.Init(t))
|
||||
defer cancel()
|
||||
|
||||
Reference in New Issue
Block a user