k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/cmd/debug.sh (about)

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