Keycloak policy enforcer not working, Sprint boot application.
I use spring boot v 2.3.1 with Keycloak version 10.0.2, i need setup policy enforcer into my app, autnentication part with keycloak work, but if i add policy enforcer config into application.properties, un have an error
===================>application.properties file:
server.port = 8082
# keycloak config
keycloak.realm = my-realm
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.resource = resource_server
keycloak.credentials.secret = 1adb9e31-cd6a-4eb5-95c5-6a45e972b64a
keycloak.ssl-required=external
keycloak.public-client = true
keycloak.bearer-only = true
#keycloak.verify-token-audience = true
keycloak.cors=true
keycloak.use-resource-role-mappings = true
keycloak.confidential-port=0
keycloak.principal-attribute=preferred_username
keycloak.policy-enforcer-config.enforcement-mode= PERMISSIVE
keycloak.policy-enforcer-config.lazy-load-paths=true
keycloak.policy-enforcer-config.paths[0].name=page_resource
keycloak.policy-enforcer-config.paths[0].path=/uma-protected-resource
keycloak.policy-enforcer-config.paths[0].methods[0].method=GET
keycloak.policy-enforcer-config.paths[0].methods[0].scopes[0]= view
================>test user evaluation in keycloak:
Result
*PERMIT
Scopes
*view
*edit
*delete
Policies
*edit_permission_resource(User-Managed Policy)
decision was PERMIT by AFFIRMATIVE decision. Granted Scopes: edit.
*view_permission_resource(User-Managed Policy)
decision was PERMIT by AFFIRMATIVE decision. Granted Scopes: view.
*delete_permission_resource(User-Managed Policy)
decision was PERMIT by AFFIRMATIVE decision. Granted Scopes: delete.
================>** Error logs**:
java.lang.RuntimeException: Failed to obtain policy enforcer
at org.keycloak.adapters.KeycloakDeployment.getPolicyEnforcer....
at org.keycloak.adapters.AuthenticatedActionsHandler.corsRequest...
at ...
at ...
Caused by: java.lang.RuntimeException: Could not find resource
at ...
at ...
Caused by: Caused by: org.keycloak.authorization.client.util.HttpResponseException: Unexpected response from server: 401 / Unauthorized
at ...
at ...
i use et user token with the right permissions, but i don't know why it doesn't work.
I think, he can't find the resource on kaycloak, but he is there with the right rights
client in keycloak: resource_server
https://i.stack.imgur.com/d3huA.png
https://i.stack.imgur.com/o9xDc.png
resource in keycloak
https://i.stack.imgur.com/mslnu.png
Thanks for your help :)
Related
I am getting following exeption connecting to Mssql Server.
> org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is java.net.UnknownHostException: failed to resolve '' after 10 queries
at org.springframework.r2dbc.connection.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:88) ~[spring-r2dbc-5.3.2.jar:5.3.2]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler com.reactive.testreactive.controller.TestStreamController#findAll() [DispatcherHandler]
|_ checkpoint ⇢ HTTP GET "/test" [ExceptionHandlingWebHandler]
I connected to JDBC with the same configuration in properties but having an issue while trying to connect to R2DBC. Happens on rest and not on starting an app.
#Bean
public MssqlConnectionFactory connectionFactory() {
return new MssqlConnectionFactory(MssqlConnectionConfiguration.builder()
.host("host")
.port(1433)
.database("DataBase")
.username("username")
.password("password")
.build());
}
Do you use absolutely the same configuration?
Because if you are starting using R2DBC you should replace database URL: jdbc:postgresql://... -> r2dbc:postgresql://
If anyone still looking for solution, I'm adding solution below.
First, make sure your database host is visible. By looking at your error statement which says -- failed to resolve '' after 10 queries, means it is empty ''. The way that you have defined the host name is not correct. If you are injecting the host value from properties, you might want to cross check that and then follow the steps below.
If you are configuring through YMLs, you can use below configurations:
spring:
data:
r2dbc:
repositories:
enabled: true
r2dbc:
url: r2dbc:sqlserver://<just_host>:<port>
username: <db_username>
password: <db_password>
name: <db_name>
spring.data.r2dbc.repositories.enabled: true is optional here.
If you are creating custom bean, you can create bean like below. Please note that I'm returning ConnectionFactory rather than MssqlConnectionFactory.
#Bean
public ConnectionFactory connectionFactory() {
return new MssqlConnectionFactory(
MssqlConnectionConfiguration.builder()
.host("just_host")
.database("db_name")
.port(1433)
.username("db_username")
.password("db_password")
.build());
}
I have configured Zuul with Eureka in a way, that 3 identical instances of a service are working parallely. I am calling the gateway on the port 8400, which routes incoming requests to ports 8420, 8430 and 8440 in a round-robin manner. It works smoothly. Now, if I switching off one of the 3 services, a small amount of incoming requests will go wrong with the following exception:
com.netflix.zuul.exception.ZuulException: Filter threw Exception
=> 1: java.util.concurrent.FutureTask.report(FutureTask.java:122)
=> 3: hu.perit.spvitamin.core.batchprocessing.BatchProcessor.process(BatchProcessor.java:106)
caused by: com.netflix.zuul.exception.ZuulException: Filter threw Exception
=> 1: com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:227)
caused by: org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException: com.netflix.zuul.exception.ZuulException: Forwarding error
=> 1: org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:124)
caused by: com.netflix.zuul.exception.ZuulException: Forwarding error
=> 1: org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:198)
caused by: com.netflix.client.ClientException: com.netflix.client.ClientException
=> 1: com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:118)
caused by: java.lang.RuntimeException: org.apache.http.NoHttpResponseException: scalable-service-2:8430 failed to respond
=> 1: rx.exceptions.Exceptions.propagate(Exceptions.java:57)
caused by: org.apache.http.NoHttpResponseException: scalable-service-2:8430 failed to respond
=> 1: org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
My Zuul routing looks like this:
### Zuul routes
zuul.routes.scalable-service.path=/scalable/**
#Authorization header will be forwarded to scalable-service
zuul.routes.scalable-service.sensitiveHeaders: Cookie,Set-Cookie
zuul.routes.scalable-service.serviceId=template-scalable-service
It takes a while until Eureka discovers the service is not available any more.
My question is: Is there a possibility, to configure Zuul so that in case of a NoHttpResponseException, it forwards the requests to another available instance in the pool?
Eureka, by default, requires lease to be renewed every 90s. That is, if a service instance doesn't get its lease renewed in 90s, Eureka server will evict the instance. In your case, the instance has not been evicted yet - the renew window for the instance was valid.
For this, you can decrease the renew duration through config setup at eureka client and eureka server as described here.
Note: If you hit the actuator /shutdown endpoint, the instance is immediately evicted
Finally I found the solution to the problem. The appropriate search phrase was 'fault tolerance'. The key is the autoretry config in the following application.properties file. The value of template-scalable-service.ribbon.MaxAutoRetriesNextServer must be set at least to 6 in case of 3 pooled services to achieve full fault tolerance. With that setup I can kill 2 of 3 services any time, no incoming request will go wrong. Finally I have set it to 10, there is no unnecessary increase of timeout, hystrix will break the line.
### Eureka config
eureka.instance.hostname=${hostname:localhost}
eureka.instance.instanceId=${eureka.instance.hostname}:${spring.application.name}:${server.port}
eureka.instance.non-secure-port-enabled=false
eureka.instance.secure-port-enabled=true
eureka.instance.secure-port=${server.port}
eureka.instance.lease-renewal-interval-in-seconds=5
eureka.instance.lease-expiration-duration-in-seconds=10
eureka.datacenter=perit.hu
eureka.environment=${EUREKA_ENVIRONMENT_PROFILE:dev}
eureka.client.serviceUrl.defaultZone=${EUREKA_SERVER:https://${server.fqdn}:${server.port}/eureka}
eureka.client.server.waitTimeInMsWhenSyncEmpty=0
eureka.client.registry-fetch-interval-seconds=5
eureka.dashboard.path=/gui
eureka.server.enable-self-preservation=false
eureka.server.expected-client-renewal-interval-seconds=10
eureka.server.eviction-interval-timer-in-ms=2000
### Ribbon
ribbon.IsSecure=true
ribbon.NFLoadBalancerPingInterval=5
ribbon.ConnectTimeout=30000
ribbon.ReadTimeout=120000
### Zuul config
zuul.host.connectTimeoutMillis=30000
zuul.host.socketTimeoutMillis=120000
zuul.host.maxTotalConnections=2000
zuul.host.maxPerRouteConnections=200
zuul.retryable=true
### Zuul routes
#template-scalable-service
zuul.routes.scalable-service.path=/scalable/**
#Authorization header will be forwarded to scalable-service
zuul.routes.scalable-service.sensitiveHeaders=Cookie,Set-Cookie
zuul.routes.scalable-service.serviceId=template-scalable-service
# Autoretry config for template-scalable-service
template-scalable-service.ribbon.MaxAutoRetries=0
template-scalable-service.ribbon.MaxAutoRetriesNextServer=10
template-scalable-service.ribbon.OkToRetryOnAllOperations=true
#template-auth-service
zuul.routes.auth-service.path=/auth/**
#Authorization header will be forwarded to scalable-service
zuul.routes.auth-service.sensitiveHeaders=Cookie,Set-Cookie
zuul.routes.auth-service.serviceId=template-auth-service
# Autoretry config for template-auth-service
template-auth-service.ribbon.MaxAutoRetries=0
template-auth-service.ribbon.MaxAutoRetriesNextServer=0
template-auth-service.ribbon.OkToRetryOnAllOperations=false
### Hystrix
hystrix.command.default.execution.timeout.enabled=false
Beside of this, I have a profile specific setup in application-discovery.properties
#Microservice environment
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=true
spring.cloud.loadbalancer.ribbon.enabled=true
I start my server in a docker container like this:
services:
discovery:
container_name: discovery
image: template-eureka
environment:
#agentlib for remote debugging
- JAVA_OPTS=-DEUREKA_SERVER=https://discovery:8400/eureka -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
- TEMPLATE_EUREKA_OPTS=-Dspring.profiles.active=default,dev,discovery
- EUREKA_ENVIRONMENT_PROFILE=dev
ports:
- '8400:8400'
- '5500:5005'
networks:
- back-tier-net
- monitoring
hostname: 'discovery'
See the complete solution in GitHub.
For a few days I try to resolve following issue:
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with name attribute value matching endpoint port is defined as well as a ws-security.signature.properties element within it.
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:158)
at com.sun.proxy.$Proxy38.getSignedDocument(Unknown Source)
at pl.mycompany.epuap.TPSigning_TPSigning_Client.main(TPSigning_TPSigning_Client.java:55)
Caused by: org.apache.cxf.ws.policy.PolicyException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with name attribute value matching endpoint port is defined as well as a ws-security.signature.properties element within it.
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.policyNotAsserted(AbstractBindingBuilder.java:315)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureBuilder(AbstractBindingBuilder.java:1851)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignature(AsymmetricBindingHandler.java:570)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:149)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:98)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:176)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:90)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:572)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:481)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:136)
... 2 more
This happens when I try to call webservice: https://pz.gov.pl/pz-services/tpSigning?wsdl with external (referenced) policy: https://pz.gov.pl/pz-services/tpSigning?wsdl=wssec-policies.wsdl.
Here is my code:
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
properties.put("org.apache.ws.security.crypto.merlin.keystore.type",config.getKeystoreType());
properties.put("org.apache.ws.security.crypto.merlin.keystore.password",config.getKeystorePass());
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias",config.getKeystoreAlias());
properties.put("org.apache.ws.security.crypto.merlin.file", config.getKeystoreFile());
outProps.put("cryptoProperties",properties);
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE);
//outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.USER, config.getKeystoreAlias());
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_REF_ID,"cryptoProperties");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{}{http://schemas.xmlsoap.org/soap/envelope/}Body");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
try{
String s = signing.addDocumentToSigning(doc, succesUrl, failureUrl, additionalInfo);
return s;
}
As I noticed, the policies aren't at all loaded by CXF engine. I tried to load policies by interceptors, but the effect is the same.
The probelm occurs also in 2.7.18 as in 3.x version.
Any help will be highly appreciated.
Regards
Mariusz
The problem is that you are mixing the "action" based approach to WS-Security, and the WS-SecurityPolicy driven approach. The WSDL you reference contains a security policy, and the CXF PolicyBasedWSS4JOutInterceptor will automatically take care of configuring security based on this. You just need to specify a few security configuration options, e.g. keystores. See here for more information: https://cxf.apache.org/docs/ws-securitypolicy.html
I'm using secure social in my Play project. I'm trying to use my own E-Mail for the registaiton process.
The how to is described here:
http://securesocial.ws/guide/views-customization.html
My Problem is, that I get an error when I try to genreate the absoute URL in the template:
#securesocial.controllers.routes.Registration.signUp(mailToken).absoluteURL(IdentityProvider.sslEnabled)
Here ist the Error Log:
[error] play - Cannot invoke the action, eventually got an error:
java.lang.Runt imeException: There is no HTTP Context available from
here. [error] application -
! #6j0al12dk - Internal server error, for (POST) [/signup] ->
play.api.Application$$anon$1: Execution exception[[RuntimeException:
There is no HTTP Context available from here.]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_
2.10.jar:2.2.3]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_
2.10.jar:2.2.3]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun
$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:264)
[play_2.10.jar:2.2.3]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun
$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:264)
[play_2.10.jar:2.2.3]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3.applyOrE
lse(PlayDefaultUpstreamHandler.scala:264) [play_2.10.jar:2.2.3] Caused
by: java.lang.RuntimeException: There is no HTTP Context available
from h ere.
at play.mvc.Http$Context.current(Http.java:30) ~[play_2.10.jar:2.2.3]
at play.mvc.Http$Context$Implicit.ctx(Http.java:196) ~[play_2.10.jar:2.2 .3]
at play.core.j.PlayMagicForJava$.requestHeader(TemplateMagicForJava.scal
a:56) ~[play-java_2.10.jar:2.2.3]
at views.html.custom.mails.signUpEmail$.apply(signUpEmail.template.scala
:42) ~[classes/:na]
at plugins.NekViews.getSignUpEmail(NekViews.scala:100) ~[classes/:na]
at securesocial.core.providers.utils.Mailer$.sendSignUpEmail(Mailer.scal
a:49) ~[securesocial_2.10-2.1.3.jar:2.1.3] [info] application -
[securesocial] unloaded identity provider: userpass [info] application
- [securesocial] unloaded password hasher bcrypt [info] play - Shutdown application
default Akka system.
Does anybody know what the mistake is?
Your template requires implicit request which is mandatory for obtaining an absolute URL.
#(/*template's parameters*/)(implicit request: RequestHeader)
This request must be available in a method which renders the template.
I had a pretty similar error if not the same, probably you're also mixing some java code in your project.
You must create a java context in your controller ( in this case the custom views controller ) for it to be used by the views.
For example:
Scala helper to create a java context
object JavaContext {
import play.mvc.Http
import play.core.j.JavaHelpers
def withContext[Status](block: => Status)(implicit header: RequestHeader): Status = {
try {
Http.Context.current.set(JavaHelpers.createJavaContext(header))
block
}
finally {
Http.Context.current.remove()
}
}
}
Usage:
class CustomSecureSocialTemplates(env:RuntimeEnvironment[_]) extends ViewTemplates.Default(env:RuntimeEnvironment[_])
{
override def getLoginPage(form: Form[(String, String)],
msg: Option[String] = None)(implicit request: RequestHeader, lang: Lang): Html = {
JavaContext.withContext {
views.html.security.login(form,msg)
}
}
//...
}
Source: dominikdorn.com
I'm running the following tutorial:
http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html
I'm getting the following prompts:
Connected to server localhost/127.0.0.1
Kerberos username [login]: {I enter my username here}
Kerberos password for login: {I enter my password here}
I get the following error:
Can you ascertain the root cause of this?
Exception in thread "main" GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))
at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Krb5InitCredential.java:333)
at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:128)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:106)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:172)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:209)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:195)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162)
at demo.SampleClient.main(SampleClient.java:145)
Caused by: javax.security.auth.login.LoginException: Message stream modified (41)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:696)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$5.run(LoginContext.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokeCreatorPriv(LoginContext.java:703)
at javax.security.auth.login.LoginContext.login(LoginContext.java:575)
at sun.security.jgss.GSSUtil.login(GSSUtil.java:246)
at sun.security.jgss.krb5.Krb5Util.getTicket(Krb5Util.java:136)
at sun.security.jgss.krb5.Krb5InitCredential$1.run(Krb5InitCredential.java:328)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Krb5InitCredential.java:325)
... 7 more
Caused by: KrbException: Message stream modified (41)
at sun.security.krb5.KrbKdcRep.check(KrbKdcRep.java:53)
at sun.security.krb5.KrbAsRep.<init>(KrbAsRep.java:96)
at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:449)
at sun.security.krb5.Credentials.sendASRequest(Credentials.java:410)
at sun.security.krb5.Credentials.acquireTGT(Credentials.java:378)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:662)
... 23 more
I got exceptions “Message stream modified (41)”, when the Kerberos realm didn’t match. The realm (in system property java.security.krb5.realm) has to match exactly, including upper/lower case.
I'm wondering if this is a possibility (ie even if registry key is set, locked out for local administrators):
http://cr.openjdk.java.net/~weijun/special/krb5winguide-2/raw_files/new/kwin
Known Issues
If an AD account is also added into local administrator group on the
client PC, Microsoft restricts such client from getting the session key
for tickets (even if you set the allowtgtsessionkey registry key to 1).
The workaround is: Just forget you're a logged in user, call kinit.exe.
Do not depends on LSA credential cache.
I cannot confirm that issue. I do have admin rights on my machine and still are able to obtain the session key from the LSA. You should enable full debug ouput on JGSS and the Krb5LoginModule. Share your krb5.ini and login.conf too. I hope your are aware that the above example cannot work because your client cannot obtain a ticket for a local host. It has to be a FQDN with an appropriate SPN set in the Active Directory.