Spring fails to resolve properties from Consul KVs if new config model (no bootstrap) is used and Consul ACLs are enabled
Describe the bug
Versions:
- Java 11
- Spring-Boot 2.4.8
- Spring-Cloud 2020.0.3
Scenario:
- Consul ACLs are enabled
- You provide the ACL to your application using the
CONSUL_TOKENenvironment variable - You have
@Valueannotations referencing Consul KVs - You are using the new config model (
application.yml, nobootstrap.yml, and nospring-cloud-starter-bootstrapdependency
Behaviour:
- The application registers with Consul successfully (so clearly the provided
CONSUL_TOKENis being picked up correctly in some contexts!) -
KV values in Consul are not considered when resolving the
@Valueannotations.
Workaround:
- Revert to the old config model (split between
application.ymlandbootstrap.yml) and include theorg.springframework.cloud:spring-cloud-starter-bootstrapdependency in your service.
Sample
A sample application, with detailed README allowing for easy reproduction, is available at https://github.com/oliverlockwood/sb2.4-consul-example
Hello. We are also facing the same issue. Setting config.aclToken explicitly works though.
Hi @spencergibb, apologies for tagging you directly, but I wondered if you or any of your colleagues have had any thoughts on this. To me this comes across as a major problem (Consul ACLs not properly supported!) but this issue has sat for almost a month without even being triaged, so I thought I'd ask the question.
Found nice workaround. In addition to CONSUL_TOKEN, also set token into SPRING_CLOUD_CONSUL_CONFIG_ACLTOKEN environment variable.
According to ConsulConfigProperties, acl token looked up in several places:
https://github.com/spring-cloud/spring-cloud-consul/blob/601a7d3cea337904b48245db68c1b4d1787ab15f/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigProperties.java#L68-L69
@Value annotation ignored here. Not sure why. But since this class annotated with @ConfigurationProperties("spring.cloud.consul.config"), we can do the trick and set spring.cloud.consul.config.aclToken property.
@OlgaMaciaszek since we've spoken on a couple of other Spring-Cloud issues, I wonder if you would please be kind enough to help me understand whether the spring-cloud-consul project is being abandoned?
As far as I can see, there's a lot of issues in https://github.com/spring-cloud/spring-cloud-consul/issues (including this one!) which seem to just have been left in "waiting-for-triage" state and ignored by the maintainers, since circa early 2021.
We're looking to upgrade to Spring-Boot 3, but as @onyn highlighted in the linked issue #768, this bug still exists, 18 months on, and I can't believe that use of Consul ACLs is a particularly extreme edge case!
The project is still supported. I'll try and look at it in the coming days
@Value annotation ignored here. Not sure why. But since this class annotated with @ConfigurationProperties("spring.cloud.consul.config"), we can do the trick and set spring.cloud.consul.config.aclToken property.
CONSUL_TOKEN was always a shortcut. The official standard property is spring.cloud.consul.config.acl-token. @Value doesn't work in spring.config.import because ConsulConfigProperties is not a bean. I'm tempted to say that for spring.config.import, if you want to use an env var, it should be SPRING_CLOUD_CONSUL_CONFIG_ACLTOKEN rather than CONSUL_TOKEN.
I could, perhaps, be convinced otherwise.
I guess the argument might be a single property to share between config and discovery. Those are the two places that use CONSUL_TOKEN and SPRING_CLOUD_CONSUL_TOKEN.
The work would be done in this method https://github.com/spring-cloud/spring-cloud-consul/blob/310ccfb99c2700e6c469fa67eed466890dea9f3a/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java#L210
Similar to https://github.com/spring-cloud/spring-cloud-consul/blob/310ccfb99c2700e6c469fa67eed466890dea9f3a/spring-cloud-consul-config/src/main/java/org/springframework/cloud/consul/config/ConsulConfigDataLocationResolver.java#L217-L219
@spencergibb thank you for taking the time to respond.
Regarding your comment
CONSUL_TOKEN was always a shortcut. The official standard property is spring.cloud.consul.config.acl-token. @Value doesn't work in spring.config.import because ConsulConfigProperties is not a bean. I'm tempted to say that for spring.config.import, if you want to use an env var, it should be SPRING_CLOUD_CONSUL_CONFIG_ACLTOKEN rather than CONSUL_TOKEN.
I could, perhaps, be convinced otherwise.
Allow me an attempt to do that convincing :-)
-
CONSUL_TOKENis conventional in the world of Consul - see e.g. https://registry.terraform.io/providers/hashicorp/consul/latest/docs . I'm not sure why you say it was "always a shortcut". - Consider also the recommendation in https://github.com/hashicorp/envconsul, specifically:
For additional security, tokens may also be read from the environment using the CONSUL_TOKEN or VAULT_TOKEN environment variables respectively. It is highly recommended that you do not put your tokens in plain-text in a configuration file.
- To the best of my knowledge, it has been supported in
spring-cloud-consulfor many years prior to the regression described by this bug ticket, which was introduced (as far as I can tell) with the move to the newspring.config.importmodel. Correct me if I'm wrong, but it appears that this was very much an accidental regression rather than a deliberate deprecation of usage, so to be honest I'd really like to hear your perspective arguing why theCONSUL_TOKENusage should be deprecated / removed, if you really believe that it should! - From a personal use-case perspective, we operate a mix of microservices, some of which are based on Spring-Boot, others are built on NodeJS / Typescript (for example). All of these need to register with Consul and use it for service discovery. We could of course duplicate the
CONSUL_TOKENenvironment variable that we use throughout intoSPRING_CLOUD_CONSUL_CONFIG_ACLTOKEN(though from your comments, it sounds like even that doesn't work at present!). However, to me it seems logical that Spring should continue to support the Consul-conventional env var, which has been supported for years, regardless of whether it also supports a Spring-specific env var. Surely one of Spring's objectives is intuitive ease of use; doesn't this fall into that category?
Call me convinced.