Keycloak Policy Enforcing - spring-boot

Application.properties:
server.port=8180
keycloak.realm = finaltest
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.resource = ex
keycloak.public-client=false
keycloak.enabled=true
keycloak.credentials.secret=secret
keycloak.ssl-required = external
keycloak.cors=true
keycloak.use-resource-role-mappings=true
keycloak.security-constraints[0].auth-roles[0]=master
keycloak.security-constraints[0].security-collections[0].patterns[0]=/*
keycloak.policy-enforcer-config.enforcement-mode=ENFORCING
keycloak.policy-enforcer-config.lazy-load-paths=true
RESOURCES:
I have two resources namely
http://localhost:8180/flights.html
http://localhost:8180/hotels.html
I have protected these using the policies in keycloak admin console.How do I enforce these policies in the application?

keycloak.policy-enforcer-config.enforcement-mode=ENFORCING this line will enforce policies.But you must have spring boot version 2.0 and above.

Related

H2 database: h2 console not working with spring-boot

I followed the next tutorial for h2 implementation. H2 works well, but the console isn't - the page isn't opened.
I tried many gifts, so my final application.properties looks so:
#Database settings
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.data.jpa.repositories.bootstrap-mode=default
spring.h2.console.enabled=true
spring.h2.console.settings.web-allow-others=true
spring.datasource.generate-unique-name = false
spring.h2.console.path=/h2-console/
spring.jpa.hibernate.ddl-auto=update
spring.datasource.tomcat.connection-properties=useUnicode=true;characterEncoding=utf-8;
spring.datasource.sql-script-encoding=UTF-8
spring.jpa.open-in-view=false
spring.datasource.initialization-mode=always
#swagger
spring.mvc.pathmatch.matching-strategy = ANT_PATH_MATCHER
#Disable thymeleaf cashing
spring.template.cache = false;
dependencies:
ext {
spring_boot_version = '2.6.6'
}
implementation "org.springframework.boot:spring-boot-starter-parent:${spring_boot_version}"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:${spring_boot_version}"
implementation "org.springframework.boot:spring-boot-starter-validation:${spring_boot_version}"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:${spring_boot_version}"
implementation "org.springframework.boot:spring-boot-starter-web:${spring_boot_version}"
runtimeOnly "com.h2database:h2:1.4.193"
....
The uri I try to open:
http://localhost:8080/h2-console
Try this:
server.port=8080
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;
Could you try to add the following configuration to the security config?
http.authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
Ideally, you need to config (depending on the spring boot version) to allow access to /h2-console URL.
You can also publicise your security configuration so that I can have a look.

Centralized Swagger/OpenAPI UI for all the different microservices on a single swagger URL i.e accessing all the URLs through one

I have around 16 microservices built in Spring Boot that communicate with each other and each microservice is having multiple APIs in it. I have configured OpenAPI for each of the microservices. So it gives me 16 "swagger-ui" URLs.
I wonder how can I centralize all Swagger URLs on one single page; I want only 1 swagger URL to access all the 16 microservices.
I have gone through the following as well but didn't get any solution
Centralize Swagger at one place for All microservices
Please guide me to the best way to achieve it.
I found a working solution on GitHub. It works with Spring Cloud Discovery but can be easily adapted to other discovery solutions. The basic idea is to generate for Swagger the list of URLs pointing to the OpenAPI JSON files.
The result is similar to one in the #shadyx's answer, but the list is generated dynamically
#RestController
public class SwaggerUiConfig {
#Autowired
private DiscoveryClient discoveryClient;
#GetMapping("/swagger-config.json")
public Map<String, Object> swaggerConfig() {
List<SwaggerUrl> urls = new LinkedList<>();
discoveryClient.getServices().forEach(serviceName ->
discoveryClient.getInstances(serviceName).forEach(serviceInstance ->
urls.add(new SwaggerUrl(serviceName, serviceInstance.getUri() + "/v3/api-docs"))
)
);
return Map.of("urls", urls);
}
}
application.yaml
springdoc:
swagger-ui:
configUrl: "/swagger-config.json"
Sample of the generated swagger-config.json
{
"urls": [
{
"url": "http://localhost:8088/v3/api-docs/users",
"name": "users"
},
{
"url": "http://localhost:8088/v3/api-docs/stores",
"name": "stores"
}
]
}
If all you µservices use the same host, you can create a Spring Boot µservice which acts as a openAPI gateway using spring-doc. (If they are not using the same host, you will have to deal with CORS issues)
First, add the following dependencies to your new gateway µservice
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Then, add the below configuration
springdoc:
api-docs:
enabled: true
swagger-ui:
configUrl: ${server.servlet.contextPath}/v3/api-docs/swagger-config
url: ${server.servlet.contextPath}/v3/api-docs
urls:
- name: api-customer
url: /customer/v3/api-docs
- name: api-cart
url: /cart/v3/api-docs
- name: api-product
url: /product/v3/api-docs
For each µservice you have to fill in the url property with is the url to the openAPI definition at json or yaml format.
For springdoc library which uses openAPI 3.0 the default url is /${µServiceContextPath}/v3/api-docs
For springfox library which uses openAPI 2.0 the default url is /${µServiceContextPath}/v2/api-docs
Finally access to /${contextPath}/swagger-ui.html and you will be able to select an openAPI

#FeignClient always timeout when using eureka service id

I have a spring-boot app which uses Declarative Feign Client
#ComponentScan
#EnableFeignClients
#EnableCircuitBreaker
#EnableDiscoveryClient
#EnableZuulProxy
#FeignClient(name = "${service-registry-name}", fallbackFactory = MyFallbackFactory.class, configuration = CommonFeignConfiguration.class)
public interface MyClient {
#RequestMapping(method = RequestMethod.GET, path = "/test/reference/data")
HttpEntity<String> getAllData();}
I have following application.yml
feign:
okhttp:
enabled: true
feign:
hystrix:
enabled: true
hystrix:
command:
MyClient#getAllData():
execution:
isolation:
thread:
timeoutInMilliseconds: 30000
hystrix:
command:
default:
execution:
timeout:
enabled: false
logging:
level:
project:
user:
MyClient: DEBUG
feign:
client:
config:
feign-name:
requestInterceptors: com.test.MyRequestHeaderProcessor
This spring-boot app works perfectly fine and when I debug the I could see that the timeout value of 30000 is properly applied.
The trouble starts when I use this code NOT as a standalone spring boot app but as a dependency jar into another project.
At this time, the timeout is always 1000, which is the default. I managed to override this as well. But despite of that, i get HystrixRunTimeException, Timeout with null.
I have feign.hystrix.enabled=true.
If I use feign.hystrix.enabled=false, I can see that my request doesnt time out but then the Fallback mechanism fails to work.
But, when I add URL attribute in FeignClient it works fine and does NOT timeout.I cannot rely on the URL attribute as this is coming from the cloud foundry service URL which can change.
Add below properties in Application.yml file.
feign:
client:
config:
default:
connectTimeout: 80000000
readTimeout: 80000000

keycloak redirect_uri is not forming correctly when called from Spring boot application

we are using nginx(as proxy SSL enabled), Spring boot1.2.2 and keycloak
1.9.8.
we are deploying spring boot application as a jar and done necessary setup
for keycloak in application.properties. Without SSL everything works fine
but whenever we used SSL, spring boot application is not forwarding
proto(https) and port(8443) to keycloak so we always get invalid
redirect_uri exception.
I tried setting follwing configuration in application.properties
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
server.tomcat.protocol-header=x-forwarded-port
Please suggest what needs to be done.
Thanks & Regards,
Chandrashekhar
Issue is resolved. we have set proto and port pragmatically in embedded tomcat container through spring Initializer class.
#Override
public void customize(final ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
//final TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
tomcat.addConnectorCustomizers(connector -> {
connector.setScheme("https");
connector.setProxyPort(443);
//connector.setScheme("https");
//connector.setProxyPort(8443);
//connector.setScheme("http");
//connector.setProxyPort(8080);
});
LOGGER.info("Enabled secure scheme (https).");
} else {
LOGGER.warn("Could not change protocol scheme because Tomcat is not used as servlet container.");
}
}

Spring Cloud Feign/Ribbon with corporate proxy

I want to consume a REST service from the outside world behind a corporate proxy with authentication.
How do I configure Spring Boot + Spring Cloud Feign/Ribbon to use our proxy?
I believe you're looking for something like this:
import feign.Feign;
import okhttp3.OkHttpClient;
import java.net.InetSocketAddress;
import java.net.Proxy;
...
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy-url", 1234));
OkHttpClient okHttpClient = new OkHttpClient.Builder().proxy(proxy).build();
Feign.builder()
.client(new feign.okhttp.OkHttpClient(okHttpClient))
.target(...);
You just have to additionally add compile 'io.github.openfeign:feign-okhttp:9.5.0' to your project.
The target clause contains your defined Interface. Further reference: https://github.com/OpenFeign/feign
Turns out there is actually a much easier solution.
The following information will be helpful (also for more advanced use cases):
Spring Cloud Commons HTTP Factories
Overriding Feign Defaults
OpenFeign Client can run with several HTTP Clients.
By default it uses java.net.URLConnection, but you can also use ApacheHttpClient or OkHttpClient.
Using Apache Http Client
Here is what you can do to set a proxy using ApacheHttpClient:
Add the following two dependencies to your pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Dependency to switch HttpClient implementation from java.net.URLConnection to Apache HTTP Client -->
<!-- See also: FeignAutoConfiguration for details. -->
<!-- See also: https://cloud.spring.io/spring-cloud-commons/reference/html/#http-clients -->
<!-- See also: https://cloud.spring.io/spring-cloud-openfeign/reference/html/#spring-cloud-feign-overriding-defaults -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
In your app expose the following bean:
// see: https://cloud.spring.io/spring-cloud-commons/reference/html/#http-clients
#Bean
public HttpClientBuilder proxiedHttpClient() {
String proxyHost = "client-envoy";
Integer proxyPort = 80
String proxyScheme = "http";
return HttpClientBuilder.create()
.setProxy(new HttpHost(proxyHost, proxyPort, proxyScheme));
}
That's it - nothing else needs to be configured in application.yaml since ApacheHttpClient will be used by default, if it is on the classpath.
Using Ok Http Client
To set a proxy using OkHttpClient you do a similar thing:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
In your application.yml make sure to enable OkHttpClient and disable ApacheHttpClient:
spring:
cloud:
httpclientfactories:
ok:
enabled: true
apache:
enabled: false
feign:
okhttp:
enabled: true
httpclient:
enabled: false
Instead of HttpClientBuilder expose a bean of type OkHttpClient.Builder.
Spring cloud feign supports three underlying implementations:
Default
Apache HttpClient
OkHttpClient
If using Default:
Create this spring bean (say by defining inside class with #Configuration annotation), no changes required in application properties/yml:
#Bean
public Client feignClient() {
return new Client.Proxied(
null, null, new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
}
If using Apache HttpClient:
that means you have feign.httpclient.enabled: true in application.yml and below in your pom.xml or build.gradle:
pom.xml
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
build.gradle
implementation 'io.github.openfeign:feign-httpclient'
Create this spring bean (say by defining inside class with #Configuration annotation):
#Bean
public CloseableHttpClient feignClient() {
return HttpClientBuilder.create().setProxy(new HttpHost(proxyHost, proxyPort)).build();
}
If using OkHttpClient:
that means you have feign.okhttp.enabled: true in application.yml and below in your pom.xml or build.gradle:
pom.xml
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
build.gradle
implementation 'io.github.openfeign:feign-okhttp'
Create this spring bean (say by defining inside class with #Configuration annotation):
#Bean
public OkHttpClient feignClient() {
return new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)))
.build();
}

Resources