<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <br>
    <div class="moz-cite-prefix">On 20/06/2023 9:04 pm, Ron Pressler
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">On 20 Jun 2023, at 06:26, Peter Firmstone <a class="moz-txt-link-rfc2396E" href="mailto:peter.firmstone@zeus.net.au"><peter.firmstone@zeus.net.au></a> wrote:

Don't get me wrong, it's good that OpenJDK is improving encapsulation, it's just OpenJDK is also undoing years of tested and hardened API's,
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
You probably meant that as a bad thing, but I read it as thank you for serving your users! </pre>
    </blockquote>
    <p>No, not at all, you're welcome.   I recognise there are different
      levels of trust, for different applications, you're bringing some
      of the benefits a well deployed SM provides, without the
      deployment cost to people who aren't using it now and in doing so
      improving their security.   Although we don't agree on everything,
      there are things we agree on, and just because we disagree on some
      things doesn't mean I don't respect your opinions.   I realise
      that SM will be removed, I'm just disappointed that we are being
      prevented from reimplementing a replacement authorization layer in
      Java, without any compromise from OpenJDK it's not possible.  We
      at least need to retain some kind of privilege action mechanism.  
      That doesn't even have to be a privileged action, maybe it could
      be an annotation, that we can find using StackWalker.<br>
    </p>
    <p>Authorization isn't a one size fits all, it's for high value
      assets, usually determined by risk assessment, Java was once
      promoted as a secure language for enterprise.<br>
    </p>
    <p>If data protected isn't of high value, or is of low complexity, a
      solution of appropriate cost will be applied, in many cases that
      isn't SM, however removing SM will reduce security below an
      acceptable level for a percentage of developers and software
      projects, the number may be small, but the impact will be
      widespread, just look at how widely deployed ElasticSearch and
      OpenSearch are.   JGDMS only gets about 30 unique cloners per
      fortnight, and about 50 clones, but sometimes its up around 200, I
      don't know how widely used it is.   But we aren't the only
      projects using it for where there is no replacement possible. 
      There are many parts of the Java API, which aren't used by all
      developers.   So far, even though I still use some of the other
      API's which have been removed from OpenJDK, it's been pretty
      straightforward to replace them with something else.  SM (JAAS
      Authorization) isn't replaceable.<br>
    </p>
    <p>I've been using and SM for 20 years, it's a lot simpler than
      people realise, there is a way to use it, that makes it easy, and
      there are ways not to, that are guaranteed to cause pain. <br>
    </p>
    <p>Arguments against SM, that I've read on this list are based on
      bad practises, or the lack of tooling provided with the default
      implementation, this indicates a lack of experience in use, I know
      that Alan and Sean were involved during the early days with Li
      Gong, but I'm pretty sure they don't have much experience
      deploying it, feel free to prove me wrong if my assumption is
      incorrect.   I'd suggest cost of maintenance also appears
      overestimated, this is partly due to policy, I have offered to
      assist with maintenance, however my offer was rejected, as this is
      considered part of security, I am not permitted to assist, I could
      submit patches to this list, but I'm not sure they'll be welcomed
      or accepted.    <br>
    </p>
    <p>When SM is used incorrectly, complexity is significantly
      increased, however the API's could be simplified, which would
      improve security and reduce complexity and maintenance.  <br>
    </p>
    <p>SM no more impacts developers who don't use it, than developers
      who don't use XML.   The biggest maintenance burden I see on
      OpenJDK is Java Serialization.<br>
    </p>
    <p>One dedicated full time resource should be sufficient, to review
      code changes to check for compliance.  It's not difficult for me
      to track down where permissions are leaking from Java API's,
      however I've assumed that as it's deprecated, there will be little
      interest in fixing them, is my assumption incorrect?   I think
      this looks like a big task, because there is a lack of tooling.  
      SpotBugs also provides static analysis to find these problems,
      although now that SM is deprecated, users are requesting it to be
      removed from SpotBugs.<br>
    </p>
    <p>Even an imperfect authorization layer is far better than no
      authorization layer at all.<br>
    </p>
    <p>Lets discuss how it should be used, and what benefits it provides
      and the situations when you might want to use it.    I only ask
      that people keep an open mind and for the moment, forget all the
      horror stories.  I realise this is academic now, and unlikely to
      change anything, however documenting it here might serve some
      historical purpose.<br>
    </p>
    <p>Firstly, if used correctly, using authorization is no more
      difficult than using an Executor framework.</p>
    <p>Some ground rules:</p>
    <ol>
      <li>Users create data.  The level of trust you have for the user
        determines the level of trust you have for their data.<br>
      </li>
      <li>Developers create code.   The level of trust you have for the
        developers determines the level of trust you have for their
        code.<br>
      </li>
      <li>Always, always, use automated tooling for the creation and
        management of policy files, start with an empty policy file with
        no permissions.<br>
      </li>
      <li>Apply the principle of least privilege.</li>
      <li>Developers, users and administrators will make mistakes, no
        one is perfect, mistakes can be fixed once identified, try to
        find ways to identify mistakes, for example, check generated
        policy files for leaking privileges, this indicates that a
        developer has forgotten to use a PrivilegedAction.</li>
      <li>Attempts at sandboxing have always failed historically, with
        increasing language complexity, the more likely a sandbox will
        be broken through, never run untrusted code, avoid parsing data
        from unauthenticated sources.  For example, code can perform DOS
        and use up all the memory on your system to bring it down.  
        Pictures can contain code, which can be compiled and run, data
        can contain SQL injection attacks.   Always validate input, eg
        use pattern matching to sanitize text.</li>
      <li>Some architectures are more secure than others, for example,
        OpenBSD on Sparc or ARM is not susceptible to Spectre, Meltdown
        or similar attacks.<br>
      </li>
      <li>SM is not a sandbox, it is an authorization layer only.<br>
      </li>
    </ol>
    <p>There are different levels of trust, for different users and
      different developers.   Note that historically, Sun or the JRE had
      unlimited trust for its own developers, this was a mistake.   100%
      Trusted code should be minimised to bootstrap code.</p>
    <p>Trust is from 0% to 100%.  0% is an unauthenticated user
      (unauthenticated unknown data source), while 100% is your
      administrator, there are many levels of trust in between.  
      Applied to developers, 0% is the unknown software your user
      downloaded from the internet, 100% shouldn't be given to
      developers, only bootstrap code.  I don't trust myself 100%
      either.   <br>
    </p>
    <p>General guidance:</p>
    <ol>
      <li> If you are not authenticating users, using data integrity
        checksums, or encryption, then you are unlikely to benefit from
        SM.  SM only provides authorization, you cannot make
        authorization decisions without first authenticating, you have
        to establish trust exists, before you can determine an
        appropriate level of trust.<br>
      </li>
      <li>Privileges must be granted to both users and developers, for
        software to function, using tooling to determine permissions
        required.<br>
      </li>
      <li>There is no such thing as 100% trusted developers, all
        developers make mistakes.   Java Serialization is my case in
        point, it bypassed all protections and there was no
        DataPermission("deserialize") to allow authorization decisions
        to be made based on the authenticated user who supplied the
        data, in many cases, due to the 100% trust given to Java
        de-serialization code, there were no adequate defences.<br>
      </li>
      <li>When the developer is given 100% trust (AllPermission, or a
        JRE ProtectionDomain with a null codesource), then the user will
        also be trusted 100%, when this code parses the user data, this
        is why so many gadget attacks were successful.</li>
      <li>If 100% trust is given to developers, it adds unnecessary
        programming complexity to reduce that trust for users, that's
        seldom applied in practise.</li>
      <li>As the developer, if you are writing code that parses data,
        you must add permission checks before parsing, this allows the
        prevention of parsing data from an untrusted user.</li>
      <li>As the developer, if you are opening a network socket,
        accessing the file system, key stores or properties, do so using
        a PrivilegedAction.  Keep the privileged action short and sweet,
        eg if opening a socket, only do what's necessary to open the
        socket, and return it.</li>
      <li>PrivilegedAction's can be used with AccessController, and
        AccessControlContext, to elevate, preserve or reduce privilege,
        however it is most commonly used to elevate it.</li>
      <li>Don't use the Policy provider supplied with OpenJDK, it relies
        on DNS.   Performance and scaling is horrible, with many
        synchronized locks, network and file system access, sorry I
        don't intend to offend, it was written a long time ago, it's
        basically broken.</li>
      <li>Generate your policy files using a deployment environment, by
        working the software through all of its use cases, for each
        role.   Properties should be defined, so the policy file
        generation tool can replace file paths and network addresses in
        policy files with configurable properties.   The policy writing
        tool only appends missing permissions, this is to allow policy
        files to be built up incrementally, periodically, the entire
        policy file should be regenerated, for example, following a
        software update.</li>
      <li>Permissions in policy files will determine the users who can
        access properties, files, network, or developers who use agents.</li>
      <li>All external connections should require authentication.   All
        authenticated connections should be given a thread of execution
        with the Subject of the authenticated user.</li>
      <li>All code should either be signed, or be given a SHA256 hash or
        better.</li>
      <li>Permissions can be used to control many Java features, such as
        the attach api, reflection, code downloads, network connections,
        but has no power to control Java serialization for example.<br>
      </li>
    </ol>
    <p>Example of a policy grant made by the policy writing tool, notice
      how both the code and principal are required to have these
      permissions, that means the user cannot accidentally grant these
      privileges to untrusted code, and it means the code doesn't have
      permission if the user isn't authenticated, or has the wrong
      credentials, the tooling works this out for you, following the
      rules of the principle of least privilege, you don't have to
      figure it out yourself, tooling significantly reduces complexity
      and provides for embarrassment free, well organised deployment:</p>
    <p>grant codebase <a class="moz-txt-link-rfc2396E" href="file:/${qa.home}/lib/jinitests.jar">"file:/${qa.home}/lib/jinitests.jar"</a>,<br>
          principal javax.security.auth.x500.X500Principal "CN=Tester"<br>
      {<br>
          permission net.jini.security.GrantPermission
      "java.lang.reflect.ReflectPermission
      \"newProxyInPackage.org.apache.river.mahalo\", \"\";
      org.apache.river.api.io.DeSerializationPermission \"ATOMIC\";
      java.lang.RuntimePermission
      \"accessClassInPackage.com.sun.proxy\", \"\";
      org.apache.river.api.io.DeSerializationPermission \"ATOMIC\";
      java.lang.RuntimePermission
      \"accessClassInPackage.com.sun.proxy\", \"\";";<br>
          permission net.jini.security.GrantPermission
      "net.jini.security.AuthenticationPermission
      \"javax.security.auth.x500.X500Principal \\\"CN=Tester\\\" peer
      javax.security.auth.x500.X500Principal \\\"CN=Mahalo\\\"\",
      \"connect\";";<br>
          permission java.net.URLPermission
      <a class="moz-txt-link-rfc2396E" href="http://${HOST}:9080/mahalo-dl-3.1.1-SNAPSHOT.jar">"http://${HOST}:9080/mahalo-dl-3.1.1-SNAPSHOT.jar"</a>, "GET:";<br>
          permission net.jini.security.AuthenticationPermission
      "javax.security.auth.x500.X500Principal \"CN=Tester\" peer
      javax.security.auth.x500.X500Principal \"CN=Mahalo\"", "accept";<br>
          permission java.io.FilePermission
      "${jsk.home}${/}lib-dl${/}${mahalo-dl.jar}", "read";<br>
          permission java.io.FilePermission
      "${jsk.home}${/}lib${/}${mahalo.jar}", "read";<br>
          permission java.io.FilePermission
      "${qa.home}${/}harness${/}configs${/}jsse${/}mahalo${/}mahalo.config",
      "read";<br>
          permission java.io.FilePermission
      "${qa.home}${/}harness${/}policy${/}defaultsecuremahalo.policy",
      "read";<br>
          permission java.io.FilePermission
      "${qa.home}${/}harness${/}trust${/}mahalo.keystore", "read";<br>
          permission java.io.FilePermission
      "${qa.home}${/}lib${/}qa1-mahalo-dl.jar", "read";<br>
      };<br>
    </p>
    <p>If we remove the ability of the Java platform to manage different
      levels of trust, by removing authorization, then all trust becomes
      100%, for users who authenticate and developers whose code you
      run, you grant them 100% trust, to access anything that might be
      available from within the JVM.   So now you have to set file
      permissions and firewall permissions to prevent the application
      from doing unauthorized things.<br>
    </p>
    <p>I would also go as far to say that no permissions is the right
      approach for loom, one perform a privileged action in a Thread,
      maybe using a task in a thread pool, then hand it off to loom, the
      same goes for ForkJoin thread pools.<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">Our duty is to maximise the utility of the JDK. The reality of the economics of software — in this case, the finite resources available to us — demands that we work on features with a relatively high ratio of utility to cost and that we do not work on features with a relatively low ratio of utility to cost. And by “utility” I mean economic utility, i.e. the total value to the ecosystem. If someone invented a galactic teleporter that no one uses, even for silly reasons — say, they don’t like its colour — its economic utility is zero.

Let me put it bluntly and only somewhat inaccurately: Every feature added to Java over the past few years is one that we believe will serve at least a million Java developers (directly or indirectly); in fact, most features added to Java have had a million users in other languages before even being considered for addition to Java based on their technical merits (of course, the calculus changes depending on cost).


</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">that we're expected to come up with DIY solutions for, with zero care from OpenJDK and some very bad examples of alternative solutions,
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
The alternative solutions are the ones preferred by the vast majority of users who, I would assume, think they are superior solutions. We are simply unable to also provide a separate solution, let alone such an expensive one, for a very small minority. It would be unfair to most of our users.

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">not to mention a completely wrong assessment of SM based on an outdated poorly maintained implementation, with lack of use and maintenance burden (when the community is willing but not allowed to maintain it) as justification for it's removal.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">

The community has not shown any willingness to maintain SM. As with other features, we only ever keep something to be maintained by others if they show both the commitment and the requisite ability (e.g. the JDK ports and GCs that are not maintained by Oracle). There are other companies beside Oracle that regularly contribute substantial, excellent work to OpenJDK, but to date none of them do so at the scale required for this, and we’re talking companies that pay several developers to work full time on OpenJDK. And that’s not even the worst of it. One of the things that makes SM so costly is that it’s not a separable feature but a cross-cutting concern that every JDK developer working primarily in the core-libraries area needs to worry about it when working on many changes in many areas.

I don’t think you’ve begun to appreciate the enormity of this task, but even you complained that injecting doPrivileged calls in keeping up with all the changes to the JDK is too much work and that’s before studying the test suite that tests all of these places. 

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
SecurityManager is just an authorization layer (that allows assigning different levels of trust), not a magic wand designed to solve all security problems (or sandbox, it was only a component in the sandbox, along with bytecode verification and ClassLoader visibility), to be discarded because it doesn't solve some other unrelated security flaw, it's an Non Functional Requirement, it doesn't bring in any revenue for Oracle, nor does it for many other development projects, so management have knocked it on the head, we get it.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
You don’t get it, because it wasn't management. The technical leadership decided to remove SM on the advice of our security experts because they’ve judged that it’s harming our users by demanding too much effort for something that too few people want to use. If management gave us fifty more developers tomorrow to employ as we please, we still wouldn’t be able to maintain SM because our responsibility to our users would still demand that we use those resources for things that would give our users more utility.</pre>
    </blockquote>
    <p><br>
    </p>
    <p>The message I got, was it was a maintenance expense OpenJDK
      doesn't want, that indicates a commercial decision.   I have seen
      arguments against it documented on JEP411, but these only apply to
      the implementation of the Policy provider supplied with OpenJDK
      and lack of tooling for policy file creation.   These arguments
      are in error, and I've demonstrated that previously, with fully
      functional high performance high scaling code.<br>
    </p>
    <p>The problem is not that SecurityManager is being removed, the
      problem is we have come to depend on using Authorization in Java,
      and now we are being prevented from reimplementing anything to
      replace it.</p>
    <p>We can handle the stack walk, using the attach api to insert
      guards, but without privileged calls in OpenJDK, permissions
      cannot be applied using the principle of least privilege, it will
      be broken and not useful.   Basically all authorization support
      foundations are being removed along with SecurityManager, there's
      nothing we can do to fix it.   Java's no longer a platform that
      supports authorization.</p>
    <p>SM was just the implementation, maybe it wasn't right, and maybe
      the experts are right to remove it.  But maybe they're wrong too.<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

Even the most security-conscious of our users have shown a clear preference for other solutions. Your argument is that you know better than the market, but one of the world’s most popular mainstream languages cannot be led in this way. Perhaps you believe that better marketing would make the market see the light, but we have a hard enough time educating our users about features that a million others already enjoy in other languages, and an even harder time educating them about more unique features (such as strong encapsulation) that in a few short years have already paid more dividends than SM. Imagine how hard it would be to convince them of an approach that’s been abandoned after a couple of decades by the users of *both* popular platforms that adopted it.

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
We know that Oracle intends to remove authorization from the Java platform, we also know that there is nothing we can say to convince Oracle it's a bad idea, the only thing management will understand is bad consequences, such as bad news headlines.   I understand that Oracle needs to monetize Java
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
If you mean that a small group of users is unable to convince us to do what they wish at the expense of most of our users, then you’re right. You say “monetize Java”, but what that really means is that you understand — without acknowledging — that most people don’t find your solution to be superior and don’t want it. I fully sympathise with the frustration when the wider public doesn’t share our views as I frequently experience it myself, but you seem to blaming us for acting rationally and accepting the reality of the market we serve.

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">the only thing management will understand is bad consequences, such as bad news headlines.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
I think what they’ll understand is actual demand. Get some real traction then we can talk again.</pre>
    </blockquote>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
We've been working hard at implementing authorization for many years, to protect against attacks, but suddenly the threat is gone?   Yeah right, there's a bridge in Brooklyn for sale.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
That is untrue, and you speak as if it’s 1996, not 2023. The threat is not gone, but the vast majority of those writing secure servers prefer other solutions to address such threats, in particular those provided at the OS level. That approach has pros and cons and we could argue on the intellectual merits of both approaches all day, but no one can deny that the economic utility of the popular approach is much higher than the one you like. Maybe you’re right and you know better than everyone else, but in that case it’s not us that you need to convince; you need to convince the market.</pre>
    </blockquote>
    <p><br>
    </p>
    <p>Most of the market has low risk, low consequences for security
      breaches, that's why security is often an afterthought, or non
      functional requirement.   It's the low probability, high
      consequence outcomes that need protection, and these are a much
      smaller part of the market.   Still it will be damaging to Java's
      reputation when one of the high consequence outcomes is
      realised.   There's going to be a lot of legacy code that isn't
      taking advantage of module encapsulation, something will go bang
      at some point.<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

BTW, we’re not removing authorisation from the Java platform. Most Java applications have authorisation and virtually none of them use SM. What you mean is removing independent checks from low level operations inside the JDK.</pre>
    </blockquote>
    <p>Yes, JEP 411 is removing JAAS authorization from the Java
      platform.  Here's a refresher if you need it:
<a class="moz-txt-link-freetext" href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/AcnAndAzn.html">https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/AcnAndAzn.html</a><br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">
The decision has been made, it's final, the debate is over, we're just waiting for the removal notice now.   How about someone raise a JEP to remove security manager, targeting a particular release version (preferably 22, but so be it if it's 21) so we can remove uncertainty and notify our users of the versions of Java we'll be supporting going forward?   Then it's over and we can stop worrying about it.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
We will (try to) follow the same process we follow for all changes, including more impactful ones. We don’t yet know what changes will be in JDK 22, let alone later releases. When we do, so will everyone else. I hope we’ll find ways to improve our process in the future so that it will inconvenience you less.</pre>
    </blockquote>
    <p>What will help will be a predictable roadmap, so we can do some
      planning around that.</p>
    <p>Thank you for your time, we both know SM is being removed, lets
      not waste any more of each others time discussing it, we just need
      to know which versions of Java we'll be unable to support and a
      timeline around that.   Then that opens the door to assessing
      which language platform is best suited to our needs going forward.<br>
    </p>
    <p>Thank you, respectfully,<br>
    </p>
    <p>Peter.<br>
    </p>
    <blockquote type="cite"
      cite="mid:C50B7D76-8D2E-4BBC-ABD6-4EDE87907494@oracle.com">
      <pre class="moz-quote-pre" wrap="">

— Ron</pre>
    </blockquote>
  </body>
</html>