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.
Related
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.
I have a Spring boot application in which users can log in and their credentials would then be used to perform an AWS ADFS login.
A preconfigured role will be assumed and we'll get an access key, secret key, and session token in return. These will then be used to create the S3 client to perform file upload/download operations.
My issue is how can we perform the AWS ADFS login from the java spring boot code? Is there a library that supports it out of the box?
Also, I understand the session obtained this way is short-lived. Is there a way to refresh the session so that these tokens do not expire? Or should the whole AWS authentication, s3 client creation be done every time an upload/download request comes in?
I have a legacy desktop application that communicates with a Spring Boot server (latest version 2.2.2.RELEASE). I'm using OAuth2 for authentication (provided by spring-boot-starter-oauth2-client). I want to avoid changing the client because is a legacy application. It is capable of collecting the credentials and start the session via HTTP Basic Authentication, and then keep the cookies for the session in the following requests.
Given this scenario, I think best option is to make use the OAuth2 Resource Owner Password Credentials grant. With this, we can exchange the collected credentials by the OAuth2 Tokens. We have two options:
Option 1:
Modify the client application to use the access tokens via the Authorization header. This will require to make an initial call to the Authorization Provider to exchange the collected credentials by the tokens.
Option 2:
Keep using the Spring session and store the information about the OAuth client in the server.
I found this project ALMOST does that: https://github.com/jgrandja/spring-security-oauth-5-2-migrate. It has a client (messaging-client-password) defined with authorization-grant-type: password which will activate the OAuth2 Resource Owner Password Credentials grant in Spring Boot.
It creates an OAuth2 client and stores its information in the session, then Spring is able to use that client in further requests. The problem with this project is it seems to only work as when the OAuth client is used to make HTTP requests (e. g. an endpoint that makes a call to another service) and not provide authentication to the controller. You can find more information about this in here:
Spring Security 5.2 Password Flow
Github related issues: link1, link2, link3
Exception thrown when we try to use the password client as authentication
The natural idea to overcome this is to implement a proxy and use the OAuth2 client in the requests. Well, Spring already offers a proxy solution, the Spring Cloud Gateway. But I don't know to accomplish that with this setup.
Any insights? Am I thinking correctly or should I follow a different approach?
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.
I am working on a Spring boot application and have received a requirement where a certain endpoint must be accessible only by authorized users that too the user must be present physically at the system serving the app. An optional case is the user could also be able to access the endpoint if the user has SSH access to the server. This makes me think that some sort of key (a file or a program) can be used to unlock the endpoint. Not being a person proficient in security, this has put me at a loss on how to implement such a feature using Spring Boot. Any help is appreciated.
Spring boot doesn't have built in support for this scenario, but what you actually need is PAM (Linux Pluggable Authentication Modules) port for java (JPam can be a good solution).
You can write your own AuthenticationProvider for spring security which will do something like this in it's validation method:
Pam pam = new Pam();
boolean authenticated = pam.authenticateSuccessful(username, password));
This library is good enough documented (pdf)
Another PAM for java solution can be found here libpam4j