Repository navigation
feat: actuator health on all apps; other endpoints require an admin token - #240
Merged
Merged
Conversation
…n token - openespi-common no longer ships management.* or spring.application.name in its jar's application.properties / profile ymls. Every dependent app loaded them: management.endpoints.enabled-by-default=false (deprecated, still honored by Boot 4.1.2) disabled all endpoints, so DC's /actuator/health returned 404, and the .properties name overrode each app's own name in metric tags. - Each app: endpoint access is opt-in (access.default: none) and read-only. Exposed: health, info, metrics (+ prometheus on DC/TP). health shows status only and enables the liveness/readiness probe groups. AS no longer exposes env. - Each app gets an actuator SecurityFilterChain (EndpointRequest): health is anonymous; everything else requires an admin access token. - DC: opaque token with DataCustodian_Admin_Access (existing introspector). - AS: authserver.admin bearer token, resolved in-process (as for #204). - TP: opaque token introspected at the AS with the TP's client credentials, scope espi.actuator.admin-scope (default ThirdParty_Admin_Access). - AS adds spring-boot-starter-actuator; TP adds the resource-server starter. - AS profiles drop enabled-by-default / endpoint.*.enabled, which Boot rejects next to the access keys. - DC/TP local profiles use the secrets the AS seeds (dc-secret, tp-secret); with "secret" every introspection got a 401 from the AS. Closes #236 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfcoffin
added a commit
that referenced
this pull request
Nov 14, 2026
…framework versions (#248) - Third Party: new public /about (AboutController + about.html on the shared GBA layout), linked from the footer, permitted anonymously. - Data Custodian and Third Party About pages now show the same fields: implementation, version, build time, the standard (NAESB REQ.21 ESPI 4.1) and a release status derived from the version (a SNAPSHOT is "Pre-release: not for production use"), plus links to GBA, the API docs, the source and SECURITY.md. - The Java and Spring Boot versions are no longer shown to anonymous visitors: exact framework versions help attackers pick known CVEs, and they stay available to admins via /actuator/info (#240). - Version and build time come from BuildProperties (spring-boot-maven-plugin:build-info, added to both apps) instead of the jar manifest, which is absent under spring-boot:run ("(development build)"). - Removed the legacy VersionRESTController (/about-version) from both apps. It read a servlet-context MANIFEST.MF that a Spring Boot jar does not have, and it filled a model key the DC template never read (DC) or rendered a template that did not exist (TP). - Tests: AboutControllerTest in both apps. GbaLayoutPagesTest now renders under the real /ThirdParty context path and asserts that every internal href/src carries it. With MockMvc's empty context path, a correct th:href="@{/about}" and a broken href="/about" rendered identically, so the previous #235 guard could not catch the bug. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
dfcoffin
added a commit
that referenced
this pull request
Nov 14, 2026
AuthorizationServerApplicationTests pins the exact set of SecurityFilterChain beans. It was written before #240 added actuatorSecurityFilterChain, so the first CI run of the rebased suite failed on that one assertion (1 of 274). Keep the pin (a new chain changes which requests the others see) and list the fifth chain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dfcoffin
added a commit
that referenced
this pull request
Nov 14, 2026
* test(#129): drop impossible security assertions from OAuthAdminControllerTest The standalone MockMvc setup installs no security filter chain and no method-security proxy, so the 401/403 (and "allowed") tests could never exercise access control. Admin API authorization is covered against the real configuration by AdminEndpointAuthorizationIntegrationTest and AdminBearerTokenIntegrationTest. The request-handling tests stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(#129): drive EspiTokenCustomizerTest with a real JwtEncodingContext Replace the strict-stubbed JwtEncodingContext mocks (UnnecessaryStubbing, NPE on null claims) with a real context and assertions on the resulting claims. Role-to-resource-URI and customer-grant cases become parameterized; duplicate "ESPI compliance" cases and null-context/null-claims/null-endpoint cases (outside the framework contract) are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(#129): replace mock-HttpSecurity config test with a real context test AuthorizationServerConfigTest called the @bean filter-chain methods against a mocked HttpSecurity and stubbed JdbcTemplate (ClassCast, UnfinishedStubbing, null @value settings, removed /connect/register and JWK expectations) - it tested the framework, not our configuration. AuthorizationServerApplicationTests booted on the H2 'local' profile, which no longer starts. AuthorizationServerApplicationTests now extends AbstractAuthserverIntegrationTest (real config, MySQL Testcontainer) and asserts what the started context holds: the four security filter chains, no JwtDecoder/JwtEncoder (opaque only, #134), issuer and protocol endpoints, the JDBC client repository, grant-context authorization service and ESPI customizer beans, and the seeded default clients' grants, scopes, token format, TTLs, consent and PKCE settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(#129): run SecurityIntegrationTest against the real config on MySQL Move SecurityIntegrationTest off the H2 'test' profile (no schema: the H2 profile had no Flyway location) onto AbstractAuthserverIntegrationTest, and correct its stale expectations: - use the seeded clients' real secrets (the "{bcrypt}secret" literal never matched) - malformed Basic header -> 400 invalid_request; client_secret_post on a client_secret_basic client -> 401 invalid_client - protocol endpoints are CSRF-exempt by design; CSRF is asserted on the session-chain admin DELETE with an MFA-complete admin instead - discovery document instead of the removed /oauth2/jwks endpoint - authorize requests use queryParam (Spring AS reads the query string) and a per-test client, and assert delegation/redirect-URI/scope outcomes exactly - introspection by the DataCustodian client of another client's token Removed: the six admin access-control cases (covered by AdminEndpointAuthorizationIntegrationTest / AdminBearerTokenIntegrationTest), the duplicate opaque-token case, the no-op CORS case, and the unused application-test.yml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci(#129): run the full openespi-authserver suite in CI and releases The authserver unit tests are repaired, so drop the -Dgroups=testcontainers-it restriction from the CI test matrix and from release-meta.sh, and update CLAUDE.md, README.md, RELEASING.md, CI_CD_SETUP.md and the testcontainers-it tag comments to say that `mvn verify -pl openespi-authserver` runs everything. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(#129): expect the actuator security filter chain added by #240 AuthorizationServerApplicationTests pins the exact set of SecurityFilterChain beans. It was written before #240 added actuatorSecurityFilterChain, so the first CI run of the rebased suite failed on that one assertion (1 of 274). Keep the pin (a new chain changes which requests the others see) and list the fifth chain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Spring Boot Actuator health to all three applications and limits anonymous access to endpoints that only report normal operation. Closes #236.
/actuator/health,/health/liveness,/health/readiness/actuator,info,metrics(+prometheuson DC/TP)DataCustodian_Admin_Accesstokenauthserver.admintokenespi.actuator.admin-scope(defaultThirdParty_Admin_Access), introspected at the ASenvWhy DC's health was 404
openespi-commonshipsapplication.properties(and profile ymls) inside its jar, and every dependent app loads it. It setmanagement.endpoints.enabled-by-default=false, which is deprecated but still honored in Boot 4.1.2, so every endpoint was disabled. The same file'sspring.application.name=OpenESPI-Commonoverrode each app's own name (a.propertiesfile outranks.yml), so all DC/TP metrics were taggedapplication="OpenESPI-Common". Both settings are removed from common.Other changes
management.endpoints.access.default: none) and read-only per endpoint.enabled-by-default/endpoint.*.enabled, which Boot rejects alongside theaccesskeys.localprofiles now use the client secrets the AS seeds (dc-secret,tp-secret). Withsecret, every token introspection failed with 401 from the AS, which broke DC's ESPI API locally as well.Test plan
ActuatorSecurityConfigurationTest(DC): health + probes anonymous with nocomponents;/actuator,info,metrics→ 401 without a token, 403 with a non-admin token, 200 with an admin tokenAdminBearerTokenIntegrationTest(AS, testcontainers-it): health anonymous;/actuator,info,metrics→ 401 / 403 (DC admin token) / 200 (authserver.admin). Not run locally (no Docker on Windows); CI runs them.mvn verifyDC: 172 tests pass; TP: 44 pass (2 skipped, pre-existing)localprofile: health/liveness/readiness 200 anonymous; every other endpoint 401 with no token or a bogus token, 403 with the wrong admin token, 200 with the right one (TP checked with the scope overridden toDataCustodian_Admin_Access, because no seeded AS client can obtainThirdParty_Admin_Accessby client credentials)Notes for reviewers
AuthenticationServiceException), not 401.infois now admin-only on DC and AS (it was anonymous).🤖 Generated with Claude Code