Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add capability to extract application role names from Windows Group Names in specified domains in JAAS implementation (resolves #1145) #1160

Closed
wants to merge 8 commits into from

Conversation

eekodeerder
Copy link
Contributor

@eekodeerder eekodeerder commented Jan 21, 2021

In a typical application environment, the application implements security roles (by name) which is used to control access to application functions. These security role names are often application specific and should be portable if the application is to run in multiple organizational domains. As an example: Tomcat access control uses a role: "manager-gui".

To use a JAAS LoginModule and Windows Active Directory to authorise the users who can perform this Tomcat role, the Waffle WindowsLoginModule should be able to translate AD groups to which an autenticated User belongs to a RolePrincipal wih the name "manager-gui".

This pull request adds this capability to the Waffle JAAS WindowsLoginModule. A new option is added in which an installer configuring an application can specify a comma-delimited list of domain names for which the WindowsLoginModule should create RolePrinciples using only the group name without the domain name (not the fqn).

This feature does not affect any existing deployments, as the FQN and/or the SID for Windows Groups can still be included in the list of RolePrinciples delivered, in addition or instead of the new simple role names.

How do I link this pull request to Issue #1145?

eekodeerder and others added 8 commits December 19, 2020 11:39
The existing code for WindowsLoginModule (since October 2016) does not bind the Windows (or Active DIrectory) group (names) to the Subject. It binds an object named "Roles" to the Subject. It therefore does not fulfill the basic function required of a JAAS WindowsLoginModule.  Refer to Issue Waffle#1114.

The packaging into a GroupPrincipal (which did not exist before the breaking change), was made to get it to work with WildFly (earlier versions as it does not work with latest versions in any case). Every Windows Group to which the User belongs, was placed into a new list of Principals (named "Roles") which was then packaged as a Principal (the GroupPrincipal) and added to the Subject.Principals list. This is just plain wrong, as it assumes that any user of the subject will know about the custom "Roles", and be able to extract the Principals from this list, This assumption is obviously invalid. The JAAS specified way is to obtain it from the Subject.Principles.getName(). The code modification also removed the ability to obtain the Windows Group (or JAAS roles) from the Subject.Principles.getName() as specified by JAAS.
The existing code for WindowsLoginModule (since October 2016) does not bind the Windows (or Active DIrectory) group (names) to the Subject. It binds an object named "Roles" to the Subject. It therefore does not fulfill the basic function required of a JAAS WindowsLoginModule.  Refer to Issue Waffle#1114.

The packaging into a GroupPrincipal (which did not exist before the breaking change), was made to get it to work with WildFly (earlier versions as it does not work with latest versions in any case). Every Windows Group to which the User belongs, was placed into a new list of Principals (named "Roles") which was then packaged as a Principal (the GroupPrincipal) and added to the Subject.Principals list. This is just plain wrong, as it assumes that any user of the subject will know about the custom "Roles", and be able to extract the Principals from this list, This assumption is obviously invalid. The JAAS specified way is to obtain it from the Subject.Principles.getName(). The code modification also removed the ability to obtain the Windows Group (or JAAS roles) from the Subject.Principles.getName() as specified by JAAS.
@eekodeerder eekodeerder changed the title Add capability to extract application role names from Windows Group Names in specified domains Add capability to extract application role names from Windows Group Names in specified domains in JAAS implementation Jan 21, 2021
@eekodeerder eekodeerder changed the title Add capability to extract application role names from Windows Group Names in specified domains in JAAS implementation Add capability to extract application role names from Windows Group Names in specified domains in JAAS implementation (resolves #1145) Jan 21, 2021
Copy link
Collaborator

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments.

@@ -77,6 +77,7 @@ The following options are supported by the module.
* debug: Set to "true" to enable debug mode. In debug mode the module will output information about successful logins, including group memberships.
* principalFormat: Specifies the name format for the principal.
* roleFormat: Specifies the name format for the role.
* mapRolesFromDomainGroups: Specifies domains for which security group names will be mapped to roles without including the domain in the role name. These roles will added in addition to roles added through the roleFormat option. In most uses cases, the need for both the roleFormat and the mapRolesFromDomainGroups should not be required.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be added

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backtickquote roleFormat

@@ -103,6 +107,10 @@ public void initialize(final Subject initSubject, final CallbackHandler initCall
.valueOf(((String) option.getValue()).toUpperCase(Locale.ENGLISH));
} else if ("roleFormat".equalsIgnoreCase(option.getKey())) {
this.roleFormat = PrincipalFormat.valueOf(((String) option.getValue()).toUpperCase(Locale.ENGLISH));
} else if ("mapRolesFromDomainGroups".equalsIgnoreCase(option.getKey())) {
// Remove quotation marks as well as whitespace for robustness
this.domains = ((String) option.getValue()).replaceAll("(\")", "").replaceAll("(^\\s*)|(\\s*$)", "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a test for this. I modified initialize_withOptions in waffle-jna\src\test\java\waffle\jaas\WindowsLoginModuleTest to simultaneously test this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant specifically for the stripping part. NBD

// add Windows Groups as role principles
for (final IWindowsAccount group : windowsIdentity.getGroups()) {
this.principals.addAll(getRolePrincipals(group, this.roleFormat));
if (domainlist.contains(group.getDomain())) {
this.principals.add(new RolePrincipal(group.getName()));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't getRolePrincipals be responsible for adding those instead of doing it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make sense to move it GetRolePrincipals. This method would then either not be static anymore, or require the domains to be passed as parameter (which kind of defeats the object of making it static). The better implementation will move lines 170 to 184 into a seperate method. I left it here as this is where the previous GroupPrincipal was also added.

In essence we have an WindowsIdentity which has Groups which is a set of Account. This needs to be translated into Java Principles. In essence we have UserPrincipals, GoupPrincipals (not the previous waffle GroupPrincipal, but a Principal representing the Windows Group in a domain) and RolePrincipal, which would be the security roles required by the application. Somewhere Windows groups have to be mapped to application roles.

A transformation method takes a WindowsIdentity and generates the Principals for a Subject from this identity. This includes generating the UserPrincipal and the one or more translations/mapings from the Groups to Roles. The Principles describe the "identities" of the WindowsIdentity which includes role and/or group memberships.

Doing it correctly would then actually move the creation of all Principals (or for the jna-tomcat Windowsrealm the Strings (Names/Identities) from a single WindowsIdentity into a seperate method.

A transformation method could in theory be re-used in JAAS, and the various jna-tomcat* implementations.

We could implement different LoginModules for different types of mapping or make them options on one LoginModule.

What I have implemented now, makes it possible to interchange the Tomcat UserDatabaseRealm, DataSourceRealm and JAASRealm as realms for the same application which uses Tomcat for authentication and passes the roles to a web-app, or for Tomcat itself. Without the modification, this is no possible,

@dblock
Copy link
Collaborator

dblock commented Jan 21, 2021

Thought about this some more. I worry that we're adding both domain\name and name through another mechanism. Would it make more sense to extend roleFormat?

@dblock
Copy link
Collaborator

dblock commented Jan 21, 2021

I mean why don't we just add a NAME format to

?

If we need more combinations, we should introduce roleFormats that can take a list and/or deprecate BOTH.

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 21, 2021

I mean why don't we just add a NAME format to

?
If we need more combinations, we should introduce roleFormats that can take a list and/or deprecate BOTH.

The difference between the method I implemented and just adding another option is that in my implemented method, you can control the domains that specify the roles. As an example: I might want the role names (group) to be managed in the organization's domain, or as groups on the hosting server. By not specifying the domain to use, it means that if the application should be managed in the domain, I could bypass the system by creating a group with the same name on the server, or vice versa. This will create a security risk.

@dblock
Copy link
Collaborator

dblock commented Jan 21, 2021

The difference between the method I implemented and just adding another option is that in my implemented method, you can control the domains that specify the roles. As an example: I might want the role names (group) to be managed in the organization's domain, or as groups on the hosting server. By not specifying the domain to use, it means that if the application should be managed in the domain, I could bypass the system by creating a group with the same name on the server, or vice versa. This will create a security risk.

I see, and agree, my suggestion was not a good one.

That said, if the app wants "manager-gui", you're now enabling "DOMAIN\manager-gui" to become "manager-gui" by stripping domain. I can't help but be worried about this because "ONE\manager-gui" can become the same thing as "TWO\manager-gui" as long as we specified "ONE" and "TWO" in this magical pattern, and not using names was really what I was going for in the original implementation - those can change, while SIDs cannot.

Would you consider something more specific? For example an ability to specify a mapping? Possibly as a separate filter on top of Waffle?

<group-to-role-mappings>
  <group-to-role-mapping>
    <group-name>ONE\manager-gui</group-name>
    <role-name>manager-gui</role-name>
  </group-to-role-mapping>
  <group-to-role-mapping>
    <group-sid>S-...</group-sid>
    <role-name>manager-gui</role-name>
  </group-to-role-mapping>
</group-to-role-mappings>

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 22, 2021

Would you consider something more specific? For example an ability to specify a mapping? Possibly as a separate filter on top of Waffle?

Yes (and no). I believe having a specific mapping is definitely a good option. Many environments provide a mapping method (Tomcat does not).
However, I believe that for JAAS, such a mapping could be beneficial inside the LoginModule, as JAAS specifically provides the capability to have customised Authentication, Authorisation and translation to Roles.

I see such a mapping as an additional method that can be supported to extend Waffle capabilities. This method has the following constraints:

  1. Using a mapping means that you have to specify each role in a map element for the environment you are going into.
  2. The mapping would have to happen in the Realm (currently the JAASRealm) to be interchangeable with the other Realms specified (Tomcat UserDatabaseRealm, DataSourceRealm). This requires a new Realm to be implemented (such as extending the jna-tomcat* WindowsRealms - which have a version for every version of Tomcat).

I basically wanted to solve a problem: We were using Waffle as one of the options (interchangeably) to do authentication for Tomcat. It worked, and now it does not work. I identified the first problem (waffle bug) and fixed that. Then (and I still cannot pinpoint where the problem originates from as operating system, jna, waffle, our own code changed) I found that I still cannot use the Tomcat JAASRealm with the WinodwsLoginModule as we were getting the domain names in there.

I have implemented one option, which works for certain use cases (ours in particular). It is an extension of the existing solution and does not break or modify anything else. It does not exclude adding additional methods of mapping inside the WindowsLoginModule; it does not exclude having mappings on top of the Waffle JAAS implementation; it does not exclude any existing capabilities.

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 22, 2021

That said, if the app wants "manager-gui", you're now enabling "DOMAIN\manager-gui" to become "manager-gui" by stripping domain. I can't help but be worried about this because "ONE\manager-gui" can become the same thing as "TWO\manager-gui" as long as we specified "ONE" and "TWO" in this magical pattern, and not using names was really what I was going for in the original implementation - those can change, while SIDs cannot.

  1. I understand that SIDs do not change when you change names in the domain, but you have to set up the group with the right SID for Windows. The group has multiple identities (or Principles). The thing to solve is: "how do I get an application specified role name (Principle) from these Windows identities?"
  2. Do you want the JAAS implementation of Waffle to only work for applications that use SID's as roles?
  3. In essence the required roles are defined by an application (Tomcat and applications running in it in our case) and not by Windows (or for that matter the domain). Windows provide standard SIDs for operating system roles and some applications use SIDs for application roles. The Realm has to provide the application roles which the user can perform from whatever Authorization is used by the Realm. This could include mapping SIDs to application roles. If the mapping does not happen inside the Realm, different Realms can only be interchangeable if they can provide the same "roles". If we limit this to SIDs, it means all Realms should all be able to hand out SIDs.
  4. This means that having either "ONE\manager-gui" or "TWO\manager-gui" being able to become "manager-gui" is not an obstacle, but an extension which enables flexibility in application hosting options.
  5. In Tomcat the other Realms we use hand out "manager-gui" as a role the user can perform. I therefore believe using the JAASRealm as specified in the documentation should be able to do the same.
  6. The job of a Realm is not to expose the authentication and authorization system, the user/group/role management and its intricacies to the application, but to hide it through the Realm abstraction.

To summarise I believe the problem is not: "How do I expose Windows Authentication (which there are no arguments about currently) and Authorisation (specifically Windows identities) to the application". The problem is: "How do I use Windows Authentication and Authorisation to manage the roles a user can play in an application?". The latter question results in a superset solution, which allows not only exposing roles as used by Windows, but more.

@dblock
Copy link
Collaborator

dblock commented Jan 22, 2021

First, thank you. I really appreciate your work here, and I come from a place of wanting to do the right thing (and not the fastest thing :)). I think I am against the magical "strip domain" version as in this PR - it introduces an option that is not generic enough and I can't help but think it's a one-way door decision of adding a feature that will bite us in the future when someone runs into wanting to do a more complex "mapping".

In a mapping solution you could, for example, implement a regex version, DOMAIN\* to $1, which would be extremely powerful for all kinds of scenarios, and allow a lot of granular control to users.

Btw, @hazendaz ultimately makes this call as the current benevolent dictator.

That said, if the app wants "manager-gui", you're now enabling "DOMAIN\manager-gui" to become "manager-gui" by stripping domain. I can't help but be worried about this because "ONE\manager-gui" can become the same thing as "TWO\manager-gui" as long as we specified "ONE" and "TWO" in this magical pattern, and not using names was really what I was going for in the original implementation - those can change, while SIDs cannot.

  1. I understand that SIDs do not change when you change names in the domain, but you have to set up the group with the right SID for Windows. The group has multiple identities (or Principles). The thing to solve is: "how do I get an application specified role name (Principle) from these Windows identities?"

Yes.

  1. Do you want the JAAS implementation of Waffle to only work for applications that use SID's as roles?

Originally I did, but you have a real problem and Waffle should solve it.

  1. In essence the required roles are defined by an application (Tomcat and applications running in it in our case) and not by Windows (or for that matter the domain). Windows provide standard SIDs for operating system roles and some applications use SIDs for application roles. The Realm has to provide the application roles which the user can perform from whatever Authorization is used by the Realm. This could include mapping SIDs to application roles. If the mapping does not happen inside the Realm, different Realms can only be interchangeable if they can provide the same "roles". If we limit this to SIDs, it means all Realms should all be able to hand out SIDs.

Yes.

  1. This means that having either "ONE\manager-gui" or "TWO\manager-gui" being able to become "manager-gui" is not an obstacle, but an extension which enables flexibility in application hosting options.

Agreed.

  1. In Tomcat the other Realms we use hand out "manager-gui" as a role the user can perform. I therefore believe using the JAASRealm as specified in the documentation should be able to do the same.

Agreed.

  1. The job of a Realm is not to expose the authentication and authorization system, the user/group/role management and its intricacies to the application, but to hide it through the Realm abstraction.

Agreed.

To summarise I believe the problem is not: "How do I expose Windows Authentication (which there are no arguments about currently) and Authorisation (specifically Windows identities) to the application". The problem is: "How do I use Windows Authentication and Authorisation to manage the roles a user can play in an application?". The latter question results in a superset solution, which allows not only exposing roles as used by Windows, but more.

Do you think the mapping implementation is better/more generic/solves more problems here? If so, give it a shot and we can compare? I know it's a lot more work, but feels like it's worth it (to someone not doing the work like me :))).

@eekodeerder
Copy link
Contributor Author

First, thank you. I really appreciate your work here, and I come from a place of wanting to do the right thing (and not the fastest thing :)). I think I am against the magical "strip domain" version as in this PR - it introduces an option that is not generic enough and I can't help but think it's a one-way door decision of adding a feature that will bite us in the future when someone runs into wanting to do a more complex "mapping".

With this I totally agree. I wrote my first program in 1982. I have been in product development since 1987. I have been doing object oriented design since 1992. Unfortunately, in terms of experience, Java ranks between the 13th to 17th language in terms of my programming experience. W.r.t. our projects that also use Java components, I am responsible for the system design. our products are long-lived and have to be supported and improved for many years.

Taking short-cuts does not work, but this does not mean that the path wih less development work is the wrong one.

In terms of a map versus just mapping the names from one or more domains:

  1. The "right" solution is the want that makes the component(s) usable with as little configuration (regardless of development) as possible.
  2. To implement a map through the LoginModule interface, means you will have to supply an external file/resource name to the LoginModule which specifies the mapping. This could be various different formats (such as .csv). This resource will now have to be configured and supplied/provisioned somewhere, in addition to somebody having to write/create a .csv or .xml file manually for every installation in order to map Windows domain groups to application roles. You still have to now create the domain groups and manage the users that have access to this. this is a lot more aand higher skilled work required for installing into a specific domain, bearing in mind that you have to redo the mapping for every domain into which you install.
  3. If you use the simple domain mapping, it means you have to create a Windows Group for every role you have in your application. You are therefore using Windows group and User Management as your editor, instead of having to be able to edit a .csv or .xml file. You could still have Domain Groups with different names (the ones you would have to map from in a .csv file) which belong to the "application role groups". You have the same flexibility, but you have less configuration and no additional editors and/or language knowledge required to set it up.

For the above reasons, I do not believe mapping is more flexible or the "right" solution. It is an alternative which may be viable when you have personnel with more IT knowledge (as it is more difficult to configure/install), but there is no use case that I can think of that you cannot handle by just mapping the domain.

Even replacing the Tomcat JAASRealm with a subclassed Realm which can use an object to define the map, will suffer from exactly the same constraint. You have to do part of your "mapping" of "group rights" outside of the official editor for your Group access rights (in this case Windows). You are effectively introducing an additional authorization mapping from the one we are supporting (Windows Group and User management). I still do not understand why you would want to do that, but there may be reasons outside of my reference frame.

I became involved in this as nobody on our time had the time to support the client to determine why they could not get Waffle authentication working again. I have spent some of my vacation time and some time paid for by the client to get to where I am. As explained, we have no need for a mapping. In our case the client supplies, installs and maintains the system at their clients' locations. These installers are NOT computer programmers.

@hazendaz
Copy link
Member

I probably need to get a cup of coffee and read through this again. The code is rather net new. It might be useful to provide a bit more in documentation of general setup and more descriptive use case. Currently I think this PR is the descriptive part which would be lost otherwise. Is it possible @eekodeerder you could add a bit more to documentation to assist others?

One unrelated item I spotted here was the README.md move. That part is tied to the .net build. Way back when, the java piece only had one pom file and using it to copy things around caused many copies. Today, we have a launcher which isn't coupled into the main build. As such, I saw that as an opportunity to clean that up so regardless of running the .net side or the java side, that file is updated if it was touched in the root of the project since the underlying piece needs it for the actual site build via maven. I'm sending that through now. So what that means to this PR, once you see that on master, please go ahead and just merge back in. That way it filters that change out and we are left just with the changes here to continue to look at.

@hazendaz hazendaz added this to the 3.1.0 milestone Jan 23, 2021
@hazendaz
Copy link
Member

I've added this as a milestone for 3.1.0 and moved out 3.1.0 until end of February to give time to get this addressed upon further discussion.

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 23, 2021

Noted, thanks. I will update the documentation. As primarily a user (not developer) of Waffle, where Windows Authentication and Authorisation is offered as one of the options to end-user organisations, I understand the decisions to be made at installation/deployment for an oranisation to be:

  1. How do we authenticate users for the application?
  2. How do we manage which users can perform which roles in the application?

Some (less sophisticated) want to administer the users and roles through an application supplied interface (using an application database for user and role management set up as a Tomcat DataSourceRealm, (or even just through the tomcat-users.xml file -> the Tomcat UserDatabaseRealm). Others want to move access authorization as well as user authentication into their domain (which for all clients is a Windows environment. It is for these end-users that Waffle is used.

For the sophisticated environment, access is controlled by a specific organizational unit, which in the main does not use the application, interface with the application or even maintain the application. This "application" includes Tomcat. The simple requirement is: "How do we manage which user(s) can perform the which security roles incorporated in the "application" using the tools supplied in Windows for managing access.

@pedroneil
Copy link
Contributor

pedroneil commented Jan 23, 2021 via email

@dblock
Copy link
Collaborator

dblock commented Jan 24, 2021

@pedroneil The feature as implemented lets users specify for which domain(s) to add a named role (which happens to not include the domain name), so it's not changing any existing roles unless I didn't read the code right.

Since it's net new I don't think there's a problem with existing implementations. My comments are really about the approach of how to achieve that, I disagree that the option should be a list of domains, it will lead to people having exactly the problems that you have listed inadvertently, IMHO.

@dblock
Copy link
Collaborator

dblock commented Jan 24, 2021

In terms of a map versus just mapping the names from one or more domains:

  1. The "right" solution is the want that makes the component(s) usable with as little configuration (regardless of development) as possible.

... and with as little side effects or surprise behaviors as possible

  1. To implement a map through the LoginModule interface, means you will have to supply an external file/resource name to the LoginModule which specifies the mapping. This could be various different formats (such as .csv). This resource will now have to be configured and supplied/provisioned somewhere, in addition to somebody having to write/create a .csv or .xml file manually for every installation in order to map Windows domain groups to application roles. You still have to now create the domain groups and manage the users that have access to this. this is a lot more aand higher skilled work required for installing into a specific domain, bearing in mind that you have to redo the mapping for every domain into which you install.

I forgot this is JAAS. I don't think we need to overthink it with external files and "serialize" a map, e.g. roleMappings=ONE\manager-gui:manager-gui;TWO\manager-gui:manager-gui? Simple enough change for your proposal here, no? Btw, code should probably handle duplicates and not add it twice (not sure if we care)?

Subsequent change can add regex support, roleMappings=ONE\*:$1;TWO\manager-gui:manager-gui. I might be up for coding that, been a while ;) And another subsequent change if anyone cares could introduce an external file with roleMappings=file:// or whatever.

  1. If you use the simple domain mapping, it means you have to create a Windows Group for every role you have in your application. You are therefore using Windows group and User Management as your editor, instead of having to be able to edit a .csv or .xml file. You could still have Domain Groups with different names (the ones you would have to map from in a .csv file) which belong to the "application role groups". You have the same flexibility, but you have less configuration and no additional editors and/or language knowledge required to set it up.

I think at the lowest level users will want to exercise the lowest level of control, which I think is group -> role where the names are unrelated. That's an application concern and belongs in the application configuration. You can do bulk domain* -> *, but I find that extremely dangerous and wouldn't want to impose this on users by default.

@eekodeerder
Copy link
Contributor Author

Since it's net new I don't think there's a problem with existing implementations. My comments are really about the approach of how to achieve that, I disagree that the option should be a list of domains, it will lead to people having exactly the problems that you have listed inadvertently, IMHO.

It does not have to be a list of domain. The way I see it: domain name is the name of where the application roles are defined as Windows Groups. It identifies the "authority" the application should rely on. Providing a list allows "multiple authorities".

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 25, 2021

I forgot this is JAAS. I don't think we need to overthink it with external files and "serialize" a map, e.g. roleMappings=ONE\manager-gui:manager-gui;TWO\manager-gui:manager-gui? Simple enough change for your proposal here, no? Btw, code should probably handle duplicates and not add it twice (not sure if we care)?

Subsequent change can add regex support, roleMappings=ONE\*:$1;TWO\manager-gui:manager-gui. I might be up for coding that, been a while ;) And another subsequent change if anyone cares could introduce an external file with roleMappings=file:// or whatever.

After finding a lot of good reasons why not to do this, I found a valid use case (which makes sense) which will be addressed by such a Regex solution:
If I have to manage application roles for multiple applications or multiple instances of the same application (managed in the same domain) which use the same application role name.
e.g. I have two Tomcat installations which are controlled through the same domain, but with different users having to access the different installations.
e.g 'roleMappings=ONE\tomcat-two-.*:$1'. Users that are membersOf ONE\tomcat-two-manager-gui group, will be able to manage the Tomcat installation that uses the WindowsLoginModule that is configured with this setting.

I will try to make some time to implement. As I said, Java is not even close to my first language.

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Jan 25, 2021

I apologise if I have missed some of the message chain and this may be irrelevant. Not JAAS related, however, my usages of waffle requires the group to be populated with the domain ie. DOMAIN\SAMACCOUNT This allows a legacy application application to continue supporting multiple domains. DOMAIN01\USER01 DOMAIN02\USER01 1. stripping the domain would cause authorization failures. 2. Keeping the domain continues to let the application to continue working with no issues. 3. For others stripping the domain loses the uniqueness of the 2 users.

This change does not influence users or user domains at all. Two users in different domains will never be confused.

It also does not influence existing Group/Role capabilities. DOMAIN\SAMACCOUNT (even for Groups) is still available exactly as you use it now, without change, using the existing options.

When using a new option, it just adds the capability to (also) provide the application role name without a domain or computer name, allowing you to get SAMACCOUNT as a role from a Windows Group DOMAIN\SAMACCOUNT. This "group" DOMAIN obviously does not have to be the same as the domain for your user.

@dblock
Copy link
Collaborator

dblock commented Jan 25, 2021

After finding a lot of good reasons why not to do this,

I am ready to change my mind (and you convinced me of various things above that I got wrong), so don't hesitate to push back. I just want the best outcome in the library.

I found a valid use case (which makes sense) which will be addressed by such a Regex solution:
If I have to manage application roles for multiple applications or multiple instances of the same application (managed in the same domain) which use the same application role name.
e.g. I have two Tomcat installations which are controlled through the same domain, but with different users having to access the different installations.
e.g 'roleMappings=ONE\tomcat-two-.*:$1'. Users that are membersOf ONE\tomcat-two-manager-gui group, will be able to manage the Tomcat installation that uses the WindowsLoginModule that is configured with this setting.

I think people will end up using this without any regex to make things more predictable. This is telling me that they will want to not use regex and just have a file with the explicit domain name mappings, but potentially many entries. If I was coding this I'd only allow a text/tab file for the mappings, so roleMappings=/etc/role-mappings, which would be consistent with other JAAS implementations I've seen for Kerberos and such. It's also the simplest implementation, reading a text file is trivial (it would only contain name=value pairs, not xml or anything). I would not want regex in my application configuration because it will enable someone to create a group that just happens to match a regex to get access to my application, and it feels too dangerous. But I am not writing the code and I am fine allowing people to shoot themselves in the foot :) Curious whether @hazendaz has an opinion here.

I will try to make some time to implement. As I said, Java is not even close to my first language.

My first language is Russian :) I think you're doing great! Thank you.

@hazendaz
Copy link
Member

@dblock I'm kind of with you on the regex. Its too easy to mess up and hard to read. It does serve a purpose much more easily though if done correctly but I think here maybe error on side of caution in general. This is security so its a little more dicey with regex.

@eekodeerder I think I fully understand now but will re-read this star to finish this weekend.

@eekodeerder
Copy link
Contributor Author

eekodeerder commented Feb 2, 2021

I have looked at the (agree messy) Regex option. One of the problems of doing mapping like that is how to seperate the Regex (or just plain string) mappings. The proposed ";" will/may cause problems, as the ";" is used as a seperator for specifications in the Tomcat login.conf. Becomes very messy and becomes dependent on the parser in Tomcat.

I also vote against a RegEx, but I do need a simple way to specify multiple application roles from one domain without having to copy it multiple times. Maybe instead of a regex, a simple wildcard can be specified: roleMappings=ONE\tomcat-two-* ? A plain domain map could be specified as roleMappings=ONE*, or just roleMappings=ONE as shorthand. Another application in the same Tomcat will have a different LoginModule configuration in login.conf.

@dblock
Copy link
Collaborator

dblock commented Feb 2, 2021

I have looked at the (agree messy) Regex option. One of the problems of doing mapping like that is how to seperate the Regex (or just plain string) mappings. The proposed ";" will/may cause problems, as the ";" is used as a seperator for specifications in the Tomcat login.conf. Becomes very messy and becomes dependent on the parser in Tomcat.

I also vote against a RegEx, but I do need a simple way to specify multiple application roles from one domain without having to copy it multiple times. Maybe instead of a regex, a simple wildcard can be specified: roleMappings=ONE\tomcat-two-* ? A plain domain map could be specified as roleMappings=ONE*, or just roleMappings=ONE as shorthand. Another application in the same Tomcat will have a different LoginModule configuration in login.conf.

Always using a file and reading it line-by-line with a = separator would solve the issue, wouldn't it? Otherwise what kind of group or regex contains a ; anyway? A wildcard is just a poor man's regex IMO.

@dblock
Copy link
Collaborator

dblock commented Feb 2, 2021

I think you're trying to find a perfect solution to an imperfect problem. I would implement a mapping without regex, then try to use it in production and come back for an incremental solution, regex or not, once you see all the problems - divide and conquer.

@eekodeerder
Copy link
Contributor Author

Thank. you. The code I have submitted is already running in the field with end-users.
It exactly meets our (current) requirements. It is running as a SNAPSHOT from my own branch. It has gone through all the testing stages. We just do not have it under our source control and cannot get it from a maven repository, which is the maintenance risk.

@dblock
Copy link
Collaborator

dblock commented Feb 2, 2021

Thank. you. The code I have submitted is already running in the field with end-users.
It exactly meets our (current) requirements. It is running as a SNAPSHOT from my own branch. It has gone through all the testing stages. We just do not have it under our source control and cannot get it from a maven repository, which is the maintenance risk.

As I said I'm against introducing mapRolesFromDomainGroups, no hard feelings. I would take an explicit mapping solution.

@hazendaz
Copy link
Member

closing as not originally accepted.

@hazendaz hazendaz closed this Jun 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants