feat(egress): refactored credential injection test to use Vault#951
feat(egress): refactored credential injection test to use Vault#951averevki merged 1 commit intoKuadrant:mainfrom
Conversation
📝 WalkthroughWalkthroughAdds Vault integration for credential injection: config template, hvac dependency, Vault test utility, dynaconf defaults, authorization model extensions for CEL/value selectors, namespace-aware service IP lookup, and Vault-backed egress credential-injection tests (with related test refactors). Changes
Sequence Diagram(s)sequenceDiagram
participant Workload as Workload
participant Authorino as Authorino
participant Vault as Vault
participant Egress as Egress_Gateway
participant Backend as MockServer
Workload->>Authorino: Request (includes K8s SA token)
Authorino->>Vault: POST /v1/auth/kubernetes/login (SA token) [metadata.http p0]
Vault-->>Authorino: Vault client token + auth info
Authorino->>Vault: GET /v1/secret/data/egress/<ns>/<sa> (using client token) [metadata.http p1]
Vault-->>Authorino: Secret { api_key: "..." }
Authorino->>Authorino: Authorization check (patternMatching)
Authorino->>Egress_Gateway: Apply response directives (inject Authorization header)
Egress_Gateway->>Backend: Outbound request (Authorization: Bearer <api_key>)
Backend-->>Egress_Gateway: 200 OK
Egress_Gateway-->>Workload: Response
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly Related PRs
Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
testsuite/kuadrant/policy/authorization/sections.py (1)
202-234:⚠️ Potential issue | 🟡 MinorConsider validating that at least one of
endpointorurl_expressionis provided.With both
endpointandurl_expressionnow optional and no mutual-exclusivity/presence check, callers can construct anhttpmetadata entry with neitherurlnorurlExpression, or with both set simultaneously. Authorino will reject it server-side, but surfacing the error at construction time makes failures easier to localise.🛡️ Suggested validation
"""Set metadata http external auth feature""" + if not endpoint and not url_expression: + raise ValueError("add_http requires either `endpoint` or `url_expression`") + if endpoint and url_expression: + raise ValueError("add_http accepts only one of `endpoint` or `url_expression`") http_config: dict = {"method": method, "headers": {"Accept": {"value": "application/json"}}}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kuadrant/policy/authorization/sections.py` around lines 202 - 234, In add_http, ensure callers supply exactly one of endpoint or url_expression: add a validation at the start of the add_http method (before building http_config) that raises a ValueError if neither endpoint nor url_expression is provided, and optionally also raise if both are provided (to enforce mutual exclusivity) so you don't construct an invalid "http" metadata object; reference the add_http function and the endpoint and url_expression parameters and perform this check before calling self.add_item.
🧹 Nitpick comments (5)
testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py (4)
115-127: Fragile manual JSON assembly in CEL; consider a readable alternative.The double-escaped JSON literal (
'"{\\"jwt\\": \\"" + ... + "\\", \\"role\\": \\"..."}}"') is hard to read and fragile — any future token whose value contains a double quote or backslash would produce invalid JSON. Since Authorino supports JSON body types viacontent_type="application/json"with a structuredbody, prefer a dict-shaped payload if the API allows it, or at minimum extract the CEL into a named helper/constant for readability.Also,
substring(7)implicitly assumes the incomingAuthorizationheader starts with exactlyBearer(7 chars). That matches the Kubernetes identity credentials convention used here, but a brief comment would save future readers a lookup.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` around lines 115 - 127, Replace the fragile manually-escaped JSON CEL expression passed to auth.metadata.add_http with a structured body using ValueOrSelector/CelExpression that builds a map/object (e.g., {"jwt": <token>, "role": <role>}) instead of concatenating JSON strings; locate the call to auth.metadata.add_http and change the body argument from the current CelExpression string concat to a map-shaped CEL expression (using ValueOrSelector with CelExpression that returns a map) or move the long CEL into a named constant for readability, and add a short inline comment next to the substring(7) usage explaining it assumes a "Bearer " prefix on request.headers.authorization to make the intent explicit.
20-20: Consider adding anissuemarker linking to#949.The PR closes issue
#949; addingpytest.mark.issue("https://github.com/Kuadrant/testsuite/issues/949")(or the Kuadrant repo URL) topytestmarkhelps with traceability in Report Portal.As per coding guidelines: "Common markers include:
@pytest.mark.authorino, ...@pytest.mark.issue('https://github.com/...'), ...".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` at line 20, Add the issue marker to the existing pytestmark declaration so the test is traceable to issue `#949`; update the pytestmark list (the pytestmark variable in this file) to include pytest.mark.issue("https://github.com/Kuadrant/testsuite/issues/949") alongside pytest.mark.kuadrant_only and pytest.mark.egress_gateway.
154-170: Consider also covering the "authenticated SA but no Vault role binding" case.The linked issue explicitly lists a 403 scenario for a workload whose ServiceAccount token is valid at the K8s TokenReview stage but has no Vault role binding. The current three tests cover valid/invalid/missing SA tokens (all rejected at Kubernetes identity stage for the negative paths), but none exercise the Vault-side authorization failure. A fourth test using a SA that is not bound to the Vault role would close that gap.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` around lines 154 - 170, Add a new test that exercises the Vault-side authorization failure: create a test function (e.g., test_egress_authenticated_no_vault_binding_returns_403) that sends a request using a ServiceAccount token that is valid for Kubernetes TokenReview but intentionally has no Vault role binding (use or add a fixture like sa_token_unbound_to_vault or construct such a token), call client.get(mockserver_expectation, headers={"Authorization": f"Bearer {sa_token_unbound_to_vault}"}), and assert the response.status_code == 403 and that the backend Authorization header was not overwritten; mirror assertions and structure from test_egress_credential_injection_via_vault to keep consistency.
22-23: S105 is a false positive here.
K8S_TOKEN_AUDIENCEholds an audience URL, not a credential. If Ruff noise becomes an issue, suppress with# noqa: S105or rename; otherwise safe to ignore.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` around lines 22 - 23, S105 is a false positive for K8S_TOKEN_AUDIENCE because it stores an audience URL, not a secret; fix by either appending a Ruff suppression or renaming the identifier: add "# noqa: S105" to the K8S_TOKEN_AUDIENCE definition or rename the constant to a clearly non-secret name such as K8S_TOKEN_AUDIENCE_URL (update all references) so the linter no longer flags it.testsuite/kubernetes/vault.py (1)
28-28: Consider makingttlconfigurable.The
ttl="1h"is hardcoded inside the wrapper, which prevents callers from overriding it for longer-running tests or negative scenarios. Exposing it as a keyword argument (with the current value as default) would keep the call sites concise while preserving flexibility.♻️ Suggested change
- def create_role(self, name: str, sa_names: list[str], sa_namespaces: list[str], policies: list[str]): + def create_role( + self, name: str, sa_names: list[str], sa_namespaces: list[str], policies: list[str], ttl: str = "1h" + ): """Create a Kubernetes auth role binding service accounts to policies""" self._client.auth.kubernetes.create_role( name, bound_service_account_names=sa_names, bound_service_account_namespaces=sa_namespaces, policies=policies, - ttl="1h", + ttl=ttl, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kubernetes/vault.py` at line 28, The hardcoded ttl="1h" in testsuite/kubernetes/vault.py prevents callers from overriding token lifetime; add a ttl keyword argument to the enclosing function (default="1h") and replace the literal ttl="1h" with the parameter so callers can pass a custom ttl; update any internal calls/tests to keep behavior unchanged by default but allow overriding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@testsuite/kubernetes/vault.py`:
- Around line 21-29: The method create_role in testsuite/kubernetes/vault.py
calls a non-existent helper self._client.auth.kubernetes.createq_role; change
that call to the correct hvac method name create_role so the function body uses
self._client.auth.kubernetes.create_role(...). Keep the existing argument names
(bound_service_account_names, bound_service_account_namespaces, policies, ttl)
and ensure the method name in the call matches the enclosing method create_role.
In
`@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py`:
- Around line 115-140: The test fixture fails because of a typo: replace the
incorrect symbol createq_role with the correct Vault.create_role call in
testsuite/kubernetes/vault.py (fix the function name where the vault fixture
invokes createq_role), ensure the module imports or class Vault exposes
create_role and update any callers to use create_role so the vault fixture and
downstream authorization fixture can initialize properly.
---
Outside diff comments:
In `@testsuite/kuadrant/policy/authorization/sections.py`:
- Around line 202-234: In add_http, ensure callers supply exactly one of
endpoint or url_expression: add a validation at the start of the add_http method
(before building http_config) that raises a ValueError if neither endpoint nor
url_expression is provided, and optionally also raise if both are provided (to
enforce mutual exclusivity) so you don't construct an invalid "http" metadata
object; reference the add_http function and the endpoint and url_expression
parameters and perform this check before calling self.add_item.
---
Nitpick comments:
In `@testsuite/kubernetes/vault.py`:
- Line 28: The hardcoded ttl="1h" in testsuite/kubernetes/vault.py prevents
callers from overriding token lifetime; add a ttl keyword argument to the
enclosing function (default="1h") and replace the literal ttl="1h" with the
parameter so callers can pass a custom ttl; update any internal calls/tests to
keep behavior unchanged by default but allow overriding.
In
`@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py`:
- Around line 115-127: Replace the fragile manually-escaped JSON CEL expression
passed to auth.metadata.add_http with a structured body using
ValueOrSelector/CelExpression that builds a map/object (e.g., {"jwt": <token>,
"role": <role>}) instead of concatenating JSON strings; locate the call to
auth.metadata.add_http and change the body argument from the current
CelExpression string concat to a map-shaped CEL expression (using
ValueOrSelector with CelExpression that returns a map) or move the long CEL into
a named constant for readability, and add a short inline comment next to the
substring(7) usage explaining it assumes a "Bearer " prefix on
request.headers.authorization to make the intent explicit.
- Line 20: Add the issue marker to the existing pytestmark declaration so the
test is traceable to issue `#949`; update the pytestmark list (the pytestmark
variable in this file) to include
pytest.mark.issue("https://github.com/Kuadrant/testsuite/issues/949") alongside
pytest.mark.kuadrant_only and pytest.mark.egress_gateway.
- Around line 154-170: Add a new test that exercises the Vault-side
authorization failure: create a test function (e.g.,
test_egress_authenticated_no_vault_binding_returns_403) that sends a request
using a ServiceAccount token that is valid for Kubernetes TokenReview but
intentionally has no Vault role binding (use or add a fixture like
sa_token_unbound_to_vault or construct such a token), call
client.get(mockserver_expectation, headers={"Authorization": f"Bearer
{sa_token_unbound_to_vault}"}), and assert the response.status_code == 403 and
that the backend Authorization header was not overwritten; mirror assertions and
structure from test_egress_credential_injection_via_vault to keep consistency.
- Around line 22-23: S105 is a false positive for K8S_TOKEN_AUDIENCE because it
stores an audience URL, not a secret; fix by either appending a Ruff suppression
or renaming the identifier: add "# noqa: S105" to the K8S_TOKEN_AUDIENCE
definition or rename the constant to a clearly non-secret name such as
K8S_TOKEN_AUDIENCE_URL (update all references) so the linter no longer flags it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e89ad610-0254-4e07-936f-67f5e647a4bc
📒 Files selected for processing (10)
config/settings.local.yaml.tplpyproject.tomltestsuite/config/__init__.pytestsuite/config/tools.pytestsuite/kuadrant/policy/authorization/__init__.pytestsuite/kuadrant/policy/authorization/sections.pytestsuite/kubernetes/vault.pytestsuite/tests/singlecluster/egress/credentials_injection/conftest.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection_by_destination.py
efb9dc6 to
af684de
Compare
maksymvavilov
left a comment
There was a problem hiding this comment.
Nice work — this is a solid PR. The test faithfully replicates the credential-injection user guide, the Vault wrapper is clean, and the API type extensions (ValueOrSelector, NamedValueOrSelector, CelPredicate in Rule) are well-structured.
What's good:
- AuthPolicy structure (kubernetesTokenReview → vault_login → vault_secret → vault_credential_check → response header injection) exactly matches the user guide. I traced through the CEL body escaping and it produces correct JSON.
- Three test scenarios (valid SA token → 200, invalid → 401, missing → 401) with a strong end-to-end assertion on the injected header value.
- Proper test isolation with
blame(), per-test Vault resources, correct LIFO cleanup order, and graceful skip when Vault isn't configured. - The
by_destinationtest is now self-contained, which makes sense since it uses a different credential injection approach (K8s Secrets). add_http()changes are backward-compatible — existing callers all passendpointandmethodexplicitly.
Left a few minor nits inline — nothing blocking.
af684de to
a277d4d
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (5)
testsuite/kuadrant/policy/authorization/sections.py (1)
218-219: Optional: make the XOR check more readable.
not bool(endpoint) ^ bool(url_expression)works (XOR inverted), butbool(endpoint) == bool(url_expression)reads more directly as “both missing or both provided → invalid”.♻️ Proposed change
- if not bool(endpoint) ^ bool(url_expression): + if bool(endpoint) == bool(url_expression): raise ValueError("Exactly one of 'endpoint' or 'url_expression' must be provided")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kuadrant/policy/authorization/sections.py` around lines 218 - 219, The current conditional using inverted XOR (not bool(endpoint) ^ bool(url_expression)) is hard to read; replace it with a clearer equivalence check so it's explicit when both are present or both are missing — e.g., use if bool(endpoint) == bool(url_expression): raise ValueError("Exactly one of 'endpoint' or 'url_expression' must be provided") — referencing the same variables endpoint and url_expression and the existing ValueError to locate the check.testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py (2)
130-142: Consider extracting the JSON-via-CEL body into a helper for readability.Constructing JSON inside a Python f-string that contains a CEL string literal with multiple levels of escaping is correct but quite hard to verify by inspection (and to amend later). A small helper or a
dedent/multiline raw string assembled from named pieces would make the resulting CEL output ({"jwt": "<token>", "role": "<role>"}) easier to read without adding runtime cost. The existing inline comment helps; this just goes one step further.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` around lines 130 - 142, The CEL JSON body construction in the call to auth.metadata.add_http (the ValueOrSelector(CelExpression(...)) argument) is hard to read due to nested escaping; extract it into a named helper variable or small function (e.g., build_vault_login_body or vault_login_cel_body) that returns the CelExpression/str assembled from clear pieces (jwt expression and vault_role) and then pass that variable to ValueOrSelector(CelExpression(...)); reference the existing symbols auth.metadata.add_http, ValueOrSelector, CelExpression, vault.url and vault_role when implementing the helper so the final add_http call simply uses the helper variable for the body, improving readability without changing behavior.
20-23: Optional: add@pytest.mark.issueto track issue#949.The PR closes issue
#949and replicates a published user-guide flow; adding@pytest.mark.issue(...)makes the traceability explicit in test output / Report Portal. Per coding guidelines,@pytest.mark.issue('https://github.com/...')is one of the documented common markers.♻️ Proposed change
-pytestmark = [pytest.mark.kuadrant_only, pytest.mark.egress_gateway] +pytestmark = [ + pytest.mark.kuadrant_only, + pytest.mark.egress_gateway, + pytest.mark.issue("https://github.com/Kuadrant/testsuite/issues/949"), +]As per coding guidelines: "Common markers include: ...
@pytest.mark.issue('https://github.com/...')".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py` around lines 20 - 23, Add the pytest issue marker for traceability by including pytest.mark.issue pointing to the issue URL in the existing pytestmark list; update the top-level pytestmark variable (the pytestmark list defined alongside VAULT_API_KEY and K8S_TOKEN_AUDIENCE in test_credential_injection.py) to include pytest.mark.issue('https://github.com/your-repo/your-org/issues/949') so the test run and Report Portal show the linked issue.testsuite/kubernetes/vault.py (2)
21-29: Optional: make the role TTL configurable.
ttl="1h"is hardcoded. It's fine for the current tests (each module-scoped fixture creates and destroys the role within a run), but exposing it as a parameter (with a"1h"default) makes the helper reusable for future tests with different lifetimes without touching this class.♻️ Proposed refactor
- def create_role(self, name: str, sa_names: list[str], sa_namespaces: list[str], policies: list[str]): + def create_role( + self, + name: str, + sa_names: list[str], + sa_namespaces: list[str], + policies: list[str], + ttl: str = "1h", + ): """Create a Kubernetes auth role binding service accounts to policies""" self._client.auth.kubernetes.create_role( name, bound_service_account_names=sa_names, bound_service_account_namespaces=sa_namespaces, policies=policies, - ttl="1h", + ttl=ttl, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kubernetes/vault.py` around lines 21 - 29, The create_role method currently hardcodes ttl="1h"; make the TTL configurable by adding a ttl parameter to create_role (e.g., def create_role(self, name: str, sa_names: list[str], sa_namespaces: list[str], policies: list[str], ttl: str = "1h")) and pass that ttl variable into the self._client.auth.kubernetes.create_role call instead of the literal "1h"; update any callers/tests that invoke create_role if they need different lifetimes or rely on the new signature.
35-43: Minor: brittle path parsing if a single-segment path is ever passed.
path.partition("/")on a string without a/returns("foo", "", ""), sosecret_pathbecomes""andcreate_or_update_secret/delete_metadata_and_all_versionsreceive an empty path. Current callers always passsecret/egress/<ns>/<sa>, so this is purely defensive — consider asserting the path contains a/(or extracting an explicitmountargument) to fail fast on misuse.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kubernetes/vault.py` around lines 35 - 43, Both store_secret and delete_secret use path.partition("/") which yields an empty secret_path when the input has no "/", making Vault calls with an empty path; update these methods (store_secret and delete_secret) to validate the input path contains a "/" (e.g., if "/" not in path: raise ValueError("path must be of form '<mount>/<secret_path>'")) before splitting, or add an explicit mount parameter and assert it's provided, so callers fail fast on misuse and the Vault client never receives an empty secret_path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@testsuite/kuadrant/policy/authorization/sections.py`:
- Around line 218-219: The current conditional using inverted XOR (not
bool(endpoint) ^ bool(url_expression)) is hard to read; replace it with a
clearer equivalence check so it's explicit when both are present or both are
missing — e.g., use if bool(endpoint) == bool(url_expression): raise
ValueError("Exactly one of 'endpoint' or 'url_expression' must be provided") —
referencing the same variables endpoint and url_expression and the existing
ValueError to locate the check.
In `@testsuite/kubernetes/vault.py`:
- Around line 21-29: The create_role method currently hardcodes ttl="1h"; make
the TTL configurable by adding a ttl parameter to create_role (e.g., def
create_role(self, name: str, sa_names: list[str], sa_namespaces: list[str],
policies: list[str], ttl: str = "1h")) and pass that ttl variable into the
self._client.auth.kubernetes.create_role call instead of the literal "1h";
update any callers/tests that invoke create_role if they need different
lifetimes or rely on the new signature.
- Around line 35-43: Both store_secret and delete_secret use path.partition("/")
which yields an empty secret_path when the input has no "/", making Vault calls
with an empty path; update these methods (store_secret and delete_secret) to
validate the input path contains a "/" (e.g., if "/" not in path: raise
ValueError("path must be of form '<mount>/<secret_path>'")) before splitting, or
add an explicit mount parameter and assert it's provided, so callers fail fast
on misuse and the Vault client never receives an empty secret_path.
In
`@testsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.py`:
- Around line 130-142: The CEL JSON body construction in the call to
auth.metadata.add_http (the ValueOrSelector(CelExpression(...)) argument) is
hard to read due to nested escaping; extract it into a named helper variable or
small function (e.g., build_vault_login_body or vault_login_cel_body) that
returns the CelExpression/str assembled from clear pieces (jwt expression and
vault_role) and then pass that variable to ValueOrSelector(CelExpression(...));
reference the existing symbols auth.metadata.add_http, ValueOrSelector,
CelExpression, vault.url and vault_role when implementing the helper so the
final add_http call simply uses the helper variable for the body, improving
readability without changing behavior.
- Around line 20-23: Add the pytest issue marker for traceability by including
pytest.mark.issue pointing to the issue URL in the existing pytestmark list;
update the top-level pytestmark variable (the pytestmark list defined alongside
VAULT_API_KEY and K8S_TOKEN_AUDIENCE in test_credential_injection.py) to include
pytest.mark.issue('https://github.com/your-repo/your-org/issues/949') so the
test run and Report Portal show the linked issue.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6cada7a3-0f60-4d92-a578-c8155f79b026
📒 Files selected for processing (10)
config/settings.local.yaml.tplpyproject.tomltestsuite/config/__init__.pytestsuite/config/tools.pytestsuite/kuadrant/policy/authorization/__init__.pytestsuite/kuadrant/policy/authorization/sections.pytestsuite/kubernetes/vault.pytestsuite/tests/singlecluster/egress/credentials_injection/conftest.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection_by_destination.py
✅ Files skipped from review due to trivial changes (2)
- config/settings.local.yaml.tpl
- pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (1)
- testsuite/config/init.py
Signed-off-by: averevki <sandyverevkin@gmail.com>
a277d4d to
dd261bb
Compare
|
rebase^ |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
testsuite/kuadrant/policy/authorization/sections.py (1)
206-214: Consider explicitT | Nonetype hints for optional parameters.The static analysis tool (Ruff RUF013) correctly identifies that PEP 484 prohibits implicit
Optional. Parameters with= Nonedefaults should have explicit type annotations.♻️ Proposed fix for type hints
def add_http( self, name, - endpoint=None, + endpoint: str | None = None, method: Literal["GET", "POST"] = "GET", - credentials: Credentials = None, - shared_secret_ref: dict[str, str] = None, + credentials: Credentials | None = None, + shared_secret_ref: dict[str, str] | None = None, *, - url_expression: str = None, - content_type: Literal["application/x-www-form-urlencoded", "application/json"] = None, - body: ValueOrSelector = None, - headers: list[NamedValueOrSelector] = None, + url_expression: str | None = None, + content_type: Literal["application/x-www-form-urlencoded", "application/json"] | None = None, + body: ValueOrSelector | None = None, + headers: list[NamedValueOrSelector] | None = None, **common_features, ):🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@testsuite/kuadrant/policy/authorization/sections.py` around lines 206 - 214, The function/method signature uses default None for several parameters without explicit optional types; update the annotations to use explicit unions (T | None) for each optional parameter: annotate endpoint as str | None, credentials as Credentials | None, shared_secret_ref as dict[str, str] | None, url_expression as str | None, content_type as Literal["application/x-www-form-urlencoded", "application/json"] | None, body as ValueOrSelector | None, and headers as list[NamedValueOrSelector] | None (leave method as Literal["GET","POST"]). Ensure the signature in the function/class (the parameter list shown) is updated accordingly to satisfy RUF013.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@testsuite/config/tools.py`:
- Line 55: Both fetch_service and fetch_service_ip declare parameters (e.g.,
namespace: str, name: str, port: int) with default None which makes their
annotated types incorrect; update the signatures to use Optional types (from
typing import Optional) for any parameter that can be None (e.g., namespace:
Optional[str] = None, name: Optional[str] = None, port: Optional[int] = None) or
give them proper non-None defaults—adjust the annotations in fetch_service and
fetch_service_ip accordingly and import Optional if needed so type hints match
the None defaults.
---
Nitpick comments:
In `@testsuite/kuadrant/policy/authorization/sections.py`:
- Around line 206-214: The function/method signature uses default None for
several parameters without explicit optional types; update the annotations to
use explicit unions (T | None) for each optional parameter: annotate endpoint as
str | None, credentials as Credentials | None, shared_secret_ref as dict[str,
str] | None, url_expression as str | None, content_type as
Literal["application/x-www-form-urlencoded", "application/json"] | None, body as
ValueOrSelector | None, and headers as list[NamedValueOrSelector] | None (leave
method as Literal["GET","POST"]). Ensure the signature in the function/class
(the parameter list shown) is updated accordingly to satisfy RUF013.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ee1ea897-175a-4dc0-8ae0-67b7c1a5b388
📒 Files selected for processing (10)
config/settings.local.yaml.tplpyproject.tomltestsuite/config/__init__.pytestsuite/config/tools.pytestsuite/kuadrant/policy/authorization/__init__.pytestsuite/kuadrant/policy/authorization/sections.pytestsuite/kubernetes/vault.pytestsuite/tests/singlecluster/egress/credentials_injection/conftest.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection.pytestsuite/tests/singlecluster/egress/credentials_injection/test_credential_injection_by_destination.py
✅ Files skipped from review due to trivial changes (2)
- config/settings.local.yaml.tpl
- pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (3)
- testsuite/config/init.py
- testsuite/kubernetes/vault.py
- testsuite/kuadrant/policy/authorization/init.py
silvi-t
left a comment
There was a problem hiding this comment.
Ran the full credential injection test suite against a cluster with Vault deployed from the helm-charts-olm. All 5 tests passed. LGTM.
Note
Requires Kuadrant/helm-charts-olm#86 to be merged first (Vault deployment in
tools-vaultnamespace).Closes #949
Description
hvacPython client for Vault management instead ofkubectl execinto the Vault podValueOrSelectorandNamedValueOrSelectordataclasses matching Authorino's API spec for typed metadata HTTP configurationfetch_service_ipto support cross-namespace service discovery for Vault intools-vaultnamespaceChanges
New Features
testsuite/kubernetes/vault.py— NewVaultclass usinghvaclibrary for managing policies, Kubernetes auth roles, and KV v2 secretsValueOrSelectordataclass wrappingValue | ValueFrom | CelExpressionto match Authorino'sValueOrSelectorspecNamedValueOrSelectorextendingValueOrSelectorwith anamefield, serializing as{name: {value/selector/expression}}CelPredicateadded to theRuletype union for CEL-based pattern matchingPlainResponse.plainnow acceptsCelExpressionin addition toABCValueRefactoring
MetadataSection.add_http()— Extended with keyword-only parameters:url_expression: str,content_type: Literal[...],body: ValueOrSelector,headers: list[NamedValueOrSelector];endpointandmethodare now optionalfetch_service_ip()— Added optionalnamespaceparameter for cross-namespace LoadBalancer lookupsmockserver_expectation,service1_api_secret,sa_token_secret,authorization) moved fromconftest.pyinto their respective test files todecouple the Vault-based and K8s-Secret-based credential injection tests
Tests
test_credential_injection.py— Rewritten to use Vault Kubernetes auth flow: creates aServiceAccount, configures Vault policy/role/secret, buildsAuthPolicywithvault_login+vault_secretmetadata steps, and validates credential injection via MockServertest_credential_injection_by_destination.py— Now self-contained with its own fixtures (previously shared from conftest)Configuration
config/settings.local.yaml.tpl— Addedvault.urlandvault.tokensettings templatetestsuite/config/__init__.py— AddedDefaultValueValidatorentries forvault.url(auto-fetched fromtools-vaultnamespace) andvault.token(defaults to"root")pyproject.toml— Addedhvacto main dependencies,types-hvacto dev dependenciesVerification steps
Summary by CodeRabbit
New Features
Tests
Chores