Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions promptbook/prompts.json
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,28 @@
],
"formatNotes": "All three. Point the tool at `application.yml`/`application.properties`, Meter/Metrics config, the build file, and any ServiceMonitor/PodMonitor or Prometheus annotation manifests; keep Actuator security changes aligned with spring-boot-actuator-hardening. Copilot: spring-micrometer-prometheus path instructions plus those files in agent mode. Claude Code: the spring-boot-micrometer-prometheus-guardrails skill plus the config and scrape manifests. Codex: AGENTS.md Micrometer section, then the diff.",
"body": "Task: Wire or harden Micrometer + Prometheus metrics for the Spring Boot service I specify. Deliver RED-ready histograms, cardinality-safe tags, and a private management-port scrape path — then give me a minimal diff I can open as a PR.\n\nContext placeholders (fill from the repo or ask only if missing):\n- App module / root: {{APP_PATH}}\n- Spring Boot version: {{BOOT_VERSION}} (2.x | 3.x | unknown)\n- Build tool: {{BUILD_TOOL}} (maven | gradle)\n- Current Actuator exposure: {{ACTUATOR_EXPOSURE}} (e.g. health,info | include=* | unknown)\n- Management port today: {{MANAGEMENT_PORT}} (number | same-as-server | unknown)\n- Scrape style: {{SCRAPE_STYLE}} (servicemonitor | podmonitor | pod-annotations | none | unknown)\n- Cluster / env: {{ENVIRONMENT}} (e.g. aks-dev, aks-prod)\n- Service name for tags: {{SERVICE_NAME}}\n- Latency SLO targets (optional): {{SLO_BUCKETS_MS}} (e.g. 100,250,500,1000,2500,5000)\n- Pain points: {{PAIN}} (no-percentiles | cardinality | scrape-404 | public-actuator | missing-red | none)\n\nRequirements:\n\n1. Inventory\n - Read {{APP_PATH}} build file and `application*.yml|properties` for Actuator, Micrometer, and management server settings\n - List existing meters (`MeterRegistry` beans, `@Timed`, Observations) and any custom tags\n - Locate scrape manifests or annotations under deploy/Helm paths; note whether scrape hits the public or management port\n - Note overlap with Actuator security config (do not weaken lockdown)\n\n2. Findings (rank by risk: public sensitive Actuator > unbounded cardinality > scrape on public Ingress > missing histograms > hygiene)\n - `include=*` or sensitive endpoints exposed alongside prometheus\n - Raw URI / user id / exception message labels\n - Summaries without histogram buckets where p95/p99 or SLO burn is required\n - Scrape targeting the public Service/Ingress\n - Missing common tags (`application`, `environment`)\n - Custom meters with unbounded label values\n\n3. Fix\n - Dependencies: ensure `spring-boot-starter-actuator` and `micrometer-registry-prometheus` for {{BUILD_TOOL}}\n - Config: separate `management.server.port` when the app has a public HTTP surface; `management.endpoints.web.exposure.include=health,prometheus` (add `info` only if safe); set `management.metrics.tags.application={{SERVICE_NAME}}` and `management.metrics.tags.environment={{ENVIRONMENT}}`\n - HTTP server metrics: enable percentile-histogram (or distribution SLO deadlines / buckets from {{SLO_BUCKETS_MS}}) for `http.server.requests` so Prometheus can compute percentiles\n - Cardinality: ensure URI tags use route templates; strip or deny tags that carry ids or free text; rewrite custom meters to bounded enums\n - Scrape: for {{SCRAPE_STYLE}}, point path at `/actuator/prometheus` (honor any `management.endpoints.web.base-path`) on the **management** port; Prefer ServiceMonitor/PodMonitor selectors over scraping Ingress. Keep changes surgical — no full Helm rewrite unless required\n - Security: keep Actuator lockdown consistent with spring-boot-actuator-hardening; if scrape needs auth, document the platform mechanism without inventing secrets in Git\n - Do not invent OTel collectors or logging pipelines here — link to otel-aks-observability / structured-logging if gaps exist\n\n4. Verification\n - Show sample lines from `/actuator/prometheus` for `http_server_requests_*` including bucket series and common tags\n - Provide PromQL sketches: request rate, 5xx error ratio, `histogram_quantile(0.95, ...)` (and 0.99 if useful)\n - Confirm scrape config targets management port; note NetworkPolicy / private Service expectations for {{ENVIRONMENT}}\n - List residual risks (auth on management, bucket fit to SLO, remaining high-cardinality candidates)\n\nConstraints:\n- Minimal diff; do not refactor unrelated config or open extra Actuator endpoints.\n- Do not invent cluster URLs, credential values, or Helm chart names — use placeholders if unknown.\n- Do not put PII or secrets into metric tags or `info`.\n- Optimize for GitHub Copilot, Claude Code, and Codex — concrete diffs and a checklist.\n- Metrics lane only; defer traces and log shipping to their skills.\n\nOutput format:\n1. Findings table: severity | location | issue | fix\n2. Patch (build + application config + meter/tag fixes + scrape manifest/annotations)\n3. Verification: sample prometheus text, PromQL, scrape target summary\n4. Residual risks and follow-ups (Actuator auth, OTel, logging)\n\nStart from {{APP_PATH}}. Fix public Actuator exposure and unbounded labels before polishing dashboards.\n"
},
{
"id": "wire-entra-service-to-service-auth",
"title": "Wire Entra ID Service-to-Service Auth in Spring Boot",
"whenToUse": "Add or harden Entra ID service-to-service auth on a Spring Boot receiver and/or caller (app-role authorization, group-to-role map with overage handling, cached client-credentials tokens, external and svc.cluster.local URLs from config) and produce a minimal diff with tests and a role matrix.",
"tools": [
"copilot",
"claude-code",
"codex"
],
"tags": [
"spring-boot",
"spring-security",
"entra-id",
"oauth2",
"jwt",
"service-to-service",
"aks",
"java"
],
"formatNotes": "All three. Point the tool at `application.yml`/`application.properties`, the `SecurityFilterChain` and JWT converter, outbound RestClient/WebClient config, and the ConfigMap/Helm values that hold downstream URLs. Keep generic JWT validation aligned with spring-security-oauth2-resource-server. Copilot: entra-service-auth path instructions plus those files in agent mode. Claude Code: the entra-id-spring-service-auth-guardrails skill plus the security config and deploy values. Codex: AGENTS.md Entra service-auth section, then the diff.",
"body": "Task: Wire or harden Microsoft Entra ID service-to-service auth for the Spring Boot service(s) I specify. The receiving side should validate Entra tokens and authorize on app roles. The calling side should get cached client-credentials tokens without secrets in Git. Both should work for external HTTPS URLs and in-cluster `svc.cluster.local` URLs. Finish with a minimal diff I can open as a PR.\n\nContext placeholders (fill from the repo or ask only if missing):\n- Service root / module: {{APP_PATH}}\n- Role of this service: {{SERVICE_ROLE}} (receiver | caller | both)\n- Spring Boot / Spring Security version: {{BOOT_VERSION}} (e.g. 3.4 / 6.4 | unknown)\n- Tenant ID(s): {{TENANT_IDS}} (single GUID | allowlist | unknown)\n- This API's Application ID URI and client ID (receiver): {{API_APP_ID_URI}} / {{API_CLIENT_ID}}\n- Token version today: {{TOKEN_VERSION}} (v2 | v1 | mixed | unknown)\n- Service app roles → endpoints (receiver): {{SERVICE_ROLE_MATRIX}} (e.g. Orders.Read.All → GET /api/orders/**)\n- User authorization source (receiver): {{USER_AUTHZ}} (app-roles | groups-map | none)\n- Allowed caller client IDs (optional): {{ALLOWED_CALLERS}}\n- Downstream APIs (caller): {{DOWNSTREAMS}} (name, Application ID URI, base URL per env — e.g. external https://api.example.com/orders, in-cluster http://orders.orders.svc.cluster.local:8080)\n- Caller credential: {{CREDENTIAL}} (aks-workload-identity | certificate | client-secret | unknown)\n- Environments / config source: {{ENVIRONMENTS}} (e.g. aks-dev, aks-prod via ConfigMap + Key Vault)\n\nRequirements:\n\n1. Inventory\n - Read {{APP_PATH}} build file, `application*.yml|properties`, `SecurityFilterChain` config, any `JwtAuthenticationConverter`, and `@Secured` / `@PreAuthorize` usage\n - List outbound HTTP clients (RestClient, WebClient, HTTP interface clients, RestTemplate), their base URLs, and how tokens are attached today\n - Find secrets, API keys, or \"trusted network\" shortcuts on service-to-service paths, and any Authorization header or JWT logging\n - Note ConfigMap / Helm values / Key Vault references under deploy paths\n\n2. Findings (rank by risk: missing aud/role checks > token sent to wrong host > secrets in Git/ConfigMap > unauthenticated in-cluster path > overage/role-mapping gaps > hygiene)\n - Tokens accepted on signature + issuer alone, with no `aud`, `tid`, or role check\n - Service-only routes reachable with delegated (user) tokens, or service roles that also allow users\n - Group display names used for roles, or a missing `groups` claim treated as \"no groups\"\n - Per-request token minting, or the OAuth2 interceptor added to every client globally\n - Audience or scope derived from the target URL, or different behaviour for `svc.cluster.local` vs external\n - Client secrets in Git, images, or plain ConfigMaps, or a hard-coded workload identity token path\n\n3. Fix — receiver (skip if {{SERVICE_ROLE}} = caller)\n - `spring.security.oauth2.resourceserver.jwt.issuer-uri: https://login.microsoftonline.com/{{TENANT_IDS}}/v2.0` (or a per-tenant issuer allowlist), plus an audience validator for {{API_CLIENT_ID}}. If {{TOKEN_VERSION}} is mixed, allowlist the exact v1 issuer/audience with a removal date\n - A converter driven by properties: `roles` → `ROLE_`, `scp` → `SCOPE_`, optional group object ID → role map from ConfigMap when {{USER_AUTHZ}} = groups-map\n - Group overage: detect `_claim_names.groups` / `hasgroups`. Either do a Graph `transitiveMemberOf` lookup with a cache and timeout, or return 403. Never assign a default role\n - Service-only rule for {{SERVICE_ROLE_MATRIX}}: required role and no `scp`, plus an `azp`/`appid` allowlist from {{ALLOWED_CALLERS}} when given\n - Recommend manifest changes as notes (don't apply them): `requestedAccessTokenVersion: 2`, Application-only service roles, Assignment required on the enterprise app\n\n4. Fix — caller (skip if {{SERVICE_ROLE}} = receiver)\n - One `spring.security.oauth2.client.registration.<name>` per entry in {{DOWNSTREAMS}}: `authorization-grant-type: client_credentials`, `scope: <app-id-uri>/.default`, and a provider `token-uri: https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token`\n - An `AuthorizedClientServiceOAuth2AuthorizedClientManager` bean, plus a **dedicated** RestClient per downstream with `OAuth2ClientHttpRequestInterceptor` and the registration ID. No global customiser\n - Base URLs bound with `@ConfigurationProperties` from ConfigMap keys per environment (external and `svc.cluster.local`), validated at startup. The audience/scope stays the same whichever URL is used\n - Credential per {{CREDENTIAL}}. Workload identity: a federated client assertion read from `AZURE_FEDERATED_TOKEN_FILE` on each exchange. Certificate/secret: from Key Vault, never inline\n - Connect/read timeouts on the token endpoint and the downstream. On a 401, evict the token and retry once. No retry loops on 401/403\n\n5. Tests\n - Receiver: app token with role → 200; app token without role → 403; delegated token on service-only route → 403; wrong `aud` / wrong `tid` / expired → 401; overage user → Graph path or 403\n - Caller: a stubbed token endpoint is called once for several downstream calls (cached), the token goes only to the configured host, and 401 → one refresh + retry\n - Use Entra-shaped claims (`roles`, `scp`, `azp`, `tid`, `ver`) through the real converter and validators\n\n6. Verification\n - Role matrix table: caller client ID → granted roles → endpoints\n - URL map per environment (external vs in-cluster) showing the same audience\n - Confirm there are no tokens or secrets in logs, ConfigMaps, or Git, and list NetworkPolicy / mTLS expectations for in-cluster paths\n\nConstraints:\n- Minimal diff. Extend the existing `SecurityFilterChain` and clients; don't add a second permissive chain.\n- Don't invent tenant IDs, client IDs, secrets, or hostnames. Use placeholders if unknown.\n- Don't disable auth for in-cluster callers or for any prod profile.\n- Optimize for GitHub Copilot, Claude Code, and Codex: give concrete diffs and a checklist.\n- Leave Entra portal / IaC changes as explicit follow-up notes unless the repo already manages them.\n\nOutput format:\n1. Findings table: severity | location | issue | fix\n2. Patch (config + converter/validators + security rules + client registrations/RestClients + ConfigMap keys)\n3. Tests added and their results\n4. Role matrix, URL map, and follow-ups (manifest changes, workload identity federation, NetworkPolicy)\n\nStart from {{APP_PATH}}. Close missing aud/role checks and token-to-wrong-host leaks before anything else.\n"
}
]
}
Loading
Loading