step.plugins.parametermanager.ParameterManagerPlugin Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (C) 2020, exense GmbH
*
* This file is part of STEP
*
* STEP is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* STEP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with STEP. If not, see .
******************************************************************************/
package step.plugins.parametermanager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import step.core.accessors.AbstractOrganizableObject;
import step.core.accessors.InMemoryAccessor;
import step.core.accessors.LayeredAccessor;
import step.core.artefacts.reports.ReportNode;
import step.core.dynamicbeans.DynamicValue;
import step.core.encryption.EncryptionManagerException;
import step.core.execution.ExecutionContext;
import step.core.execution.ExecutionContextBindings;
import step.core.execution.ExecutionEngineContext;
import step.core.objectenricher.ObjectPredicate;
import step.core.plugins.IgnoreDuringAutoDiscovery;
import step.core.plugins.Plugin;
import step.core.plugins.exceptions.PluginCriticalException;
import step.core.variables.VariableType;
import step.core.variables.VariablesManager;
import step.engine.execution.ExecutionManager;
import step.engine.plugins.AbstractExecutionEnginePlugin;
import step.engine.plugins.BasePlugin;
import step.functions.Function;
import step.parameter.Parameter;
import step.parameter.ParameterManager;
import step.parameter.ParameterScope;
import step.security.SecurityManager;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
@Plugin(dependencies = {BasePlugin.class})
@IgnoreDuringAutoDiscovery
public class ParameterManagerPlugin extends AbstractExecutionEnginePlugin {
private static final String RESOLVER_PREFIX_PARAMETER = "parameter:";
private static final String PARAMETER_SCOPE_VALUE_DEFAULT = "default";
private static final String PARAMETERS_BY_SCOPE = "$parametersByScope";
public static Logger logger = LoggerFactory.getLogger(ParameterManagerPlugin.class);
protected ParameterManager parameterManager;
private boolean grantAccessToProtectedParametersWithinPlans;
private boolean isConfigured = false;
protected ParameterManagerPlugin(){
}
public ParameterManagerPlugin(ParameterManager parameterManager) {
super();
configure(parameterManager);
}
protected void configure(ParameterManager parameterManager) {
this.parameterManager = parameterManager;
grantAccessToProtectedParametersWithinPlans = parameterManager.getEncryptionManager() == null;
isConfigured = true;
}
@Override
public void initializeExecutionContext(ExecutionEngineContext executionEngineContext, ExecutionContext context) {
if (!isConfigured) {
return;
}
super.initializeExecutionContext(executionEngineContext, context);
context.put(ParameterManager.class,
ParameterManager.copy(parameterManager, new LayeredAccessor<>(List.of(new InMemoryAccessor<>(), parameterManager.getParameterAccessor())))
);
}
@Override
public void executionStart(ExecutionContext context) {
if (!isConfigured) {
return;
}
ReportNode rootNode = context.getReport();
// Resolve the active parameters
Map contextBindings = ExecutionContextBindings.get(context);
ObjectPredicate objectPredicate = context.getObjectPredicate();
Map allParameters = getParameterManagerFromContext(context).getAllParameters(contextBindings, objectPredicate);
// Add all the active parameters to the execution parameter map of the Execution object
buildExecutionParametersMapAndUpdateExecution(context, allParameters);
initializeParameterResolver(context, allParameters);
// Build the map of parameters by scope
Map>> parametersByScope = getAllParametersByScope(allParameters);
context.put(PARAMETERS_BY_SCOPE, parametersByScope);
// Declare the global parameters including protected parameters if no encryption manager is available
addScopeParametersToContext(context, rootNode, parametersByScope, ParameterScope.GLOBAL,
PARAMETER_SCOPE_VALUE_DEFAULT, grantAccessToProtectedParametersWithinPlans, true);
}
@Override
public void beforeFunctionExecution(ExecutionContext context, ReportNode node, Function function) {
if (!isConfigured) {
return;
}
// Function scoped parameters
@SuppressWarnings("unchecked")
Map>> parametersByScope = (Map>>) context.get(PARAMETERS_BY_SCOPE);
// Declare the global protected parameters that haven't been added to the
// context in executionStart
addScopeParametersToContext(context, node, parametersByScope, ParameterScope.GLOBAL,
PARAMETER_SCOPE_VALUE_DEFAULT, !grantAccessToProtectedParametersWithinPlans, false);
Map attributes = function.getAttributes();
if(attributes != null) {
addScopeParametersToContext(context, node, parametersByScope, ParameterScope.FUNCTION,
attributes.get(AbstractOrganizableObject.NAME), true, true);
if(attributes.containsKey(Function.APPLICATION)) {
addScopeParametersToContext(context, node, parametersByScope, ParameterScope.FUNCTION,
attributes.get(Function.APPLICATION) + "." + attributes.get(AbstractOrganizableObject.NAME),
true, true);
addScopeParametersToContext(context, node, parametersByScope, ParameterScope.APPLICATION,
attributes.get(Function.APPLICATION), true, true);
}
}
}
protected ParameterManager getParameterManagerFromContext(ExecutionContext executionContext){
return executionContext.require(ParameterManager.class);
}
private void buildExecutionParametersMapAndUpdateExecution(ExecutionContext context, Map allParameters) {
ExecutionManager executionManager = context.getExecutionManager();
// This map corresponds to the parameters displayed in the panel "Execution Parameters" of the execution view
// which lists the parameters available in the plan after activation (evaluation of the activation expressions)
Map executionParameters = new HashMap<>();
allParameters.forEach((k,v)->{
DynamicValue value = v.getValue();
executionParameters.put(k, value != null ? value.get():"");
});
executionManager.updateExecution(execution-> {
Map parameters = execution.getParameters();
if(parameters == null) {
parameters = new HashMap<>();
execution.setParameters(parameters);
}
parameters.putAll(executionParameters);
});
}
private Map>> getAllParametersByScope(Map allParameters) {
Map>> parametersByScope = new HashMap<>();
allParameters.forEach((k,v)->{
ParameterScope scope = v.getScope() != null ? v.getScope() : ParameterScope.GLOBAL;
String scopeValue = v.getScopeEntity() != null ? v.getScopeEntity() : PARAMETER_SCOPE_VALUE_DEFAULT;
parametersByScope.computeIfAbsent(scope, t->new HashMap>())
.computeIfAbsent(scopeValue, t->new ArrayList())
.add(v);
});
return parametersByScope;
}
private void addScopeParametersToContext(ExecutionContext context, ReportNode node, Map>> parametersByScope,
ParameterScope scope, String scopeValue, boolean includeProtectedParameters, boolean includeNonProtectedParameters) {
final VariablesManager varMan = context.getVariablesManager();
Map> scopeSpecificParameters = parametersByScope.get(scope);
if(scopeSpecificParameters != null) {
List scopeValueSpecificParameters = scopeSpecificParameters.get(scopeValue);
if(scopeValueSpecificParameters != null) {
scopeValueSpecificParameters.forEach(p->{
if((isProtected(p) && includeProtectedParameters) || (!isProtected(p) && includeNonProtectedParameters)) {
varMan.putVariable(node, VariableType.IMMUTABLE, p.getKey(), getParameterValue(p, getParameterManagerFromContext(context)));
}
});
}
}
}
private void initializeParameterResolver(ExecutionContext context, Map parameters) {
final ConcurrentMap parameterValues = parameters.values().stream().map(p -> {
return new SimpleEntry(p.getKey(), getParameterValue(p, getParameterManagerFromContext(context)));
}).collect(Collectors.toConcurrentMap(SimpleEntry::getKey, SimpleEntry::getValue));
context.getResolver().register(e -> {
if (e != null && e.startsWith(RESOLVER_PREFIX_PARAMETER)) {
// As the parameterValues map may contain protected parameter values, calling
// this method from custom scripts is forbidden
SecurityManager.assertNotInExpressionHandler();
String key = e.replace(RESOLVER_PREFIX_PARAMETER, "");
String value = parameterValues.get(key);
if (value != null) {
return value;
} else {
return null;
}
} else {
return null;
}
});
}
private boolean isProtected(Parameter p) {
Boolean isProtectedValue = p.getProtectedValue();
return isProtectedValue != null && isProtectedValue;
}
private String getParameterValue(Parameter p, ParameterManager parameterManager) {
String encryptedValue = p.getEncryptedValue();
String value;
if(encryptedValue != null) {
if(parameterManager.getEncryptionManager() != null) {
try {
value = parameterManager.getEncryptionManager().decrypt(encryptedValue);
} catch (EncryptionManagerException e) {
throw new PluginCriticalException("Error while decrypting value of parameter "+p.getKey(), e);
}
} else {
throw new PluginCriticalException("Unable to decrypt value of parameter "+p.getKey()+". No encryption manager available");
}
} else {
value = p.getValue().get();
}
return value;
}
public static void putVariables(ExecutionContext context, ReportNode rootNode, Map parameters, VariableType type) {
VariablesManager varMan = context.getVariablesManager();
if(parameters!=null) {
for(String key:parameters.keySet()) {
varMan.putVariable(rootNode, type, key, parameters.get(key));
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy