Alternative mechanism for reflective access control (#ReflectiveAccessToNonExportedTypes / #AwkwardStrongEncapsulation)
David M. Lloyd
david.lloyd at redhat.com
Wed Sep 28 11:24:30 UTC 2016
On 09/28/2016 05:31 AM, Gunnar Morling wrote:
> David,
>
>> there is too much existing work out there, and the requirements go far
> beyond
>> what can be satisfied by these simple questions.
>
> What are examples for such requirements? I.e. what from the list of your
> requirements cannot be mapped to the mechanism suggested by Stephen? I
> find his proposal quite appealing and am wondering whether it couldn't
> be tweaked to cater for the remaining requirements.
I would rather in this case ask: how does his proposal solve all of our
requirements? The burden is always on the implementer to solve
requirements, not the other way around.
> Btw. I second the concern that the exposure of internal parts for
> reflective access should not be implicitly enabled by merely depending
> on a module requesting such access. It seems too easy for users to
> accidentally give access to internal code without being aware of it.
Possibly. But that's a usability concern and does not change the
requirement.
For example it's not hard to imagine that someone importing such a
module has to acknowledge the requested access explicitly (without
defining the specifics of it) in order for the module to successfully
link. Of course that's just one idea to illustrate that the requirement
can be addressed; it's not a proposal.
>
>
> 2016-09-27 16:30 GMT+02:00 David M. Lloyd <david.lloyd at redhat.com
> <mailto:david.lloyd at redhat.com>>:
>
> Hi Stephen,
>
> I just want to point out that this isn't a proposal per se. I don't
> advocate any particular syntax, nor recommendation for patterns that
> users should use. This is merely a set of requirements that we (Red
> Hat) have identified as necessary in order to enable the widest
> range of existing middleware systems to continue to function with a
> minimum of disruption or security compromises. Any proposal that we
> accept will necessarily meet these requirements, though these
> requirements may or may not be sufficient for acceptance (only
> testing will tell us the full story).
>
> The reason I didn't boil it down to the same set of questions that
> you have asked is that those questions are simply not sufficient to
> meet the requirements of a modern middleware application. To quote
> the JSR description: "This JSR will define an approachable yet
> scalable module system [...] so that developers can use it to
> construct and maintain libraries and large applications for both the
> Java SE and Java EE Platforms. [...]"
>
> I think it's very possible for the platform module system to be
> specified and implemented in such a way as to enable the continued
> maintenance of existing libraries and large applications, however in
> order to do so, it is our estimation that these requirements must be
> met.
>
> In response to the way you've narrowed down the scope of
> requirements: I agree that such simplifications work well when
> establishing boundaries for a new project and encouraging good usage
> patterns. But I don't think we can really do that here; there is
> too much existing work out there, and the requirements go far beyond
> what can be satisfied by these simple questions.
>
>
> On 09/26/2016 05:11 AM, Stephen Colebourne wrote:
>
> Having read this proposal a number of times, and considering how the
> talks explained things at JavaOne, I have come to the conclusion
> that
> this proposal is too complex. FWIW, I like the idea that a module
> should be able to declare that it needs reflective access from its
> users, however given that the proposal is what results from the
> idea,
> it doesn't seem as appealing as it should.
>
> The reason why I put forward the exports/exposes approach [1] is
> that
> it keeps the questions that must be asked when creating a module
> simple:
> - what do I depend on publicly (requires)
> - what do I publish publicly (exports)
> - what do I publish privately (exposes)
>
> From a security point of view it also seems that it should be the
> responsibility of a module to allow the publishing of its private
> details, and simply depending on another module seems very minimal
> (and easy to miss) as a mechanism to allow that extra permission.
>
> Stephen
>
> [1]
> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-September/009370.html
> <http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-September/009370.html>
>
>
> On 21 September 2016 at 17:39, David M. Lloyd
> <david.lloyd at redhat.com <mailto:david.lloyd at redhat.com>> wrote:
>
> In our internal discussion of the proposal for
> #ReflectiveAccessToNonExportedTypes, we discussed the ins
> and outs of
> various behaviors and have come up with a few ideas or
> starting points for
> solutions that we think would be more workable in
> conjunction with existing
> middleware (ours and others').
>
> For reasons previously explained, we do not think that weak
> modules are a
> good way forward; I won't go into that again here. But the
> logical
> re-starting point is: If not weak modules, then what?
>
> I will boil it down to a few basic requirements that we have
> established.
> This list is probably non-exhaustive but hopefully complete
> enough to go on
> for now:
>
> • A module definition must be able to establish that a
> dependent has (or all
> modules have) access to one or more (or all) packages for
> public reflection
> only.
> • A module definition must be able to establish that a
> dependent has (or all
> modules have) access to one or more (or all) packages for
> public or private
> reflection only.
> • A module definition must be able to establish that a
> dependent has (or all
> modules have) access to one or more (or all) packages for
> public reflection
> and compilation/linkage (i.e. it's an export by today's
> terminology).
> • A module definition must be able to establish that a
> dependent has (or all
> modules have) access to one or more (or all) packages for
> public or private
> reflection and compilation/linkage (i.e. it's a "private"
> export by today's
> terminology).
> • As today, any packages not declared in one or more of the
> above categories
> is inaccessible outside of the module in any way (note that
> as I showed
> previously we have also concluded that it should continue to
> be impossible
> to export a package for compilation/linkage without public
> reflection, as we
> have not discovered any use for such a mode).
>
> More generally:
>
> • The syntax for all of the above has no particular
> constraint (in fact I
> will try to actively avoid touching what could be a very
> bikeshedding-rich
> discussion), except that it should not be construable as
> being pejorative
> against the usage of reflective frameworks; rather, it
> should be clear what
> level of trust is being established without raising undue
> warning.
> • Applications should not need gratuitous amounts of
> declarations in their
> module(s) in order to utilize frameworks.
> • As previously established, it should not be possible for
> one declaration
> to reduce the scope of access of another declaration in a
> module definition.
> • Access to a module (for reflective purposes only) must not
> cause conflicts
> if multiple such modules which contain identical packages
> are accessible to
> a single consumer; in other words, reflection-only access into
> non-dependency modules is not bound by duplicate package
> restrictions as
> long as each package is unique per class loader, as per the
> current (Java 8)
> class loader rules.
>
> The above cover the useful access modes that we have
> identified. This is
> _nearly_ adequate to cover the use cases that we are
> currently concerned
> about; for example, I could export all packages for public
> reflection only
> to a specific framework, if only I know the module name of the
> implementation.
>
> Unfortunately, this does not work well in the case where a
> module may
> consume a framework whose specification is separate from the
> implementation.
> An application module may need to use (say) EJB and JPA;
> there is presently
> no clean way to do so without either (a) relying on a
> container environment
> to rewrite the descriptor or (b) opening up the module and
> defeating the
> security mechanism (e.g. "weak"). Without either of these
> workarounds, the
> application developer must have a good deal of knowledge
> about what modules
> provide what services within a framework-rich environment,
> possibly
> resulting in a very verbose (and error-prone) descriptor;
> none of these
> options is really satisfactory.
>
> Thus, apart from the option of redesigning (to an extent)
> the security
> mechanism (thereby eliminating the need to seal off access
> to public
> reflection, which is definitely still an attractive option
> for various
> reasons from our perspective, but which is also a very different
> discussion), we need some sort of mechanism which decouples
> the literal
> dependency system from access permission (much like
> uses/provides does).
>
> For example if I could declare that my module uses
> "javax.ejb", and, in so
> doing, automatically grants public and private reflective
> access to the
> module that provides that service, this would be a good
> outcome. A module
> which answers to that service name could be responsible for
> reflective
> access to the application module, providing that information
> privately to
> any other framework modules which require it.
>
> The migration story looks much better in this light: module
> descriptors
> still can be quite terse and specific. Applications which
> use reflective
> frameworks do not need gratuitous exports; in fact it's much
> more fluid for
> a user to say "I require these helper libraries; I use EJB;
> that's it" which
> means they don't have to worry about the details of whatever
> particular
> environment they run in. This also has the advantage of
> allowing new Java
> 9-generation specifications to stipulate standard service
> names for each
> specification (e.g. "javax.ejb", "javax.cdi", that sort of
> thing).
>
> While this doesn't cover 100% of our remaining issues with
> Jigsaw (of
> course; we'll all continue moving through the issues list as
> we have been to
> get us there), meeting these requirements would go a long
> way towards at
> least having a reflection story that is more practical for
> present-day
> frameworks to move forward with. So the last requirement
> would be:
>
> • A module definition must be able to establish that an
> "indirect"
> dependency exists on an otherwise unknown module providing a
> capability,
> wherein that module may require public or public+private
> reflection access
> to some or all packages without compile/link access. This
> could possibly
> exist in conjunction with, or as an evolution of, the
> current services
> mechanism, however a complicating factor is that the current
> mechanism is
> based specifically on types, whereas a purely symbolic
> relationship might be
> better for this purpose (this is not a requirement though if
> it can be made
> to work as-is). Note that any symbolic relationship system
> would need some
> in-code discovery mechanism such that consumers of the
> capability are made
> available to the provider and/or vice-versa, in order to
> make practical use
> of the relationship.
>
> The following example syntax is meant to be unambiguous and
> illustrative; no
> specific attempt is made to reuse existing keywords (for
> example), or even
> to imply an endorsement of the current descriptor mechanism
> at all, but to
> clarify how this might look in practice and provide a
> practical application
> of the ideas herein.
>
> Example 1: A contrived provider of the fictional framework
> "javax.fictional.orm" illustrating provides/uses-based
> access granting
>
> module org.foo.orm.provider {
>
> // Require a module dependency, and give it private
> reflection access
> to everything
> requires org.apache.commons.beanutils with private
> reflection on *;
>
> // Require a module dependency with no reflection
> requires org.apache.commons.logging;
>
> // Provide the framework
> provides javax.fictional.orm.ORM
> using private reflection
> with org.foo.orm.provider.ORMImpl1,
> org.foo.orm.provider.ORMImpl2;
> }
>
> Example 2: A contrived consumer of #1
>
> module com.mycompany.application {
> uses javax.fictional.orm.ORM; // automatically gives
> private
> reflection
> }
>
> Example 3: Grant reflection access to a couple of packages
> to a named
> non-dependency module
>
> module com.mycompany.application {
> grant public reflection on
> com.mycompay.application.package1,
> com.mycompay.application.package2
> to org.foo.framework;
> }
>
> Example 4: Behave like Java 8
>
> module com.mycompany.application {
> grant private reflection on * to *;
> }
>
> Example 5: Behave like Java 8, but restrict private access
> without requiring
> a security manager
>
> module com.mycompany.application {
> grant public reflection on * to *;
> }
>
> Example 6: An example of using CDI and EJB with symbolic
> capabilities
>
> module com.mycompany.application {
> uses capability javax.ejb, javax.cdi
> }
>
> Example 7: An example of providing EJB with symbolic
> capabilities
>
> module org.foo.ejb.provider {
> [...]
> provides capability javax.ejb using private reflection;
> }
>
>
> --
> - DML
>
>
> --
> - DML
>
>
--
- DML
More information about the jigsaw-dev
mailing list