GUACAMOLE-1629: Hook KSM vault code into base vault code and clean up.

This commit is contained in:
James Muehlner
2022-06-29 20:29:58 +00:00
parent 16efc0cdc1
commit fee2f8b416
9 changed files with 627 additions and 667 deletions

View File

@@ -22,6 +22,8 @@ package org.apache.guacamole.vault.secret;
import java.util.Map;
import java.util.concurrent.Future;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.Connectable;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.apache.guacamole.token.TokenFilter;
@@ -55,7 +57,9 @@ public interface VaultSecretService {
/**
* Returns a Future which eventually completes with the value of the secret
* having the given name. If no such secret exists, the Future will be
* completed with null.
* completed with null. The secrets retrieved from this method are independent
* of the context of the particular connection being established, or any
* associated user context.
*
* @param name
* The name of the secret to retrieve.
@@ -72,6 +76,35 @@ public interface VaultSecretService {
*/
Future<String> getValue(String name) throws GuacamoleException;
/**
* Returns a Future which eventually completes with the value of the secret
* having the given name. If no such secret exists, the Future will be
* completed with null. The connection or connection group, as well as the
* user context associated with the request are provided for additional context.
*
* @param userContext
* The user context associated with the connection or connection group for
* which the secret is being retrieved.
*
* @param connectable
* The connection or connection group for which the secret is being retrieved.
*
* @param name
* The name of the secret to retrieve.
*
* @return
* A Future which completes with value of the secret having the given
* name. If no such secret exists, the Future will be completed with
* null. If an error occurs asynchronously which prevents retrieval of
* the secret, that error will be exposed through an ExecutionException
* when an attempt is made to retrieve the value from the Future.
*
* @throws GuacamoleException
* If the secret cannot be retrieved due to an error.
*/
Future<String> getValue(UserContext userContext, Connectable connectable,
String name) throws GuacamoleException;
/**
* Returns a map of token names to corresponding Futures which eventually
* complete with the value of that token, where each token is dynamically
@@ -80,6 +113,12 @@ public interface VaultSecretService {
* function should be implemented to provide automatic tokens for those
* secrets and remove the need for manual mapping via YAML.
*
* @param userContext
* The user context from which the connectable originated.
*
* @param connectable
* The connection or connection group for which the tokens are being replaced.
*
* @param config
* The configuration of the Guacamole connection for which tokens are
* being generated. This configuration may be empty or partial,
@@ -99,7 +138,7 @@ public interface VaultSecretService {
* If an error occurs producing the tokens and values required for the
* given configuration.
*/
Map<String, Future<String>> getTokens(GuacamoleConfiguration config,
TokenFilter filter) throws GuacamoleException;
Map<String, Future<String>> getTokens(UserContext userContext, Connectable connectable,
GuacamoleConfiguration config, TokenFilter filter) throws GuacamoleException;
}

View File

@@ -31,6 +31,7 @@ import java.util.concurrent.Future;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.Connectable;
import org.apache.guacamole.net.auth.Connection;
import org.apache.guacamole.net.auth.ConnectionGroup;
import org.apache.guacamole.net.auth.TokenInjectingUserContext;
@@ -193,6 +194,10 @@ public class VaultUserContext extends TokenInjectingUserContext {
* corresponding values from the vault, using the given TokenFilter to
* filter tokens within the secret names prior to retrieving those secrets.
*
* @param connectable
* The connection or connection group to which the connection is being
* established.
*
* @param tokenMapping
* The mapping dictating the name of the secret which maps to each
* parameter token, where the key is the name of the parameter token
@@ -222,7 +227,8 @@ public class VaultUserContext extends TokenInjectingUserContext {
* If the value for any applicable secret cannot be retrieved from the
* vault due to an error.
*/
private Map<String, Future<String>> getTokens(Map<String, String> tokenMapping,
private Map<String, Future<String>> getTokens(
Connectable connectable, Map<String, String> tokenMapping,
TokenFilter secretNameFilter, GuacamoleConfiguration config,
TokenFilter configFilter) throws GuacamoleException {
@@ -247,14 +253,16 @@ public class VaultUserContext extends TokenInjectingUserContext {
// Initiate asynchronous retrieval of the token value
String tokenName = entry.getKey();
Future<String> secret = secretService.getValue(secretName);
Future<String> secret = secretService.getValue(
this, connectable, secretName);
pendingTokens.put(tokenName, secret);
}
// Additionally include any dynamic, parameter-based tokens
pendingTokens.putAll(secretService.getTokens(config, configFilter));
pendingTokens.putAll(secretService.getTokens(
this, connectable, config, configFilter));
return pendingTokens;
}
@@ -329,7 +337,8 @@ public class VaultUserContext extends TokenInjectingUserContext {
// Substitute tokens producing secret names, retrieving and storing
// those secrets as parameter tokens
tokens.putAll(resolve(getTokens(confService.getTokenMapping(), filter,
tokens.putAll(resolve(getTokens(
connectionGroup, confService.getTokenMapping(), filter,
null, new TokenFilter(tokens))));
}
@@ -409,8 +418,8 @@ public class VaultUserContext extends TokenInjectingUserContext {
// Substitute tokens producing secret names, retrieving and storing
// those secrets as parameter tokens
tokens.putAll(resolve(getTokens(confService.getTokenMapping(), filter,
config, new TokenFilter(tokens))));
tokens.putAll(resolve(getTokens(connection, confService.getTokenMapping(),
filter, config, new TokenFilter(tokens))));
}