HashiCorp Vault dynamic secrets and Spring Boot - spring-boot

I am confused about the use case where HashiCorp Vault is used to provide database secrets dynamically for Spring Boot. Lets say you have two microservices: one containing the application logic and one running a database engine. The first obviously needs to authenticate towards the database and this is where dynamic secrets come into play. Vault can provide such credentials to the first microservice so you don't have to use e.g. ENV variables in a docker-compose file managing both microservices.
The App could be a Spring Boot microservice relying on Spring Cloud Vault to handle communication with HashiCorp Vault for credentials management. The microservice asks Vault for temporary db credentials (in this case they last for one hour) when it is started. During this one hour interval, the app can connect to the database and do whatever needs to be done. After one hour, the credentials expire and no communications is allowed.
The Spring Boot Cloud Vault documentation mentions
Spring Cloud Vault does not support getting new credentials and configuring your DataSource with them when the maximum lease time has been reached. That is, if max_ttl of the Database role in Vault is set to 24h that means that 24 hours after your application has started it can no longer authenticate with the database.
In other words, after one hour, the connection is lost and there seems to be no other way to get new db credentials other then by restarting the microservice.
So if have the following questions:
What is the added value of using Vault in this particular example if you are (seemingly) forced to restart your entire application each time the TTL expires?
Does the same apply when you use static secrets instead?
Can this issue be solved without changing microservice code? (K8S, Istio, etc.?)
My guess is the intended use of Vault with Spring Boot is different compared to my understanding.

This article describes 4 possible solutions to mitigate the issue described in the question. Being valid approaches to solve the problem, a more generic (referring to the 'heavy rotation of dynamic secrets'-approach) and less aggressive (referring to the 'restarting the service when connectivity is lost'-approaches) should be in place.

Related

Scaling Spring Authorization Server on GCP Cloud Run

We are experiencing an issue in production which seems identical to when we restart our dev boxes and try to authenticate using the token that was generated with the previous instance of our SSO Spring Boot App and powered by Spring Authorization Server.
The error is: Wrong nonce
In production, it looks to occur when our SSO app scales up due to a user spike. We could see this happening at a point with high user activity and we would continually get logged out.
Now, of course we do not want all our active users to suddenly have invalid tokens just because a new instances of SSO is added.
This questions also relates to the currently unanswered, but much older question here: Can Spring Security OAuth2 Authorization Server scale horizontally?
Please advise. It is the number 1 most frustrating issue we are having in production right now and we are not quite sure how to proceed. We are not using any In-Memory implementations of classes.
2022-07-12 - Update: The question was asked "How are we storing the session?"
We are storing OAuth2 authorizations, authorization consents and registered clients in MongoDb.
We implemented OAuth2AuthorizationService, OAuth2AuthorizationConsentService and RegisteredClientRepository
Spring Authorization Server is built on Spring Security (see docs Overview) and does require knowledge of Spring Security (see Getting Help).
In particular, you'll want to review the Authentication chapter of Spring Security documentation. Session management falls under this topic, and if you're using (for example) form login or something similar, you'll almost certainly want to add Spring Session to your server to manage distributed sessions.
You are also likely running into an issue on the client side if you are not managing sessions in a database, so once again looking into Spring Session for the client will help alleviate issues such as the nonce error you mentioned. You will also want to look into the OAuth2 Client documentation and review the core interfaces as you will need to be storing your client authorizations in a database as well.
Steve writes a great response above already and I marked it as the answer.
To answer the title of this question:
Yes, Spring Authorization Server can easily be scaled to include multiple instances without suffering from the original misconfiguration issue we were experiencing.
Spring Authorization Server does not have any magic tools to persist a session across instances. It is reliant on session management being configured correctly. We use Spring Session backed by MongoDb for our purpose.
Session validity best practices is probably something that should be addressed and whether some of them should have the same timeout values.
Servlet session timeout
Spring Session timeout (this overrides 1 when present)
Remember me timeout
Token timeout
We are still figuring out / playing with what these values should be and have found no document or article that speak of one best way of doing things.

Where to manage session in microservices architecture with Spring Boot

I am fairly new in microservices architecture. I've been trying to build a microservices stack using Spring Boot, Spring Cloud and Netflix OSS libraries.
I want to know what is the correct way and place to store session.
Here is an overview of the infrastructure that I created:
OAuth2 backed Authorization/Authentication Server
UI Service (Spring Boot, Front end service)
Backend Service-1
Backend Service-2
Redis Server to store session and other cachable data
Discovery Server (eureka)
Currently, I'm trying to store session in Redis by configuring UI service to perform it. It seems to be working fine, although I haven't had the chance to try it for multiple service instances. However, I'm already having serialization/deserialization issues while developing.
By the way, trying to store the session on front end app is the correct place to do or it should be done in Authorization/Authentication service as authentication is processed in that service?
Here is my Session config in UI service (front end service)
#Configuration
#EnableRedisHttpSession
public class SessionConfig extends
AbstractHttpSessionApplicationInitializer {
public SessionConfig() {
super(RedisConfig.class);
}
}
To sum up, I'm expecting to achieve and use best practices on this project. Your kind assistance would be appreciated.
The idea of a general server side user session and a microservices style architecture don't go together well. The reason being that you are likely to break the separation of concern that you use separate the domain boundaries of your services.
Remember, every service is supposed to service a specific domain problem autonomously - including all required data persistence. So for example if there is anything to remember for a users connected devices you would do that in the one service that is responsible for those device connections and nowhere else. The service would be responsible for processing those request and persisting any status that the devices require. Similarly when there is anything to remember about he users authorization you would do that in the authorization service.
And regarding the question to use Redis or not - In a microservices architecture the choice of storage system would be up to the service architect. Maybe one service stores its data in a relational database, maybe another uses a key-value-store and yet another may use an event queue system or a time series database.
So in summary you have to ask yourself what your session really is used for and make the corresponding services responsible to persist that information in a domain specific way. (If you give some more details in your question about this, I can give you my opinion).

Automatically renew AWS credentials in a Spring Boot application using Spring Cloud Vault

I'm trying to create a Spring Boot application that regularly fetch data from AWS S3.
The AWS S3 credentials are fetched from Vault using Spring Cloud Vault when the application start.
My issue is that AWS S3 credentials have a limited lifespan due to Vault policy so I have to restart my application from time to time to obtain new credentials from Vault
Is there a way to automatically restart bean using those credentials?
TL;DR
No, there is no automatism, but you can do this yourself.
The longer read
Spring Boot and Spring Cloud aren't really intended for applying continuous updates to the configuration without interruption. Spring Cloud Config ships with Refresh Scope support that allows to annotate beans with #RefreshScope and trigger a refresh of the beans that get re-initialized. This approach requires either integration with a message bus or triggering the refresh endpoint.
The other alternative, which is limited to AWS functionality, is providing an own AWSCredentialsProvider implementation that is backed by a Vault PropertySource that applies rotation to your credential. This requires you to provide a bit of code that integrates with VaultConfigurer or even directly via SecretLeaseContainer to get secret lifecycle event callbacks. See here for an integration example.
There is a ticket asking for the same question that contains background why this pattern isn't widely applicable.

how to protect secret from application log in spring cloud vault?

we am trying to use vault to keep database credentials and using token in by spring boot application to fetch secrets. Credentials are kept at secret back-end at vault. Connection with application and vault is secure to TLS. This kind of secret distribution is still vulnerable and depends on the developers maturity. Once application has the access to secrets it can be logged in the files. Unlike traditional JEE application, data source is looked up in resource jndi and application never now the database credential. resource setup was done by operations team and access to credentials were limited. Application never has the credential visibility.
Is my understanding correct, if that so how we can make secrets more secure in spring boot application or is this the trade off we have to compromise with.
Very Good Question.
As I think secrets can be logged in the files. As we are getting from vault.
We have to compromise on this. Its same as any secure information (eg. customer data) regarding application can also be logged in the files.
It should be taken care by developer and reviewer.

Spring Boot: When to call remote service?

I have serveral microservices communicating with each other.
For general configuration I use Spring Cloud Config which works well.
Some of the services need to access database resources of a legacy system. So they need to know where the database (databases in a multi-tenant environment) is located and which credentials to use.
Using Spring Cloud Config I see two possibilities:
application.properties: This would expose the db settings to all services. That´s no option.
my-crazy-service.properties: This would work fine but I would have to configure any service which needs db access. Doesn´t scale well.
So my idea is to implement another microservice which is responsible for any connection infomation. This service exposes a rest endpoint using spring-data-rest.
In case Service A wants to use the legacy db it can call the new service and ask for the required data.
Now I wonder when the best time is to request the connection info from the remote service.
On startup of each microservice? Where should such startup code be located?
In general where should initialization stuff be done?

Resources