Spring boot security - Actuator - spring

I am trying to configure my application to always expose actuator end points and if config is set to say security is required then apply it to my end points for websocket connectivity
As it stands i was under the impression that ant matchers matched in order - meaning that
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/health", "/actuator", "actuator/health").permitAll();
if (authenticationRequired) {
http.authorizeRequests().antMatchers("/**").authenticated().and().httpBasic();
}
}
the above code should permit the actuator end points ALWAYS
It seems as though however this is not the case. Please can someone help describe what is wrong with my approach here.
/health and /actuator to me should be governed by permitAll()

I Fixed this using the following matchers
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/health", "/actuator/**").permitAll();
if (authenticationRequired) {
http.authorizeRequests().antMatchers("/**").authenticated().and().httpBasic();
}
}
I was missing a leading /

Related

Spring boot security block non RestController endpoints

I have an app that is exposing a bunch of endpoints that I did not expect. For example localhost:8080/app/ returns a list of URL that among other things exposes information related to the hibernate entities.
I DO NOT want basic auth enabled as I have my own authentication configured.
But if the URL is not one that is represented by a RestController I have written then I want it to an existing forbidden page that I have.
Here is my current config but it does not prevent the unwanted endpoints:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**").antMatchers("/v2/**").antMatchers("/webjars/**").antMatchers("/swagger-resources/**")
.antMatchers("/swagger-ui.html");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider()).authorizeRequests().anyRequest().authenticated()
.antMatchers("/v2/**").permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll();
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
So in this case localhost:8080/app/api/SearchControler/{var} should work but localhost:8080/app/ should go to my Forbidden entry point. Instead localhost:8080/app/ is going to the spring username and password page.
First off I don't know why these endpoints are even showing up when there is no RestController for them and second why is redirecting to a 403 page so difficult.
I'm not sure what config I am missing.
* EDIT *
I have also tried:
http.formLogin().and().httpBasic().disabled();
as well as:
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
and nothing seems to stop spring from taking over and doing whatever it feels like doing.
Try again after removing super.configure(http); in your configure(HttpSecurity http) method.
Documentation
Override this method to configure the {#link HttpSecurity}. Typically
subclasses * should not invoke this method by calling super as it
may override their * configuration. The default configuration is:
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
I think there is more configuration which you didn't show to as, but anyway:
#Override
public void configure(WebSecurity web) throws Exception {
//this is only for ignoring static resources in your app, sth that is never changed (you can cash it) and public (available for any user on the internet (ex. /js /css - sth else static img etc)
web.ignoring().antMatchers("/webjars/**").antMatchers("/swagger-resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http); this call the default configuration, if you implement this method you shouldn't call the default one
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider())
.authorizeRequests() // the order is matter here, if antMatchers() will match the request the others after him will not be checked, anyRequest() will match any request, so it should be at the end
//.permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll() - there is no need to duplicate what is in web.ignoring() - such requests will not reach this point
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll()
.anyRequest().authenticated()
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
This issue is completely related to transitive dependencies. After removing some dependencies and adding excludes to others the core problem has been solved.

Spring Security Java Configuration: How to combine requirements via logical or?

I have a webapplication based on spring boot that should be secured via http basic auth except the request is send from a specific IP address.
I am able to set-up both configurations for themselves but not combined via or.
IP Filter
private String allowedIp = "123.456.789.123/32";
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.anyRequest().hasIpAddress(allowedIp);
or
HTTP Basic Auth
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.anyRequest().authenticated().and().httpBasic().authenticationEntryPoint(cncAuthEntryPoint);
}
How can I combine these two configurations?
I am using
Spring 5.0.4,
Spring Boot 2.0.0, and
Spring Security 5.0.3.
Do you need any addtional information?

How to disable spring security for certain resource paths

I am implementing spring security in a spring boot application to perform JWT validation where I have a filter and an AuthenticationManager and an AuthenticationProvider. What I want to do is that I want to disable security for certain resource paths (make them unsecure basically).
What I have tried in my securityConfig class (that extends from WebSecuirtyConfigurerAdapater) is below:
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(),
UsernamePasswordAuthenticationFilter.class);
httpSecurity.authorizeRequests().antMatchers("/**").permitAll();
httpSecurity.csrf().disable();
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
What I am trying to do right now is that I want to make all my resource paths to be un-secure,
but the above code doesn't work and my authenticate method in my CustomAuthenticationProvider (that extends from AuthenticationProvider) get executed every time
Authentication piece gets executed irrespective of using permitAll on every request. I have tried anyRequest too in place of antMatchers:
httpSecurity.authorizeRequests().anyRequest().permitAll();
Any help would be appreciated.
Override the following method in your class which extends WebSecuirtyConfigurerAdapater:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/unsecurePage");
}
try updating your code in order to allow requests for specific paths as below
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(),
UsernamePasswordAuthenticationFilter.class);
httpSecurity.authorizeRequests().antMatchers("/").permitAll().and()
.authorizeRequests().antMatchers("/exemptedPaths/").permitAll();
httpSecurity.csrf().disable();
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

Allowing a client application to configure http security from an already wired WebSecurityConfigurerAdapter

I am using spring-boot and spring-security.
I have a generic WebSecurityConfigurerAdapter setup for a number of different projects. The problem is that I want custom Controller security for each project, everything else remains the same. The most obvious solution was to make it Abstract and force each project to extend it but I suspect there is a better way through events or something.
Here is the configure method of WebSecurityConfigurerAdapter
#Override
protected void configure(final HttpSecurity http) throws Exception {
...
http.authorizeRequests()
.antMatchers("/health*").permitAll()
.antMatchers("/endpoints/**").permitAll()
.antMatchers("/rest/open/**").permitAll()
.antMatchers("/login/impersonate*").hasAnyRole("ADMIN", "ADMINISTRATOR")
// AT THIS POINT I WOULD LIKE EACH PROJECT TO OPTIONALLY CONFIGURE http AS THEY WISH
http.authorizeRequests().antMatchers("/**").authenticated();
...
}
Is there a cool way to do this in spring though a bean configuration or something?
#Bean //something like this perhaps????
public void configureSecurity(final HttpSecurity http) {
http.authorizeRequests()
.antMatchers("/rest/admin*").hasAnyRole("ADMIN", "ADMINISTRATOR")
}
you can use multiple WebSecurityConfigurerAdapter classes, juste make sure each of them are in packages scanned by Springboot autoconfiguration.
if a client project want to override existing security constraints, add the #Order annotation:
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
public class ClientSecurityConfig extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) {
http.antMatcher("/rest/admin*").authorizeRequests().anyRequest().hasAnyRole("ADMIN", "ADMINISTRATOR");
}
}
Pay attention to the antMatcher() that is before the authorizeRequests(), this is done to limit the scope of the client config. without that, it will erase all of the default config (every URL except /rest/admin* will return 403 Unauthorized).

#EnableOAuth2Sso - How to protect / unprotect resources?

I’m trying to use the #EnableOAuth2Sso feature in Spring Cloud Security. Specifically, I’m attempting to protect some resources with OAuth2 while leaving others publicly accessible. I've managed to get this working, but I'm looking at the resulting code and wondering if there is a cleaner way.
I’m following the documentation here: https://github.com/spring-cloud/spring-cloud-security/blob/master/src/main/asciidoc/spring-cloud-security.adoc AND similar guidance from the Spring Boot reference. I have a tiny code example that illustrates my dilemma: https://github.com/kennyk65/oAuthSsoExample.
In a nutshell, I want the localhost:8080/unprotected resource to be publicly available, and I want the localhost:8080/protected resource to require OAuth2 (via github, as configured). I’m able to get the basic OAuth2 behavior to work just fine, but causing /unprotected to be publicly available is problematic.
First, The docs indicate that you can just use the OAuth2SsoConfigurer’s match() method to specify the resources to protect. I've found this doesn't work; when I try I get an IllegalStateException saying that at least one mapping is required. This appears to be referring to the unimplemented configure(HttpSecurity) method.
Next, I’ve tried to specify a mapping in configure(HttpSecurity) that states that the ‘unprotected’ resources should be unprotected. However, this results in Http basic security being applied to that resource. Curiously, this results in the ‘protected’ resource being completely public!
// This results in “unprotected” being protected by HTTP Basic
// and “protected” being completely open!
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/unprotected/**").permitAll();
}
}
On a whim I tried deliberately adding that the protected resource should be authenticated. This resulted in the protected resource getting OAuth2 protection (hurrah!) but the unprotected resource got http basic security applied (huh?).
// This results in “protected” being protected by OAuth 2
// and “unprotected” being protected by HTTP Basic, even though we say permitAll():
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/protected/**”).authenticated();
.antMatchers("/unprotected/**").permitAll();
}
}
At wit’s end to try to find the magic combination, I tried simply switching HTTP basic authentication off using security.basic.enabled: false. This worked (hurrah!), though I’m still a bit puzzled what the issue is with the mappings.
So I guess my question is, is this correct? What is the best way to protect some resources with OAuth 2 and leave others alone?
If you match on /protected/** then it makes no sense to then add an access rule to /unprotected/** (the path doesn't match so the rule will never be applied). You either need another filter chain for your "unprotected" resources, or a wider match for the SSO one. In the former case, the default one that you get from Spring Security will do if you don't mind switching off the security it is providing. E.g.
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**”).authenticated();
}
}
and set security.basic.enabled=false.

Resources