So, for anyone reading this post my concern was for security. I wanted to keep using the Docker secrets mechanism to give a secret.properties to my application instead of using a volume, which is less safe.
First I created a secret in my Docker compose: secrets: secrets.properties: file: ./secrets/secrets.properties and I exposed this secret for the CAS container echempad-cas: (...) secrets: - secrets.properties After that I configured CATALINA_OPTS to point to the location where Docker will mount the secret: echempad-cas: (...) - SPRING_PROFILES_ACTIVE=standalone,ldap,db,prod,container,secrets - CATALINA_OPTS=-Dspring.config.additional-location=/run/secrets/secrets.properties I also added the declaration of SPRING_PROFILES_ACTIVE containing a value "secrets", which is the name for the profile that I want active in CAS in order to load the variables declared in secrets.properties That was most of it. I created a small script tool to read all the individual secrets and create the secrets.properties file, so I can work faster if I need to regenerate my work environment. El viernes, 11 de octubre de 2024 a las 17:38:23 UTC+2, Aleix Mariné escribió: > 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 aleix...@gmail.com. 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 cas-user+unsubscr...@apereo.org. To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/9a95efbe-4f55-4ed5-9283-329ff0eef80bn%40apereo.org.