Skip to content

Commit b03928d

Browse files
author
weichao
committed
fix(eks): forward stored AWS integration credentials to k8s client builder
Fixes Tracer-Cloud#969. Follow-up to Tracer-Cloud#724. Problem ------- PR Tracer-Cloud#724 let EKS be detected when the AWS integration is configured with stored IAM user credentials (access_key_id + secret_access_key, no role_arn), but build_k8s_clients still had no way to use those stored credentials. After Tracer-Cloud#724 it supports: 1. role_arn -> STS AssumeRole 2. ambient botocore chain (env / shared config / instance profile / IRSA) The stored integration credentials (persisted by resolve_integrations and surfaced in _eks_int['credentials']) were silently dropped. On hosts that happen to have ambient credentials pointing elsewhere, this picks up the wrong principal; on hosts without ambient credentials the call fails entirely, even though the integration has perfectly usable keys. Fix (approach Tracer-Cloud#2, pre-approved by Greptile in PR Tracer-Cloud#724 review) ------------------------------------------------------------- Forward the stored credentials through the existing eks_params pipeline: * detect_sources.py: set eks_params['credentials'] = _eks_int.get( 'credentials') or None alongside the other EKS integration fields. * eks_k8s_client.build_k8s_clients: accept an optional credentials kwarg. Resolution priority: 1. explicit credentials kwarg (stored-integration, new) 2. role_arn AssumeRole (existing production path) 3. ambient botocore chain (Tracer-Cloud#724 fallback) The two secondary fixes from Tracer-Cloud#724 are preserved (empty SessionToken coerced to None, regional STS endpoint). Test plan --------- - py_compile passes on both files. - ruff check + ruff format clean on both files. - Regression safety: the role_arn (AssumeRole) and ambient-botocore branches are unchanged; the new explicit branch only runs when the credentials kwarg is truthy and has access_key_id + secret_access_key. Related ------- - Fixes Tracer-Cloud#969. - Follow-up to Tracer-Cloud#724. - Greptile pre-approved this approach in Tracer-Cloud#724 (comment)
1 parent 72dc93b commit b03928d

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

app/nodes/plan_actions/detect_sources.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,12 @@ def detect_sources(
714714
"role_arn": _eks_int.get("role_arn", ""),
715715
"external_id": _eks_int.get("external_id", ""),
716716
"cluster_names": _eks_int.get("cluster_names", []),
717+
# Forward stored AWS integration credentials so build_k8s_clients
718+
# can use them explicitly instead of silently missing them when
719+
# the AWS integration is configured with IAM user credentials
720+
# (access_key_id + secret_access_key, no role_arn). Follow-up
721+
# to #724 (stored-integration credential forwarding).
722+
"credentials": _eks_int.get("credentials") or None,
717723
}
718724
if _has_injected_eks_backend:
719725
# Backend-only path: only fixture-aware EKS tools should activate,

app/services/eks/eks_k8s_client.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ def _generate_eks_token(cluster_name: str, assumed_creds: dict[str, Any], region
4040
creds = botocore.credentials.Credentials(
4141
access_key=assumed_creds["AccessKeyId"],
4242
secret_key=assumed_creds["SecretAccessKey"],
43-
token=assumed_creds["SessionToken"],
43+
token=assumed_creds["SessionToken"] or None,
4444
)
4545

46-
sts_url = "https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15"
46+
sts_url = f"https://sts.{region}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15"
4747
request = botocore.awsrequest.AWSRequest(
4848
method="GET",
4949
url=sts_url,
@@ -76,21 +76,61 @@ def build_k8s_clients(
7676
role_arn: str,
7777
external_id: str,
7878
region: str,
79+
credentials: dict[str, Any] | None = None,
7980
) -> tuple[k8s_client.CoreV1Api, k8s_client.AppsV1Api]:
8081
"""Assume role, describe cluster, build in-memory Kubernetes API clients.
8182
83+
Credential resolution priority:
84+
1. Explicit `credentials` kwarg (stored AWS integration IAM user creds).
85+
2. `role_arn` → STS AssumeRole (existing behaviour).
86+
3. Ambient botocore chain (env AK/SK, shared config, instance profile / IRSA).
87+
8288
Returns (CoreV1Api, AppsV1Api) ready to query pods, events, nodes, deployments.
8389
No kubeconfig file is written to disk.
8490
"""
85-
assumed = _assume_role(role_arn, external_id, "TracerEKSK8sInvestigation")
91+
if credentials and credentials.get("access_key_id") and credentials.get("secret_access_key"):
92+
# Explicit stored-integration credentials path (highest priority).
93+
# Matches the catalog + resolve_integrations flow: the AWS integration
94+
# is configured with IAM user creds (access_key_id + secret_access_key),
95+
# possibly with a session_token, and no role_arn. Previously these
96+
# silently fell through to the ambient botocore chain which missed
97+
# the stored values entirely when ambient creds were also set but
98+
# pointed elsewhere.
99+
logger.info("[eks] Using explicit stored-integration AWS credentials")
100+
assumed = {
101+
"AccessKeyId": credentials["access_key_id"],
102+
"SecretAccessKey": credentials["secret_access_key"],
103+
"SessionToken": credentials.get("session_token") or "",
104+
}
105+
elif role_arn:
106+
assumed = _assume_role(role_arn, external_id, "TracerEKSK8sInvestigation")
107+
else:
108+
# No role_arn and no explicit creds: fall back to ambient AWS
109+
# credentials (env AK/SK, shared config profile, or instance profile
110+
# / IRSA). Preserves the #724 fallback behaviour.
111+
logger.info("[eks] No role_arn or explicit credentials; using ambient AWS credentials")
112+
import botocore.session as _bsession
113+
114+
sess = _bsession.get_session()
115+
ambient = sess.get_credentials()
116+
if ambient is None:
117+
msg = "No AWS credentials available for EKS investigation"
118+
logger.error("[eks] %s", msg)
119+
raise RuntimeError(msg)
120+
frozen = ambient.get_frozen_credentials()
121+
assumed = {
122+
"AccessKeyId": frozen.access_key,
123+
"SecretAccessKey": frozen.secret_key,
124+
"SessionToken": frozen.token or "",
125+
}
86126

87127
logger.info("[eks] Describing cluster: %s in region %s", cluster_name, region)
88128
eks = boto3.client(
89129
"eks",
90130
region_name=region,
91131
aws_access_key_id=assumed["AccessKeyId"],
92132
aws_secret_access_key=assumed["SecretAccessKey"],
93-
aws_session_token=assumed["SessionToken"],
133+
aws_session_token=assumed["SessionToken"] or None,
94134
)
95135
cluster_info = eks.describe_cluster(name=cluster_name)["cluster"]
96136
endpoint = cluster_info["endpoint"]

0 commit comments

Comments
 (0)