Hello Spring Cloud Team,
I have read the security vulnerability guideline. But I am not sure if this is more of a bug, a feature an issue.
But I believe with the current design, one app can get secrets of another app by pretending to be the other app simply by changing its app name.
For instance.
I have two micro services.
MicroserviceA is PetService. MicroServiceB is CustomerService.
They both register themselves to a Spring Cloud Config Server. Both PetService and CustomerService has the right to use this Spring Cloud Config Server instance, in order to get their own respective secrets.
Spring Cloud Config Server has a Vault back end. Vault is great. So, under the path, route secret/petservice, all the secrets from PetService are there. Likewise, under the path secret/customerservice, all the secrets from CustomerService are there.
When the app starts, everything is fine, PetService gets its own secrets, same for CustomerService.
The thing is, if CustomerService know that there is a PetService, and in its properties, simply change CustomerService spring.application.name=petservice, I believe this can be a potential risk.
To put a more concert example, Another team of my org has their own database, doing their own sensitive business. Their database password is saved inside Vault, and they thought only their app could access it.
I just knew their app name, changed my app name to their app name. On my application startup, we both connect to our same company Spring Cloud Config Server.
I was able to get their app database password in my app.
Comment From: spencergibb
Security vulnerabilities should not be reported here, but via https://spring.io/security-policy
I don't think that this is one. You should secure your config server instance with Spring Security and not allow applications to request other applications configuration. This is built in to our commercial offering
Comment From: patpatpat123
Understood @spencergibb , and please feel free to close.
And we are already using Spring Security, with the client certificate Subject parsing as well as auth token.
I am not talking about a RogueService, that was not supposed to access the Config Server in the first place. Let's say PetService, CustomerService and RogueService are in play. Agree, Config server can be configured to accept only PetService and CustomerService, and reject RogueService.
But due to the nature of the current design, which is to append the application name at the end of the Vault path by default, an app that is properly authenticated to Config Server, can by changing the app name, get the Vault secrets of another app.
Comment From: spencergibb
Globally authenticated is different than securing certain url paths
Comment From: patpatpat123
Understood. But just to emphasize, this means Spring Cloud Config Server, should be made sure to be used with Spring Security, and on Spring Cloud Config server side, to have the proper Spring Security rules.
For instance, in my example, Spring Cloud Config Server + Spring Security should take the role of making sure PetService can access https://the-spring-cloud-config-server.com/secret/petservice, but reject CustomerService to access https://the-spring-cloud-config-server.com/secret/petservice (yet still allowing CustomerService to access his own https://the-spring-cloud-config-server.com/secret/customerservice) even if CustomerService changes its application name.
Comment From: avnerstr
patpatpat123 -Do you have a workaround for this issue? I suffer from the same problem.
Comment From: ryanjbaxter
@avnerstr Basically what we are suggesting is that you use spring security to secure the rest apis of the config server so that an app only has access to the api for itself and not any other paths
Comment From: patpatpat123
Ryan @ryanjbaxter is correct @avnerstr .
Our goal is similar to yours I believe. We have a Spring Cloud Config Server instance, with Vault back end. The Vault back end protects all our very sensitive secrets. Vault is quite good at that.
Most of all, we would like our Spring Cloud Config Clients apps to connect to Spring Cloud Config Server (and by definition to Vault) in order to retrieve all secrets.
With this architecture, all config clients will be free, of storing any secrets, at any time, only Spring Cloud Config Server (via Vault) has them. We believed this architecture was quite nice.
Unfortunately, this approach was not secure at all. We quickly discovered via the rest API path, is actually crafted with the combination of the service name. Quickly, other services who knew our Spring Cloud Config Server instance URL, as well as the service name of the good service inside Vault, could read the services secrets.
As suggested by @spencergibb, we combined it with Spring Security, which works. We tried protecting the rest API path (the one with the service name) with username password, with a token mechanism, with a x509 certificate mechanism.
All our attempts ended up indeed securing the secrets. For example, rogue-service even knowing the URL of Config Server and knowing inside Vault has a good-service folder, cannot just query Config server pretending to be good-service, since it will not have the correct username password, the correct token or the correct certificate.
But this presents again a drawback. Meaning Spring Cloud Config Clients do need to store at least one secret, the secret to "get the rest of the secrets" (connect to Spring Cloud Config Server securely).
https://github.com/spring-cloud/spring-cloud-config/issues/1867#issuecomment-854087271
In which case, for our usage, defeated the purpose of Spring Cloud Config Server in the first place, since now, we need to find a way to truly secure at least one secret for all clients (in which case, we could just drop Vault and Spring Cloud Config Server at all and use same mechanism to secure everything else).
This is just a humble comment. I really think Spring Cloud Config is one of the best Spring Cloud project, just an observation we ended up with.
But again, Spencer and Ryan's suggestion, to use Spring Security to secure the Vault path is correct.
Comment From: avnerstr
Hi @patpatpat123
Thank you for your detailed answer. I'm trying to understand how you configure it in the spring cloud config server.
Do you have different username/passwword for every application? or one username/password for all the applications.
If you have one username/password for all the applications, you still didn't solve the problem of getting other applications secrets. In such case, the application itself can still get the information of the other apps because it's one user/password for all applications.
If you have different username/password for each application, It means that for each {application} path in the Spring Cloud Config server you have different basic authentication. I'm not familiar enough with Spring Security. Can you provide an example how you did it in the Client side and Server side of the Spring cloud config?
Another question, In case you do have different username/password for every application, Does it mean that every time a new application/microservice is added, I need to add code to the Spring cloud config server, so it will have it's own basic auth
thanks, Avner
Comment From: avnerstr
@avnerstr Basically what we are suggesting is that you use spring security to secure the rest apis of the config server so that an app only has access to the api for itself and not any other paths
Hi @ryanjbaxter, As I wrote to @patpatpat123 Is there a way by using spring security to give different basic authentication : usernanme/password for every application? Using one username/password to all apps - what I see in many examples doesn't solve the issue.
And if the answer is yes, do you have an example how it can be done? and what will happen if I will add a new application, do I need to update the code of the Spring Cloud Config server every time?
Comment From: ryanjbaxter
That's a spring security question so it's best to pose the question to them. Unfortunately that is not my area of expertise
Comment From: avnerstr
That's a spring security question so it's best to pose the question to them. Unfortunately that is not my area of expertise
I don't think it's a Spring Security question. I think without the support of spring cloud config this can't work. for example. In the spring security I can protect specific path but Spring cloud config server for example has path like : localhost:8888/{application} or localhost:8888/{application}-{profile}/
It means that if I want to use spring security with different username/password for every application, I will have to change the code of the spring security in the spring cloud config server whenever I add new application
for example:
one security for path /app-1 second for /app-2 third for /app-3 and so on
it doesn't make sense and it's impossible to maintain. think of microservice environment that I might have 60-70 different MS.
Unless you have another idea
Comment From: ryanjbaxter
I agree that pattern would not be maintainable, but maybe there is another way to do this with Spring Security, I am not sure, that is why I a saying it is a question for Spring Security. This is not a problem that would be specific to Spring Cloud Config any application could have this same use case.
Comment From: spencergibb
This is something that we have built for the commercial offering of config server. Using something like oauth2 to verify what app is making a request and then verifying the app configuration that is being requested is relatively straightforward but is very custom to each environment. I'll let @csterwa comment on the possible availability of this in open source in the future.
Comment From: avnerstr
@spencergibb thank you for the answer. In the meantime, do you have a suggestion what I can do with in order to support our Info-sec requirement that each application can only ask her configuration? beside using the commercial offering? I think even basic auth for each app will be enough.
Comment From: spencergibb
I can only echo Ryan:
it is a question for Spring Security. This is not a problem that would be specific to Spring Cloud Config any application could have this same use case.
I can't suggest how you do authentication because I have no knowledge of your environment. We have built-in support for username/password and also a token header. Anything else (oauth2, etc...) you will need a custom RestTemplate for config client.
Once you've authenticated its a matter of matching the principal with the path see https://docs.spring.io/spring-security/site/docs/current/reference/html5/#el-access-web-path-variables
Comment From: spencergibb
A guide for this would probably be extremely useful for folks https://github.com/spring-cloud/spring-cloud-config/issues/1902
Comment From: dyroberts
@patpatpat123 @avnerstr The config-client apps are passing a vault token with every request to config-server. I believe you could provide the client apps with their own tokens that only grant them access to their own secrets. Or maybe I'm missing something there.
Comment From: avnerstr
@dyroberts Although I'm having the same use case I'm not using Vault but AWS CodeCommit (managed git by AWS). I'm not familiar with the s solution you mention. I'm not sure it's written in the manual. All I found regarding security from the client side is example of basic authentication. https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_security_2
Anyway, do you think your solution can work for Git or AWS CodeCommit? I will be happy to understand how it can be done.
One more important thing, A solution that requires that every time I'm adding a new app I will have to modify the code of the Spring cloud config server is cumbersome and un-maintainable.
there should be a solution that is similar to the existing solution for multiple repositories in the server side: https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_placeholders_in_git_uri I don't have to change the server side code every time I have a new application. so as you said - if the Cloud Config server side will validate the username/password of the client against GIT and will allow it to access only the repos that Git allows I think it can work, but I don't think this is the way it works today. From the doc I found, the server side has the access to the different repos in git and the client are authenticated against the cloud config server. Are you familiar with another model?
Comment From: avnerstr
@spencergibb the username/password solution you have in the manual shows one username/password for all apps If I want to have different username/passwords for different apps it requires to create a new spring-security path authentication in the server side
for example: one configuration for app1 with path /app1/ username/password: user1/password1 second configuration for app2 with path /app2/ username/password: user2/password2 and so on...
this is very cumbersome and unmaintainable
Do you have a better idea?
Comment From: dyroberts
@avnerstr I don't believe the git-based backend was intended as a secret store, nor is config-server itself. If you have sensitive configuration you should probably not be using config-server with a git backend to deliver it to an app. The Vault backend support for config-server is meant as one option to cover this use-case. spring-cloud-vault also provides similar functionality.
Also, this issue is Vault specific. So it seems like you should at least be filing a separate issue.
Comment From: avnerstr
@dyroberts I'm not talking about sensitive, I'm talking about authorization, that one application will not read the other application configuration so easily. It sounds to me like a reasonable request. Anyway I found a way to support that, using Spring Security and I generate the spring security dynamically based on list of applications at runtime. You can close this issue.