Hello,

I am working with CAS 6.6.12 with WAR overlay, standalone and no spring 
cloud. I am building a Docker container with my CAS. 

Right now I am trying to set some java properties (application properties) 
that are secret into the CAS container, but even though they are set, they 
do not seem to affect the behavior of CAS as if they were introduced using 
a profile config file or other accepted method. I also could introduce 
these properties using system variables, command-line args or profile 
configuration files, but they are less secure than using Docker secrets. 
Due to that, I want to use Docker secrets (which simply put a file with the 
secret inside the container, then the app needs to read it and use it), 
which forces me to declare the application property programmatically at 
startup after reading its value from the corresponding Docker secret. 

That is why I am reading all Docker secrets from /run/secrets and setting 
them into the corresponding Java property on startup time. To do that I 
created a custom class to execute this code on startup. 


@Component
public class StartupSecretsLoading implements 
ApplicationListener<ApplicationEnvironmentPreparedEvent> 
{

private final static String SECRETS_FOLDER = "/run/secrets/";

/**
* Reads a secret and introduces it into the environment of .application 
properties.
*
* @param secretName name of the secret to read from /run/secrets default 
Docker secrets folder.
* @param property Property to write / update.
* @param propertyOverrides Provides access to a map with all the properties 
that will be loaded into Java env.
*/
private void addSecretProperty(String secretName, String property, 
Map<String, Object> propertyOverrides)
{
String secretPath = SECRETS_FOLDER + secretName;

try {
String secretContent = Files.readString(Path.of(secretPath));

// Remove trailing newlines (\n or \r\n) but leave spaces intact
secretContent = secretContent.replaceAll("[\\r\\n]+$", "");

// is this line really setting a Java property? 
System.setProperty(property, secretContent);

// Alternative to set the Java property?
propertyOverrides.put(secretName, secretContent);

Logger.getGlobal().warning("Read the secret: " + secretPath + " with 
content " + secretContent);
} catch (IOException e) {
Logger.getGlobal().warning("Failed to read the secret: " + e.getMessage());
}
}

/**
* Loads all secrets into the Java properties environment
*/
private void loadSecrets(ConfigurableEnvironment environment) {

Map<String, Object> propertyOverrides = new LinkedHashMap<>();

try {
this.addSecretProperty("CAS_TGC_CRYPTO_ENCRYPTION_KEY", 
"cas.tgc.crypto.encryption.key", propertyOverrides);
this.addSecretProperty("CAS_TGC_CRYPTO_SIGNING_KEY", 
"cas.tgc.crypto.signing.key", propertyOverrides);
this.addSecretProperty("CAS_WEBFLOW_CRYPTO_SIGNING_KEY", 
"cas.webflow.crypto.signing.key", propertyOverrides);
this.addSecretProperty("CAS_WEBFLOW_CRYPTO_ENCRYPTION_KEY", 
"cas.webflow.crypto.encryption.key", propertyOverrides);
this.addSecretProperty("LDAP_TOKEN", "cas.authn.ldap[0].bindCredential", 
propertyOverrides);
this.addSecretProperty("DB_PASSWORD", "cas.authn.jdbc.query[0].password", 
propertyOverrides);
this.addSecretProperty("ORCID_TOKEN", "cas.authn.pac4j.oauth2[0].secret", 
propertyOverrides);
} catch (Exception e) {
throw new RuntimeException("Failed to load secrets from " + 
StartupSecretsLoading.SECRETS_FOLDER, e);
}

// Add the loaded properties to the environment
environment.getPropertySources().addFirst(new MapPropertySource(
"customSecrets", propertyOverrides));
}

/**
* This method is executed before loading beans and after the basic 
environment initializations. You can inject data
* needed for the initialization of those beans.
* <p>
* @param event Event object that contains information about the 
ApplicationEnvironmentPreparedEvent event.
*/
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
Logger.getGlobal().warning("Loading secrets from " + SECRETS_FOLDER);
this.loadSecrets(event.getEnvironment());
Logger.getGlobal().warning("Finished loading secrets from " + SECRETS_FOLDER
);
}


So in this method I was trying two different methods of injecting 
variables. The first to appear is System.setProperty(property, 
secretContent);, which seems to leave the variable empty anyway. 

The second that I tried is propertyOverrides.put(secretName, 
secretContent);, continued by environment.getPropertySources().addFirst(new 
MapPropertySource("customSecrets", propertyOverrides));, which also does 
not work. 

I 
read 
https://apereo.github.io/cas/7.0.x/configuration/Configuration-Management-Reload.html
 
from the official documentation, and it seems that loading application 
properties programmatically on startup is not trivial. Can someone with 
more knowledge hint me in the right direction or explain me how I must 
proceed to read a file on startup and declare using its data an application 
property that affect the behaviour of CAS as if the property was loaded 
using an application profile file? 

Thank you very much, I am lost in here and need some help. 


Aleix


-- 
- Website: https://apereo.github.io/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
--- 
You received this message because you are subscribed to the Google Groups "CAS 
Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to cas-user+unsubscr...@apereo.org.
To view this discussion on the web visit 
https://groups.google.com/a/apereo.org/d/msgid/cas-user/ac7476c5-ae73-4fd7-bdfa-c75da9bc101dn%40apereo.org.

Reply via email to