READ 1ST: Re: Authorization layer API and low level access checks
Peter Firmstone
peter.firmstone at zeus.net.au
Sat Jun 26 12:05:48 UTC 2021
On 26/06/2021 3:41 pm, Peter Firmstone wrote:
>
> Apologies for multiple earlier emails, please ignore and read this
> instead.
>
> This proposal is about stripping out and simplifying as much of the
> dilapidated and complex SecurityManager infrastructure as possible,
> while retaining the ability for developers to implement a better high
> scaling and performant Authorization layer, without prohibitively
> preventing it.
>
> Summary of Proposed Changes:
>
> 1. GuardFactory & GuardFactorySpi to provide hooks for authorization
> checks without SecurityManager or Policy. (Note GuardFactory
> should never return null and instead return a no-op Guard that
> hotspot can optimize out.
> 2. Existing Permission implementations to be obtained using
> GuardFactorySpi implementations, until their removal. Note that
> when SecurityManager is stubbed out and Permission implementations
> are deprecated for removal, these should no longer be provided by
> default, but instead need to be enabled by entries in the
> java.security config file, in preparation for their removal.
> 3. JDK code to no longer call Permission implementations directly,
> instances obtained using GuardFactory, when enabled in the
> java.security configuration file.
> 4. Threads (system and virtual) updated to use a singleton
> *unprivileged* AccessControlContext, instead of inherited
> AccessControlContext, this is more appropriate for Executors, the
> original inherited context was designed before Executors were
> introduced.
> 5. Deprecation for removal of all Permission implementations from the
> JDK platform. The existing implementations of Permission
> introduce unnecessary complexity; they lack sufficient flexibility
> resulting in a proliferation of Permission grants required in
> policy files and some make blocking network calls.
> 6. Introduce a system property to change AccessController's default
> behaviour, disable the stack walk by default, but allow it to be
> re-enabled with a system property, replace the stack walk array
> result of ProtectionDomains with an *unprivileged*
> AccessControlContext, the SubjectDomainCombiner can replace it
> with a, AccessControlContext containing a single element array,
> containing one ProtectionDomain with Principals.
> 7. AccessController::doPrivileged erases the DomainCombiner by
> default, deprecate these methods for removal (make private),
> retain doPrivilegedWithCombiner methods that preserve the
> SubjectDomainCombiner. Developers should replace their
> doPrivileged methods with doPrivilegedWithCombiner. Create a new
> method AccessController::doUnprivileged, clear intent, to erase
> the DomainCombiner, and use the *unprivileged*
> AccessControlContext. Update
> AccessController.AccHolder.innocuousAcc to refer to an
> *unprivileged* context, as per the definition below.
> 8. Deprecate for removal the CodeSource::implies method.
> 9. Give unique ProtectionDomain's with a meaninful CodeSource to Java
> modules mapped to the boot loader, rather than using a Shared
> ProtectionDomain with a null CodeSource.
> 10. Deprecate for removal AccessController::checkPermission and
> AccessControlContext::checkPermission methods.
>
AccessController.checkPermission calls AccessControlContext.optimize,
which invokes the DomainCombiner, prior to calling
AccessControlContext.checkPermission
In my implementation of SecurityManager, I call
AccessController.getContext from within a PrivilegedAction, to optimise
a newly created AccessControlContext, (AccessController.getContext also
calls AcessControlConext.optimize), prior to calling
AccessControlContext.checkPermission.
I think it would be simpler however, to create a new method in
AccessController to replace checkPermission which also calls optimize.
I think something could be done here with Stream and Consumer to perform
the function checking ProtectionDomain's. Needs a little more thought,
but basically we want to be able to check each ProtectionDomain, without
being restricted to Permission or Policy implementations.
Eg:
AccessController.stream(AccessControlContext context).forEach(domain ->
Check::domain)
Or
AccessController.checkDomains(AccessControlContext context,
Consumer<ProtectionDomain>)
This method would have a relevant Guard.check "RUNTIME"
"getProtectionDomain" prior to calling AccessControlContext.optimize and
the developer would need to make the call from a PrivilegedAction, and
remember pass the relevant guard check for it's own AccessControlContext.
> 11. Undeprecate AccessController, AccessControlContext,
> DomainCombiner, SubjectDomainCombiner and Subject::doAs methods,
> while deprecating for removal methods stated in items above.
> 12. Deprecate for removal ProtectionDomain::implies,
> ProtectionDomain::getPermissions and
> ProtectionDomain::staticPermissionsOnly
> 13. Replace PermissionCollection type argument with Object in
> ProtectionDomain constructors, ignore the permissions parameter,
> and deprecate existing constructors. Deprecate
> PermissionCollection for removal.
> 14. Create a new constructor: ProtectionDomain(CodeSource cs,
> ClassLoader cl, Principal[] p).
> 15. Create a new factory method
> ProtectionDomain::newInstance(Principal[] p), to allow a weak
> cache of ProtectionDomain instances for each Principal[], to be
> utilised by SubjectDomainCombiner to avoid unnecessary duplication
> of objects. This is an optimization for
> AccessControlContext::equals and ::hashCode methods. Using a
> cache of AccessControlContext, it is possible to avoid rechecking
> authorization that has already been checked. For example, when
> using an Executor with many tasks, all with the same
> AccessControlContext, you only need to check once and return the
> same result for subsequent checks. This is an optimization I
> have used previously to great effect.
>
The ProtectionDomain::newInstance is just a nice to have,
SubjectDomainCombiner already caches PD's, just seems a better place to
cache for the following reasons:
* Cache can be utilised by other implementations.
* Simplification of SubjectDomainCombiner.
* Responsibility of ProtectionDomain.
It's not an essential item, however, just seems like an opportunity for
a little refactoring.
> To clarify what an *unprivileged* AccessControlContext is:
>
> An instance of AccessControlContext, that contains a single
> element array, containing a ProtectionDomain, with a null
> ClassLoader, null Principal[] and a *non-null* CodeSource,
> containing a null URL.
>
> So as to distinguish between what is traditionally a JDK bootstrap
> ProtectionDomain and unprivileged domain after
> ProtectionDomain::getPermissions is removed.
>
> Stubbing of SecurityManager and Policy, for runtime backward
> compatibility. Update ProtectionDomain::implies method, to *not*
> consult with the Policy. Note it's possible to get access to the
> ProtectionDomain array contained within AccessControlContext using a
> DomainCombiner.
>
> This is backward compatible with existing usages of JAAS and least
> painful method of transition for all concerned as well as allowing
> complete flexibility of implementation.
>
> Regards,
>
> Peter Firmstone.
>
> On 25/06/2021 3:59 pm, Peter Firmstone wrote:
>> Thanks Dalibor,
>>
>> Would targeting Java 18 be practical?
>>
>> Also it won't take long to code a prototype, just not sure of the
>> process.
>>
>> Cheers,
>>
>> Peter.
>>
>>
>> On 24/06/2021 9:30 pm, Dalibor Topic wrote:
>>> On 24.06.2021 04:24, Peter Firmstone wrote:
>>>> Thanks Andrew,
>>>>
>>>> For the simple case, of replacing the SecurityManager stack walk,
>>>> one could use reflection.
>>>>
>>>> Thank you for also confirming that is not possible (or at least
>>>> very unlikely) to add a GuardBuilder to Java 8, the proposal is for
>>>> JDK code to use a provider mechanism, to intercept permission
>>>> checks, so custom authentication layers can be implemented, this
>>>> could be accepted in future versions of Java, but not existing. As
>>>> it is said, there is no harm in asking.
>>>
>>> Generally speaking, adding any public APIs to a platform release
>>> after its specification has been published, is always going to be a
>>> very tall order involving the JCP, among other things. It's not
>>> really worth it, when other technical solutions, such as
>>> multi-release JARs, already exist, that alleviate the necessity.
>>>
>>> cheers,
>>> dalibor topic
>>>
--
Regards,
Peter Firmstone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20210626/932f1c4e/attachment.htm>
More information about the security-dev
mailing list