Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When CreatePod fails, dump pod options #2467

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions pkg/kube/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ func CreatePod(ctx context.Context, cli kubernetes.Interface, opts *PodOptions)

pod, err = cli.CoreV1().Pods(pod.Namespace).Create(ctx, pod, metav1.CreateOptions{})
if err != nil {
log.Error().WithContext(ctx).WithError(err).Print("Failed to create pod.", field.M{"pod": getRedactedPod(pod), "options": getRedactedOptions(opts)})
return nil, errors.Wrapf(err, "Failed to create pod. Namespace: %s, NameFmt: %s", opts.Namespace, opts.GenerateName)
}
return pod, nil
Expand Down Expand Up @@ -488,3 +489,60 @@ func GetPodReadyWaitTimeout() time.Duration {

return DefaultPodReadyWaitTimeout
}

// getRedactedEnvVariables returns array of variables with removed values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just add to the comment explaining that this is done because the env vars can contain sensitive info

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

// This function should be used every time when env variables are logged
func getRedactedEnvVariables(env []v1.EnvVar) []v1.EnvVar {
if len(env) == 0 {
return nil
}

result := make([]v1.EnvVar, len(env))
for i, ev := range env {
result[i] = v1.EnvVar{
Name: ev.Name,
Value: "XXXXX",
}
}

return result
}

// getRedactedPod hides all values of env variables from pod, so that it should be safely logged
func getRedactedPod(pod *v1.Pod) *v1.Pod {
if pod == nil {
return nil
}

result := *pod // Make shallow copy

getSanitizedContainers := func(containers []v1.Container) []v1.Container {
if len(containers) == 0 {
return nil
}

result := make([]v1.Container, len(containers))
for i, c := range containers {
result[i] = c
result[i].Env = getRedactedEnvVariables(c.Env)
}
return result
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also redact or hide the command passed into the pod

result.Spec.Containers = getSanitizedContainers(result.Spec.Containers)
result.Spec.InitContainers = getSanitizedContainers(result.Spec.InitContainers)

return &result
}

// getRedactedOptions hides all values of env variables from pod options, so that they should be safely logged
func getRedactedOptions(opts *PodOptions) *PodOptions {
if opts == nil {
return nil
}

result := *opts // Make shallow copy

result.EnvironmentVariables = getRedactedEnvVariables(result.EnvironmentVariables)
return &result
}
76 changes: 76 additions & 0 deletions pkg/kube/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,82 @@ func (s *PodSuite) TestSetLifecycleHook(c *C) {
c.Assert(pod.Spec.Containers[0].Lifecycle, DeepEquals, lch)
}

func (s *PodSuite) TestGetRedactedOptions(c *C) {
opts := &PodOptions{
Namespace: s.namespace,
GenerateName: "test-",
Image: consts.LatestKanisterToolsImage,
Command: []string{"sh", "-c", "tail -f /dev/null"},
EnvironmentVariables: []corev1.EnvVar{
{Name: "abc", Value: "def", ValueFrom: &corev1.EnvVarSource{}},
{Name: "ooo", Value: "aaa", ValueFrom: &corev1.EnvVarSource{}},
},
}

po1 := getRedactedOptions(opts)

c.Assert(po1.Namespace, Equals, opts.Namespace)
c.Assert(po1.GenerateName, Equals, opts.GenerateName)
c.Assert(po1.Image, Equals, opts.Image)
c.Assert(po1.Command, DeepEquals, opts.Command)
c.Assert(po1.EnvironmentVariables, DeepEquals, []corev1.EnvVar{
{Name: "abc", Value: "XXXXX"},
{Name: "ooo", Value: "XXXXX"},
})
}

func (s *PodSuite) TestGetRedactedPod(c *C) {
pod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Some kind",
APIVersion: "FakeAPI-1.0",
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "c1",
Image: "img1",
Env: []corev1.EnvVar{
{Name: "ev1", Value: "23", ValueFrom: &corev1.EnvVarSource{}},
{Name: "ev2", Value: "dd", ValueFrom: &corev1.EnvVarSource{}},
},
},
{
Name: "c2",
Image: "img2",
Env: []corev1.EnvVar{
{Name: "a1", Value: "v1", ValueFrom: &corev1.EnvVarSource{}},
{Name: "a2", Value: "v2", ValueFrom: &corev1.EnvVarSource{}},
},
},
},
},
}

p1 := getRedactedPod(pod)

c.Assert(p1.TypeMeta, DeepEquals, pod.TypeMeta)
c.Assert(len(p1.Spec.Containers), Equals, len(pod.Spec.Containers))
c.Assert(p1.Spec.Containers, DeepEquals, []corev1.Container{
{
Name: "c1",
Image: "img1",
Env: []corev1.EnvVar{
{Name: "ev1", Value: "XXXXX"},
{Name: "ev2", Value: "XXXXX"},
},
},
{
Name: "c2",
Image: "img2",
Env: []corev1.EnvVar{
{Name: "a1", Value: "XXXXX"},
{Name: "a2", Value: "XXXXX"},
},
},
})
}

func (s *PodControllerTestSuite) TestContainerNameFromPodOptsOrDefault(c *C) {
for _, tc := range []struct {
podOptsContainerName string
Expand Down