Plugin-security.policy has not effect

I'm trying to build a plugin that needs the following permissions:

grant {
  permission java.lang.RuntimePermission "accessDeclaredMembers";
};

When I install the plugin I get the warning saying that the plugin asks for permissions (which means the installation sees the above) but then when I try to use the plugin I get an error saying:

java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")

What gives?

Did you read this? https://www.elastic.co/guide/en/elasticsearch/plugins/current/plugin-authors.html#plugin-authors-jsm

Yes I have. I have my code in a doPrivileged block but it's not changing anything.

 public int analyzeSentiment(String text){
   return AccessController.doPrivileged(new PrivilegedAction<Integer>() {
        public Integer run(){
            StringByValue str = new StringByValue();
            str.setP(text);
            str.setN(text.length());
            return gs.ClassifySentiment(str);
        }
    });
}

PS: I think the ES docs for plugins (for authors) have to be a lot more expansive than they are. There is barely any documentation for it apart from the page you linked and the 4 examples linked in it.

2 Likes

Are you sure the policy file is within the plugin distribution ? When you install it, are you prompted to authorize additional settings?

Yes. When it installs I get the big warning with all the @ symbols. However I'm using docker so there's no stdin so I'm using the -b flag for the installation (don't think that makes a difference). Then I get a message saying successfully installed *plugin_name*. I also checked the actual build to make sure the file is there. I'm running out of ideas here.

I don't know. May be @rjernst knows?

If the permission check is failing, something on the stack does not have permission. You can debug this using the security debug sysprop in java:
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars003.html

Add this to your jvm.options:
-Djava.security.debug=access,failure

Then find the failure and paste here (in a gist if it is large), it should show exactly what is failing the check.

Okay so I did that. Here's the paste of the relevant part of the debug log. I can't really figure out what's making it fail.

The way to read this is to look at the failing stack, back to the doPrivileged call:

access: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
java.lang.Exception: Stack trace
    at java.base/java.lang.Thread.dumpStack(Thread.java:1387)
    at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:462)
    at java.base/java.security.AccessController.checkPermission(AccessController.java:895)
    at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:322)
    at java.base/java.lang.Class.checkMemberAccess(Class.java:2848)
    at java.base/java.lang.Class.getDeclaredFields(Class.java:2247)
    at com.sun.jna.Structure.getFieldList(Structure.java:931)
    at com.sun.jna.Structure.validateFields(Structure.java:1160)
    at com.sun.jna.Structure.<init>(Structure.java:189)
    at com.sun.jna.Structure.<init>(Structure.java:182)
    at com.sun.jna.Structure.<init>(Structure.java:169)
    at com.sun.jna.Structure.<init>(Structure.java:161)
    at de.spinscale.elasticsearch.ingest.sentiment.GoString.<init>(GoString.java:16)
    at de.spinscale.elasticsearch.ingest.sentiment.SentimentAnalyzer.lambda$analyzeSentiment$0(SentimentAnalyzer.java:41)
    at java.base/java.security.AccessController.doPrivileged(Native Method)

Everything on that stack must have permission. Later in the log, we see exactly what doesn't have permission:

access: domain that failed ProtectionDomain  (file:/usr/share/elasticsearch/lib/jna-4.5.1.jar <no signer certificates>)

The problem is jna is a jar provided by elasticsearch, and your bare grant statement only applies to jars provided by your plugin. Unfortunately there isn't currently a way for a plugin to extend the permissions of core jars.

I see three possible solutions:

  • Modify your code to not use jna
  • Modify your jna usage to not trigger accessDeclaredMembers (note that this means you are getting all private/protected variables and methods, is this really necessary, or do you just need public?)
  • Set the system policy to give jna access (elasticsearch builds on this policy if it exists). This will be tricky, as you need to give the exact path to the jna jar within the elasticsearch installation. It would look something like this:
grant codeBase "/usr/share/elasticsearch/lib/jna-4.5.1.jar" {
   permission java.lang.RuntimePermission "accessDeclaredMembers";
}

Note however that this is extremely fragile: it can and will change as elasticsearch in upgraded, so the first two options are much better, but this might get you by temporarily.

2 Likes

Just tried option 3 and it doesn't work. The debug log is pretty much the same. Also I think it should be:

grant codeBase "file:/usr/share/elasticsearch/lib/jna-4.5.1.jar" {
   permission java.lang.RuntimePermission "accessDeclaredMembers";
} 

Without the file: prefix it gives me an error about a malformed URL and with it, it seems like it doesn't recognize it because I'm not getting the warning when installing the plugin now.

Regarding the second option, I'm not explicitly calling any protected or private code myself. I'm just inheriting a class from JNA which apparently has some protected/private methods (including the constructor) so I can't even use it as a superclass. It sucks that this is so hard to do :confused:

I'm not going to use JNA anymore. I found a decent alternative but I have to execute a binary. I changed the security permissions and I'm now getting a nullpointerexception because ES apparently doesn't have permission to execute the file (even though I gave it read and execute perms):

exception: java.io.IOException: Cannot run program "/usr/share/elasticsearch/bin/ingest-opennlp/sentiment": error=13, Permission denied

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.