Force HTTPS in Spring Boot - spring

It seems that setting server.ssl.enabled in an Spring Boot application forces all requests to use HTTPS. Also, from the documentation and other articles (like here), it seems that requiresSecure() is for forcing HTTPS. What's their relation and when should each one be used?
p.s. When I use server.ssl.enabled=true, it seems that HTTPS is enforced on all pages regardless of the fact that I have set requiresInsecure(). And, when server.ssl.enabled is not set, setting requiresSecure() didn't seem to have any effect.

From the documentation [1], default value of server.ssl.enabled is true. So when server.ssl.enabled is not set, it is still taken as true. requiresSecure is used to make sure, only https get used (there by avoiding http request).
The main usage of server.ssl.enabled is to use in combination with server.ssl.key-store/key-store-apssworrd to enable ssl for embedded Tomcat.

Related

deprecated property: connection-timeout: 12000

I have this property into Spring Boot application:
server:
connection-timeout: 12000
I get warning:
Deprecated Each server behaves differently. Use server specific properties instead.
Gradle: org.springframework.boot:spring-boot-autoconfigure:2.6.8 (spring-boot-autoconfigure-2.6.8.jar)
is there some better configuration property that I can use?
I don't even know why you receive a deprecated warning.
According to the documentation from Spring Boot version 2.3 and onwards this property is removed not deprecated any more.
As you can read here, there are some other properties which you can use instead depending on the server that runs your spring boot application.
server.tomcat.connection-timeout should be used if you have tomcat as running server.
server.netty.connection-timeout should be used if netty is used.
server.jetty.connection-idle-timeout should be used if jetty is used
Basically each server has it's own implementation, so you must read your server's documentation to see what it allows and how this behaves. There might be slight differences from how one server behaves and how it interprets connection-timeout and how another server behave and interprets a similar configuration.
This is I think the reason that Spring decides to move to server specific configuration on property connection-timeout instead of a general property and also a very important reason was that some servers may not even have this configuration available to them. So then you have a general property configured in your spring boot application which the server that runs the application can't even respect.
Therefore you now have specific properties for specific servers and now you can be sure upfront whether this configuration is available in your server and you can also read the server documentation to understand exactly what the behavior will be.
Although this setting is being deprecated, we still can use the timeout function.
According to official document, we can use #Transactional(timeout = 1) to do the track in the controller
https://www.baeldung.com/spring-rest-timeout

Log4j Vulnerability (CVE-2021-44228) on Google Cloud Platform and PCF

Currently there are so many suggested steps that have been posted for excluding log4j-core library from dependency or upgrading to the latest (above version 2.15) version according to Spring Blog . Are there any recommended tools that can be used for protecting spring application deployed in Google App Engine or Pivotal Cloud Foundry(PCF) for protecting instead of patching them for redeployment?
Another necessary question is, does it make my application(microservice spring application) to be vulnerable if it uses another microservice for some of its service if it depends on another microservice and if that microservice already uses vulnerable version of log4j-core?
In regard to your first question, you can set an environment variable in order to disable the replacement lookups in log4j:
LOG4J_FORMAT_MSG_NO_LOOKUPS=true
Please note that this only works for log4j >= 2.10.
I believe you can set environment variables in PCF without having to redeploy the service (of course, a restart would be needed), so no new release would be needed. See: https://docs.pivotal.io/pivotalcf/2-3/devguide/deploy-apps/environment-variable.html and https://cli.cloudfoundry.org/en-US/v6/set-env.html
In order to see whether your spring-boot application is vulnerable to the exploit, you could use a spring-boot test I created for that purpose: https://github.com/chilit-nl/log4shell-example - You could test your application with and without the environment variable, to see if it has any effect (assuming that your application currently is vulnerable).
Short answer to your first question is may be. You can protect your application/service by using rules in WAF to discard the ${jndi://ldap pattern. However, there are so many mutations of this (base64 encoding etc.) that it will not be foolproof. If you are worried about dependencies, you should set the JVM Parameter and redeploy your app to prevent the lookup as a workaround.
Regarding your 2nd question - the answer is yes if the the 2nd micro service is being passed the same input and it's logging.

How to programatically set management server port for Spring Boot Actuator

Is there a simple way to set management.server.port programmatically, based on the management.server value? I would like to set
management.server.port=${server.port + 2}
What I was thinking is creating http connector manually for actuator but it is a lot of afford.
You can tune the environment on startup using an EnvironmentPostProcessor. This will work as long as you don't see server.port to 0. When you do that, the underlying connector is responsible to allocate a random, free port and that will happen after the environment has been prepared.
The idea behind the implementation is to read the value of server.port, apply whatever logic you need and set a management.server.port property.
There is more explanation and a sample in the Spring Boot Reference Guide.

How to require SSL in some environments using Spring Boot 2.0.0.M4+

While upgrading my Spring Boot applications through the 2.0.0 milestone releases, I've noticed that starting in 2.0.0.M4 security.require-ssl and other security configuration options are gone. I didn't find any mention of deprecations or a new approach in the current docs so I dug around and found the GitHub issue where the work originated. I applaud the goal in the GitHub issue to:
significantly simplify security configuration in 2.0.
and am happy change my patterns to upgrade, but I'm a little stuck on how to require SSL in specific environments. I know I can accomplish a similar outcome in my WebSecurityConfigurerAdapter configuration using http.requiresChannel().anyRequest().requiresSecure() but I don't want to enable this setting in every environment I run my applications in (e.g. pre-production environments without a certificate, local development on localhost). I know I could put some conditional logic in my WebSecurityConfigurerAdapter configuration but I like to keep my Spring configurations "environment agnostic" and keep my environment specific configurations in properties files specific to a profile.
After these recent simplifying changes to Spring Boot's security configuration, what's a recommended approach to require SSL in some environments?
There are a few options depending on your setup.
Changing the RequestMatcher
If the only time you require HTTPS is in an environment with a custom header injected by a Proxy (i.e. X-Forwarded-* headers), you can do something like this:
http
.requiresChannel()
.requestMatchers( r -> r.getHeader("X-Forwarded-Proto") != null).requiresSecure()
.and()
// ...
The nice thing about this approach is that you do not need to do anything to turn HTTPS on or off. The downside is that there is a very minimal performance hit of comparing the headers. This performance hit should be negligible, but may not be aesthetically pleasing to some.
Conditional Configuration
Since this is Java Code you can always have a boolean flag that determines if you require HTTPS or not. For example, create a member variable and resolve it to Externalized Configuration with something like this:
#Value("${security.require_ssl}")
private boolean requireHttps;
Then use something like this:
if(this.requireHttps) {
http
.requiresChannel()
.anyRequest().requiresSecure();
}
http
// ...
This approach aligns nicely with Spring Boot 1.x approach and it does not suffer from the additional if statement in each request. However, it requires a property to be managed.
Profiles
As mentioned by Madhura you can also use #Profile. I find this approach is better suited if you have lots of differences between environments and not as ideal for something minor like determining if HTTPS is required. The problem with this approach when making a small change is you run into a lot of duplication.
You're absolutely right about adding your own WebSecurityConfigurerAdapter for customizing security configuration. To keep that configuration environment agnostic, you can add an #Profile so that it can be switched on and off depending on the active profile. If it is only the ssl configuration that is environment agnostic, and the rest of the security configuration is the same for all environments, you can add a WebSecurityConfigurerAdapter that only configures http.requiresChannel().anyRequest().requiresSecure() that has the #Profile on it and order it such that it is the first one that kicks in.

Externalizing logging in Spring Boot apps

I'm trying to externalize logging configuration. However, any configuration I establish (e.g. -Dlogback.configurationFile=...) is wiped out the moment I call SpringApplication.run(). Is there a way to prevent this?
Try 'logging.config' (or use one of the the conventional locations, e.g. 'classpath:/logback.xml'). Docs here: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-custom-log-configuration.

Resources