JS policy should use ScriptingSPI
This commit is contained in:
parent
93105a2182
commit
0b5e6b0d49
3 changed files with 36 additions and 24 deletions
|
@ -17,37 +17,27 @@
|
|||
*/
|
||||
package org.keycloak.authorization.policy.provider.js;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.ScriptModel;
|
||||
import org.keycloak.scripting.InvocableScriptAdapter;
|
||||
import org.keycloak.scripting.ScriptingProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class JSPolicyProvider implements PolicyProvider {
|
||||
|
||||
private Supplier<ScriptEngine> engineProvider;
|
||||
|
||||
public JSPolicyProvider(Supplier<ScriptEngine> engineProvider) {
|
||||
this.engineProvider = engineProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(Evaluation evaluation) {
|
||||
ScriptEngine engine = engineProvider.get();
|
||||
|
||||
engine.put("$evaluation", evaluation);
|
||||
|
||||
Policy policy = evaluation.getPolicy();
|
||||
|
||||
try {
|
||||
engine.eval(policy.getConfig().get("code"));
|
||||
} catch (ScriptException e) {
|
||||
getInvocableScriptAdapter(policy, evaluation).eval();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error evaluating JS Policy [" + policy.getName() + "].", e);
|
||||
}
|
||||
}
|
||||
|
@ -56,4 +46,24 @@ public class JSPolicyProvider implements PolicyProvider {
|
|||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
private InvocableScriptAdapter getInvocableScriptAdapter(Policy policy, Evaluation evaluation) {
|
||||
String scriptName = policy.getName();
|
||||
String scriptCode = policy.getConfig().get("code");
|
||||
String scriptDescription = policy.getDescription();
|
||||
|
||||
AuthorizationProvider authorization = evaluation.getAuthorizationProvider();
|
||||
RealmModel realm = authorization.getRealm();
|
||||
|
||||
ScriptingProvider scripting = authorization.getKeycloakSession().getProvider(ScriptingProvider.class);
|
||||
|
||||
//TODO lookup script by scriptId instead of creating it every time
|
||||
ScriptModel script = scripting.createScript(realm.getId(), ScriptModel.TEXT_JAVASCRIPT, scriptName, scriptCode, scriptDescription);
|
||||
|
||||
//how to deal with long running scripts -> timeout?
|
||||
return scripting.prepareInvocableScript(script, bindings -> {
|
||||
bindings.put("script", script);
|
||||
bindings.put("$evaluation", evaluation);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package org.keycloak.authorization.policy.provider.js;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
|
@ -19,9 +15,7 @@ import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
|||
*/
|
||||
public class JSPolicyProviderFactory implements PolicyProviderFactory<JSPolicyRepresentation> {
|
||||
|
||||
private static final String ENGINE = "nashorn";
|
||||
|
||||
private JSPolicyProvider provider = new JSPolicyProvider(() -> new ScriptEngineManager().getEngineByName(ENGINE));
|
||||
private JSPolicyProvider provider = new JSPolicyProvider();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
|
|
@ -78,6 +78,14 @@ public class InvocableScriptAdapter implements Invocable {
|
|||
}
|
||||
}
|
||||
|
||||
public Object eval() throws ScriptExecutionException {
|
||||
try {
|
||||
return scriptEngine.eval(scriptModel.getCode());
|
||||
} catch (ScriptException e) {
|
||||
throw new ScriptExecutionException(scriptModel, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getInterface(Class<T> clazz) {
|
||||
return getInvocableEngine().getInterface(clazz);
|
||||
|
|
Loading…
Reference in a new issue