I have an application on SpringBoot that is deployes to Cloud Foundry. It has a bound service that attaches some information to VCAP_SERVICES that I can use in my application.properties file to receive security related data.
This services variables are in the user-provided
sub-json of whole VCAP_SERVICE environment variable and looks like this:
"user-provided": [
{
"credentials": {
"auth-scopes": {
"group-1": "superadmin",
"group-2": "admin"
},
"base64ClientCredential": "SSBBTSBOT1QgVEhBVCBTSUxMWSA6LUQ=",
"client-id": "my-app",
"client-secret": "g1234567890",
"token-info-uri": "https://XYZ.predix.io/check_token",
"user-info-uri": "https://XYZ.predix.io/userinfo"
},
"label": "user-provided",
"name": "my-app-creds",
"syslog_drain_url": "",
"tags": [],
"volume_mounts": []
}
]
In my application.properties I have
security.properties.client-id=${vcap.services.my-app-creds.credentials.client-id}
security.properties.client-secret=${vcap.services.my-app-creds.credentials.client-secret}
security.properties.token-info-uri=${vcap.services.my-app-creds.credentials.token-info-uri}
security.properties.user-info-uri=${vcap.services.my-app-creds.credentials.user-info-uri}
security.properties.auth-scopes=${vcap.services.my-app-creds.credentials.auth-scopes}
I also created class SecurityProperties
that reads those properties and stores in JAVA:
@Component
@PropertySource("classpath:application.properties")
@ConfigurationProperties(prefix = "security.properties")
public class SecurityProperties {
String clientId;
String clientSecret;
String tokenInfoUri;
String userInfoUri;
//Required getters and setters
}
And this class successfully binds those fields to information received from application.properties
.
The problem occurs when I want to receive Map:
"auth-scopes": {
"group-1": "superadmin",
"group-2": "admin"
}
I tried adding to SecurityProperties
class field:
HashMap<String, String> authScopes;
But it fails
I also tried with inner class
AuthScopes authScopes;
public static class AuthScopes {
//various different implementations
//to read this but no success at all
}
I ran out of other ideas. I just can't figure out how to get this. I will also accept that auth-scopes
json from VCAPS
will be read as a string, and then I will parse it - no problem. The issue is that even if I add to SecurityProperties
field String authScopes
it is bound with exactly this string: "${vcap.services.my-app-creds.credentials.auth-scopes}"
. Nothing useful.
If you have any idea - please share.
Spring Boot provides the vcap.
properties via the CloudFoundryVcapEnvironmentPostProcessor. That class reads the VCAP_SERVICES
JSON and flattens it into a set of discrete properties. If you add Spring Boot actuators to your application and access the /env
endpoint, you will see the set of vcap.
properties that get created.
In your example, the properties will contain these values:
"vcap": {
...
"vcap.services.my-app-creds.credentials.auth-scopes.group-1": "******",
"vcap.services.my-app-creds.credentials.auth-scopes.group-2": "******",
}
There is no vcap.services.my-service.credentials.auth-scopes
property in that list, because the JSON get completely flattened. The property names use the dot notation to reflect the JSON structure, but the hierarchy is not preserved in the set of properties. In short, what you are trying to do won't work with Boot properties.
One alternative would be to set those values as a string instead of a hash in the JSON, as in "auth-scopes": "group-1:superadmin,group-2:admin"
or "auth-scopes": "group-1=superadmin,group-2=admin"
. Your SecurityProperties
could then get the value of vcap.services.my-service.credentials.auth-scopes
and parse the String into a Map.