You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Mark Thomas <ma...@apache.org> on 2013/04/19 23:28:26 UTC
and security constraints
Currently, Tomcat only checks against <security-role-ref> elements if
there is a call to isUserInRole(). Prior to Servlet 3.0 this made sense.
The person deploying the web application has control over web.xml and
hence the security roles (those used in security constraints) but no
control over application roles (those used by developers in Servlets
with isUserInRole()) and therefore needed a mechanism to map the
application roles to security roles.
This mechanism is usually used to map application roles to security
roles that exist in an external authentication and authorisation system
such as an LDAP directory. For example, the application role admin in
the HR application may get mapped to the hr-manager role that exists in
the LDAP directory.
With Servlet 3.0 plugability features the picture changes a little.
Now a fragment may define security constraints that use a security role
that does not match the organisations security roles and can't be
modified in the application's web.xml. For example, an HR application
with two fragments may define a role "admin" in fragment A and "sysuser"
in fragment B both of which need to be mapped to the "hr-manager" role.
Oh, and just to throw a spanner in the works, if a Filter uses
isUserInRole() there is no way to map the application role to a security
role.
I'm currently unsure how this issue should be addressed. The options as
I see them are:
a) There is an obvious solution I have missed.
b) Check <security-role-ref>'s when processing security constraints.
c) Something else.
Given the Filter issue, I think c) is the only viable option.
Tomcat's current behaviour looks to be specification compliant but there
appears to me to be an issue here the the Servlet EG needs to address.
Before I move this issue there what do folks think about this? Is there
an issue or am I missing the obvious?
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: and security constraints
Posted by Jeremy Boynes <jb...@apache.org>.
On Apr 21, 2013, at 11:37 PM, David Jencks <da...@yahoo.com> wrote:
> On Apr 21, 2013, at 3:56 PM, Jeremy Boynes <jb...@apache.org> wrote:
>
>> On Apr 19, 2013, at 11:04 PM, David Jencks <da...@yahoo.com> wrote:
>>> IMO you have misinterpreted roles in the ee specs. The specs including the servlet spec define application roles and base the declarative security constraints on them. Then you can map strings that bits of the application like, at least ejbs and servlets, to these declared security roles using a security-role-ref. The role-link has to be one of the declared application roles. For web apps the security-role-ref is defined on servlets. The application roles no matter where defined are scoped to the entire application not just one web app or web fragment. If a security-role-ref is not defined for a string, and you call isUserInRole with that string, the string is assumed to be a defined application role.
>>
>> Mark does bring up a gap here though. Before 3.0, the only reference to a role from code would be in the parameter value passed to isUserInRole(), and the assembler was responsible for listing all of those in web.xml; the deployer was responsible for linking them to actual roles in <security-role> elements, and then linking those to groups/principals in the authorization system in a container-specific manner. Declarative security (security-constraint/auth-constraint) did not require a linkage mechanism as the deployer could modify the value in the <auth-constraint> declaration in web.xml. With 3.0 annotations, however, the auth-constraint is now declared in code and the deployer has no mechanism to link its roleNames() to an actual role.
>
> Not quite following you here. I thought you'd declare all your roles using the @DeclareRoles annotation or in @AllowRoles inside constraints. These are equivalent to <security-role> elements in web.xml. If for some reason you don't like the role names in the annotations you can always override them in web.xml just like you can override other non-cdi annotations. Otherwise the deployer can link the principal names to the role names just like with web.xml.
I may be wrong, but I've viewed @DeclareRoles as more akin to <security-role-ref> in that is declaring a role reference I make from within code in a discoverable way; without annotation, an assembler or deployer would need to rely on documentation supplied with the code to know this reference was made. That's different to @RolesAllowed et al. which are specifying the deployment concern of what roles are permitted to access the servlet.
Or, putting it another way, @DeclaresRole is metadata describing what the implementation code does whereas @RolesAllowed is configuration about the how the code should be used. Changing the role reference described by @DeclaresRole requires modifying the code that calls isUserInRole() which is outside the assembly/deployment role.
>> Option b) sounds like a potential solution but as you say that is not something the spec currently allows. The spec could be extended to allow this, and I think that would even be a compatible change given the existing requirement for <security-role-ref> to default to a <security-role> with the same name if no explicit link is specified.
>
> How is this different from the existing possibility to define a proprietary mapping between principal names and application role names?
It's a portable way for an assembler creating a web-application from components provided by different suppliers to link the roles declared in the annotations (whose names are defined by the component providers) to a common set of application roles (defined by the assembler). The deployer then maps one set of application roles to principal names in a proprietary way.
Its trying to address the situation where two components from different providers both specify @RolesAllowed("user") but mean different things by "user," or where one defines "user" and the other defines "customer" and the assembler wants them to map to the same application role.
Cheers
Jeremy
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: and security constraints
Posted by David Jencks <da...@yahoo.com>.
On Apr 21, 2013, at 3:56 PM, Jeremy Boynes <jb...@apache.org> wrote:
> On Apr 19, 2013, at 11:04 PM, David Jencks <da...@yahoo.com> wrote:
>> IMO you have misinterpreted roles in the ee specs. The specs including the servlet spec define application roles and base the declarative security constraints on them. Then you can map strings that bits of the application like, at least ejbs and servlets, to these declared security roles using a security-role-ref. The role-link has to be one of the declared application roles. For web apps the security-role-ref is defined on servlets. The application roles no matter where defined are scoped to the entire application not just one web app or web fragment. If a security-role-ref is not defined for a string, and you call isUserInRole with that string, the string is assumed to be a defined application role.
>
> Mark does bring up a gap here though. Before 3.0, the only reference to a role from code would be in the parameter value passed to isUserInRole(), and the assembler was responsible for listing all of those in web.xml; the deployer was responsible for linking them to actual roles in <security-role> elements, and then linking those to groups/principals in the authorization system in a container-specific manner. Declarative security (security-constraint/auth-constraint) did not require a linkage mechanism as the deployer could modify the value in the <auth-constraint> declaration in web.xml. With 3.0 annotations, however, the auth-constraint is now declared in code and the deployer has no mechanism to link its roleNames() to an actual role.
Not quite following you here. I thought you'd declare all your roles using the @DeclareRoles annotation or in @AllowRoles inside constraints. These are equivalent to <security-role> elements in web.xml. If for some reason you don't like the role names in the annotations you can always override them in web.xml just like you can override other non-cdi annotations. Otherwise the deployer can link the principal names to the role names just like with web.xml.
>
>
> Option b) sounds like a potential solution but as you say that is not something the spec currently allows. The spec could be extended to allow this, and I think that would even be a compatible change given the existing requirement for <security-role-ref> to default to a <security-role> with the same name if no explicit link is specified.
How is this different from the existing possibility to define a proprietary mapping between principal names and application role names?
thanks
david jencks
>
> There is a scoping issue for role ref names but that is not new - 2.x libraries can also conflict by using the same value in calls to isUserInRole().
>
>> Based on the JACC WebRoleRefPermission, where the constructor arguments are the servlet name and the role name, I've concluded that the a filter gets the same isUserInRole behavior as the servlet the request ends up at after going through the filter. I think this is a satisfactory solution, and it's passed quite a few ee tcks by now. It's also quite easy to implement :-). I think talking to Ron Monzilla if you disagree with it would be the way to go.
>
> As the spec stands with <security-role-ref>/@DeclareRoles only allowed on Servlets and not on Filters I'd come to the same conclusion. It is a weird coupling though as the role reference is made by the filter and not the servlet, the servlet author does not know a-priori what filters will be applied or vice versa. Again, more of an issue now we have annotation based config. IMO, getting the spec to clarify this, and potentially allowing filters to declare role references would be useful.
>
> I've assumed the same model would apply for calls to isUserInRole() from within listeners e.g. request or request attribute? Or from within an extension-mapped servlet like the JSP servlet?
>
>> Then you presumably have an external security system such as ldap with some defined entities such as groups, and these usually get represented as Principals, perhaps in a Subject.. These are not application roles. You need to map the externally defined entities to the application roles.
> +1, although falling back to mapping application roles to groups in the absence of configuration by the deployer is temptingly convenient (although with the "new-group" problem you mention).
> ...
>> On Apr 19, 2013, at 2:28 PM, Mark Thomas <ma...@apache.org> wrote:
> ...
>>>
>>> Tomcat's current behaviour looks to be specification compliant but there
>>> appears to me to be an issue here the the Servlet EG needs to address.
>>> Before I move this issue there what do folks think about this? Is there
>>> an issue or am I missing the obvious?
>
> Seems to me there's ambiguity there that would be worth clarifying.
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
Re: and security constraints
Posted by Jeremy Boynes <jb...@apache.org>.
On Apr 19, 2013, at 11:04 PM, David Jencks <da...@yahoo.com> wrote:
> IMO you have misinterpreted roles in the ee specs. The specs including the servlet spec define application roles and base the declarative security constraints on them. Then you can map strings that bits of the application like, at least ejbs and servlets, to these declared security roles using a security-role-ref. The role-link has to be one of the declared application roles. For web apps the security-role-ref is defined on servlets. The application roles no matter where defined are scoped to the entire application not just one web app or web fragment. If a security-role-ref is not defined for a string, and you call isUserInRole with that string, the string is assumed to be a defined application role.
Mark does bring up a gap here though. Before 3.0, the only reference to a role from code would be in the parameter value passed to isUserInRole(), and the assembler was responsible for listing all of those in web.xml; the deployer was responsible for linking them to actual roles in <security-role> elements, and then linking those to groups/principals in the authorization system in a container-specific manner. Declarative security (security-constraint/auth-constraint) did not require a linkage mechanism as the deployer could modify the value in the <auth-constraint> declaration in web.xml. With 3.0 annotations, however, the auth-constraint is now declared in code and the deployer has no mechanism to link its roleNames() to an actual role.
Option b) sounds like a potential solution but as you say that is not something the spec currently allows. The spec could be extended to allow this, and I think that would even be a compatible change given the existing requirement for <security-role-ref> to default to a <security-role> with the same name if no explicit link is specified.
There is a scoping issue for role ref names but that is not new - 2.x libraries can also conflict by using the same value in calls to isUserInRole().
> Based on the JACC WebRoleRefPermission, where the constructor arguments are the servlet name and the role name, I've concluded that the a filter gets the same isUserInRole behavior as the servlet the request ends up at after going through the filter. I think this is a satisfactory solution, and it's passed quite a few ee tcks by now. It's also quite easy to implement :-). I think talking to Ron Monzilla if you disagree with it would be the way to go.
As the spec stands with <security-role-ref>/@DeclareRoles only allowed on Servlets and not on Filters I'd come to the same conclusion. It is a weird coupling though as the role reference is made by the filter and not the servlet, the servlet author does not know a-priori what filters will be applied or vice versa. Again, more of an issue now we have annotation based config. IMO, getting the spec to clarify this, and potentially allowing filters to declare role references would be useful.
I've assumed the same model would apply for calls to isUserInRole() from within listeners e.g. request or request attribute? Or from within an extension-mapped servlet like the JSP servlet?
> Then you presumably have an external security system such as ldap with some defined entities such as groups, and these usually get represented as Principals, perhaps in a Subject.. These are not application roles. You need to map the externally defined entities to the application roles.
+1, although falling back to mapping application roles to groups in the absence of configuration by the deployer is temptingly convenient (although with the "new-group" problem you mention).
...
> On Apr 19, 2013, at 2:28 PM, Mark Thomas <ma...@apache.org> wrote:
...
>>
>> Tomcat's current behaviour looks to be specification compliant but there
>> appears to me to be an issue here the the Servlet EG needs to address.
>> Before I move this issue there what do folks think about this? Is there
>> an issue or am I missing the obvious?
Seems to me there's ambiguity there that would be worth clarifying.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: and security constraints
Posted by Mark Thomas <ma...@apache.org>.
On 20/04/2013 07:04, David Jencks wrote:
> Hi Mark,
>
> I hope my being tired doesn't come across as being unpleasant… if so
> I apologize in advance.
Not at all. No need to apologize.
> I think a lot of the security discussion in the servlet spec is vague
> and misleading. I think the JACC spec provides a firmer basis for
> thinking about how security is supposed to work.
The Servlet spec plus the J2EE spec should provide all the necessary
information. If the Servlet spec needs clarification then specific areas
can be raised with the Servlet EG. For 3.1 requests for clarification
were generally actioned fairly quickly.
> IMO you have misinterpreted roles in the ee specs.
Quite possibly. I certainly should have read the Servlet spec more
carefully before posting and probably the J2EE spec as well. I've just
read the Servlet spec and it does clarify a couple of things but I think
there are still some problems around plugability.
> Based on the JACC WebRoleRefPermission, where the constructor
> arguments are the servlet name and the role name, I've concluded that
> the a filter gets the same isUserInRole behavior as the servlet the
> request ends up at after going through the filter. I think this is a
> satisfactory solution, and it's passed quite a few ee tcks by now.
> It's also quite easy to implement :-). I think talking to Ron
> Monzilla if you disagree with it would be the way to go.
That seems reasonable prior to Servlet 3.0 and is exactly what Tomcat
does at the moment.
For Servlet 3.0 I think there is a potential issue if a request is
mapped to a Filter and a Servlet from different fragments and the Filter
and Servlet require different security-role-ref entries. There is
currently no easy way to handle this.
I don't yet see a simple solution to this problem. That said, so far
this is only a theoretical problem and one solution could just be to
clarify the situation (calls to isUserInRole in Filters always use the
mapping from the mapped Servlet) in the Servlet spec.
> IIUC tomcat has chosen to only support mappings where the principal
> name equals the name of the application security role. IIRC the last
> time I looked many years ago tomcat did not verify that all the
> security roles used in security constraints or by isUserInRole calls
> were actually declared application roles.
Not quite. Using the Servlet spec language (particularly 13.5) Tomcat
supports Principals that are members of groups and only supports a
one-to-one mapping of groups to application security roles.
That is certainly a limitation of Tomcat's security implementation and
one we could look at improving.
> From my limited recollection of tomcat internals, I don't understand
> why tomcat doesn't verify that security roles that are used are
> declared,
Tomcat does verify this. It logs a warning if an undeclared role is used
and then proceeds as if the role had been declared. We could change it
to fail the web application when STRICT_SERVLET_COMPLIANCE is used but
that isn't something I feel is necessary.
> and why there isn't a more flexible mapping from e.g.
> groups to application roles.
No-one has felt the need to scratch that particular itch.
> For your specific example "admin" and "sysuser" are distinct
> application roles available for use across the entire application and
> the problem is that there is no way in tomcat to map the hr-manager
> principal representing an ldap group to roles with different names.
Yes, that part of my example is a Tomcat limitation.
> I think (a) is correct, by providing a more flexible way to map
> between principals and application roles.
I agree that that would solve that part of the problem but the issue
does remain for Filters and Servlets from different fragments needing
different security-role-refs.
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: and security constraints
Posted by David Jencks <da...@yahoo.com>.
Hi Mark,
I hope my being tired doesn't come across as being unpleasant… if so I apologize in advance.
I think a lot of the security discussion in the servlet spec is vague and misleading. I think the JACC spec provides a firmer basis for thinking about how security is supposed to work.
IMO you have misinterpreted roles in the ee specs. The specs including the servlet spec define application roles and base the declarative security constraints on them. Then you can map strings that bits of the application like, at least ejbs and servlets, to these declared security roles using a security-role-ref. The role-link has to be one of the declared application roles. For web apps the security-role-ref is defined on servlets. The application roles no matter where defined are scoped to the entire application not just one web app or web fragment. If a security-role-ref is not defined for a string, and you call isUserInRole with that string, the string is assumed to be a defined application role.
Based on the JACC WebRoleRefPermission, where the constructor arguments are the servlet name and the role name, I've concluded that the a filter gets the same isUserInRole behavior as the servlet the request ends up at after going through the filter. I think this is a satisfactory solution, and it's passed quite a few ee tcks by now. It's also quite easy to implement :-). I think talking to Ron Monzilla if you disagree with it would be the way to go.
Then you presumably have an external security system such as ldap with some defined entities such as groups, and these usually get represented as Principals, perhaps in a Subject.. These are not application roles. You need to map the externally defined entities to the application roles.
IIUC tomcat has chosen to only support mappings where the principal name equals the name of the application security role. IIRC the last time I looked many years ago tomcat did not verify that all the security roles used in security constraints or by isUserInRole calls were actually declared application roles.
From my limited recollection of tomcat internals, I don't understand why tomcat doesn't verify that security roles that are used are declared, and why there isn't a more flexible mapping from e.g. groups to application roles.
For your specific example "admin" and "sysuser" are distinct application roles available for use across the entire application and the problem is that there is no way in tomcat to map the hr-manager principal representing an ldap group to roles with different names.
Your option (b) is IMO definitely and very clearly not spec compliant.
I think (a) is correct, by providing a more flexible way to map between principals and application roles. I've always thought that even a default map between principals and roles using name equality was somewhat dangerous in the case that you don't want to assign any groups to a particular role. The ldap administrators could not know about the role and create a matching group and suddenly there are users in that role.
A little googling to try to remind myself about security-role-refs turned up http://docs.oracle.com/javaee/5/tutorial/doc/bncav.html#bncax which indicates very clearly that Sun thinks groups are not roles and that you need a flexible mapping between them. (see the sun-web-app snippet at the bottom).
thanks
david jencks
On Apr 19, 2013, at 2:28 PM, Mark Thomas <ma...@apache.org> wrote:
> Currently, Tomcat only checks against <security-role-ref> elements if
> there is a call to isUserInRole(). Prior to Servlet 3.0 this made sense.
> The person deploying the web application has control over web.xml and
> hence the security roles (those used in security constraints) but no
> control over application roles (those used by developers in Servlets
> with isUserInRole()) and therefore needed a mechanism to map the
> application roles to security roles.
>
> This mechanism is usually used to map application roles to security
> roles that exist in an external authentication and authorisation system
> such as an LDAP directory. For example, the application role admin in
> the HR application may get mapped to the hr-manager role that exists in
> the LDAP directory.
>
> With Servlet 3.0 plugability features the picture changes a little.
>
> Now a fragment may define security constraints that use a security role
> that does not match the organisations security roles and can't be
> modified in the application's web.xml. For example, an HR application
> with two fragments may define a role "admin" in fragment A and "sysuser"
> in fragment B both of which need to be mapped to the "hr-manager" role.
>
> Oh, and just to throw a spanner in the works, if a Filter uses
> isUserInRole() there is no way to map the application role to a security
> role.
>
> I'm currently unsure how this issue should be addressed. The options as
> I see them are:
>
> a) There is an obvious solution I have missed.
>
> b) Check <security-role-ref>'s when processing security constraints.
>
> c) Something else.
>
>
> Given the Filter issue, I think c) is the only viable option.
>
>
> Tomcat's current behaviour looks to be specification compliant but there
> appears to me to be an issue here the the Servlet EG needs to address.
> Before I move this issue there what do folks think about this? Is there
> an issue or am I missing the obvious?
>
> Mark
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org