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>

Reply via email to