k8s.io/kubernetes@v1.29.3/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  
    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  
    95  run_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  
   128  run_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  
   173  run_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  
   208  run_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  
   253  run_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  
   286  run_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  
   388  run_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  
   461  run_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  
   499  run_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  }