Class ApiKey
java.lang.Object
org.frontcache.core.ApiKey
The The property was
Renamed, with NO fallback to the old name: a node whose
One form, everywhere: the agent, the console, The legacy
That header was the Frontcache convention through 2.6 and is still accepted, deprecated, with a
warning naming the caller. It cannot simply be dropped:
front-cache.api-key check, in one place.
This is the management API's only access control - the thing that decides whether a caller
may invalidate a cache, dump its keys or read its metrics. There used to be a
front-cache.management.port check in front of it, which was never a boundary: it compared
the port the caller ADDRESSED, taken from the Host header. It is gone; restricting which connector
answers management traffic is the reverse proxy's job.
Extracted because there was one implementation in FrontCacheIOServlet and a second endpoint
needed the same rule, and two implementations of one security check is one too many - the copy is
always the one that goes stale.
The property was front-cache.site-key through 2.8
Renamed, with NO fallback to the old name: a node whose frontcache.properties still says
front-cache.site-key reads no key at all and comes up with its management API, dashboard
stream and /fc-metrics OPEN. Rename the property when you upgrade. The credential on the
wire did not change, so callers - agent, console, peer nodes, Prometheus - need no coordination
with this; only the node's own config file does.
Authorization: Bearer <api-key> is the way to send it
One form, everywhere: the agent, the console, FrontCacheClient, node-to-node replication and
a Prometheus scrape all use it. It is a standard scheme with standard tooling, and it is the only
form Prometheus can send at all - a scrape_config offers basic_auth, authorization and
oauth2, and no way to set an arbitrary header - which is what settled the choice between the two.
The legacy x-frontcache-site-key header, for one release
That header was the Frontcache convention through 2.6 and is still accepted, deprecated, with a
warning naming the caller. It cannot simply be dropped: frontcache-agent is a published
artifact embedded in customer applications, the console is deployed separately from the fleet, and
nodes replicate to each other - so at any moment some caller is older than the node it is calling,
and a node that refused the old header would break all of them on upgrade rather than at a time
anyone chose. Same treatment get-hystrix-configs got in 2.7. Remove once every supported
caller is 2.7 or later.
The SSE stream's check is stricter, on purpose
FCUtils.isAuthorizedApiKeyHeader - used by FcSampleSseServlet - is a third spelling
of this, and it is NOT the same rule: it goes through FrontCacheEngine.isNodeApiKey, which
refuses a request when the node has no API key at all, where this returns true. Folding them
together would have to pick one of those, and both directions are a behaviour change on somebody's
node - the stream would open where it is closed today, or the management API would close where it is
open. Left as it is, and written down here, because the difference is invisible at both call sites.
Read per request
Rather than cached at servlet init, so that reloading a node's configuration changes the key that is actually enforced. A property read per management request costs nothing measurable.-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringPublic so a refusal message can name the property the operator has to set. -
Method Summary
Modifier and TypeMethodDescriptionstatic Stringstatic booleanisAuthorized(jakarta.servlet.http.HttpServletRequest request) static booleanisAuthorizedToWrite(jakarta.servlet.http.HttpServletRequest request) The stricter rule, for management calls that WRITE.static booleanstatic Stringpresented(jakarta.servlet.http.HttpServletRequest request) The credential the caller presented, or null.
-
Field Details
-
API_KEY_PROPERTY
Public so a refusal message can name the property the operator has to set.- See Also:
-
-
Method Details
-
configured
- Returns:
- the configured API key, or "" when the node has none
-
isConfigured
public static boolean isConfigured()- Returns:
- true when this node has an API key at all. When it does not, the management API has no access control at all.
-
isAuthorized
public static boolean isAuthorized(jakarta.servlet.http.HttpServletRequest request) - Parameters:
request- the inbound request- Returns:
- true when the request carries this node's API key, or when the node has no API key configured (the historical default - an unconfigured node is open, and says so at startup rather than refusing traffic on upgrade)
-
isAuthorizedToWrite
public static boolean isAuthorizedToWrite(jakarta.servlet.http.HttpServletRequest request) The stricter rule, for management calls that WRITE.Why an un-keyed node is refused here and allowed by
An un-keyed node is open, deliberately, and that is tolerable for reads and for cache invalidation. Accepting arbitrary content into conf/guard-rules.conf (redirects, rate limits, allowed redirect hosts), conf/bots.conf (who is classified how, hence what is cached and for how long) or conf/resilience.properties (the timeouts and breakers in front of the origin) is a different thing: it is remote configuration of how the node handles requests. And the un-keyed state is usually accidental - a 2.9.0 upgrade that leftisAuthorized(HttpServletRequest)front-cache.site-keyin the properties file produces a node with no key at all and no failure to notice. Writes must not be what that state silently enables. This is the third rule in the family, alongsideFCUtils.isAuthorizedApiKeyHeaderfor the SSE stream (see the class comment above), and it lives here so there is only one spelling of it.- Returns:
- true when the node has an API key AND the request carries it
-
presented
The credential the caller presented, or null. Public because the SSE stream reads the same credential and applies a different rule to it (see the class javadoc) - so the two share how a caller SENDS the key while keeping their own answers about what it means.- Parameters:
request- the inbound request- Returns:
- the API key the caller sent, by the current or the legacy route, or null
-