On 20/06/2023 9:04 pm, Ron Pressler wrote:

On 20 Jun 2023, at 06:26, Peter Firmstone<peter.firmst...@zeus.net.au>  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,
You probably meant that as a bad thing, but I read it as thank you for serving 
your users!

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.

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.

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.

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.

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.

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.

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.

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.

Even an imperfect authorization layer is far better than no authorization layer at all.

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.

Firstly, if used correctly, using authorization is no more difficult than using an Executor framework.

Some ground rules:

1. Users create data.  The level of trust you have for the user
   determines the level of trust you have for their data.
2. Developers create code.   The level of trust you have for the
   developers determines the level of trust you have for their code.
3. Always, always, use automated tooling for the creation and
   management of policy files, start with an empty policy file with no
   permissions.
4. Apply the principle of least privilege.
5. 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.
6. 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.
7. Some architectures are more secure than others, for example, OpenBSD
   on Sparc or ARM is not susceptible to Spectre, Meltdown or similar
   attacks.
8. SM is not a sandbox, it is an authorization layer only.

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.

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.

General guidance:

1.   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.
2. Privileges must be granted to both users and developers, for
   software to function, using tooling to determine permissions required.
3. 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.
4. 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.
5. If 100% trust is given to developers, it adds unnecessary
   programming complexity to reduce that trust for users, that's seldom
   applied in practise.
6. 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.
7. 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.
8. PrivilegedAction's can be used with AccessController, and
   AccessControlContext, to elevate, preserve or reduce privilege,
   however it is most commonly used to elevate it.
9. 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.
10. 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.
11. Permissions in policy files will determine the users who can access
   properties, files, network, or developers who use agents.
12. All external connections should require authentication.   All
   authenticated connections should be given a thread of execution with
   the Subject of the authenticated user.
13. All code should either be signed, or be given a SHA256 hash or better.
14. 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.

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:

grant codebase "file:/${qa.home}/lib/jinitests.jar",
    principal javax.security.auth.x500.X500Principal "CN=Tester"
{
    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\", \"\";";     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\";";     permission java.net.URLPermission "http://${HOST}:9080/mahalo-dl-3.1.1-SNAPSHOT.jar";, "GET:";     permission net.jini.security.AuthenticationPermission "javax.security.auth.x500.X500Principal \"CN=Tester\" peer javax.security.auth.x500.X500Principal \"CN=Mahalo\"", "accept";     permission java.io.FilePermission "${jsk.home}${/}lib-dl${/}${mahalo-dl.jar}", "read";     permission java.io.FilePermission "${jsk.home}${/}lib${/}${mahalo.jar}", "read";     permission java.io.FilePermission "${qa.home}${/}harness${/}configs${/}jsse${/}mahalo${/}mahalo.config", "read";     permission java.io.FilePermission "${qa.home}${/}harness${/}policy${/}defaultsecuremahalo.policy", "read";     permission java.io.FilePermission "${qa.home}${/}harness${/}trust${/}mahalo.keystore", "read";     permission java.io.FilePermission "${qa.home}${/}lib${/}qa1-mahalo-dl.jar", "read";
};

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.

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.


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).


that we're expected to come up with DIY solutions for, with zero care from 
OpenJDK and some very bad examples of alternative solutions,
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.

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.

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.

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.
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.


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.

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.

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.

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.



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.

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
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.

the only thing management will understand is bad consequences, such as bad news 
headlines.
I think what they’ll understand is actual demand. Get some real traction then 
we can talk again.

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.
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.


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.



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.

Yes, JEP 411 is removing JAAS authorization from the Java platform.  Here's a refresher if you need it: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/AcnAndAzn.html



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.
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.

What will help will be a predictable roadmap, so we can do some planning around that.

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.

Thank you, respectfully,

Peter.


— Ron

Reply via email to