mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUACAMOLE-1656: Fall back to user KSM config for single value fetch.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.vault.ksm;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* A class that is basically equivalent to the standard Supplier class in
|
||||
* Java, except that the get() function can throw GuacamoleException, which
|
||||
* is impossible with any of the standard Java lambda type classes, since
|
||||
* none of them can handle checked exceptions
|
||||
*/
|
||||
public abstract class GuacamoleExceptionSupplier<T> {
|
||||
|
||||
/**
|
||||
* Returns a value of the declared type.
|
||||
*
|
||||
* @return
|
||||
* A value of the declared type.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while attemping to calculate the return value.
|
||||
*/
|
||||
public abstract T get() throws GuacamoleException;
|
||||
}
|
@@ -34,7 +34,6 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -45,10 +44,12 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.User;
|
||||
import org.apache.guacamole.vault.ksm.conf.KsmConfigurationService;
|
||||
import org.apache.guacamole.vault.secret.WindowsUsername;
|
||||
import org.apache.guacamole.vault.ksm.GuacamoleExceptionSupplier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -595,6 +596,38 @@ public class KsmClient {
|
||||
* is invalid.
|
||||
*/
|
||||
public Future<String> getSecret(String notation) throws GuacamoleException {
|
||||
return getSecret(notation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the secret stored within Keeper Secrets Manager and
|
||||
* represented by the given Keeper notation. Keeper notation locates the
|
||||
* value of a specific field, custom field, or file associated with a
|
||||
* specific record. See: https://docs.keeper.io/secrets-manager/secrets-manager/about/keeper-notation
|
||||
* If a fallbackFunction is provided, it will be invoked to generate
|
||||
* a return value in the case where no secrest is found with the given
|
||||
* keeper notation.
|
||||
*
|
||||
* @param notation
|
||||
* The Keeper notation of the secret to retrieve.
|
||||
*
|
||||
* @param fallbackFunction
|
||||
* A function to invoke in order to produce a Future for return,
|
||||
* if the requested secret is not found. If the provided Function
|
||||
* is null, it will not be run.
|
||||
*
|
||||
* @return
|
||||
* A Future which completes with the value of the secret represented by
|
||||
* the given Keeper notation, or null if there is no such secret.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the requested secret cannot be retrieved or the Keeper notation
|
||||
* is invalid.
|
||||
*/
|
||||
public Future<String> getSecret(
|
||||
String notation,
|
||||
@Nullable GuacamoleExceptionSupplier<Future<String>> fallbackFunction)
|
||||
throws GuacamoleException {
|
||||
validateCache();
|
||||
cacheLock.readLock().lock();
|
||||
try {
|
||||
@@ -614,6 +647,11 @@ public class KsmClient {
|
||||
catch (Error e) {
|
||||
logger.warn("Record \"{}\" does not exist.", notation);
|
||||
logger.debug("Retrieval of record by Keeper notation failed.", e);
|
||||
|
||||
// If the secret is not found, invoke the fallback function
|
||||
if (fallbackFunction != null)
|
||||
return fallbackFunction.get();
|
||||
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
|
@@ -48,6 +48,7 @@ import org.apache.guacamole.net.auth.Directory;
|
||||
import org.apache.guacamole.net.auth.UserContext;
|
||||
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
||||
import org.apache.guacamole.token.TokenFilter;
|
||||
import org.apache.guacamole.vault.ksm.GuacamoleExceptionSupplier;
|
||||
import org.apache.guacamole.vault.ksm.conf.KsmAttributeService;
|
||||
import org.apache.guacamole.vault.ksm.conf.KsmConfigurationService;
|
||||
import org.apache.guacamole.vault.secret.VaultSecretService;
|
||||
@@ -147,7 +148,24 @@ public class KsmSecretService implements VaultSecretService {
|
||||
// Attempt to find a KSM config for this connection or group
|
||||
String ksmConfig = getConnectionGroupKsmConfig(userContext, connectable);
|
||||
|
||||
return getClient(ksmConfig).getSecret(name);
|
||||
return getClient(ksmConfig).getSecret(name, new GuacamoleExceptionSupplier<Future<String>>() {
|
||||
|
||||
@Override
|
||||
public Future<String> get() throws GuacamoleException {
|
||||
|
||||
// Get the user-supplied KSM config, if allowed by config and
|
||||
// set by the user
|
||||
String userKsmConfig = getUserKSMConfig(userContext, connectable);
|
||||
|
||||
// If the user config happens to be the same as admin-defined one,
|
||||
// don't bother trying again
|
||||
if (userKsmConfig != ksmConfig)
|
||||
return getClient(userKsmConfig).getSecret(name);
|
||||
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,6 +353,44 @@ public class KsmSecretService implements VaultSecretService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the KSM config blob for the current user IFF user KSM configs
|
||||
* are enabled globally, and are enabled for the given connectable. If no
|
||||
* KSM config exists for the given user or KSM configs are not enabled,
|
||||
* null will be returned.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context from which the current user should be fetched.
|
||||
*
|
||||
* @param connectable
|
||||
* The connectable to which the connection is being established. This
|
||||
* is the conneciton which will be checked to see if user KSM configs
|
||||
* are enabled.
|
||||
*
|
||||
* @return
|
||||
* The base64 encoded KSM config blob for the current user if one
|
||||
* exists, and if user KSM configs are enabled globally and for the
|
||||
* provided connectable.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while attempting to fetch the KSM config.
|
||||
*/
|
||||
private String getUserKSMConfig(
|
||||
UserContext userContext, Connectable connectable) throws GuacamoleException {
|
||||
|
||||
// Check if user KSM configs are enabled globally, and for the given connectable
|
||||
if (confService.getAllowUserConfig() && isKsmUserConfigEnabled(connectable))
|
||||
|
||||
// Return the user-specific KSM config, if one exists
|
||||
return userContext.self().getAttributes().get(
|
||||
KsmAttributeService.KSM_CONFIGURATION_ATTRIBUTE);
|
||||
|
||||
|
||||
// If user-specific KSM config is disabled globally or for the given
|
||||
// connectable, return null to indicate that no user config exists
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Future<String>> getTokens(UserContext userContext, Connectable connectable,
|
||||
GuacamoleConfiguration config, TokenFilter filter) throws GuacamoleException {
|
||||
@@ -351,16 +407,9 @@ public class KsmSecretService implements VaultSecretService {
|
||||
|
||||
// Only use the user-specific KSM config if explicitly enabled in the global
|
||||
// configuration, AND for the specific connectable being connected to
|
||||
if (confService.getAllowUserConfig() && isKsmUserConfigEnabled(connectable)) {
|
||||
|
||||
// Find a user-specific KSM config, if one exists
|
||||
String userKsmConfig = userContext.self().getAttributes().get(
|
||||
KsmAttributeService.KSM_CONFIGURATION_ATTRIBUTE);
|
||||
|
||||
// If a user-specific config exsts, process it first
|
||||
String userKsmConfig = getUserKSMConfig(userContext, connectable);
|
||||
if (userKsmConfig != null && !userKsmConfig.trim().isEmpty())
|
||||
ksmClients.add(0, getClient(userKsmConfig));
|
||||
}
|
||||
|
||||
// Iterate through the KSM clients, processing using the user-specific
|
||||
// config first (if it exists), to ensure that any admin-defined values
|
||||
@@ -431,6 +480,7 @@ public class KsmSecretService implements VaultSecretService {
|
||||
addRecordTokens(tokens, "KEEPER_USER_",
|
||||
ksm.getRecordByLogin(filter.filter(username), null));
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
|
||||
|
Reference in New Issue
Block a user