Surviving JEP411 deprecation [WAS]: Implementing an Authorization framework on Java.

Peter Firmstone peter.firmstone at zeus.net.au
Thu Feb 9 23:03:10 UTC 2023


Maybe I had the wrong Subject?

I'm still trying to figure out how to migrate before removal of 
deprecated API's.

 1. Our software architecture is designed and currently relies on
    classes in JEP411 for authorisation decisions.
 2. It's not possible for our software to have security bolted on as an
    afterthought, following removal of authorization.
 3. Without authorization, we cannot allow the JVM to have access to
    sensitive information.
 4. We could place the JVM inside an isolated VM as suggested by JEP411
    proponents, but we can no longer allow the JVM to have access to
    sensitive information.   It is technically possible to do this,
    provided we accept we could no longer use encryption or
    authentication, as we cannot introduce sensitive information into
    the JVM, then we could use observability tools as a watchdog, to
    shutdown and restart the VM if it becomes compromised.   However,
    that leaves us with very limited functionality.

I realise that OpenJDK likely thinks this is BS, we can just safely 
remove SM, it's obsolete now right?

The problem is, we don't fit the standard category of server 
programming, eg: once the JVM's warmed up, it no longer dynamically 
loads classes, hotspot has compiled them to native binary code; a server 
that fits the publish subscribe model, where it only need parse and 
validate incoming data from clients, and publish responses.  Server 
programming is OpenJDK's target market, we get that.   Anything in the 
client space is frowned upon, we get that too, but we're not in the 
client space.   Our clients are also servers.

Our distributed service architecture provides dynamic discovery of 
services (globally over IPv6).   We rely on Authentication, Encryption 
(Privacy) and Authorization.   Clients of services are often required to 
download code dynamically, clients and services first discover and 
authenticate available service registrar's using an X500 IPv6 multicast 
discovery process, with checksums to validate details required to 
establish a unicast connection. Unicast IPv6 TCP with Encryption is used 
to ensure that communications are private between authenticated 
connections while establishing connections to service registrar's.

Nodes in the distributed network, aren't distinguished as servers and 
clients, a node that acts as a client will also provide services, even 
if it's just listening to an event service.   All threads are run with 
authenticated client endpoint Subject's, and service responses with 
server Subject's, to allow the use of authenticated TLS connections.

After nodes have discovered each other, the connection is established 
like so:

 1. Authentication & Establish an Encrypted connection.
 2. The service provides the client with;  code signer certificates, if
    the service requires codebase download, or it may provide a security
    hash, used to validate files, it will also communicate a string that
    represents URL's from which code can be downloaded.  It will also
    communicate any permissions it requires.   The client Subject is
    allowed to grant a restricted set of permissions.   The client may
    elect to grant the requested permissions, if it has the privileges
    to do so.
 3. The client provisions a ClassLoader, that's a child of the
    ClassLoader that contains the Service's public API, the identity of
    this ClassLoader is determined by the CodeSource URI's as well as
    the Authenticated identity of the Service.   The ClassLoader of the
    service proxy represents it's identity in authorization decisions at
    the client.   Other service proxy's may use the same codebase URL's,
    but unless they have identical identity, cannot load their classes
    into another service proxy's ClassLoader.
 4. At this point, the client unmarshal's the service proxy's Object
    state into the ClassLoader, it doesn't use Java de-serialization to
    do this, just in case anyone is curious.
 5. Only ClassLoaders are responsible for Class resolution, codebase
    annotations are not used, neither is RMIClassLoader used to resolve
    classes.
 6. Now the client (and server) applies constraints to their service
    endpoints, placing restrictions on the level of encryption the
    service can use for network communications, or the Principal's the
    Subject that invokes the service must have.
 7. The client can now use the service, by passing parameters to the
    proxy's methods and accepting returns.   The service proxy may
    accept or return other services, these services will have the same
    constraints applied, unless clients or services, apply new constraints.
 8. A JVM node may have any number of services proxy's while also
    providing services to other nodes, of many different identities,
    numerous services may participate in transactions, each one with
    it's own identity.

During this process permissions are granted as they are required, once a 
service is no longer used, its ClassLoader becomes unreachable, 
permissions granted dynamically are removed.   The client environment is 
otherwise locked down with least privilege policy files, that were 
generated and audited during deployment.

We would like to continue to invest in the development of this software, 
it's performant, it scales, encryption is very fast, thanks to recent 
developments in Java session tickets.  We've eliminated unnecessary DNS 
calls (the JVM makes many of these, eg URL, SecureClassLoader, 
CodeSource), and cleared out synchronized and blocking code, replaced it 
with concurrent non blocking code where possible.   It's well tested, 
much time has been invested into static analysis and cleaning up and 
modernizing code.   All our hotspots are native JVM methods.   I suspect 
this is why we are finding bugs in your TLS code, it isn't thread safe ;)

Hopefully there is a future for this software, however it will depend 
our ability to migrate to new versions of Java as they're released.

At least allow us just these few classes to remain (un-deprecated 
please, so developers aren't motivated to remove their privileged 
calls), even if they contain no implementation, so that we may 
instrument them, as we attempt to stay current with OpenJDK.

We are not asking OpenJDK to maintain OpenJDK security using an 
authorization framework, we are just asking you to make it possible for 
us to maintain our software's security ourselves while running on your 
platform.  It's not really possible for us to run on anything else.

-- 
Regards,
  
Peter.

On 9/02/2023 10:20 am, Peter Firmstone wrote:
>
> I don't think I'm really asking for much here.   JEP411's plan will 
> destroy our ability to manage user and service authorization in our 
> existing software, at least cut us a little slack.  I wish we built 
> our software on some other authorization API, unfortunately we didn't.
>
> We're just trying to migrate as best we can to future versions of Java.
>
> -- 
> Regards,
>   
> Peter Firmstone
> On 7/02/2023 12:53 pm, Peter Firmstone wrote:
>>
>> Hello OpenJDK folk,
>>
>> SecurityManager, AccessController and AccessControlContext will be 
>> removed in a future version of Java.
>>
>> Just briefly: Our software is heavily dependant on Java's 
>> Authorization framework, we use ProtectionDomain's to represent 
>> remote services for authorization decisions.  We are working out how 
>> to implement a new authorization framework after SecurityManager's 
>> removal.
>>
>> Many libraries call AccessController#doPrivileged methods, when these 
>> methods are removed, we're going to have a big problem with viral 
>> permissions.   Restricted authorization will become meaningless if it 
>> has to be granted to all domains on a call stack.
>>
>> https://github.com/opensearch-project/OpenSearch/issues/1687
>>
>> Retaining methods in the platform that developers can instrument will 
>> provide a common frame of reference for authorization decisions, 
>> that's runtime backward non-breaking, without burdening OpenJDK with 
>> maintenance.
>>
>> I'm requesting retaining the DomainController interface, 
>> AccessController, AccessControlContext and Subject methods as no-op's 
>> for instrumentation?    Please leave them deprecated as no-op's, but 
>> not "deprecated for removal".
>>
>> https://github.com/pfirmstone/HighPerformanceSecurity
>>
>> Some thoughts:
>>
>>  1. Ability to disable finalizers in Java 18 onwards is important to
>>     prevent finalizer attacks when instrumenting constructors to
>>     throw a RuntimeException.
>>  2. Guard#check methods can be no-op's for instrumentation. If I can
>>     replace all instances of SecurityManager#checkPermission in
>>     OpenJDK with Guard#check, I can contribute the patches, this will
>>     assist greatly in the transition process of retaining existing
>>     hooks, while developing replacements.
>>  3. Reduce the size of the Java Platform's trusted computing base by
>>     giving all system ProtectionDomain's a CodeSource with a non-null
>>     meaningful URL.   Unfortunately Java Serialization is in the base
>>     module, so we cannot authorize it's use with a permission check,
>>     as the base module needs AllPermission, it has to be managed with
>>     serial filters
>>     (https://dzone.com/articles/a-first-look-into-javas-new-serialization-filterin
>>     - perhaps someone will write a serialfilter generation tool that
>>     works similarly to our POLP policy generation tool?). Privileges
>>     cannot be elevated by an authenticated Subject, when all domains
>>     on the call stack are already privileged. If Serialization was in
>>     a different ProtectionDomain, then we could prevent
>>     de-serialization for unauthenticated Subject's.   Perhaps OpenJDK
>>     might consider moving Serialization into a different module in
>>     future before it's eventual removal?
>>  4. Instrument all data parsing methods with guard checks, eg XML.  
>>     This allows authorization decisions to parse remote data based on
>>     the Principal's of the remotely authenticated Subject, to prevent
>>     injection attacks.
>>  5. We already have principle of least privilege policy generation
>>     tools and efficient policy checking tools for authorization in
>>     place.   These allow for simple policy file generation, auditing,
>>     editing and deployment.
>>
>> -- 
>> Regards,
>>   
>> Peter Firmstone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20230210/7ce11018/attachment.htm>


More information about the security-dev mailing list