From 1cf84b7439d29f1eb7a689d1fbd5faf1940a48fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Varl=C4=B1?= <burakvar@amazon.co.uk> Date: Fri, 12 Jul 2024 16:07:57 +0100 Subject: [PATCH 1/6] Run e2e tests on AL2023 (with SELinux) and Ubuntu 20.04 as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a prework for SELinux support. We wanted to make sure we're running our end-to-end tests on hosts with old kernel (Ubuntu 20.04) and SELinux enforcing mode (AL2023). Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- .github/matrix.yaml | 11 +++++++++++ .github/workflows/e2e-tests.yaml | 1 + .../kops-patch-node-selinux-enforcing.yaml | 8 ++++++++ tests/e2e-kubernetes/scripts/kops.sh | 5 +++++ tests/e2e-kubernetes/scripts/run.sh | 17 +++++++++++++++-- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/e2e-kubernetes/scripts/kops-patch-node-selinux-enforcing.yaml diff --git a/.github/matrix.yaml b/.github/matrix.yaml index 2d035403..c5463079 100644 --- a/.github/matrix.yaml +++ b/.github/matrix.yaml @@ -26,6 +26,17 @@ matrix: arch: "arm" family: "Ubuntu2204" kubernetes-version: "1.32.1" + # Since we only enable enforcing mode for SELinux in AL2023, it's easier to list it in "include" + # field rather than trying to exclude all other variants. + - cluster-type: "kops" + arch: "arm" + family: "AmazonLinux2023" + kubernetes-version: "1.28.13" + selinux-mode: "enforcing" + - cluster-type: "eksctl" + arch: "x86" + family: "AmazonLinux2023" + selinux-mode: "enforcing" exclude: - cluster-type: "kops" family: "Bottlerocket" diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml index b1fd165a..dd9d6fbd 100644 --- a/.github/workflows/e2e-tests.yaml +++ b/.github/workflows/e2e-tests.yaml @@ -80,6 +80,7 @@ jobs: # and in order to get latest supported version by envtest we convert it to 1.28. K8S_VERSION: "${{ matrix.kubernetes-version }}" ENVTEST_K8S_VERSION: "${K8S_VERSION%.*}" + SELINUX_MODE: "${{ matrix.selinux-mode }}" steps: - name: Checkout uses: actions/checkout@v4 diff --git a/tests/e2e-kubernetes/scripts/kops-patch-node-selinux-enforcing.yaml b/tests/e2e-kubernetes/scripts/kops-patch-node-selinux-enforcing.yaml new file mode 100644 index 00000000..0be2ec41 --- /dev/null +++ b/tests/e2e-kubernetes/scripts/kops-patch-node-selinux-enforcing.yaml @@ -0,0 +1,8 @@ +spec: + additionalUserData: + - name: selinux-settings.txt + type: text/cloud-config + content: | + #cloud-config + selinux: + mode: enforcing diff --git a/tests/e2e-kubernetes/scripts/kops.sh b/tests/e2e-kubernetes/scripts/kops.sh index 02c4c8bc..9c750875 100755 --- a/tests/e2e-kubernetes/scripts/kops.sh +++ b/tests/e2e-kubernetes/scripts/kops.sh @@ -33,6 +33,7 @@ function kops_create_cluster() { KOPS_PATCH_NODE_FILE=${11} KOPS_STATE_FILE=${12} SSH_KEY=${13} + KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE=${14} if kops_cluster_exists "${CLUSTER_NAME}" "${BIN}" "${KOPS_STATE_FILE}"; then kops_delete_cluster "$BIN" "$CLUSTER_NAME" "$KOPS_STATE_FILE" @@ -58,6 +59,10 @@ function kops_create_cluster() { kops_patch_cluster_file "$CLUSTER_FILE" "$KOPS_PATCH_FILE" "Cluster" "" kops_patch_cluster_file "$CLUSTER_FILE" "$KOPS_PATCH_NODE_FILE" "InstanceGroup" "Node" + if [ -n "$KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE" ]; then + kops_patch_cluster_file "$CLUSTER_FILE" "$KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE" "InstanceGroup" "Node" + fi + ${BIN} create --state "${KOPS_STATE_FILE}" -f "${CLUSTER_FILE}" ${BIN} update cluster --state "${KOPS_STATE_FILE}" "${CLUSTER_NAME}" --yes ${BIN} export kubecfg --state "${KOPS_STATE_FILE}" "${CLUSTER_NAME}" --admin --kubeconfig "${KUBECONFIG}" diff --git a/tests/e2e-kubernetes/scripts/run.sh b/tests/e2e-kubernetes/scripts/run.sh index 86b600d5..9baaaf68 100755 --- a/tests/e2e-kubernetes/scripts/run.sh +++ b/tests/e2e-kubernetes/scripts/run.sh @@ -27,6 +27,7 @@ KUBECTL_BIN=${KUBECTL_INSTALL_PATH}/kubectl CLUSTER_TYPE=${CLUSTER_TYPE:-kops} ARCH=${ARCH:-x86} AMI_FAMILY=${AMI_FAMILY:-AmazonLinux2} +SELINUX_MODE=${SELINUX_MODE:-} # kops: must include patch version (e.g. 1.19.1) # eksctl: mustn't include patch version (e.g. 1.19) @@ -67,11 +68,21 @@ CLUSTER_FILE=${TEST_DIR}/${CLUSTER_NAME}.${CLUSTER_TYPE}.yaml KOPS_PATCH_FILE=${KOPS_PATCH_FILE:-${BASE_DIR}/kops-patch.yaml} KOPS_PATCH_NODE_FILE=${KOPS_PATCH_NODE_FILE:-${BASE_DIR}/kops-patch-node.yaml} KOPS_STATE_FILE=${KOPS_STATE_FILE:-"s3://mountpoint-s3-csi-driver-kops-state-store"} +KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE=${KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE:-${BASE_DIR}/kops-patch-node-selinux-enforcing.yaml} +if [[ "${SELINUX_MODE}" != "enforcing" ]]; then + KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE="" +fi + SSH_KEY=${SSH_KEY:-""} HELM_RELEASE_NAME=mountpoint-s3-csi-driver EKSCTL_VERSION=${EKSCTL_VERSION:-0.202.0} EKSCTL_PATCH_FILE=${EKSCTL_PATCH_FILE:-${BASE_DIR}/eksctl-patch.json} +EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${EKSCTL_PATCH_SELINUX_ENFORCING_FILE:-${BASE_DIR}/eksctl-patch-selinux-enforcing.json} +if [[ "${SELINUX_MODE}" != "enforcing" ]]; then + EKSCTL_PATCH_SELINUX_ENFORCING_FILE="" +fi + CI_ROLE_ARN=${CI_ROLE_ARN:-""} MOUNTER_KIND=${MOUNTER_KIND:-systemd} @@ -124,7 +135,8 @@ function create_cluster() { "$KOPS_PATCH_FILE" \ "$KOPS_PATCH_NODE_FILE" \ "$KOPS_STATE_FILE" \ - "$SSH_KEY" + "$SSH_KEY" \ + "$KOPS_PATCH_NODE_SELINUX_ENFORCING_FILE" elif [[ "${CLUSTER_TYPE}" == "eksctl" ]]; then eksctl_create_cluster \ "$CLUSTER_NAME" \ @@ -138,7 +150,8 @@ function create_cluster() { "$CI_ROLE_ARN" \ "$INSTANCE_TYPE" \ "$AMI_FAMILY" \ - "$K8S_VERSION_EKSCTL" + "$K8S_VERSION_EKSCTL" \ + "$EKSCTL_PATCH_SELINUX_ENFORCING_FILE" fi } From ad8023aeae9801fd19e6de83abe5815ce2361c73 Mon Sep 17 00:00:00 2001 From: Jiayi Nie <jiayinie@amazon.com> Date: Thu, 16 Jan 2025 16:30:24 +0000 Subject: [PATCH 2/6] Enforce SELinux on EKS clusters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- ...-patch-selinux-enforcing-AmazonLinux2.json | 11 +++++++ ...tch-selinux-enforcing-AmazonLinux2023.json | 12 ++++++++ tests/e2e-kubernetes/scripts/eksctl.sh | 30 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json create mode 100644 tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json diff --git a/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json new file mode 100644 index 00000000..e6968e25 --- /dev/null +++ b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json @@ -0,0 +1,11 @@ +[ + { + "op": "add", + "path": "/managedNodeGroups/0/preBootstrapCommands", + "value": [ + "yum -y install policycoreutils selinux-policy selinux-policy-targeted", + "setenforce 1", + "sed -i \"s/SELINUX=disabled/SELINUX=enforcing/\" /etc/selinux/config" + ] + } + ] \ No newline at end of file diff --git a/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json new file mode 100644 index 00000000..d8bc2436 --- /dev/null +++ b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json @@ -0,0 +1,12 @@ +[ + { + "op": "add", + "path": "/managedNodeGroups/0/preBootstrapCommands", + "value": [ + "dnf install -y container-selinux", + "setenforce 1", + "sed -i \"s/SELINUX=permissive/SELINUX=enforcing/\" /etc/selinux/config", + "reboot" + ] + } + ] \ No newline at end of file diff --git a/tests/e2e-kubernetes/scripts/eksctl.sh b/tests/e2e-kubernetes/scripts/eksctl.sh index e36f24dd..352c759b 100644 --- a/tests/e2e-kubernetes/scripts/eksctl.sh +++ b/tests/e2e-kubernetes/scripts/eksctl.sh @@ -25,6 +25,7 @@ function eksctl_create_cluster() { NODE_TYPE=${10} AMI_FAMILY=${11} K8S_VERSION=${12} + EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${13} eksctl_delete_cluster "$BIN" "$CLUSTER_NAME" "$REGION" @@ -42,8 +43,19 @@ function eksctl_create_cluster() { CLUSTER_FILE_TMP="${CLUSTER_FILE}.tmp" ${KUBECTL_BIN} patch -f $CLUSTER_FILE --local --type json --patch "$(cat $EKSCTL_PATCH_FILE)" -o yaml > $CLUSTER_FILE_TMP mv $CLUSTER_FILE_TMP $CLUSTER_FILE + + if [ -n "$EKSCTL_PATCH_SELINUX_ENFORCING_FILE" ]; then + ${KUBECTL_BIN} patch -f $CLUSTER_FILE --local --type json --patch "$(cat $EKSCTL_PATCH_SELINUX_ENFORCING_FILE)" -o yaml > $CLUSTER_FILE_TMP + mv $CLUSTER_FILE_TMP $CLUSTER_FILE + fi + ${BIN} create cluster -f "${CLUSTER_FILE}" --kubeconfig "${KUBECONFIG}" + # EKS cluster with AmazonLinux2 requires a manual reboot to enforce SELinux + if [ -n "$EKSCTL_PATCH_SELINUX_ENFORCING_FILE" ] && [ "$AMI_FAMILY" == "AmazonLinux2" ]; then + reboot_nodes "$KUBECTL_BIN" "$REGION" + fi + if [ -n "$CI_ROLE_ARN" ]; then ${BIN} create iamidentitymapping --cluster ${CLUSTER_NAME} --region=${REGION} \ --arn ${CI_ROLE_ARN} --username admin --group system:masters \ @@ -51,6 +63,24 @@ function eksctl_create_cluster() { fi } + +function reboot_nodes() { + KUBECTL_BIN=${1} + REGION=${2} + # Fetch and split node names into an array + NODE_NAMES=($(${KUBECTL_BIN} get nodes -o jsonpath='{.items[*].metadata.name}')) + for NODE in "${NODE_NAMES[@]}"; do + echo "Rebooting node: ${NODE}" + INSTANCE_ID=$(${KUBECTL_BIN} get node ${NODE} -o jsonpath='{.spec.providerID}' | awk -F '/' '{print $NF}') + if [ -n "$INSTANCE_ID" ]; then + aws ec2 reboot-instances --instance-ids ${INSTANCE_ID} --region ${REGION} + else + echo "Failed to fetch instance ID for node: ${NODE}" + fi + done +} + + function eksctl_delete_cluster() { BIN=${1} CLUSTER_NAME=${2} From b69d17ae3467f4ee845ac8dd1a0ea91929576b62 Mon Sep 17 00:00:00 2001 From: Jiayi Nie <jiayinie@amazon.com> Date: Thu, 16 Jan 2025 17:16:19 +0000 Subject: [PATCH 3/6] Fix EKS SELinux enforcing patch file format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- tests/e2e-kubernetes/scripts/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e-kubernetes/scripts/run.sh b/tests/e2e-kubernetes/scripts/run.sh index 9baaaf68..e54feaed 100755 --- a/tests/e2e-kubernetes/scripts/run.sh +++ b/tests/e2e-kubernetes/scripts/run.sh @@ -78,7 +78,7 @@ HELM_RELEASE_NAME=mountpoint-s3-csi-driver EKSCTL_VERSION=${EKSCTL_VERSION:-0.202.0} EKSCTL_PATCH_FILE=${EKSCTL_PATCH_FILE:-${BASE_DIR}/eksctl-patch.json} -EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${EKSCTL_PATCH_SELINUX_ENFORCING_FILE:-${BASE_DIR}/eksctl-patch-selinux-enforcing.json} +EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${EKSCTL_PATCH_SELINUX_ENFORCING_FILE:-${BASE_DIR}/eksctl-patch-selinux-enforcing-${AMI_FAMILY}.json} if [[ "${SELINUX_MODE}" != "enforcing" ]]; then EKSCTL_PATCH_SELINUX_ENFORCING_FILE="" fi From 1c78ac5cf2102284f1aa17c318385bf8ecad37f3 Mon Sep 17 00:00:00 2001 From: Jiayi Nie <jiayinie@amazon.com> Date: Fri, 17 Jan 2025 11:10:25 +0000 Subject: [PATCH 4/6] Remove EKS AL2 testing with SELinux to avoid manual reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- ...-patch-selinux-enforcing-AmazonLinux2.json | 11 --------- ...on => eksctl-patch-selinux-enforcing.json} | 0 tests/e2e-kubernetes/scripts/eksctl.sh | 23 ------------------- tests/e2e-kubernetes/scripts/run.sh | 2 +- 4 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json rename tests/e2e-kubernetes/scripts/{eksctl-patch-selinux-enforcing-AmazonLinux2023.json => eksctl-patch-selinux-enforcing.json} (100%) diff --git a/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json deleted file mode 100644 index e6968e25..00000000 --- a/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "op": "add", - "path": "/managedNodeGroups/0/preBootstrapCommands", - "value": [ - "yum -y install policycoreutils selinux-policy selinux-policy-targeted", - "setenforce 1", - "sed -i \"s/SELINUX=disabled/SELINUX=enforcing/\" /etc/selinux/config" - ] - } - ] \ No newline at end of file diff --git a/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json b/tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing.json similarity index 100% rename from tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing-AmazonLinux2023.json rename to tests/e2e-kubernetes/scripts/eksctl-patch-selinux-enforcing.json diff --git a/tests/e2e-kubernetes/scripts/eksctl.sh b/tests/e2e-kubernetes/scripts/eksctl.sh index 352c759b..973db3ce 100644 --- a/tests/e2e-kubernetes/scripts/eksctl.sh +++ b/tests/e2e-kubernetes/scripts/eksctl.sh @@ -51,11 +51,6 @@ function eksctl_create_cluster() { ${BIN} create cluster -f "${CLUSTER_FILE}" --kubeconfig "${KUBECONFIG}" - # EKS cluster with AmazonLinux2 requires a manual reboot to enforce SELinux - if [ -n "$EKSCTL_PATCH_SELINUX_ENFORCING_FILE" ] && [ "$AMI_FAMILY" == "AmazonLinux2" ]; then - reboot_nodes "$KUBECTL_BIN" "$REGION" - fi - if [ -n "$CI_ROLE_ARN" ]; then ${BIN} create iamidentitymapping --cluster ${CLUSTER_NAME} --region=${REGION} \ --arn ${CI_ROLE_ARN} --username admin --group system:masters \ @@ -63,24 +58,6 @@ function eksctl_create_cluster() { fi } - -function reboot_nodes() { - KUBECTL_BIN=${1} - REGION=${2} - # Fetch and split node names into an array - NODE_NAMES=($(${KUBECTL_BIN} get nodes -o jsonpath='{.items[*].metadata.name}')) - for NODE in "${NODE_NAMES[@]}"; do - echo "Rebooting node: ${NODE}" - INSTANCE_ID=$(${KUBECTL_BIN} get node ${NODE} -o jsonpath='{.spec.providerID}' | awk -F '/' '{print $NF}') - if [ -n "$INSTANCE_ID" ]; then - aws ec2 reboot-instances --instance-ids ${INSTANCE_ID} --region ${REGION} - else - echo "Failed to fetch instance ID for node: ${NODE}" - fi - done -} - - function eksctl_delete_cluster() { BIN=${1} CLUSTER_NAME=${2} diff --git a/tests/e2e-kubernetes/scripts/run.sh b/tests/e2e-kubernetes/scripts/run.sh index e54feaed..9baaaf68 100755 --- a/tests/e2e-kubernetes/scripts/run.sh +++ b/tests/e2e-kubernetes/scripts/run.sh @@ -78,7 +78,7 @@ HELM_RELEASE_NAME=mountpoint-s3-csi-driver EKSCTL_VERSION=${EKSCTL_VERSION:-0.202.0} EKSCTL_PATCH_FILE=${EKSCTL_PATCH_FILE:-${BASE_DIR}/eksctl-patch.json} -EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${EKSCTL_PATCH_SELINUX_ENFORCING_FILE:-${BASE_DIR}/eksctl-patch-selinux-enforcing-${AMI_FAMILY}.json} +EKSCTL_PATCH_SELINUX_ENFORCING_FILE=${EKSCTL_PATCH_SELINUX_ENFORCING_FILE:-${BASE_DIR}/eksctl-patch-selinux-enforcing.json} if [[ "${SELINUX_MODE}" != "enforcing" ]]; then EKSCTL_PATCH_SELINUX_ENFORCING_FILE="" fi From 069b4a45a2dc0f68542dff46d32f29e4d2e4782c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Varl=C4=B1?= <burakvar@amazon.co.uk> Date: Fri, 21 Feb 2025 10:35:29 +0000 Subject: [PATCH 5/6] Specify Kubernetes version in AL2023 + SELinux cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- .github/matrix.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/matrix.yaml b/.github/matrix.yaml index c5463079..4ccfb2ba 100644 --- a/.github/matrix.yaml +++ b/.github/matrix.yaml @@ -36,6 +36,7 @@ matrix: - cluster-type: "eksctl" arch: "x86" family: "AmazonLinux2023" + kubernetes-version: "1.32.1" selinux-mode: "enforcing" exclude: - cluster-type: "kops" From 9d98c576f8d01bc7ffe790e8b634b3e1ca1933a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Varl=C4=B1?= <burakvar@amazon.co.uk> Date: Fri, 21 Feb 2025 10:41:34 +0000 Subject: [PATCH 6/6] Skip `SystemdMounter` tests if SELinux is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Burak Varlı <burakvar@amazon.co.uk> --- .github/workflows/e2e-tests.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml index dd9d6fbd..3c13212f 100644 --- a/.github/workflows/e2e-tests.yaml +++ b/.github/workflows/e2e-tests.yaml @@ -120,12 +120,15 @@ jobs: tests/e2e-kubernetes/scripts/run.sh # Test SystemdMounter + # SystemdMounter tests are skipped if SELinux is enabled as SystemdMounter won't work with SELinux. - name: Install the driver (SystemdMounter) + if: matrix.selinux-mode != 'enforcing' env: ACTION: "install_driver" run: | tests/e2e-kubernetes/scripts/run.sh - name: Run E2E Tests (SystemdMounter) + if: matrix.selinux-mode != 'enforcing' env: ACTION: "run_tests" run: | @@ -157,13 +160,13 @@ jobs: tests/e2e-kubernetes/scripts/format_benchmark_data.py ${{ env.BENCHMARK_ARTIFACTS_FOLDER }}/benchmark-data.json ${{ env.BENCHMARK_ARTIFACTS_FOLDER }}/quicksight-data.json aws s3 cp ${{ env.BENCHMARK_ARTIFACTS_FOLDER }} ${{ env.BENCHMARK_BUCKET }} --recursive - name: Post e2e cleanup (SystemdMounter) - if: always() + if: matrix.selinux-mode != 'enforcing' && always() env: ACTION: "e2e_cleanup" run: | tests/e2e-kubernetes/scripts/run.sh - name: Uninstall the driver (SystemdMounter) - if: always() + if: matrix.selinux-mode != 'enforcing' && always() env: ACTION: "uninstall_driver" run: |