RFR: 8315487: Security Providers Filter [v13]

Xue-Lei Andrew Fan xuelei at openjdk.org
Mon Dec 2 00:40:39 UTC 2024


On Fri, 29 Nov 2024 14:28:27 GMT, Martin Balao <mbalao at openjdk.org> wrote:

>> In addition to the goals, scope, motivation, specification and requirement notes in [JDK-8315487](https://bugs.openjdk.org/browse/JDK-8315487), we would like to describe the most relevant decisions taken during the implementation of this enhancement. These notes are organized by feature, may encompass more than one file or code segment, and are aimed to provide a high-level view of this PR.
>> 
>> ## ProvidersFilter
>> 
>> ### Filter construction (parser)
>> 
>> The providers filter is constructed from a string value, taken from either a system or a security property with name "jdk.security.providers.filter". This process occurs at sun.security.jca.ProvidersFilter class —simply referred as ProvidersFilter onward— static initialization. Thus, changes to the filter's overridable property are not effective afterwards and no assumptions should be made regarding when this class gets initialized.
>> 
>> The filter's string value is processed with a custom parser of order 'n', being 'n' the number of characters. The parser, represented by the ProvidersFilter.Parser class, can be characterized as a Deterministic Finite Automaton (DFA). The ProvidersFilter.Parser::parse method is the starting point to get characters from the filter's string value and generate state transitions in the parser's internal state-machine. See ProvidersFilter.Parser::nextState for more details about the parser's states and both valid and invalid transitions. The ParsingState enum defines valid parser states and Transition the reasons to move between states. If a filter string cannot be parsed, a ProvidersFilter.ParserException exception is thrown, and turned into an unchecked IllegalArgumentException in the ProvidersFilter.Filter constructor.
>> 
>> While we analyzed —and even tried, at early stages of the development— the use of regular expressions for filter parsing, we discarded the approach in order to get maximum performance, support a more advanced syntax and have flexibility for further extensions in the future.
>> 
>> ### Filter (structure and behavior)
>> 
>> A filter is represented by the ProvidersFilter.Filter class. It consists of an ordered list of rules, returned by the parser, that represents filter patterns from left to right (see the filter syntax for reference). At the end of this list, a match-all and deny rule is added for default behavior. When a service is evaluated against the filter, each filter rule is checked in the ProvidersFilter.Filter::apply method. The rule makes an all...
>
> Martin Balao has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Undo SunNativeProvider provider changes. They will be implemented in JDK-8345221.

Thank you for the response, but I'm not sure I get all of your points.

On Sat, Nov 30, 2024 at 11:04 PM Martin Balao Alonso <
***@***.***> wrote:

> Hi @XueleiFan <https://github.com/XueleiFan> ,
>
> Looks to me that this is a significant change compared to what we proposed
> and would require a heavier specification.  I am not seeing a compelling
> argument at the moment.
>
Sorry if it will be a significant change of the proposal.  But it is the
case for review, right?

My first concern is not so much the work that would be required now but the
> burden of maintaining these APIs in the future if it turns out to be a low
> demand for them, a marginal benefit or both.
>
Yes, I am on your side on this point.  That's also the reason why I am here.


> While the decision of introducing a built-in filter requires a new
> system/security property that will need to be maintained, it's not
> incompatible with a more powerful, extensible and pluggable API in the
> future. We will not be with our hands tied in that sense. If we introduce a
> pluggable API, that is a stronger commitment.
>
I see it differently.  This proposal impacts the compatibility for future
introduction of pluggable APIs.  Any new APIs for similar purposes have to
consider the impact of this proposal, implementation and deployment.   If
we have a goal, it would be nice to do it right at the beginning,
especially if the extensible and pluggable API solution is more simple and
more powerful.

> The idea of a pluggable core security component looks to me like a door
> open for different filtering criteria and potential risk of confusion. I
> see the filter more like a simple firewall with a clear and single
> specification, that does not leave any room for intepretation or
> differences in implementation. This core component builds on top of a well
> defined and unambiguous concept: services are defined as a combination of a
> provider, service type and algorithm (*).
>
I'm not sure how it is possible, or how it is only possible with your
current proposal.  If I get it right, the filter will not appear in the
default Java security, and it allows people to edit it.   When you allow
people to edit it, it is already a public API.  I did not see the point
about "does not leave any room for interpretation or differences in
implementation".  The security property is editable.  If it is the goal of
yours, does the following an alternative proposal looks right, which also
update java.security file:
java.security.filter="ThisIsMyFilterProvoder"

It only exposes the provider name, it is not editable, and one cannot
interpret it differently or implement it differently.

The form could be as simple as the following.
1. One line java.security update:
java.security.filter="ThisIsMyFilterProvider"

2. The filter provider ThisIsMyFilterProvider should implement the
Function<Boolean, Provider.service>.

Basically, that's all the open APIs.

When we dig into the algorithm level, things start to get less universal.
>
Yes, that's also my concern.  It could be hard to use a predefined filter
syntax to cover the cases. I also ran into some cases while analyzing your
proposal.

The 1st case is about decrypted algorithms, for example MD5.  MD5 is bad
for crypto level operations, but it is still good for generating UUID.  We
normally cannot filter it out or remove it from crypto level, but we also
don't want to use it for crypto level operation.  I don't think it is easy
to archive with your proposed filter syntax.  But it is doable with
ThisIsMyFilterProvider as above.

Beside that, you have too many files updated.  You can look through all JDK
classes like XMLSignatureFactory, but there is not much we can do for those
classes we don't know yet.  I would like a solution that is not required to
update classes like XMLSignatureFactory, and call the
ProvidersFilter.isAllowed() method everywhere.

The java.security.Provider is not final and has many public extendable
APIs.  For example, getServices() and getService() can be extended.  Your
proposal will only work for those providers that do not override the two
methods.  There are such providers in practice.    If those providers need
to support this feature, and they need a way to support it.    The built-in
design cannot do that.  It is doable with the
ThisIsMyFilterProvider proposal above.


> As explained in the JEP proposal, this is an initial iteration of a
> built-in filter to address the most critical —basic, if you will—
> use-cases. We reserved characters in the syntax to potentially extend
> filtering granularity and base decisions on algorithm-specific elements
> such as parameters, key sizes, etc. We are open to that but would like to
> see how this settles first, and have more discussion. For example, we can
> theoretically have the same algorithm X but two providers bringing their
> own parameters with the key size specified in bytes and bits respectively.
> Without a common framework, the idea of filtering X key sizes with a single
> rule is more tricky than what it looks at first glance.
>
I agreed.  If you want to define a rule for it, it would be tricky.  But if
flexibility is allowed, it is not a big problem at all.

At minimum, the filter rules you want to define, is a special case for the
general Function<Boolean, Provider.service> proposal.  You can add it
whenever you want:
java.security.filter="JdkBuiltInFilter"

Your proposal is wonderful.  I was just wondering if it is possible to
simplify it and extend it to a big scope.  I appreciated your feedback.
 Thank you!

Best,
Xuelei

> Regards,
> Martin.-
>
> --
> (*) - We had to address the special case of Cipher transformations, but
> that was more to address a (less-than-ideal, in my view) design choice made
> in the past for a critical service type. For design purity, I wish we
> didn't have it; it was a trade-off.
>
>> Reply to this email directly, view it on GitHub
> <https://github.com/openjdk/jdk/pull/15539#issuecomment-2509605866>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AQSB3ECQ3MGROMCHHH7XCQL2DKYHBAVCNFSM6AAAAAA4HWWOTGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMBZGYYDKOBWGY>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>

-------------

PR Comment: https://git.openjdk.org/jdk/pull/15539#issuecomment-2510340586


More information about the core-libs-dev mailing list