Implement Auth - #35
Conversation
|
/agentic_review |
Code Review by Qodo
1.
|
46dd469 to
095ed65
Compare
|
@chadcrum PTAL on this one for Auth in the agent :) |
PR Summary by QodoAdd OIDC JWT authentication for environment agent APIs
AI Description
Diagram
High-Level Assessment
Files changed (21)
|
|
Code review by qodo was updated up to the latest commit 095ed65 |
095ed65 to
888b199
Compare
|
Resolved 3 stale qodo-code-review threads that were left open after the
|
888b199 to
b88eb57
Compare
PR review feedback (gciavarrini, PR dcm-project#35) noted that OIDCValidator is only proven to work by control-plane's real-Keycloak subsystem test; this repo's own tests only exercise the fully-mocked auth.JWTValidator interface, never real OIDC discovery, JWKS, or a signed token. Add internal/auth/jwt_realistic_test.go: a self-contained test that generates a local RSA keypair, serves an OIDC discovery document and a JWKS via httptest.Server, and signs RS256 JWTs shaped like real Keycloak access tokens (azp, scope, realm_access, resource_access, matching kid). Three cases exercise auth.NewOIDCValidator/Validate end-to-end: - audience configured and matching the token's aud claim: succeeds - audience configured but mismatched: fails - no aud claim at all (default Keycloak client, no audience mapper) and no configured audience (SkipClientIDCheck path): succeeds The third case is the operationally important one per REQ-AUTH-110: it proves auth fails open on audience, rather than silently breaking, when operators haven't configured an audience mapper or AGENT_AUTH_JWT_AUDIENCE. A bonus case confirms SkipClientIDCheck ignores aud regardless of whether it's present. This harness is built from scratch, not reused from anywhere: neither this repo nor control-plane has an existing httptest-based OIDC-discovery harness to reuse. It is independent of control-plane's tests. Promotes github.com/go-jose/go-jose/v4 from an indirect to a direct dependency (go mod tidy) since it's now imported directly to build the JWKS and sign test tokens; go.sum is unchanged. Assisted by: Claude Code - Claude Sonnet 5 Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
b88eb57 to
134e571
Compare
chadcrum
left a comment
There was a problem hiding this comment.
Medium: RequestLogger records the inner response before RequestTimeout can replace it with the client-facing 503. A timed-out request can therefore produce an audit record with status 200/401/etc. while the client receives 503. Can we emit the audit record after timeout finalization, or propagate the final status to the logger? It would also be good to add an integration assertion covering both the HTTP response and audit status.
jordigilh
left a comment
There was a problem hiding this comment.
Second review summary
Substantive findings are posted inline below. The PR has one existing human approval. No live Keycloak or deployed-agent evidence is available.
Verdict: Not GA-ready
| NakDelay time.Duration `env:"ROUTING_NAK_DELAY" envDefault:"500ms"` | ||
| } | ||
|
|
||
| // AuthConfig holds JWT authentication configuration. |
There was a problem hiding this comment.
AGENT_AUTH_DISABLED defaults to true, but the operator documentation does not explain the issuer, audience, Keycloak mapper, or steps required to enable authentication. Please document the production configuration and fail-safe expectations.
There was a problem hiding this comment.
@gciavarrini should this be done in the website once you PR dcm-project/dcm-project.github.io#22 is merged? And then add a reference link to the guide in this repo README
What is done here is similar to what is done for the CP
There was a problem hiding this comment.
Yes. Better putting agent auth enablement on the website (after docs PR dcm-project/dcm-project.github.io#22) same idea as the CP guide.
No need to block this PR
There was a problem hiding this comment.
PR review feedback (gciavarrini, PR dcm-project#35) noted that OIDCValidator is only proven to work by control-plane's real-Keycloak subsystem test; this repo's own tests only exercise the fully-mocked auth.JWTValidator interface, never real OIDC discovery, JWKS, or a signed token. Add internal/auth/jwt_realistic_test.go: a self-contained test that generates a local RSA keypair, serves an OIDC discovery document and a JWKS via httptest.Server, and signs RS256 JWTs shaped like real Keycloak access tokens (azp, scope, realm_access, resource_access, matching kid). Three cases exercise auth.NewOIDCValidator/Validate end-to-end: - audience configured and matching the token's aud claim: succeeds - audience configured but mismatched: fails - no aud claim at all (default Keycloak client, no audience mapper) and no configured audience (SkipClientIDCheck path): succeeds The third case is the operationally important one per REQ-AUTH-110: it proves auth fails open on audience, rather than silently breaking, when operators haven't configured an audience mapper or AGENT_AUTH_JWT_AUDIENCE. A bonus case confirms SkipClientIDCheck ignores aud regardless of whether it's present. This harness is built from scratch, not reused from anywhere: neither this repo nor control-plane has an existing httptest-based OIDC-discovery harness to reuse. It is independent of control-plane's tests. Promotes github.com/go-jose/go-jose/v4 from an indirect to a direct dependency (go mod tidy) since it's now imported directly to build the JWKS and sign test tokens; go.sum is unchanged. Assisted by: Claude Code - Claude Sonnet 5 Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
b29103c to
cc56775
Compare
Adds a dedicated Environment Agent Authentication guide covering the two independent auth surfaces introduced by environment-agent#35 and environment-agent#38: - Inbound: AGENT_AUTH_DISABLED / AGENT_AUTH_ISSUER_URL / AGENT_AUTH_JWT_AUDIENCE protecting the agent's own REST API (external SP registration, provider listing), health-path bypass, RFC 7807 error format, and the intentional audience fail-open behavior. - Outbound: DCM_AUTH_TOKEN / DCM_AUTH_TOKEN_ENDPOINT / DCM_AUTH_CLIENT_ID / DCM_AUTH_CLIENT_SECRET for the agent's own registration/heartbeat calls to the control plane, mode precedence, token refresh and failure behavior, Keycloak service-account setup, and the known reference-realm audience-mapper gap. Addresses the open documentation request from environment-agent#35 (review thread on internal/config/config.go, dcm-project/environment-agent#35 (comment)): 'put agent auth enablement on the website... same idea as the CP guide.' Content validated against the latest reviewed commits on both PR branches (config.go, jwt.go, middleware.go, token.go, client.go, main.go, openapi.yaml, README.md, decisions.md) rather than assumed from the PR descriptions alone. Updates the control-plane Authentication guide's Service-providers callout and troubleshooting row to link to the new page instead of a vague 'still landing' note, and cross-links from Local Setup and the Getting Started index. Signed-off-by: Gabriel Farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: gabriel-farache <gfarache@redhat.com>
|
I think this is worth of enahcement to reason about why we have chosen this type of authn. |
@machacekondra this PR is really an shamefulness replication of what is done in the Control Plane so I guess https://github.com/dcm-project/enhancements/blob/main/enhancements/authentication/authentication.md would still apply to this. |
cc56775 to
5a98e24
Compare
| panic("auth: NewOIDCValidator context must not be nil") | ||
| } | ||
| if httpClient == nil { | ||
| httpClient = &http.Client{Timeout: defaultOIDCHTTPTimeout} |
There was a problem hiding this comment.
honestly, if you're not going to use TLS I fail to see the point of integrating authN/Z at all.
There was a problem hiding this comment.
testing purposes to avoid issue with certificates
There was a problem hiding this comment.
makes no sense to me: the business logic is constrained to use HTTP to avoid testing adding a layer of complexity with TLS? Am I reading it correctly?
There was a problem hiding this comment.
I think I replied to quickly on this one
This http client is created for the refresh of the JWKS (from your comment #35 (comment))
and regarding TLS, this will be the scheme that will determine if it is used or not (http vs https) but we do not enforce HTTPS everywhere to allow easier dev testing; a warn is clearly logged when using http and its usage is discouraged in the doc as well
There was a problem hiding this comment.
My concern is self signed certs will fail unless you load the CA into the client or into the cert store.
There was a problem hiding this comment.
yes, in PROD you must use a certificate that is known from the org CA, while in dev/test you can just start in http mode to avoid that, at least that's how I imagined things
I had my fair share of battle with this kind of stuff so I just want to let dev/test go on plain http and not to worry about the certs issues
There was a problem hiding this comment.
in air gapped environments, you could end up running with a self signed cert from the org. We have such case in our own environments.
There was a problem hiding this comment.
I had my fair share of battle with this kind of stuff so I just want to let dev/test go on plain http and not to worry about the certs issues
I don't compromise security for test convenience.
There was a problem hiding this comment.
in air gapped environments,
Is this a current requirement for this milestone? As far as I am aware, it is not but I may be mistaken
I don't compromise security for test convenience.
Me neither, in this example, it fall on the admin/user to configure properly the application, a warning message is even log to reduce the human-error factor
Our main target as customers are bank at the moment, so I am pretty sure they also have internal guidelines and safeguard to avoid a so obvious mis-configuration in PROD
Again, this should evolve when maturing the application but at our current state, logging a warning is enough and changing the behaviour to reject instead of warning has little to no impact
|
@gabriel-farache have you tested this locally in your environment to ensure it work with keycloak? |
@jordigilh I did it once but I did not create test for it, I have now 1343619 This mimic what is done in the control-plane repo as the code is similar But at least now there the beginning of the start of subsystem/e2e tests in the agent and not just IT |
Add section 4.10 API Authentication to the spec with 11 REQ-AUTH entries and 10 AC-AUTH acceptance criteria covering JWT Bearer validation via Keycloak OIDC, health endpoint bypass, disabled auth mode, RFC 7807 error responses, and config validation. Add section 13 Authentication to the unit test plan with UT-AUTH-010 through UT-AUTH-090 covering extractBearerToken, middleware behavior, DisabledMiddleware, RFC 7807 format, and config validation. Update traceability matrix. Update three "out of scope" annotations that previously declared authentication deferred — now cross-reference §4.10. Assisted by: Claude Code - opus-4.6 Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted by: Claude Code - opus-4.6 Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Adds test/subsystem/auth: a docker-compose stack (real Keycloak 26.0.1 + NATS + the agent's own Containerfile image) plus a Ginkgo -tags=subsystem suite proving REQ-AUTH-010/040 against a genuine IdP end-to-end, not just the mocked JWTValidator (AC-AUTH-010/030/040) or the self-signed OIDC harness (AC-AUTH-120). - Realm fixture: dcm realm, environment-agent client (audience mapper -> environment-agent-api) and environment-agent-no-audience client (no mapper, used for the wrong-audience negative case). - Four cases (ST-AUTH-010..040): valid token -> 200, missing token -> 401, tampered token -> 401, wrong-audience token -> 401. - New AC-AUTH-130 in the spec; reworded the stale S4.11 note that leaned on control-plane's own real-Keycloak test as the only such proof. - New Makefile targets (subsystem-env, auth-subsystem-test-up/-test/-down) and .github/workflows/subsystem.yaml calling the shared black-box.yaml workflow, mirroring control-plane's test/subsystem pattern. - AGENT_SP_PERSISTENCE_PATH is pinned to /app/data/registrations.json in the compose env: the config default is not writable by the Containerfile's non-root UID 1001, which would otherwise crash the agent before /health ever comes up. - nats runs with -m 8222 to expose the monitoring endpoint the compose healthcheck probes; without it the container never reports healthy. Verified locally: make auth-subsystem-test-up && make auth-subsystem-test && make auth-subsystem-test-down (docker) -- 4/4 specs pass. Assisted by: Claude Code - sonnet-5 Signed-off-by: gabriel-farache <gfarache@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: gabriel-farache <gfarache@redhat.com>
Signed-off-by: gabriel-farache <gfarache@redhat.com>
d1d7632 to
4e74523
Compare
I would normally not advise to do this, but in this case since there are no e2e automation and this is green field that we're adding, I'd ask you to perform an e2e validation to ensure all the pieces work together, otherwise when QE runs this they might get unexpected surprises. Unless auth is not required in the milestone and we can skip testing for now. In that case I'm fine |
@gabriel-farache who can reach this endpoint? I'm concerned about DDoS attacks. Perhaps for now it's not worth the pain, just raising it here for awareness. |
@jordigilh I think it's common practice to leave the health unprotected as it is used to probe the liveliness/readiness in K8s. I think the CP is doing the same
WDYM? The subsystem test is spinning all real services (keycloak, the agent, nats) and validate the authN is working on the protected endpoints |
Yes, but in k8s there is a virtual network that prevents this port from being accessed outside the cluster. If env agent is deployed as a quadlet, can we ensure a similar protection? |
Just that: end to end validation with keycloak to ensure a successful authN. |
@jordigilh No but right now I would discard this concern as AFAIK, our target to deploy is K8s no?
Ok, it's already there so cool :) |
yes, we can discard this, as I mentioned it's not a blocker, just raising this for awareness. This is a perfect case where narrowing down the platform would've reduced the amount of work required to get it ready. Having so many deployment platforms is a huge headache from the start. |
Implement Auth mechanism to protect the environment agent's endpoints (register, list SP, ...)
Health is left unprotected