JEP411: Missing use-case: Security Manager and Java Scripting (JSR 223)
Peter Firmstone
peter.firmstone at zeus.net.au
Thu Jul 22 01:01:39 UTC 2021
JEP 411 is quite a conundrum for downstream developers that depend on SM.
SecurityManager has its problems, but it's the only authorization layer
we have.
If I had a complaint about SM, it's the implementation of:
1. SocketPermission doesn't allow netmask wild cards.
2. Thread inherited AccessControlContext and Executors.
My own implementations are not subject to the issues that the JVM's SM
and Policy provider implementations suffer documented in JEP 411.
I think if authorization was redesigned from the ground up, Java would
have a privileged mode, or privileged call (where permissions are
checked) and everything else would be unprivileged, so there is no stack
walk required for unpriviledged code, only privileged and it would be
very short and not persist across threads.
Java has a very large API surface, compared to other languages.
It's a difficult decision to stick with Java, I keep looking at the
other languages with their smaller API's , I keep wondering if I'm
better off in the long term changing to another development language.
OpenJDK has quite rightly identified that the cost of maintaining an
authorization layer for Java is too high, given it's vast API surface
area, it would be simpler to develop an authorization layer for another
language with a smaller API. For now I'm trying to stick with Java.
But the reality is, I have until 2030 to transition if I revert to Java
8, and Java 11 gets us through to 2029. Java has some great new
features, but they come at a cost. Everything is a compromise, and one
must select the right compromise. I have a lot of code I've developed in
Java and have also invested a lot of time into it. It is also likely
there will be more deprecation for removal JEP's in future, I mean,
someone might come up with the argument we don't require dynamic class
loading, because that's for applets. Dynamic class loading allows
loading of untrusted code, so we should only allow trusted code to run
that was installed statically by an administrator, because Java is only
for Servers now.
This is the message I'm getting loud and clear, Java is only for servers
in future. I'm in the server space, but it's not the server model that
OpenJDK developers have in mind. This reminds me of the Unix
workstation, with Unix retreating to servers then being replaced by Linux.
When is Java no longer Java? Rather than continuing to evolve Java,
why not use the JVM to create a new language project, or maybe a CVM
(Clojure virtual machine?) which learns from the lessons of Java and let
Java continue to be Java?
For now at least, I am trying to stick with Java, but it's not a clear
decision.
It would be an easier decision to make if OpenJDK could provide some
hooks where permission checks are currently made, so that we can
implement our own authorization layer.
Anyway, these are just my personal thoughts and opinions, I do realize
that they are probably unwelcome here.
Regards,
Peter.
On 22/07/2021 5:31 am, Sean Mullan wrote:
> Hi,
>
> I am not an expert in JSR 223. However, some JSR 223 implementations
> include a mechanism for restricting access to Java classes, for
> example Nashorn [1] and Rhino [2], which might be sufficient for your
> needs. (Note, Nashorn was deprecated and removed from JDK 15 [3]). I
> think most of the permissions you list below can be mapped to a small
> list of Java classes that check those permissions. Also, with strong
> encapsulation of JDK internals enforced by default in JDK 17 [4], you
> get additional protection that is not dependent on the Security Manager.
>
> What JSR 223 implementation do you use?
>
> --Sean
>
> [1]
> https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html#classfilter_introduction
> [2]
> https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ClassShutter.html
> [3] https://openjdk.java.net/jeps/372
> [4] https://openjdk.java.net/jeps/403
>
> On 7/21/21 12:35 PM, Alexey Shponarsky wrote:
>> Hello,
>>
>> At Jelastic PaaS, we are using SecurityManager within Java Scripting
>> (JSR 223). Specifically, Java Scripting allows us and our customers
>> to easily extend the core platform functionality with custom logic.
>> The developers can execute their custom scriptlets inside a Java
>> Scripting runtime environment with pre-injected core platform API
>> methods. For example,
>>
>> //@req(pathFrom, pathTo)
>>
>> varmountFrom = "${nodes.build.first.id <http://nodes.build.first.id/>}",
>>
>> envName = "${settings.targetEnv}",
>>
>> mountTo = "cp";
>>
>> varresp = jelastic.env.file.RemoveMountPointByGroup(envName, session,
>> mountTo, pathTo);
>>
>> if(resp.result != 0) returnresp;
>>
>> returnjelastic.env.file.AddMountPointByGroup(envName, session,
>> mountTo, pathTo, 'nfs', null, pathFrom, mountFrom, '', false);
>>
>> As Java Scripting engine / technology provides quite powerful
>> runtimes, we have to restrict certains actions such as execution of
>> any reflection methods, change of any system environment variables,
>> exit, calling some dangerous static methods, reading files outside of
>> the sandbox folder, etc. The SecurityManager mechanism provided an
>> ability to configure permissions easily.
>>
>> To achieve this we create an instance of AccessControlContext with
>> required permissions and pass it to AccessController.doPrivileged
>> <https://docs.oracle.com/javase/8/docs/api/java/security/AccessController.html#doPrivileged-java.security.PrivilegedAction-java.security.AccessControlContext->method:
>>
>> //Create list of Permission:
>>
>> Collection<Permission> perms= new LinkedList<Permission>();
>>
>> perms.add(new RuntimePermission("createClassLoader"));
>>
>> perms.add(new RuntimePermission("getClassLoader"));
>>
>> perms.add(new RuntimePermission("accessDeclaredMembers"));
>>
>> perms.add(new RuntimePermission("getProtectionDomain"));
>>
>> perms.add(new PropertyPermission("*", "read"));
>>
>> perms.add(new SocketPermission("*", "connect,accept,resolve"));
>>
>> perms.add(new SocketPermission("localhost:0-",
>> "connect,accept,resolve,listen"));
>>
>> //Create AccessControlContext
>>
>> ProtectionDomain domain = new ProtectionDomain(new CodeSource(null,
>> (Certificate[]) null), perms);
>>
>> AccessControlContext acc= new AccessControlContext(new
>> ProtectionDomain[]{domain});
>>
>> //Run untrusted code using created AccessControlContext
>>
>> @Override
>>
>> public ScriptEvalResponse call() throws Exception {
>>
>> Object obj = AccessController.doPrivileged(new
>> PrivilegedAction<Object>() {
>>
>> @Override
>>
>> public Object run() {
>>
>> try {
>>
>> Object response = compiledScript.eval(ctx);
>>
>> ScriptEvalResponse evalResponse = new ScriptEvalResponse(Response.OK);
>>
>> evalResponse.setResponse(response);
>>
>> return evalResponse;
>>
>> } catch (Exception ex) {
>>
>> logger.debug("Error occurred during eval script:", ex);
>>
>> return ex;
>>
>> }
>>
>> }
>>
>> }, acc);
>>
>> if (obj instanceof Exception) {
>>
>> throw (Exception) obj;
>>
>> }
>>
>> return (ScriptEvalResponse) obj;
>>
>> }
>>
>> How can we implement a similar solution after the removal of
>> SecurityManager? Could you help us to find an alternative?
>>
>>
>>
>> --
>> Alexey Shponarsky Director of R&D
>> Twitter <https://twitter.com/Jelastic>Facebook
>> <https://www.facebook.com/Jelastic/>YouTube
>> <http://www.youtube.com/user/JelasticCloud>LinkedIn
>> <https://www.linkedin.com/company/2426564/>Google+
>> <https://plus.google.com/+JelasticInc>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20210722/8b7d36d1/attachment.htm>
More information about the security-dev
mailing list