...

Text file src/k8s.io/kubernetes/test/cmd/debug.sh

Documentation: k8s.io/kubernetes/test/cmd

     1#!/usr/bin/env bash
     2
     3# Copyright 2020 The Kubernetes Authors.
     4#
     5# Licensed under the Apache License, Version 2.0 (the "License");
     6# you may not use this file except in compliance with the License.
     7# You may obtain a copy of the License at
     8#
     9#     http://www.apache.org/licenses/LICENSE-2.0
    10#
    11# Unless required by applicable law or agreed to in writing, software
    12# distributed under the License is distributed on an "AS IS" BASIS,
    13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14# See the License for the specific language governing permissions and
    15# limitations under the License.
    16
    17set -o errexit
    18set -o nounset
    19set -o pipefail
    20
    21run_kubectl_debug_pod_tests() {
    22  set -o nounset
    23  set -o errexit
    24
    25  create_and_use_new_namespace
    26  kube::log::status "Testing kubectl debug (pod tests)"
    27
    28  ### Pod Troubleshooting by ephemeral containers
    29
    30  # Pre-Condition: Pod "nginx" is created
    31  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
    32  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
    33  # Command: create a copy of target with a new debug container
    34  kubectl debug target -it --image=busybox --attach=false -c debug-container "${kube_flags[@]:?}"
    35  # Post-Conditions
    36  kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
    37  # Clean up
    38  kubectl delete pod target "${kube_flags[@]:?}"
    39
    40  ### Pod Troubleshooting by Copy
    41
    42  # Pre-Condition: Pod "nginx" is created
    43  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
    44  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
    45  # Command: create a copy of target with a new debug container
    46  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
    47  # Post-Conditions
    48  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
    49  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
    50  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
    51  # Clean up
    52  kubectl delete pod target target-copy "${kube_flags[@]:?}"
    53
    54  # Pre-Condition: Pod "nginx" is created
    55  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
    56  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
    57  # Command: create a copy of target with a new debug container replacing the previous pod
    58  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false --replace "${kube_flags[@]:?}"
    59  # Post-Conditions
    60  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target-copy:'
    61  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
    62  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
    63  # Clean up
    64  kubectl delete pod target-copy "${kube_flags[@]:?}"
    65
    66  # Pre-Condition: Pod "nginx" is created
    67  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
    68  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
    69  kube::test::get_object_assert pod/target '{{(index .spec.containers 0).name}}' 'target'
    70  # Command: copy the pod and replace the image of an existing container
    71  kubectl debug target --image=busybox --container=target --copy-to=target-copy "${kube_flags[@]:?}" -- sleep 1m
    72  # Post-Conditions
    73  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
    74  kube::test::get_object_assert pod/target-copy "{{(len .spec.containers)}}:{{${image_field:?}}}" '1:busybox'
    75  # Clean up
    76  kubectl delete pod target target-copy "${kube_flags[@]:?}"
    77
    78  # Pre-Condition: Pod "nginx" is created
    79  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
    80  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
    81  kube::test::get_object_assert pod/target '{{(index .spec.containers 0).name}}' 'target'
    82  # Command: copy the pod and replace the image of an existing container
    83  kubectl get pod/target -o yaml > "${KUBE_TEMP}"/test-pod-debug.yaml
    84  kubectl debug -f "${KUBE_TEMP}"/test-pod-debug.yaml --image=busybox --container=target --copy-to=target-copy "${kube_flags[@]:?}" -- sleep 1m
    85  # Post-Conditions
    86  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
    87  kube::test::get_object_assert pod/target-copy "{{(len .spec.containers)}}:{{${image_field:?}}}" '1:busybox'
    88  # Clean up
    89  kubectl delete pod target target-copy "${kube_flags[@]:?}"
    90
    91  set +o nounset
    92  set +o errexit
    93}
    94
    95run_kubectl_debug_node_tests() {
    96  set -o nounset
    97  set -o errexit
    98
    99  create_and_use_new_namespace
   100  kube::log::status "Testing kubectl debug (pod tests)"
   101
   102  ### Node Troubleshooting by Privileged Container
   103
   104  # Pre-Condition: Pod "nginx" is created
   105  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   106  # Command: create a new node debugger pod
   107  output_message=$(kubectl debug node/127.0.0.1 --image=busybox --attach=false "${kube_flags[@]:?}" -- true)
   108  # Post-Conditions
   109  kube::test::get_object_assert pod "{{(len .items)}}" '1'
   110  debugger=$(kubectl get pod -o go-template="{{(index .items 0)${id_field:?}}}")
   111  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   112  kube::test::get_object_assert "pod/${debugger:?}" "{{${image_field:?}}}" 'busybox'
   113  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.nodeName}}' '127.0.0.1'
   114  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostIPC}}' 'true'
   115  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostNetwork}}' 'true'
   116  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostPID}}' 'true'
   117  kube::test::get_object_assert "pod/${debugger:?}" '{{(index (index .spec.containers 0).volumeMounts 0).mountPath}}' '/host'
   118  kube::test::get_object_assert "pod/${debugger:?}" '{{(index .spec.volumes 0).hostPath.path}}' '/'
   119  # Clean up
   120  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   121  # presumably waiting for a kubelet that's not present. Force the delete.
   122  kubectl delete --force pod "${debugger:?}" "${kube_flags[@]:?}"
   123
   124  set +o nounset
   125  set +o errexit
   126}
   127
   128run_kubectl_debug_general_tests() {
   129  set -o nounset
   130  set -o errexit
   131
   132  create_and_use_new_namespace
   133  kube::log::status "Testing kubectl debug profile general"
   134
   135  ### Debug by pod copy
   136  ### probes are removed, sets SYS_PTRACE in debugging container, sets shareProcessNamespace
   137
   138  # Pre-Condition: Pod "nginx" is created
   139  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   140  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   141  # Command: create a copy of target with a new debug container
   142  kubectl debug --profile general target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
   143  # Post-Conditions
   144  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   145  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   146  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
   147  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ''
   148  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ''
   149  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ''
   150  kube::test::get_object_assert pod/target-copy '{{(index (index .spec.containers 1).securityContext.capabilities.add 0)}}' 'SYS_PTRACE'
   151  kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
   152  # Clean up
   153  kubectl delete pod target target-copy "${kube_flags[@]:?}"
   154
   155  ### Debug by EC
   156  ### sets SYS_PTRACE in ephemeral container
   157
   158  # Pre-Condition: Pod "nginx" is created
   159  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   160  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   161  # Command: create a copy of target with a new debug container
   162  kubectl debug --profile general target -it --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
   163  # Post-Conditions
   164  kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{.image}}{{end}}' 'debug-container:busybox'
   165  kube::test::get_object_assert pod/target '{{(index (index .spec.ephemeralContainers 0).securityContext.capabilities.add 0)}}' 'SYS_PTRACE'
   166  # Clean up
   167  kubectl delete pod target "${kube_flags[@]:?}"
   168
   169  set +o nounset
   170  set +o errexit
   171}
   172
   173run_kubectl_debug_general_node_tests() {
   174  set -o nounset
   175  set -o errexit
   176
   177  create_and_use_new_namespace
   178  kube::log::status "Testing kubectl debug profile general (node)"
   179
   180  ### Debug node
   181  ### empty securityContext, uses host namespaces, mounts root partition
   182
   183  # Pre-Condition: node exists
   184  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   185  # Command: create a new node debugger pod
   186  output_message=$(kubectl debug --profile general node/127.0.0.1 --image=busybox --attach=false "${kube_flags[@]:?}" -- true)
   187  # Post-Conditions
   188  kube::test::get_object_assert pod "{{(len .items)}}" '1'
   189  debugger=$(kubectl get pod -o go-template="{{(index .items 0)${id_field:?}}}")
   190  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   191  kube::test::get_object_assert "pod/${debugger:?}" "{{${image_field:?}}}" 'busybox'
   192  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.nodeName}}' '127.0.0.1'
   193  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostIPC}}' 'true'
   194  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostNetwork}}' 'true'
   195  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostPID}}' 'true'
   196  kube::test::get_object_assert "pod/${debugger:?}" '{{(index (index .spec.containers 0).volumeMounts 0).mountPath}}' '/host'
   197  kube::test::get_object_assert "pod/${debugger:?}" '{{(index .spec.volumes 0).hostPath.path}}' '/'
   198  kube::test::get_object_assert "pod/${debugger:?}" '{{if (index (index .spec.containers 0) "securityContext")}}:{{end}}' ''
   199  # Clean up
   200  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   201  # presumably waiting for a kubelet that's not present. Force the delete.
   202  kubectl delete --force pod "${debugger:?}" "${kube_flags[@]:?}"
   203
   204  set +o nounset
   205  set +o errexit
   206}
   207
   208run_kubectl_debug_baseline_tests() {
   209  set -o nounset
   210  set -o errexit
   211
   212  create_and_use_new_namespace
   213  kube::log::status "Testing kubectl debug profile baseline"
   214
   215  ### Debug by pod copy
   216  ### probes are removed, empty securityContext, sets shareProcessNamespace
   217
   218  # Pre-Condition: Pod "nginx" is created
   219  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   220  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   221  # Command: create a copy of target with a new debug container
   222  kubectl debug --profile baseline target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
   223  # Post-Conditions
   224  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   225  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   226  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
   227  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "livenessProbe")}}:{{end}}{{end}}' ''
   228  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "readinessProbe")}}:{{end}}{{end}}' ''
   229  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{if (index . "startupProbe")}}:{{end}}{{end}}' ''
   230  kube::test::get_object_assert pod/target-copy '{{if (index (index .spec.containers 0) "securityContext")}}:{{end}}' ''
   231  kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
   232  # Clean up
   233  kubectl delete pod target target-copy "${kube_flags[@]:?}"
   234
   235  ### Debug by EC
   236  ### empty securityContext
   237
   238  # Pre-Condition: Pod "nginx" is created
   239  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   240  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   241  # Command: create a copy of target with a new debug container
   242  kubectl debug --profile baseline target -it --image=busybox --container=debug-container --attach=false "${kube_flags[@]:?}"
   243  # Post-Conditions
   244  kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{.image}}{{end}}' 'debug-container:busybox'
   245  kube::test::get_object_assert pod/target '{{if (index (index .spec.ephemeralContainers 0) "securityContext")}}:{{end}}' ''
   246  # Clean up
   247  kubectl delete pod target "${kube_flags[@]:?}"
   248
   249  set +o nounset
   250  set +o errexit
   251}
   252
   253run_kubectl_debug_baseline_node_tests() {
   254  set -o nounset
   255  set -o errexit
   256
   257  create_and_use_new_namespace
   258  kube::log::status "Testing kubectl debug profile baseline (node)"
   259
   260  ### Debug node
   261  ### empty securityContext, uses isolated namespaces
   262
   263  # Pre-Condition: node exists
   264  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   265  # Command: create a new node debugger pod
   266  output_message=$(kubectl debug --profile baseline node/127.0.0.1 --image=busybox --attach=false "${kube_flags[@]:?}" -- true)
   267  # Post-Conditions
   268  kube::test::get_object_assert pod "{{(len .items)}}" '1'
   269  debugger=$(kubectl get pod -o go-template="{{(index .items 0)${id_field:?}}}")
   270  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   271  kube::test::get_object_assert "pod/${debugger:?}" "{{${image_field:?}}}" 'busybox'
   272  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.nodeName}}' '127.0.0.1'
   273  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostIPC}}' '<no value>'
   274  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostNetwork}}' '<no value>'
   275  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostPID}}' '<no value>'
   276  kube::test::get_object_assert "pod/${debugger:?}" '{{if (index (index .spec.containers 0) "securityContext")}}:{{end}}' ''
   277  # Clean up
   278  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   279  # presumably waiting for a kubelet that's not present. Force the delete.
   280  kubectl delete --force pod "${debugger:?}" "${kube_flags[@]:?}"
   281
   282  set +o nounset
   283  set +o errexit
   284}
   285
   286run_kubectl_debug_restricted_tests() {
   287  set -o nounset
   288  set -o errexit
   289
   290  create_and_use_new_namespace  
   291  kube::log::status "Testing kubectl debug profile restricted"
   292
   293  ### Pod Troubleshooting by ephemeral containers with restricted profile
   294  # Pre-Condition: Pod "nginx" is created
   295  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   296  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   297  # Restricted profile just works in not restricted namespace
   298  # Command: add a new debug container with restricted profile
   299  output_message=$(kubectl debug target -it --image=busybox --attach=false -c debug-container --profile=restricted "${kube_flags[@]:?}")
   300  kube::test::if_has_not_string "${output_message}" 'forbidden: violates PodSecurity'
   301  # Post-Conditions
   302  kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
   303  # Clean up
   304  kubectl delete pod target "${kube_flags[@]:?}"
   305
   306  ### Pod Troubleshooting by pod copy with restricted profile
   307  # Pre-Condition: Pod "nginx" is created
   308  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   309  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   310  # Restricted profile just works in not restricted namespace
   311  # Command: create a copy of target with a new debug container
   312  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false --profile=restricted "${kube_flags[@]:?}"
   313  # Post-Conditions
   314  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   315  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   316  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
   317  # Clean up
   318  kubectl delete pod target target-copy "${kube_flags[@]:?}"
   319
   320  ns_name="namespace-restricted"
   321  # Command: create namespace and add a label
   322  kubectl create namespace "${ns_name}"
   323  kubectl label namespace "${ns_name}" pod-security.kubernetes.io/enforce=restricted
   324  output_message=$(kubectl get namespaces "${ns_name}" --show-labels)
   325  kube::test::if_has_string "${output_message}" 'pod-security.kubernetes.io/enforce=restricted'
   326 
   327  ### Pod Troubleshooting by ephemeral containers with restricted profile (restricted namespace)
   328  # Pre-Condition: Pod "busybox" is created that complies with the restricted policy
   329  kubectl create -f hack/testdata/pod-restricted-runtime-default.yaml -n "${ns_name}"
   330  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   331  # Restricted profile works when pod's seccompProfile is RuntimeDefault
   332  # Command: add a new debug container with restricted profile
   333  output_message=$(kubectl debug target -it --image=busybox --attach=false -c debug-container --profile=restricted -n "${ns_name}" "${kube_flags[@]:?}")
   334  kube::test::if_has_not_string "${output_message}" 'forbidden: violates PodSecurity'
   335  # Post-Conditions
   336  kube::test::get_object_assert "pod/target -n ${ns_name}" '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
   337  # Clean up
   338  kubectl delete pod target -n "${ns_name}" "${kube_flags[@]:?}"
   339
   340  ### Pod Troubleshooting by pod copy with restricted profile (restricted namespace)
   341  # Pre-Condition: Pod "nginx" is created
   342  kubectl create -f hack/testdata/pod-restricted-runtime-default.yaml -n "${ns_name}"
   343  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   344  # Restricted profile works when pod's seccompProfile is RuntimeDefault
   345  # Command: create a copy of target with a new debug container
   346  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false --profile=restricted -n ${ns_name} "${kube_flags[@]:?}"
   347  # Post-Conditions
   348  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   349  kube::test::get_object_assert "pod/target-copy -n ${ns_name}" '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   350  kube::test::get_object_assert "pod/target-copy -n ${ns_name}" '{{range.spec.containers}}{{.image}}:{{end}}' "busybox:busybox:"
   351  # Clean up
   352  kubectl delete pod target target-copy -n "${ns_name}" "${kube_flags[@]:?}"
   353
   354  ### Pod Troubleshooting by ephemeral containers with restricted profile (restricted namespace)
   355  # Pre-Condition: Pod "busybox" is created that complies with the restricted policy
   356  kubectl create -f hack/testdata/pod-restricted-localhost.yaml -n "${ns_name}"
   357  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   358  # Restricted profile works when pod's seccompProfile is Localhost
   359  # Command: add a new debug container with restricted profile
   360  output_message=$(kubectl debug target -it --image=busybox --attach=false -c debug-container --profile=restricted -n ${ns_name} "${kube_flags[@]:?}")
   361  kube::test::if_has_not_string "${output_message}" 'forbidden: violates PodSecurity'
   362  # Post-Conditions
   363  kube::test::get_object_assert "pod/target -n ${ns_name}" '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
   364  # Clean up
   365  kubectl delete pod target -n ${ns_name} "${kube_flags[@]:?}"
   366
   367  ### Pod Troubleshooting by pod copy with restricted profile (restricted namespace)
   368  # Pre-Condition: Pod "nginx" is created
   369  kubectl create -f hack/testdata/pod-restricted-localhost.yaml -n "${ns_name}"
   370  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   371  # Restricted profile works when pod's seccompProfile is Localhost
   372  # Command: create a copy of target with a new debug container
   373  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false --profile=restricted -n ${ns_name} "${kube_flags[@]:?}"
   374  # Post-Conditions
   375  kube::test::get_object_assert "pod -n ${ns_name}" "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   376  kube::test::get_object_assert "pod/target-copy -n ${ns_name}" '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   377  kube::test::get_object_assert "pod/target-copy -n ${ns_name}" '{{range.spec.containers}}{{.image}}:{{end}}' "busybox:busybox:"
   378  # Clean up
   379  kubectl delete pod target target-copy -n "${ns_name}" "${kube_flags[@]:?}"
   380
   381  # Clean up restricted namespace
   382  kubectl delete namespace "${ns_name}"
   383
   384  set +o nounset
   385  set +o errexit
   386}
   387
   388run_kubectl_debug_restricted_node_tests() {
   389  set -o nounset
   390  set -o errexit
   391
   392  create_and_use_new_namespace  
   393  kube::log::status "Testing kubectl debug profile restricted (node)"
   394
   395  ### Debug node with restricted profile
   396  # Pre-Condition: node exists
   397  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   398  # Restricted profile just works in not restricted namespace
   399  # Command: create a new node debugger pod
   400  output_message=$(kubectl debug --profile restricted node/127.0.0.1 --image=busybox --attach=false "${kube_flags[@]:?}" -- true)
   401  kube::test::if_has_not_string "${output_message}" 'forbidden: violates PodSecurity'
   402  # Post-Conditions
   403  kube::test::get_object_assert pod "{{(len .items)}}" '1'
   404  debugger=$(kubectl get pod -o go-template="{{(index .items 0)${id_field:?}}}")
   405  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   406  kube::test::get_object_assert "pod/${debugger:?}" "{{${image_field:?}}}" 'busybox'
   407  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.nodeName}}' '127.0.0.1'
   408  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostIPC}}' '<no value>'
   409  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostNetwork}}' '<no value>'
   410  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostPID}}' '<no value>'
   411  kube::test::get_object_assert "pod/${debugger:?}" '{{index .spec.containers 0 "securityContext" "allowPrivilegeEscalation"}}' 'false'
   412  kube::test::get_object_assert "pod/${debugger:?}" '{{index .spec.containers 0 "securityContext" "capabilities" "drop"}}' '\[ALL\]'
   413  kube::test::get_object_assert "pod/${debugger:?}" '{{if (index (index .spec.containers 0) "securityContext" "capabilities" "add") }}:{{end}}' ''
   414  kube::test::get_object_assert "pod/${debugger:?}" '{{index .spec.containers 0 "securityContext" "runAsNonRoot"}}' 'true'
   415  kube::test::get_object_assert "pod/${debugger:?}" '{{index .spec.containers 0 "securityContext" "seccompProfile" "type"}}' 'RuntimeDefault'
   416  # Clean up
   417  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   418  # presumably waiting for a kubelet that's not present. Force the delete.
   419  kubectl delete --force pod "${debugger:?}" "${kube_flags[@]:?}"
   420
   421  ns_name="namespace-restricted"
   422  # Command: create namespace and add a label
   423  kubectl create namespace "${ns_name}"
   424  kubectl label namespace "${ns_name}" pod-security.kubernetes.io/enforce=restricted
   425  output_message=$(kubectl get namespaces "${ns_name}" --show-labels)
   426  kube::test::if_has_string "${output_message}" 'pod-security.kubernetes.io/enforce=restricted'
   427
   428  ### Debug node with restricted profile (restricted namespace)
   429  # Pre-Condition: node exists
   430  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   431  # Restricted profile works in restricted namespace
   432  # Command: create a new node debugger pod
   433  output_message=$(kubectl debug --profile restricted node/127.0.0.1 --image=busybox --attach=false -n ${ns_name} "${kube_flags[@]:?}" -- true)
   434  kube::test::if_has_not_string "${output_message}" 'forbidden: violates PodSecurity'
   435  # Post-Conditions
   436  kube::test::get_object_assert "pod -n ${ns_name}" "{{(len .items)}}" '1'
   437  debugger=$(kubectl get pod -n ${ns_name} -o go-template="{{(index .items 0)${id_field:?}}}")
   438  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   439  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" "{{${image_field:?}}}" 'busybox'
   440  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{.spec.nodeName}}' '127.0.0.1'
   441  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{.spec.hostIPC}}' '<no value>'
   442  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{.spec.hostNetwork}}' '<no value>'
   443  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{.spec.hostPID}}' '<no value>'
   444  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{index .spec.containers 0 "securityContext" "allowPrivilegeEscalation"}}' 'false'
   445  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{index .spec.containers 0 "securityContext" "capabilities" "drop"}}' '\[ALL\]'
   446  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{if (index (index .spec.containers 0) "securityContext" "capabilities" "add") }}:{{end}}' ''
   447  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{index .spec.containers 0 "securityContext" "runAsNonRoot"}}' 'true'
   448  kube::test::get_object_assert "pod/${debugger:?} -n ${ns_name}" '{{index .spec.containers 0 "securityContext" "seccompProfile" "type"}}' 'RuntimeDefault'
   449  # Clean up
   450  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   451  # presumably waiting for a kubelet that's not present. Force the delete.
   452  kubectl delete --force pod "${debugger:?}" -n ${ns_name} "${kube_flags[@]:?}"
   453
   454  # Clean up restricted namespace
   455  kubectl delete namespace "${ns_name}"
   456
   457  set +o nounset
   458  set +o errexit
   459}
   460
   461run_kubectl_debug_netadmin_tests() {
   462  set -o nounset
   463  set -o errexit
   464
   465  create_and_use_new_namespace  
   466  kube::log::status "Testing kubectl debug profile netadmin"
   467
   468  ### Pod Troubleshooting by ephemeral containers with netadmin profile  
   469  # Pre-Condition: Pod "nginx" is created
   470  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   471  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   472  # Command: add a new debug container with netadmin profile
   473  output_message=$(kubectl debug target -it --image=busybox --attach=false -c debug-container --profile=netadmin "${kube_flags[@]:?}")
   474  # Post-Conditions
   475  kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
   476  kube::test::get_object_assert pod/target '{{(index (index .spec.ephemeralContainers 0).securityContext.capabilities.add)}}' '\[NET_ADMIN NET_RAW\]'
   477  # Clean up
   478  kubectl delete pod target "${kube_flags[@]:?}"
   479
   480  ### Pod Troubleshooting by pod copy with netadmin profile
   481  # Pre-Condition: Pod "nginx" is created
   482  kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
   483  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
   484  # Command: create a copy of target with a new debug container
   485  kubectl debug target -it --copy-to=target-copy --image=busybox --container=debug-container --attach=false --profile=netadmin "${kube_flags[@]:?}"
   486  # Post-Conditions
   487  kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
   488  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.name}}:{{end}}' 'target:debug-container:'
   489  kube::test::get_object_assert pod/target-copy '{{range.spec.containers}}{{.image}}:{{end}}' "${IMAGE_NGINX:?}:busybox:"
   490  kube::test::get_object_assert pod/target-copy '{{.spec.shareProcessNamespace}}' 'true'
   491  kube::test::get_object_assert pod/target-copy '{{(index (index .spec.containers 1).securityContext.capabilities.add)}}' '\[NET_ADMIN NET_RAW\]'
   492  # Clean up
   493  kubectl delete pod target target-copy "${kube_flags[@]:?}"
   494
   495  set +o nounset
   496  set +o errexit
   497}
   498
   499run_kubectl_debug_netadmin_node_tests() {
   500  set -o nounset
   501  set -o errexit
   502
   503  create_and_use_new_namespace  
   504  kube::log::status "Testing kubectl debug profile netadmin (node)"
   505
   506  ### Debug node with netadmin profile
   507  # Pre-Condition: node exists
   508  kube::test::get_object_assert nodes "{{range.items}}{{${id_field:?}}}:{{end}}" '127.0.0.1:'
   509  # Command: create a new node debugger pod
   510  output_message=$(kubectl debug --profile netadmin node/127.0.0.1 --image=busybox --attach=false "${kube_flags[@]:?}" -- true)
   511  # Post-Conditions
   512  kube::test::get_object_assert pod "{{(len .items)}}" '1'
   513  debugger=$(kubectl get pod -o go-template="{{(index .items 0)${id_field:?}}}")
   514  kube::test::if_has_string "${output_message:?}" "${debugger:?}"
   515  kube::test::get_object_assert "pod/${debugger:?}" "{{${image_field:?}}}" 'busybox'
   516  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.nodeName}}' '127.0.0.1'
   517  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostNetwork}}' 'true'
   518  kube::test::get_object_assert "pod/${debugger:?}" '{{.spec.hostPID}}' 'true'
   519  kube::test::get_object_assert "pod/${debugger:?}" '{{index .spec.containers 0 "securityContext" "capabilities" "add"}}' '\[NET_ADMIN NET_RAW\]'
   520  # Clean up
   521  # pod.spec.nodeName is set by kubectl debug node which causes the delete to hang,
   522  # presumably waiting for a kubelet that's not present. Force the delete.
   523  kubectl delete --force pod "${debugger:?}" "${kube_flags[@]:?}"
   524
   525  set +o nounset
   526  set +o errexit
   527}

View as plain text