This is an automated email from the ASF dual-hosted git repository.

shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 3107af07cd1 Use POSIX-compliant tail to extract token line in EKS 
command (#73690)
3107af07cd1 is described below

commit 3107af07cd163a73d43a6e857fcbd21c48804496
Author: Alejandro Morgante <[email protected]>
AuthorDate: Sun Sep 27 15:09:37 2026 -0300

    Use POSIX-compliant tail to extract token line in EKS command (#73690)
    
    The bash parameter expansion with $'\n' quoting used to strip to the
    last line of the token helper output is a bash-specific extension not
    guaranteed by POSIX; it silently breaks on sh implementations that do
    not support it. Replace with `printf '%s\n' "$output" | tail -n 1`,
    which is portable and also handles spurious stdout lines from
    dependencies that bypass the stderr redirect.
---
 .../src/airflow/providers/amazon/aws/hooks/eks.py  |  6 ++--
 .../amazon/tests/unit/amazon/aws/hooks/test_eks.py | 40 ++++++++++++++++++----
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py 
b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
index 032d7e16833..5a20629ef91 100644
--- a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
+++ b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
@@ -105,10 +105,8 @@ COMMAND = """
                 exit "$status"
             fi
 
-            # Use pure bash below to parse so that it's posix compliant
-            # Only the token line should be on stdout (stderr captured above)
-
-            last_line=${{output##*$'\\n'}}  # strip everything up to the last 
newline
+            # Keep only the token line even if a dependency logs to stdout.
+            last_line=$(printf '%s\\n' "$output" | tail -n 1)
 
             timestamp=${{last_line#expirationTimestamp: }}  # drop the label
             timestamp=${{timestamp%%,*}}  # keep up to the first comma
diff --git a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py 
b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
index 521005a19ed..af8b7c0e6ce 100644
--- a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
+++ b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
@@ -17,6 +17,8 @@
 # under the License.
 from __future__ import annotations
 
+import json
+import subprocess
 import sys
 from copy import deepcopy
 from pathlib import Path
@@ -53,7 +55,7 @@ from moto.eks.models import (
     NODEGROUP_NOT_FOUND_MSG,
 )
 
-from airflow.providers.amazon.aws.hooks.eks import EksHook
+from airflow.providers.amazon.aws.hooks.eks import COMMAND, EksHook
 
 from unit.amazon.aws.utils.eks_test_constants import (
     DEFAULT_CONN_ID,
@@ -1275,8 +1277,6 @@ class TestEksHook:
 
     def test_command_template_captures_stderr_separately(self):
         """Verify COMMAND keeps stderr out of stdout while preserving 
errors."""
-        from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
         # Verify stderr is not merged with stdout (the core correctness 
requirement)
         assert "2>&1" not in COMMAND, (
             "COMMAND must not use 2>&1 — merging stderr with stdout breaks 
bash token parsing"
@@ -1286,10 +1286,38 @@ class TestEksHook:
         assert 'cat "$stderr_file" >&2' in COMMAND
         assert "2>/dev/null" not in COMMAND
 
+    def test_command_template_uses_last_stdout_line_with_posix_shell(self, 
tmp_path):
+        credentials_file = tmp_path / "credentials"
+        credentials_file.write_text(
+            "export AWS_ACCESS_KEY_ID='test-access-key'\nexport 
AWS_SECRET_ACCESS_KEY='test-secret-key'\n"
+        )
+        token_helper = tmp_path / "token-helper"
+        token_helper.write_text(
+            "#!/bin/sh\n"
+            "printf '%s\\n' '2026-09-04T17:50:59Z [info] Found credentials in 
environment variables.'\n"
+            "printf '%s\\n' 'expirationTimestamp: 2026-09-04T18:04:59Z, token: 
test-token'\n"
+        )
+        token_helper.chmod(0o700)
+        command = COMMAND.format(
+            credentials_file=credentials_file,
+            sts_url="https://sts.us-east-1.amazonaws.com";,
+            python_executable=token_helper,
+            eks_cluster_name="test-cluster",
+            args="",
+            authentication_api_version="client.authentication.k8s.io/v1",
+        )
+
+        result = subprocess.run(["sh", "-c", command], capture_output=True, 
text=True, check=True)
+
+        assert json.loads(result.stdout) == {
+            "kind": "ExecCredential",
+            "apiVersion": "client.authentication.k8s.io/v1",
+            "spec": {},
+            "status": {"expirationTimestamp": "2026-09-04T18:04:59Z", "token": 
"test-token"},
+        }
+
     def test_command_template_does_not_print_token_output_on_error(self):
         """Verify the error path does not echo stdout, which can contain a 
token."""
-        from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
         failure_block = COMMAND.split('if [ "$status" -ne 0 ]; then', 
1)[1].split("fi", 1)[0]
         assert '"$output"' not in failure_block
 
@@ -1299,8 +1327,6 @@ class TestEksHook:
         a malformed ExecCredential with an empty token is sent to the API 
server,
         resulting in 401 Unauthorized with an empty user identity in audit 
logs.
         """
-        from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
         # Verify token validation check exists
         assert 'if [ -z "$token" ]' in COMMAND, (
             "COMMAND must validate that token is non-empty before producing 
ExecCredential JSON"

Reply via email to