From d6a491f933d6aeb8ab4b055fa1a45708305f4373 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 18 Feb 2024 23:18:43 -0800 Subject: [PATCH] GUACAMOLE-374: Automatically read properties from files pointed to by "*_FILE" environment variables. --- Dockerfile | 3 +- .../GuacamoleServletContextListener.java | 32 +++++++++- ...temFileEnvironmentGuacamoleProperties.java | 64 +++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 guacamole/src/main/java/org/apache/guacamole/SystemFileEnvironmentGuacamoleProperties.java diff --git a/Dockerfile b/Dockerfile index b37a9d913..80aa578ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -97,7 +97,8 @@ RUN useradd --system --create-home --shell /usr/sbin/nologin --uid $UID --gid $G USER guacamole # Environment variable defaults -ENV GUACAMOLE_HOME=/etc/guacamole +ENV GUACAMOLE_HOME=/etc/guacamole \ + ENABLE_FILE_ENVIRONMENT_PROPERTIES=true # Start Guacamole under Tomcat, listening on 0.0.0.0:8080 EXPOSE 8080 diff --git a/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java b/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java index 1068477c4..df0766238 100644 --- a/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java +++ b/guacamole/src/main/java/org/apache/guacamole/GuacamoleServletContextListener.java @@ -95,7 +95,7 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener /** * A property that determines whether environment variables are evaluated - * to override properties specified in guacamole.properties. + * to supply properties not specified in guacamole.properties. */ private static final BooleanGuacamoleProperty ENABLE_ENVIRONMENT_PROPERTIES = new BooleanGuacamoleProperty() { @@ -105,6 +105,19 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener } }; + /** + * A property that determines whether environment variables of the form + * "*_FILE" are evaluated to supply properties not specified in + * guacamole.properties nor in environment variables. + */ + private static final BooleanGuacamoleProperty ENABLE_FILE_ENVIRONMENT_PROPERTIES = + new BooleanGuacamoleProperty() { + @Override + public String getName() { + return "enable-file-environment-properties"; + } + }; + /** * The Guacamole server environment. */ @@ -172,6 +185,23 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener logger.debug("Error reading \"{}\" property from guacamole.properties.", ENABLE_ENVIRONMENT_PROPERTIES.getName(), e); } + // For any values not defined in GUACAMOLE_HOME/guacamole.properties + // nor in the system environment, read from files pointed to by + // corresponding "*_FILE" variables in the system environment if + // "enable-file-environment-properties" is set to "true" + try { + if (environment.getProperty(ENABLE_FILE_ENVIRONMENT_PROPERTIES, false)) { + environment.addGuacamoleProperties(new SystemFileEnvironmentGuacamoleProperties()); + logger.info("Additional configuration parameters may be read " + + "from files pointed to by \"*_FILE\" environment " + + "variables."); + } + } + catch (GuacamoleException e) { + logger.error("Unable to configure support for file environment properties: {}", e.getMessage()); + logger.debug("Error reading \"{}\" property from guacamole.properties.", ENABLE_FILE_ENVIRONMENT_PROPERTIES.getName(), e); + } + // Now that at least the main guacamole.properties source of // configuration information is available, initialize the session map sessionMap = new HashTokenSessionMap(environment); diff --git a/guacamole/src/main/java/org/apache/guacamole/SystemFileEnvironmentGuacamoleProperties.java b/guacamole/src/main/java/org/apache/guacamole/SystemFileEnvironmentGuacamoleProperties.java new file mode 100644 index 000000000..8b0825292 --- /dev/null +++ b/guacamole/src/main/java/org/apache/guacamole/SystemFileEnvironmentGuacamoleProperties.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole; + +import com.google.common.io.Files; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import org.apache.guacamole.properties.GuacamoleProperties; +import org.apache.guacamole.token.TokenName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * GuacamoleProperties implementation which reads all properties from files + * whose filenames are stored in environment variables. The name of the + * environment variable corresponding to the filename is determined from the + * original property using {@link TokenName#canonicalize(java.lang.String)} + * with an additional "_FILE" suffix. + */ +public class SystemFileEnvironmentGuacamoleProperties implements GuacamoleProperties { + + /** + * Logger for this class. + */ + private static final Logger logger = LoggerFactory.getLogger(SystemFileEnvironmentGuacamoleProperties.class); + + @Override + public String getProperty(String name) { + + String filename = System.getenv(TokenName.canonicalize(name) + "_FILE"); + if (filename != null) { + try { + return Files.asCharSource(new File(filename), StandardCharsets.UTF_8).read(); + } + catch (IOException e) { + logger.error("Property \"{}\" could not be read from file \"{}\": {}", name, filename, e.getMessage()); + logger.debug("Error reading property value from file.", e); + } + } + + return null; + + } + +} +