Date
1 - 20 of 28
Solution for hardcoded values in IdentityStore properties within Soteria
Rudy De Busscher
Hi All, The issue is already mentioned a few times when I gave a talk and is also logged as an issue in our GitHub https://github.com/javaee-security-spec/soteria/issues/76. I think we cannot specify anything on the spec level, because we should wait for something like a configuration spec. But on the level of Soteria itself, we can implement something to reference environment variables or retrieve values from the 'outside'. We have 2 options I think (but please give your own opinion about this) - Something like Payara does, see https://payara.gitbooks.io/payara-server/content/documentation/core-documentation/configuration/var-substitution/usage-of-variables.html - Or supporting EL expressions. What are your thoughts. best regards Rudy
|
|
Hi,
This is indeed a big thing that we just didn't get too, unfortunately. I would have loved to start addressing this in the November/December 2016 timeframe, but then I was quite busy with finalising JSR 372. My initial idea was to make all annotation attributes EL enabled, but then everything has to be a string, which in the case of numbers, booleans, enums, etc is a tad weird. Second idea was to have parallel attributes for EL enabled expressions, e.g. "int timeInSeconds" and "String timeInSecondsExpr", but since it wasn't discussed I didn't put it in, and the discussion wasn't started either, until now that is. Kind regards, Arjan Tijms
|
|
Rudy De Busscher
I agree, not all properties can be easily updated to support EL expressions. And I don't blame you Arjan for not putting it in. You did already a great job. But at a minimum, we need to address a property like password, otherwise Soteria is basically useless because the developer needs to put the password in plain text within the code.
On 21 June 2017 at 17:19, Arjan Tijms <arjan.tijms@...> wrote: Hi,
|
|
Hi, I share the concern a 100%. On the one hand there's precedent for this in Java EE since @DataSourceDefinition does exactly this, but on the other hand this is precisely the thing that makes @DataSourceDefinition difficult to use in practice. I just remembered btw that I did another proposal on one of the lists (possibly the Java EE list as a general solution for all annotation *Definitions in Java EE), and that's having a single attribute that takes a "value provider", which the CDI extension -or- the Bean<T> uses to call with an instance of the existing annotation and which returns a new annotation instance. If the CDI extension does the call, it must be a plain class without any usage of CDI, since CDI itself is still booting at that point and thus can't be used. If the call is delayed until the bean instance is created (which is normally the case), CDI could be used. For instance: @DataBaseIdentityStoreDefinition( dataSourceLookup="java:global/MyDS", callerQuery="select password from caller where name = ?", valueProvider = DBStoreProvider.class ) public class DBStoreProvider { public DataBaseIdentityStoreDefinition getValue(DataBaseIdentityStoreDefinition dataBaseIdentityStoreDefinition) { DataBaseIdentityStoreDefinition newDataBaseIdentityStoreDefinition; // Take over values from dataBaseIdentityStoreDefinition if so desired // Get new values from wherever (external file, internal file, based on some logic), ... return dataBaseIdentityStoreDefinition; } } or via EL: @DataBaseIdentityStoreDefinition( dataSourceLookup="java:global/MyDS", callerQuery="select password from caller where name = ?", valueProvider = "#{somewhere.someProvider}"; ) As far as I remember there was no reply to that proposal back then, but I'm not 100% sure anymore. Kind regards, Arjan Tijms
On Wed, Jun 21, 2017 at 8:36 PM, Rudy De Busscher <rdebusscher@...> wrote:
|
|
Rudy De Busscher
On 21 June 2017 at 23:12, Arjan Tijms <arjan.tijms@...> wrote:
Or we can wait as long as possible to execute the EL expression. Even do it everytime the validate() is executed.
Adding an option here is not an option for this release as it requires an additional member and thus a spec change. But for a next release this is a very good solution.
|
|
reza_rahman <reza_rahman@...>
This problem was supposed to be solved through the configuration JSR.
On Jun 21, 2017, at 5:12 PM, Arjan Tijms <arjan.tijms@...> wrote:
|
|
Hi,
After the last EG call it was decided that this issue is critical enough to address one way or the other. The options provided above still all stand, but for now the option with the EL enabled attributes for Strings and 2nd parallel String attributes for non-String types seemed to have the most support. When a value is provided for this second attribute, it takes precedence over the non-expression based one. E.g. The RememberMe annotation now has an integer attribute, several boolean attributes and a string attribute that's already EL enabled: @RememberMe(
cookieMaxAgeSeconds = 3600,
cookieHttpOnly = false,
cookieSecureOnly = false,
isRememberMeExpression ="self.isRememberMe(httpMessageContext)"
)
With the proposal implemented that could become: @RememberMe(
cookieMaxAgeSecondsExpression="#{someBean.config.cookieAge}" cookieHttpOnlyExpression="#{someOtherBean.httpOnly}" cookieSecureOnly = false,
isRememberMeExpression ="#{self.isRememberMe(httpMessageContext)}"
)
Note that the #{} is not strictly needed for the EL 3.0 processor, but is for consistency with attributes that also take normal (constant) strings, e.g. @DataBaseIdentityStoreDefinition(
dataSourceLookup="java:global/MyDS",
callerQuery="select password from caller where name = ?",
groupsQuery="select group_name from caller_groups where caller_name = ?"
)
Which could become: @DataBaseIdentityStoreDefinition(
dataSourceLookup="#{someBean.dataSource}",
callerQuery="#{someBean.callerQuery}",
groupsQuery="#{someBean.groupQuery}"
)
ACTION: Please let me know if this is ok by end of day
Sunday 9 July 2017 CEST. If I don't hear anything, I'll assume this is ok.
Kind regards, Arjan Tijms
|
|
Guillermo González de Agüero
Hi, Glad to see this issue solved, although it's sad that it will probably result in duplication when the Configuration spec is in place.I just have some questions: - How will the user register beans for this expressions? Will it just take every @Named beans? - Did you talk about integration with container specific expressions? GlassFish/Payara password aliases for example. Could they be used where expressions are allowed? I think that should be easy if the spec just mandates to evaluate #{} expressions but leaves the door open to other kind of expressions been accepted (with unspecified behavior). Regards, Guillermo González de Agüero
On Fri, Jul 7, 2017 at 1:17 AM, Arjan Tijms <arjan.tijms@...> wrote: Hi,
|
|
Hi, On Fri, Jul 7, 2017 at 7:50 AM, Guillermo González de Agüero <z06.guillermo@...> wrote:
Indeed, it's roughly like the Javadoc of RemembeMe.isRememberMeExpression already specifies. The ELProcessor that processes these exceptions is basically created via; ELProcessor elProcessor = new ELProcessor(); elProcessor.getELManager().addELResolver(beanManager.getELResolver());
People can always put something else into a string attribute, and an attribute processor (could even be a CDI extension perhaps) can transform that into anything else before the spec compliant processing code seeing it. E.g. @DataBaseIdentityStoreDefinition( dataSourceLookup="@@my very own expression @@", callerQuery="#{someBean.callerQuery}", groupsQuery="#{someBean.groupQuery}" ) If the container or a user CDI extension processes this and changes it any either a plain string or another EL expression, I guess it would not interfere. Kind regards, Arjan
|
|
Rudy De Busscher
Hi, Container specific features are discouraged as we want to maximize the portability. But as Arjan explained, any container is allowed to use a custom mechanism IN ADDITION TO the standard defined one. Since expressions will be resolved by the EL processor, those rule will be applied. So in practice, the easiest solution is to use @Named beans. Best regards Rudy
On 7 July 2017 at 08:31, Arjan Tijms <arjan.tijms@...> wrote:
|
|
Rudy De Busscher
Arjan, Will, Maybe an important aspect of this proposal we forgot: When is the Expression evaluated, at deploy time or when the IdentityStores is called by the IdentityStoreHandler? (and reevaluated each time) Probably need to add this for clarity. At deploy time it will be easier and more consistent, but when IdentityStore is used offers more flexibility. My preference: When Identity store is called. Best regards Rudy
On 7 July 2017 at 08:49, Rudy De Busscher <rdebusscher@...> wrote:
|
|
Guillermo González de Agüero
El vie., 7 de julio de 2017 8:32, Arjan Tijms <arjan.tijms@...> escribió:
That's maybe true, but the user CDI extension can't change the annotation values, it just can wrap the AnnotatedType. That forces JSR375 implementations to also parse it via a CDI extension. And if we want expressions to be evaluated each time the authentication is used, that means storing the effective AnnotatedType (I don't know if it can be retrieved at runtime).
|
|
Guillermo González de Agüero
El vie., 7 de julio de 2017 8:49, Rudy De Busscher <rdebusscher@...> escribió:
I totally agree with that. Portability is the main reasons why spec are needed. But still innovation has to be happen in vendor specific ways, and in this case, I'm thinking about consistency for vendor solutions. Payara allows to use password aliases on the @DatasourceDefinition annotation. I imagine customers will expect it to work the same way on this annotations. I'm using Payara as an example but I'm sure at least WildFly offers similar functionality. Consistency on vendor features is obviously not a spec concern, but we should try not to prevent it when possible.
|
|
Hi Rudy, That's a very good remark, indeed that should be specified. There's several options. If we evaluate it when the bean is created, it's once per application (most beans are application scoped), but it's at a time when CDI is fully available. E.g. in this code: optionalDBStore.ifPresent(dataBaseIdentityStoreDefinition -> { logActivatedIdentityStore(DataBaseIdentityStoreDefinition.class, beanClass); identityStoreBeans.add(new CdiProducer<IdentityStore>() .scope(ApplicationScoped.class) .beanClass(IdentityStore.class) .types(Object.class, IdentityStore.class, DataBaseIdentityStore.class) .addToId(DataBaseIdentityStoreDefinition.class) .create(e -> new DataBaseIdentityStore(dataBaseIdentityStoreDefinition)) ); }); That would mean in the constructor, which is executed when the lambda is called, which is when the bean is created for the given scope. Alternative, indeed, just simply every time the value is needed. The latter may be the most flexible thing indeed. Kind regards, Arjan Tijms
On Fri, Jul 7, 2017 at 8:52 AM, Rudy De Busscher <rdebusscher@...> wrote:
|
|
Will Hopkins
Aren't these parameters going to be pretty static most of the time?
It seems like a waste of processing power looking up every
configuration value on each invocation for an IdentityStore. An LDAP
URL isn't likely to ever change.
On 07/07/2017 11:41 AM, Arjan Tijms
wrote:
-- Will Hopkins | WebLogic Security Architect | +1.781.442.0310 Oracle Application Development 35 Network Drive, Burlington, MA 01803
|
|
Hi, Indeed, but by default users can put them in say an @ApplicationScoped bean and only do the actual lookup (i.e. read from a file) in its @PostConstruct. Just evaluating the EL expression and fetching the value from a simple getter in that @ApplicationScoped bean should be fast enough. Anyone else has any idea about this?
On Fri, Jul 7, 2017 at 6:09 PM, Will Hopkins <will.hopkins@...> wrote:
|
|
Will Hopkins
On 07/07/2017 10:00 AM, Guillermo
González de Agüero wrote:
This seems like another argument for evaluating only once, at application startup. I'm OK with allowing container-specific syntax, such as handling Payara-specific password aliases, as long as the standard syntax continues to work with predictable/expected results. In the case of Payara aliases specifically, it seems that could be handled internally by the Payara implemenetation of the LDAP/DB IdentityStore; it doesn't have to be handled by annotation processing.
-- Will Hopkins | WebLogic Security Architect | +1.781.442.0310 Oracle Application Development 35 Network Drive, Burlington, MA 01803
|
|
Will Hopkins
On 07/07/2017 12:19 PM, Arjan Tijms
wrote:
Fast enough, I suppose, but is there any reason to specify it this way, if the values in question are expected to be static? Flexibility for flexibility's sake often creates complexity, and simplicity is one of the goals of the JSR ...
-- Will Hopkins | WebLogic Security Architect | +1.781.442.0310 Oracle Application Development 35 Network Drive, Burlington, MA 01803
|
|
Guillermo González de Agüero
What about a multitenant setup? Every tenant may potentially connect to different servers. I'm not saying this is the way to handle that case. Just a thought. Apart from that, I'm with you Will in that most attributes should be fairly static. Annotations are a static way of defining settings. For really dynamic configurations I'd go for plain Java code instead. Given the time constraints, that would go into Soteria for this version. Regards, Guillermo González de Agüero.
On Fri, Jul 7, 2017 at 6:09 PM, Will Hopkins <will.hopkins@...> wrote:
|
|
Will Hopkins
Good point; but we aren't really addressing multi-tenant, and there
are other solutions. I'd as soon keep things simple for now.
That said, if there's general agreement that invocation time is better, we can specify it that way. On 07/07/2017 12:56 PM, Guillermo
González de Agüero wrote:
-- Will Hopkins | WebLogic Security Architect | +1.781.442.0310 Oracle Application Development 35 Network Drive, Burlington, MA 01803
|
|