can i use spring data elasticsearch to connect to elastic cloud? - spring-data-elasticsearch

#Bean
public RestHighLevelClient restClient() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("hostandport")
.usingSsl()
.withBasicAuth("username", "password")
.build();
return RestClients.create(clientConfiguration).rest();
}
can I use spring data elasticsearch to connect to elastic cloud and fetch the data?
Do I need any config else than restclient configuration, to fetch the data from Elastic cloud?

Why not? Add the cluster URL(s), the authentication either as basic auth or header (https://www.elastic.co/guide/en/cloud/current/ec_connect_a_client.html) and you should be fine.

Related

How to configure Spring OAuth2 in JHipster for stateless authentication against GitLab?

I have set up an OAuth2-based installation (spring-security-oauth2-core 5.2.4) of JHipster (3.9.0) against a gitlab repository. Mainly following https://www.jhipster.tech/security/#oauth2 but using gitlab instead of keycloak.
This is an excerpt from the application.yml:
spring: ...
security:
oauth2:
client:
provider:
oidc:
issuer-uri: https://gitlab.mysite.com
registration:
oidc:
client-id: 1234123412322312312312312312321312321312
client-secret: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Indeed the oauth2-authentication works well, until the session internally expires. When the client then returns the jsession-Id cookie, the underlying undertow-infrastructure throws a java.lang.IllegalStateException: UT000010: Session is invalid.
It seems that org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository.saveAuthorizationRequest stores the authorizationRequest in the user session not caring about session management configuration: (see last line below)
#Override
public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request,
HttpServletResponse response) {
Assert.notNull(request, "request cannot be null");
Assert.notNull(response, "response cannot be null");
if (authorizationRequest == null) {
this.removeAuthorizationRequest(request, response);
return;
}
String state = authorizationRequest.getState();
Assert.hasText(state, "authorizationRequest.state cannot be empty");
Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(request);
authorizationRequests.put(state, authorizationRequest);
request.getSession().setAttribute(this.sessionAttributeName, authorizationRequests);
}
This approach seems to contradict the stateless JWT-based authentication approach of JHipster (see e.g. https://github.com/jhipster/generator-jhipster/issues/8627).
Anyway the spring2 OAuth2 management seems to counterfeit classical load balancing approaches.
Is there a way to configure OAuth2 management in spring to work stateless with GitLab?

Spring Authorization Server and Spring Resource Server in one server

Has anyone tried using both the newly release Spring Authorization Server 0.1.0 and the regular Spring Resource Server in 1 project and in 1 server such as:
The resource server is at http://localhost:8080 and the authorization server is also at http://localhost:8080? Any ideas on how to do it?
The problem is that at start up, the resource server checks the authorization server's /.well-known/openid-configuration which is obviously not yet avaialble.
Instead of issuer-uri, you can instead specify the jwk-set-uri, which isn't pinged at startup.
Or, since the authorization server and resource server will use the memory space for keys, you might construct your own Nimbus JWTProcessor instead so that you skip the internal HTTP request:
#Bean
JwtDecoder jwtDecoder() {
JWKSource<SecurityContext> source = // ... some internal store for the public keys, e.g. not RemoteJWKSet
ConfigurableJWTProcessor<SecurityContext> processor = new DefaultJWTProcessor<>();
JWSKeySelector<SecurityContext> selector = new JWSVerificationKeySelector(
JWSAlgorithm.RS256, source);
processor.setJWSKeySelector(selector);
NimbusJwtDecoder decoder = new NimbusJwtDecoder(processor);
decoder.setJwtValidator(... add any validation rules ...);
return decoder;
}
I believe you can just set your jwtDecoder as follows:
#Bean
JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
As you probably already have that defined as a Bean elsewhere when setting up your auth server
#Bean
public JWKSource<SecurityContext> jwkSource() {
// implementation ...
}

webflux security multi roles in same match

I use spring security in spring cloud gateway. cloud version is Finchely.SR2 and spring boot version is 2.0.x
Then i set two role in one matcher like this:
.pathMatchers("/apis/**").hasRole("TEST1")
.pathMatchers("/apis/**").hasRole("TEST2")
but, when i startup application and do test, just TEST1 role can access. TEST2 role get FORBIDDEN 403 response.
I know in spring-boot-starter-web with spring-security, it has any method like
.antMatchers("/apis/**").hasAnyRole("TEST1", "TEST2")
Does webflux spring security has any API like hasAnyRole(String...roles) to use?
There isn't one available in the base APIs from Spring Security, however I've been using the following for anyAuthority,
public class HasAnyAuthority<T> implements ReactiveAuthorizationManager<T> {
private final Collection<String> allowedAuthorities;
public HasAnyAuthority(Collection<String> allowedAuthorities) {
this.allowedAuthorities = allowedAuthorities;
}
#Override
public Mono<AuthorizationDecision> check(final Mono<Authentication> authentication,
T object) {
return authentication.filter(Authentication::isAuthenticated)
.flatMapIterable(Authentication::getAuthorities)
.map(GrantedAuthority::getAuthority).any(allowedAuthorities::contains)
.map(AuthorizationDecision::new)
.defaultIfEmpty(new AuthorizationDecision(false));
}
with usage like,
.access(new HasAnyAuthority<>(allowedAuth.getAuthorities())
hasAnyRole and hasAnyAuthority will be available in WebFlux in Spring Security 5.2.0.
You can try them out now in 5.2.0.M3.
The syntax is the same
.pathMatchers("/apis/**").hasAnyRole("TEST1", "TEST2")
If it helps anyone
.pathMatchers("/apis/**")
.access((mono, context) -> mono.map(auth -> auth.getAuthorities().stream()
.filter(e -> (e.getAuthority().contains(TEST1) || e.getAuthority().contains(TEST2)))
.count() > 0)
.map(AuthorizationDecision::new))

Zuul reverse proxy with Keycloak server

I'm configuring a Spring Cloud (Angel.SR6) application using the Zuul reverse proxy utility, in order to hide the internal service ports. My zuul (edge) service is published in the 8765 port and my organizations service is in the 8083 one. Everything goes smoothly when I access the application with no security, http://localhost:8765/organization/organizations returns the JSON with all the organizations.
However, now I want to integrate a Keycloak SSO (OAuth2) server for authorization purposes. I have added the Spring Security adapter in my organization service and configured it to authenticate in http://localhost:8080/auth. Everything goes well, except that zuul performs a redirection instead of proxying. So when authentication is successful, I get redirected to http://localhost:8083/organizations instead of http://localhost:8765/organization/organizations. Here there are my browser requests:
That's because the keycloak adapter creates a token verification endpoint in the http://localhost:8083/sso/login, from which it performs a redirection to the authorization server in order to validate the token. When authorization server acknowledges it, a redirection is sent to the organization service, with the /organization path, so the end url being loaded is http://localhost:8083/organizations. But I would like the first requested url to be loaded instead.
Which choice do I have?
Recently I've had the same problem. I've solved it by:
Add to application.properties in Zuul
zuul.sensitive-headers=Cookie,Set-Cookie
Introduce KeycloakFilterRoute in Zuul
class KeycloakFilterRoute extends ZuulFilter {
private static final String AUTHORIZATION_HEADER = "authorization";
#Override
public String filterType() {
return "route";
}
#Override
public int filterOrder() {
return 0;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.getRequest().getHeader(AUTHORIZATION_HEADER) == null) {
addKeycloakTokenToHeader(ctx);
}
return null;
}
private void addKeycloakTokenToHeader(RequestContext ctx) {
RefreshableKeycloakSecurityContext securityContext = getRefreshableKeycloakSecurityContext(ctx);
if (securityContext != null) {
ctx.addZuulRequestHeader(AUTHORIZATION_HEADER, buildBearerToken(securityContext));
}
}
private RefreshableKeycloakSecurityContext getRefreshableKeycloakSecurityContext(RequestContext ctx) {
if (ctx.getRequest().getUserPrincipal() instanceof KeycloakAuthenticationToken) {
KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) ctx.getRequest().getUserPrincipal();
return (RefreshableKeycloakSecurityContext) token.getCredentials();
}
return null;
}
private String buildBearerToken(RefreshableKeycloakSecurityContext securityContext) {
return "Bearer " + securityContext.getTokenString();
}
}
(Migrated from comment to answer)
I ended up making a Github project in order to explain my problem to the keycloak team, and got a pull request from one of the development team members trying to help me out. Following their recommendations, I came into the conclusion that zuul is good to hide stateless services (bearer only ones), but not the ones that user directly interacts with. Here it is the whole thread in the mailing list.

Access Neo4j in server mode with EmbeddedGraphDatabase?

If I run neo4j in server mode so it is accessible using the REST API, can I access the same neo4j instance with EmbeddedGraphDatabase-class?
I am thinking of a production setup where a Java-app using EmbeddedGraphDatabase is driving the logic, but other clients might navigate the data with REST in readonly mode.
What you are describing is a server plugin or extension. That way you expose your database via the REST API but at the same time you can access the embedded graph db hihgly performant from your custom plugin/extension code.
In your custom code you can get a GraphDatabaseService injected on which you operate.
You deploy your custom extensions as jars with your neo4j-server and have client code operate over a domain oriented restful API with it.
// extension sample
#Path( "/helloworld" )
public class HelloWorldResource {
private final GraphDatabaseService database;
public HelloWorldResource( #Context GraphDatabaseService database) {
this.database = database;
}
#GET
#Produces( MediaType.TEXT_PLAIN )
#Path( "/{nodeId}" )
public Response hello( #PathParam( "nodeId" ) long nodeId ) {
// Do stuff with the database
return Response.status( Status.OK ).entity(
( "Hello World, nodeId=" + nodeId).getBytes() ).build();
}
}
Docs for writing plugins and extensions.

Resources