diff --git a/extensions/guacamole-vault/modules/guacamole-vault-azure/src/main/java/org/apache/guacamole/vault/azure/secret/AzureKeyVaultSecretService.java b/extensions/guacamole-vault/modules/guacamole-vault-azure/src/main/java/org/apache/guacamole/vault/azure/secret/AzureKeyVaultSecretService.java index 07337eb12..401a44607 100644 --- a/extensions/guacamole-vault/modules/guacamole-vault-azure/src/main/java/org/apache/guacamole/vault/azure/secret/AzureKeyVaultSecretService.java +++ b/extensions/guacamole-vault/modules/guacamole-vault-azure/src/main/java/org/apache/guacamole/vault/azure/secret/AzureKeyVaultSecretService.java @@ -34,6 +34,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.protocol.GuacamoleConfiguration; +import org.apache.guacamole.token.TokenFilter; import org.apache.guacamole.vault.azure.conf.AzureKeyVaultAuthenticationException; import org.apache.guacamole.vault.azure.conf.AzureKeyVaultConfigurationService; import org.apache.guacamole.vault.secret.CachedVaultSecretService; @@ -123,8 +124,8 @@ public class AzureKeyVaultSecretService extends CachedVaultSecretService { } @Override - public Map> getTokens(GuacamoleConfiguration config) - throws GuacamoleException { + public Map> getTokens(GuacamoleConfiguration config, + TokenFilter filter) throws GuacamoleException { return Collections.emptyMap(); } diff --git a/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/secret/VaultSecretService.java b/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/secret/VaultSecretService.java index 4cc5bb4a8..76349bad9 100644 --- a/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/secret/VaultSecretService.java +++ b/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/secret/VaultSecretService.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.concurrent.Future; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.protocol.GuacamoleConfiguration; +import org.apache.guacamole.token.TokenFilter; /** * Generic service for retrieving the value of a secret stored in a vault. @@ -84,6 +85,11 @@ public interface VaultSecretService { * being generated. This configuration may be empty or partial, * depending on the underlying implementation. * + * @param filter + * A TokenFilter instance that applies any tokens already available to + * be applied to the configuration of the Guacamole connection. These + * tokens will consist of tokens already supplied to connect(). + * * @return * A map of token names to their corresponding future values, where * each token and value may be dynamically determined based on the @@ -93,7 +99,7 @@ public interface VaultSecretService { * If an error occurs producing the tokens and values required for the * given configuration. */ - Map> getTokens(GuacamoleConfiguration config) - throws GuacamoleException; + Map> getTokens(GuacamoleConfiguration config, + TokenFilter filter) throws GuacamoleException; } diff --git a/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/user/VaultUserContext.java b/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/user/VaultUserContext.java index 6df30fdad..53901483e 100644 --- a/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/user/VaultUserContext.java +++ b/extensions/guacamole-vault/modules/guacamole-vault-base/src/main/java/org/apache/guacamole/vault/user/VaultUserContext.java @@ -189,13 +189,18 @@ public class VaultUserContext extends TokenInjectingUserContext { * may contain its own tokens, which will be substituted using values * from the given filter. * + * @param secretNameFilter + * The filter to use to substitute values for tokens in the names of + * secrets to be retrieved from the vault. + * * @param config * The GuacamoleConfiguration of the connection for which tokens are * being retrieved, if available. This may be null. * - * @param filter - * The filter to use to substitute values for tokens in the names of - * secrets to be retrieved from the vault. + * @param configFilter + * A TokenFilter instance that applies any tokens already available to + * be applied to the configuration of the Guacamole connection. These + * tokens will consist of tokens already supplied to connect(). * * @return * A Map of token name to Future, where each Future represents the @@ -207,8 +212,8 @@ public class VaultUserContext extends TokenInjectingUserContext { * vault due to an error. */ private Map> getTokens(Map tokenMapping, - GuacamoleConfiguration config, TokenFilter filter) - throws GuacamoleException { + TokenFilter secretNameFilter, GuacamoleConfiguration config, + TokenFilter configFilter) throws GuacamoleException { // Populate map with pending secret retrieval operations corresponding // to each mapped token @@ -219,7 +224,7 @@ public class VaultUserContext extends TokenInjectingUserContext { // secrets which cannot be translated String secretName; try { - secretName = filter.filterStrict(entry.getValue()); + secretName = secretNameFilter.filterStrict(entry.getValue()); } catch (GuacamoleTokenUndefinedException e) { logger.debug("Secret for token \"{}\" will not be retrieved. " @@ -237,7 +242,7 @@ public class VaultUserContext extends TokenInjectingUserContext { } // Additionally include any dynamic, parameter-based tokens - pendingTokens.putAll(secretService.getTokens(config)); + pendingTokens.putAll(secretService.getTokens(config, configFilter)); return pendingTokens; @@ -298,8 +303,8 @@ public class VaultUserContext extends TokenInjectingUserContext { } @Override - protected Map getTokens(ConnectionGroup connectionGroup) - throws GuacamoleException { + protected void addTokens(ConnectionGroup connectionGroup, + Map tokens) throws GuacamoleException { String name = connectionGroup.getName(); String identifier = connectionGroup.getIdentifier(); @@ -313,7 +318,8 @@ public class VaultUserContext extends TokenInjectingUserContext { // Substitute tokens producing secret names, retrieving and storing // those secrets as parameter tokens - return resolve(getTokens(confService.getTokenMapping(), null, filter)); + tokens.putAll(resolve(getTokens(confService.getTokenMapping(), filter, + null, new TokenFilter(tokens)))); } @@ -353,7 +359,7 @@ public class VaultUserContext extends TokenInjectingUserContext { } @Override - protected Map getTokens(Connection connection) + protected void addTokens(Connection connection, Map tokens) throws GuacamoleException { String name = connection.getName(); @@ -392,7 +398,8 @@ public class VaultUserContext extends TokenInjectingUserContext { // Substitute tokens producing secret names, retrieving and storing // those secrets as parameter tokens - return resolve(getTokens(confService.getTokenMapping(), config, filter)); + tokens.putAll(resolve(getTokens(confService.getTokenMapping(), filter, + config, new TokenFilter(tokens)))); } diff --git a/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/java/org/apache/guacamole/vault/ksm/secret/KsmSecretService.java b/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/java/org/apache/guacamole/vault/ksm/secret/KsmSecretService.java index e1c3137ce..6fd9f203c 100644 --- a/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/java/org/apache/guacamole/vault/ksm/secret/KsmSecretService.java +++ b/extensions/guacamole-vault/modules/guacamole-vault-ksm/src/main/java/org/apache/guacamole/vault/ksm/secret/KsmSecretService.java @@ -31,6 +31,7 @@ import java.util.concurrent.Future; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.protocol.GuacamoleConfiguration; +import org.apache.guacamole.token.TokenFilter; import org.apache.guacamole.vault.secret.VaultSecretService; /** @@ -71,14 +72,11 @@ public class KsmSecretService implements VaultSecretService { } @Override - public Map> getTokens(GuacamoleConfiguration config) - throws GuacamoleException { + public Map> getTokens(GuacamoleConfiguration config, + TokenFilter filter) throws GuacamoleException { Map> tokens = new HashMap<>(); - // TODO: Ensure tokens within parameters are evaluated when considering - // whether a KSM record matches (ie: "username" might be ${GUAC_USERNAME}) - // TODO: Verify protocol before assuming meaning of "hostname" // parameter @@ -87,7 +85,7 @@ public class KsmSecretService implements VaultSecretService { // Retrieve and define server-specific tokens, if any String hostname = parameters.get("hostname"); if (hostname != null && !hostname.isEmpty()) { - KeeperRecord record = ksm.getRecordByHost(hostname); + KeeperRecord record = ksm.getRecordByHost(filter.filter(hostname)); if (record != null) { // Username of server-related record