Open joggeli34 opened 3 years ago
/cc @geoand
cc @sberyozkin
@joggeli34 If quarkus.keycloak.policy-enforcer.enforcement-mode=enforcing
then an attempt is made to check the remote configuration - I think you need to disable a policy check for this path to avoid the remote calls, can you try it please ?
CC @pedroigor
The same happens also when changing the configuraiton to:
quarkus.keycloak.policy-enforcer.enable=true
quarkus.keycloak.policy-enforcer.enforcement-mode=enforcing
quarkus.keycloak.policy-enforcer.paths.q.path=/q/*
quarkus.keycloak.policy-enforcer.paths.q.enforcement-mode=disabled
When using follwing configuration (as all my paths are under /api/ anyway), the authentication is disabled "/api/" too, but I was expecting that it would be enabled for all the paths under /api/*
quarkus.keycloak.policy-enforcer.enable=true
quarkus.keycloak.policy-enforcer.enforcement-mode=disabled
quarkus.keycloak.policy-enforcer.paths.api.path=/api/*
quarkus.keycloak.policy-enforcer.paths.api.enforcement-mode=enforcing
@joggeli34 Policy enforcer matching code might not be able to handle wildcards when it comes to nested paths, so perhaps it should be
quarkus.keycloak.policy-enforcer.paths.q.path=/q/health/*
quarkus.keycloak.policy-enforcer.paths.q.enforcement-mode=disabled
After some debugging, I found out, that the matcher correctly matches /q/*
aswell as /q/health/*
.
But the path is always checked with keycloak if it has a wildcard. But it also always checks invalidated path, and the path gets always invalidated after some time even when using the the full path /q/health/live
.
Here the code from the PolicyEnforcer which does the check (line 270)
if (enforcerConfig.getLazyLoadPaths() || enforcerConfig.getPathCacheConfig() != null) {
if ((pathConfig == null || pathConfig.isInvalidated() || pathConfig.getPath().contains("*"))) {
try {
List<ResourceRepresentation> matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri);
if (matchingResources.isEmpty()) {
// if this config is invalidated (e.g.: due to cache expiration) we remove and return null
if (pathConfig != null && pathConfig.isInvalidated()) {
paths.remove(targetUri);
return null;
}
} else {
After it was invalidated, it even get removed from the path and is then handled as if it was never defined. So I can't see a possibility currently to not check public paths against keycloak on each call.
When adding:
quarkus.keycloak.policy-enforcer.paths.q.name=disabled
with the corresponding resource in keycloak, the pathConfig gets marked as static and is then not invalidated anymore. Would it be a possibility to mark all disabled-paths as static directly?
@joggeli34 It might be possible to update the recorder to keep a local path to enforcement mode configuration available outside of Keycloak PolicyEnforcer
code, per every tenant, so return not only PolicyEnforcerConfig
but also a pair of path
+ mode
from here.
Then preserve it here - ex, instead of using PolicyEnforcer
as a default and tenant values, use PolicyEnforcerProvider
which would hold PolicyEnforcer
and that pair of path/mode
.
Finally, add this local path/mode check above this check which may cause a remote call.
If a user has disabled a check for a given path then there is no need to do any further checks, allow the access and return immediately.
The same check should also be done here - if it is a proactive authentication then the token/security identity will be available even when accessing a public resource
I can have a look later - but if you could consider creating a PR then it would accelerate it thanks
@joggeli34 That said, may be we should check with Pedro @pedroigor first - perhaps some configuration is also possible
perhaps some configuration is also possible
After going through Keycloak PolicyEnforcer
and PathMatcher
, I don't believe there is. Path check performed by PathConfigMatcher
is very complex and it can't avoid remote calls for non-static paths with patterns that are not yet in cache. I'd suggest that we go with a check suggested by @sberyozkin above, however instead of doing full path config match, we only solve this issue for cases when path of disabled enforcement policy ends with asterisk. Then we check disabled enforcement path starts with incoming URI (and we create cache and remember it for each tenant), if so, we do not need further checks.
This won't help with complex patterns and path parameters and suffixes described by https://www.keycloak.org/docs/latest/authorization_services/#_enforcer_overview, but fixes the issue as it only complains about paths ending with wildcards. If there are no objections, I'll try that.
I gave up on contributing to Keycloak the change we need after few months waiting without response. Someone else will need to contribute to Keycloak in order to fix this issue.
Describe the bug
When using keycloak-authorization, the public endpoints (e.g. /q/health/live) are logging following exception when keycloak is not reachable (due to restart or something else).
The api call stays responsive, even if this error is logged. So it's more a problem about polluting the log and not about the functionality.
But I assumed that keycloak is not called if the endpoint is public anyway, which probably reduces the load on the keycloak-server as the liveness check is called often in a kubernetes-deployment.
Expected behavior
No error is logged for public endpoints as I assumed that keycloak must not be called if the endpoint is public anyway.
Actual behavior
The exception is logged, but the endpoint is reachable with out a problem.
How to Reproduce?
Output of
uname -a
orver
No response
Output of
java -version
No response
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.0.2.Final
Build tool (ie. output of
mvnw --version
orgradlew --version
)No response
Additional information
No response