Ray,

I confirm that your approach of giving a destination location to tomcat for 
a application.properties for the secrets worked (with minor adjusts).

Thank you for your fast response.

I will detail how my solution works in a future post in this 
conversationfor the record. 

Meanwhile, you can mark this conversation as closed if applicable. 

Thank you so much.


Aleix



El jueves, 10 de octubre de 2024 a las 5:10:07 UTC+2, Ray Bon escribió:

> Aleix,
>
> You can use variable substitution for secrets (or anything that might 
> change between dev and prod). For example, in cas 
> src/main/resources/application.yml:
> cas:
>   authn:
>     oauth:
>       access-token:
>         crypto:
>           encryption:
>             key: ${variable-name}
>
> Create an application.properties file (the one in docker secrets) with the 
> variable definitions:
> variable-name=123abc...
>
> You can also put the entire definition in application.properties:
> cas.service-registry.ldap.bind-credential=password
>
> Then provide the destination location to tomcat (or the app server you are 
> using) on startup:
>
> CATALINA_OPTS="-Dspring.config.additional-location=/run/secrets/application.properties
>  
> ..."
>
> Cas will look in /etc/cas by default (in this case /etc/cas/config), if 
> you want to put application.properties there (I am not sure what options 
> you have with docker secrets).
>
> Ray
>
> P.S. I like the variable approach because all cas config is in one file 
> and it is stored in our cas-overlay-template git repo. Ops only has to 
> supply the variable file. You could of course put all config in 
> application.properites.
>
>
> On Wed, 2024-10-09 at 02:48 -0700, Aleix Mariné wrote:
>
> You don't often get email from [email protected]. Learn why this is 
> important <https://aka.ms/LearnAboutSenderIdentification>
>
> 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 StartupSecretsLoadingimplements 
> ApplicationListener<ApplicationEnvironmentPreparedEvent> 
> {
>
>
>
> private final static String SECRETS_FOLDER = "/run/secrets/";
>
> /**
> * Reads a secret and introduces it into the environment of .application 
> properties.
> *
>
> * @paramsecretName name of the secret to read from /run/secrets default 
> Docker secrets folder.
> * @paramproperty Property to write / update.
> * @parampropertyOverridesProvides access to a map with all the properties 
> that will be loaded into Java env.
> */
> private voidaddSecretProperty(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 voidloadSecrets(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(newMapPropertySource(
> "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 voidonApplicationEvent(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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/a/apereo.org/d/msgid/cas-user/4f4e9c39-2f9c-4695-b6b6-b23f0799b044n%40apereo.org.

Reply via email to