Skip to content

Commit a494d6a

Browse files
l-qingtekton-robot
authored andcommitted
fix(taskrun): emit warning for missing secret in ServiceAccount instead of failing
fix #7760 Log a warning if a Secrets in service account does not exist
1 parent fba68b7 commit a494d6a

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

pkg/pod/creds_init.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"regexp"
24+
"strings"
2425

2526
"github.com/tektoncd/pipeline/pkg/apis/config"
2627
"github.com/tektoncd/pipeline/pkg/apis/pipeline"
@@ -29,8 +30,12 @@ import (
2930
"github.com/tektoncd/pipeline/pkg/credentials/gitcreds"
3031
"github.com/tektoncd/pipeline/pkg/names"
3132
corev1 "k8s.io/api/core/v1"
33+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
3234
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35+
"k8s.io/apimachinery/pkg/runtime"
3336
"k8s.io/client-go/kubernetes"
37+
"knative.dev/pkg/controller"
38+
"knative.dev/pkg/logging"
3439
)
3540

3641
const (
@@ -51,7 +56,8 @@ var dnsLabel1123Forbidden = regexp.MustCompile("[^a-zA-Z0-9-]+")
5156
// Any errors encountered during this process are returned to the
5257
// caller. If no matching annotated secrets are found, nil lists with a
5358
// nil error are returned.
54-
func credsInit(ctx context.Context, serviceAccountName, namespace string, kubeclient kubernetes.Interface) ([]string, []corev1.Volume, []corev1.VolumeMount, error) {
59+
func credsInit(ctx context.Context, obj runtime.Object, serviceAccountName, namespace string, kubeclient kubernetes.Interface) ([]string, []corev1.Volume, []corev1.VolumeMount, error) {
60+
logger := logging.FromContext(ctx)
5561
cfg := config.FromContextOrDefaults(ctx)
5662
if cfg != nil && cfg.FeatureFlags != nil && cfg.FeatureFlags.DisableCredsInit {
5763
return nil, nil, nil, nil
@@ -73,6 +79,17 @@ func credsInit(ctx context.Context, serviceAccountName, namespace string, kubecl
7379
var volumeMounts []corev1.VolumeMount
7480
var volumes []corev1.Volume
7581
var args []string
82+
var missingSecrets []string
83+
84+
defer func() {
85+
recorder := controller.GetEventRecorder(ctx)
86+
if len(missingSecrets) > 0 && recorder != nil && obj != nil {
87+
recorder.Eventf(obj, corev1.EventTypeWarning, "FailedToRetrieveSecret",
88+
"Unable to retrieve some secrets (%s); attempting to use them may not succeed.",
89+
strings.Join(missingSecrets, ", "))
90+
}
91+
}()
92+
7693
// Track duplicated secrets, prevent errors like this:
7794
// Pod "xxx" is invalid: spec.containers[0].volumeMounts[12].mountPath: Invalid value:
7895
// "/tekton/creds-secrets/demo-docker-credentials": must be unique
@@ -87,6 +104,11 @@ func credsInit(ctx context.Context, serviceAccountName, namespace string, kubecl
87104
visitedSecrets[secretEntry.Name] = struct{}{}
88105

89106
secret, err := kubeclient.CoreV1().Secrets(namespace).Get(ctx, secretEntry.Name, metav1.GetOptions{})
107+
if k8serrors.IsNotFound(err) {
108+
missingSecrets = append(missingSecrets, secretEntry.Name)
109+
logger.Warnf("Secret %q in ServiceAccount %s/%s not found, skipping", secretEntry.Name, namespace, serviceAccountName)
110+
continue
111+
}
90112
if err != nil {
91113
return nil, nil, nil, err
92114
}

pkg/pod/creds_init_test.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
"k8s.io/apimachinery/pkg/runtime"
3030
fakek8s "k8s.io/client-go/kubernetes/fake"
31+
"k8s.io/client-go/tools/record"
32+
"knative.dev/pkg/controller"
3133
logtesting "knative.dev/pkg/logging/testing"
3234
"knative.dev/pkg/system"
3335
)
@@ -49,6 +51,7 @@ func TestCredsInit(t *testing.T) {
4951
wantVolumeMounts []corev1.VolumeMount
5052
objs []runtime.Object
5153
envVars []corev1.EnvVar
54+
events []string
5255
ctx context.Context
5356
}{{
5457
desc: "service account exists with no secrets; nothing to initialize",
@@ -288,11 +291,52 @@ func TestCredsInit(t *testing.T) {
288291
MountPath: "/tekton/creds-secrets/my-creds",
289292
}},
290293
ctx: context.Background(),
294+
}, {
295+
desc: "service account has not found secrets",
296+
objs: []runtime.Object{
297+
&corev1.ServiceAccount{
298+
ObjectMeta: metav1.ObjectMeta{Name: serviceAccountName, Namespace: namespace},
299+
Secrets: []corev1.ObjectReference{
300+
{Name: "my-creds"},
301+
{Name: "not-exist-1"},
302+
{Name: "not-exist-2"},
303+
},
304+
},
305+
&corev1.Secret{
306+
ObjectMeta: metav1.ObjectMeta{
307+
Name: "my-creds",
308+
Namespace: namespace,
309+
Annotations: map[string]string{
310+
"tekton.dev/git-0": "github.com",
311+
},
312+
},
313+
Type: "kubernetes.io/basic-auth",
314+
Data: map[string][]byte{
315+
"username": []byte("foo"),
316+
"password": []byte("BestEver"),
317+
},
318+
},
319+
},
320+
envVars: []corev1.EnvVar{},
321+
wantArgs: []string{
322+
"-basic-git=my-creds=github.com",
323+
},
324+
wantVolumeMounts: []corev1.VolumeMount{{
325+
Name: "tekton-internal-secret-volume-my-creds-9l9zj",
326+
MountPath: "/tekton/creds-secrets/my-creds",
327+
}},
328+
events: []string{
329+
`Warning FailedToRetrieveSecret Unable to retrieve some secrets (not-exist-1, not-exist-2); attempting to use them may not succeed.`,
330+
},
331+
ctx: context.Background(),
291332
}} {
292333
t.Run(c.desc, func(t *testing.T) {
293334
names.TestingSeed()
335+
eventObj := &corev1.Event{}
294336
kubeclient := fakek8s.NewSimpleClientset(c.objs...)
295-
args, volumes, volumeMounts, err := credsInit(c.ctx, serviceAccountName, namespace, kubeclient)
337+
recorder := record.NewFakeRecorder(1000)
338+
c.ctx = controller.WithEventRecorder(c.ctx, recorder)
339+
args, volumes, volumeMounts, err := credsInit(c.ctx, eventObj, serviceAccountName, namespace, kubeclient)
296340
if err != nil {
297341
t.Fatalf("credsInit: %v", err)
298342
}
@@ -305,6 +349,15 @@ func TestCredsInit(t *testing.T) {
305349
if d := cmp.Diff(c.wantVolumeMounts, volumeMounts); d != "" {
306350
t.Fatalf("Diff %s", diff.PrintWantGot(d))
307351
}
352+
if len(recorder.Events) != len(c.events) {
353+
t.Fatalf("Expected %d events, got %d", len(c.events), len(recorder.Events))
354+
}
355+
for i, e := range c.events {
356+
message := <-recorder.Events
357+
if message != e {
358+
t.Fatalf("Expected event %d to be %q, got %q", i, e, message)
359+
}
360+
}
308361
})
309362
}
310363
}

pkg/pod/pod.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1.TaskRun, taskSpec v1.Ta
179179
if config.IsSpireEnabled(ctx) {
180180
commonExtraEntrypointArgs = append(commonExtraEntrypointArgs, "-enable_spire")
181181
}
182-
credEntrypointArgs, credVolumes, credVolumeMounts, err := credsInit(ctx, taskRun.Spec.ServiceAccountName, taskRun.Namespace, b.KubeClient)
182+
credEntrypointArgs, credVolumes, credVolumeMounts, err := credsInit(ctx, taskRun, taskRun.Spec.ServiceAccountName, taskRun.Namespace, b.KubeClient)
183183
if err != nil {
184184
return nil, err
185185
}

0 commit comments

Comments
 (0)