Skip to content

feat(ingester): restrict /flush and /shutdown endpoints to POST only#7674

Open
Goutham-Annem wants to merge 4 commits into
cortexproject:masterfrom
Goutham-Annem:fix/3243-post-only-flush-shutdown
Open

feat(ingester): restrict /flush and /shutdown endpoints to POST only#7674
Goutham-Annem wants to merge 4 commits into
cortexproject:masterfrom
Goutham-Annem:fix/3243-post-only-flush-shutdown

Conversation

@Goutham-Annem

Copy link
Copy Markdown

What this PR does:

The /ingester/flush, /ingester/shutdown, /flush, and /shutdown endpoints previously accepted GET requests, making it possible to accidentally trigger a destructive ingester operation by clicking a link in a browser or via a pre-fetch proxy following the index page's links.

This PR makes three coordinated changes:

  1. Route restriction (pkg/api/api.go): The four flush/shutdown RegisterRoute calls now only list "POST". A browser GET (or curl without -X POST) returns 405 Method Not Allowed.

  2. Index page template (pkg/api/handlers.go): Links in the Dangerous: section now render as <form method="POST"><button> elements instead of <a href> anchors. This ensures that clicking in the browser issues a POST, not a GET. Non-dangerous links continue to render as plain anchors. A template function IsDangerous(section string) bool drives the branching.

  3. Migration script (tools/migrate-ingester-statefulsets.sh): The BusyBox wget invocation inside kubectl exec is updated to wget --post-data="" -T 5 .... BusyBox wget supports --post-data, so the script continues to work without requiring curl inside the Cortex container image (which is unavailable per the original issue discussion).

Which issue(s) this PR fixes:
Fixes #3243

Checklist

  • Tests updated — TestIndexPageContent extended with assertions that dangerous links produce method="POST" forms and no <a href>; new TestIndexHandlerDangerousLinksUsePostForms covers prefix behaviour for dangerous links
  • CHANGELOG.md updated
  • Documentation added (N/A — behaviour is visible in the UI itself)

Note: This PR was developed with AI assistance (Claude Code).

The /ingester/flush, /ingester/shutdown, /flush, and /shutdown endpoints
previously accepted GET requests, making it possible to accidentally
trigger a destructive ingester operation by clicking a link in a browser
or by a pre-fetch proxy following links on the index page.

Changes:
- Route registration for flush/shutdown changed from ["GET","POST"] to ["POST"].
  A browser GET (or curl without -X POST) now returns 405 Method Not Allowed.
- Index page template updated to render links in the "Dangerous:" section as
  HTML <form method="POST"> submit buttons rather than plain <a href> anchors,
  preventing browser-initiated GET requests while keeping the UI functional.
- tools/migrate-ingester-statefulsets.sh updated to use `wget --post-data=""`
  (BusyBox wget supports this flag) so the script continues to work after the
  GET handler is removed.
- Two tests added/extended to assert the POST-form rendering for dangerous links.

Fixes cortexproject#3243

Signed-off-by: Goutham Annem <gouthemannem@gmail.com>
@friedrichg

Copy link
Copy Markdown
Member

this should trigger a change in the docs too https://cortexmetrics.io/docs/api/#shutdown

Reflects the change introduced in pkg/api/api.go that removed GET
from the allowed methods for /ingester/flush, /flush, /ingester/shutdown,
and /shutdown. Browsers and scripts must now use POST to trigger these
operations.

Signed-off-by: Goutham Annem <gouthemannem@gmail.com>
@Goutham-Annem

Copy link
Copy Markdown
Author

Gentle ping — CI is passing, happy to address any feedback.

@Goutham-Annem

Copy link
Copy Markdown
Author

Gentle ping — CI is passing and there are no conflicts. Happy to address any feedback!

The /flush endpoint now only accepts POST (changed in feat cortexproject#3243).
Update the integration test to call e2e.PostRequest instead of e2e.GetRequest
so the test stays consistent with the enforced method restriction.

Signed-off-by: Goutham Annem <gouthemannem@gmail.com>

@friedrichg friedrichg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am ok with this.
But also brings the question of what should happen with /ingester/mode and /ingester/renewTokens

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jul 21, 2026
@friedrichg
friedrichg requested a review from danielblando July 21, 2026 23:36
Signed-off-by: Goutham Annem <gouthemannem@gmail.com>
@Goutham-Annem

Copy link
Copy Markdown
Author

Good point — extended the PR to also restrict /ingester/renewTokens and /ingester/mode to POST-only. Both are already in SectionDangerous, so the index page template already renders them as POST forms (including the query string in the action attribute, so mode=READONLY / mode=ACTIVE still work). No test changes needed since neither endpoint has dedicated API tests.

@SungJin1212

Copy link
Copy Markdown
Member

@Goutham-Annem
lgtm, can you share a new UI?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ingester lgtm This PR has been approved by a maintainer size/M type/security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Restrict /flush and /shutdown ingester endpoints to POST method only

3 participants