GUACAMOLE-1772: Allow user configuration of KSM API call timeout.

This commit is contained in:
James Muehlner
2022-11-29 20:58:51 +00:00
parent c1b6ce4d8d
commit b9044caf65
4 changed files with 61 additions and 14 deletions

View File

@@ -28,6 +28,7 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
import org.apache.guacamole.properties.LongGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
import org.apache.guacamole.vault.conf.VaultConfigurationService;
@@ -120,6 +121,17 @@ public class KsmConfigurationService extends VaultConfigurationService {
}
};
/**
* The minimum number of milliseconds between KSM API calls.
*/
private static final LongGuacamoleProperty KSM_API_CALL_INTERVAL = new LongGuacamoleProperty() {
@Override
public String getName() {
return "ksm-api-call-interval";
}
};
/**
* Creates a new KsmConfigurationService which reads the configuration
* from "ksm-token-mapping.yml" and properties from
@@ -176,6 +188,20 @@ public class KsmConfigurationService extends VaultConfigurationService {
return environment.getProperty(MATCH_USER_DOMAINS, false);
}
/**
* Return the minimum number of milliseconds between KSM API calls. If not
* otherwise configured, this value will be 10 seconds.
*
* @return
* The minimum number of milliseconds between KSM API calls.
*
* @throws GuacamoleException
* If the value specified within guacamole.properties cannot be
* parsed or does not exist.
*/
public long getKsmApiInterval() throws GuacamoleException {
return environment.getProperty(KSM_API_CALL_INTERVAL, 10000L);
}
/**
* Return the globally-defined base-64-encoded JSON KSM configuration blob
@@ -189,7 +215,12 @@ public class KsmConfigurationService extends VaultConfigurationService {
* If the value specified within guacamole.properties cannot be
* parsed or does not exist.
*/
@Nonnull
@SuppressWarnings("null")
public String getKsmConfig() throws GuacamoleException {
// This will always return a non-null value; an exception would be
// thrown if the required value is not set
return environment.getRequiredProperty(KSM_CONFIG);
}
@@ -235,6 +266,7 @@ public class KsmConfigurationService extends VaultConfigurationService {
* @throws GuacamoleException
* If an invalid ksmConfig parameter is provided.
*/
@Nonnull
public SecretsManagerOptions getSecretsManagerOptions(@Nonnull String ksmConfig) throws GuacamoleException {
return new SecretsManagerOptions(

View File

@@ -95,12 +95,6 @@ public class KsmClient {
*/
private static final Pattern KEEPER_FILE_NOTATION = Pattern.compile("^(keeper://)?[^/]*/file/.+");
/**
* The maximum amount of time that an entry will be stored in the cache
* before being refreshed, in milliseconds.
*/
private static final long CACHE_INTERVAL = 5000;
/**
* The KSM configuration associated with this client instance.
*/
@@ -115,6 +109,13 @@ public class KsmClient {
*/
private final ReadWriteLock cacheLock = new ReentrantReadWriteLock();
/**
* The maximum amount of time that an entry will be stored in the cache
* before being refreshed, in milliseconds. This is also the shortest
* possible interval between API calls to KSM.
*/
private final long cacheInterval;
/**
* The timestamp that the cache was last refreshed, in milliseconds, as
* returned by System.currentTimeMillis(). This value is automatically
@@ -215,19 +216,27 @@ public class KsmClient {
private final Set<String> cachedAmbiguousDomains = new HashSet<>();
/**
* Create a new KSM client based around the provided KSM configuration.
* Create a new KSM client based around the provided KSM configuration and
* API timeout setting.
*
* @param ksmConfig
* The KSM configuration to use when retrieving properties from KSM.
*
* @param apiInterval
* The minimum number of milliseconds that must elapse between KSM API
* calls.
*/
@AssistedInject
public KsmClient(@Assisted SecretsManagerOptions ksmConfig) {
public KsmClient(
@Assisted SecretsManagerOptions ksmConfig,
@Assisted long apiInterval) {
this.ksmConfig = ksmConfig;
this.cacheInterval = apiInterval;
}
/**
* Validates that all cached data is current with respect to
* {@link #CACHE_INTERVAL}, refreshing data from the server as needed.
* {@link #cacheInterval}, refreshing data from the server as needed.
*
* @throws GuacamoleException
* If an error occurs preventing the cached data from being refreshed.
@@ -240,7 +249,7 @@ public class KsmClient {
// continuing
cacheLock.readLock().lock();
try {
if (currentTime - cacheTimestamp < CACHE_INTERVAL)
if (currentTime - cacheTimestamp < cacheInterval)
return;
}
finally {
@@ -252,7 +261,7 @@ public class KsmClient {
// Cache may have been updated since the read-only check. Re-verify
// that the cache has expired before continuing with a full refresh
if (currentTime - cacheTimestamp < CACHE_INTERVAL)
if (currentTime - cacheTimestamp < cacheInterval)
return;
// Attempt to pull all records first, allowing that operation to

View File

@@ -30,16 +30,21 @@ public interface KsmClientFactory {
/**
* Returns a new instance of a KsmClient instance associated with
* the provided KSM configuration options.
* the provided KSM configuration options and API interval.
*
* @param ksmConfigOptions
* The KSM config options to use when constructing the KsmClient
* object.
*
* @param apiInterval
* The minimum number of milliseconds that must elapse between KSM API
* calls.
*
* @return
* A new KsmClient instance associated with the provided KSM config
* options.
*/
KsmClient create(@Nonnull SecretsManagerOptions ksmConfigOptions);
KsmClient create(
@Nonnull SecretsManagerOptions ksmConfigOptions, long apiInterval);
}

View File

@@ -124,7 +124,7 @@ public class KsmSecretService implements VaultSecretService {
// Create and store a new KSM client instance for the provided KSM config blob
SecretsManagerOptions options = confService.getSecretsManagerOptions(ksmConfig);
ksmClient = ksmClientFactory.create(options);
ksmClient = ksmClientFactory.create(options, confService.getKsmApiInterval());
KsmClient prevClient = ksmClientMap.putIfAbsent(ksmConfig, ksmClient);
// If the client was already set before this thread got there, use the existing one
@@ -274,6 +274,7 @@ public class KsmSecretService implements VaultSecretService {
* no KSM config is found in the connection group tree, and the value is also not
* defined in the config file.
*/
@Nonnull
private String getConnectionGroupKsmConfig(
UserContext userContext, Connectable connectable) throws GuacamoleException {