Status

Current state: Pending

Discussion threadhere

JIRA

Motivation

The current group.principal.mapping configuration within the default and common identity assertion providers is limited in what it can do. The only mapping that is possible there is the mapping of a group or groups to a user principal.

This implementation was created early in Knox history and was the short term approach to adding groups before we had actual group lookup from LDAP and local OS accounts, etc.

There are a number of times that it would have been advantageous to be able to map your LDAP/OS group membership to another group membership within the gateway. There is currently no way to do this.

Approach

In order to keep the current functionality backward compatible and simple, let's introduce a new concept for mapping users to Virtual Groups. Virtual groups will provide us the ability to define Gateway level application groups or roles. 

These groups will not be present in the actual LDAP or local OS accounts but will be derived by attributes within the established security context and perhaps request and/or session.

By defining these Virtual Groups, Knox would be able to enforce Authorization policies through Ranger or ACLs that are defined with these calculated groups in mind. Knox would also be able to potentially affect routing decisions, QoS, throttling, etc based on these groups.

We have encountered a specific instance where all users within a given environment (local accounts exist or groups can be found via lookup, etc) need to be granted a particular group membership. There are environment specific constraints that degrade performance and scalability directly related to the number of users in a group. Adding this limitation to the environment just so that we can do authorization checks for a user's permission to access the environment from the gateway level is artificially limiting the scalability for no reason. If we can determine that a user is a member of the specific environment from within the gateway and reflect this within the security context via Java Principals then the ACLs and Ranger authorization policies can be enforced.

NOTE: In order for this to work properly, we will need to have the virtual group mapping happen after group lookup. I don't know off the top of my head whether that is the case currently with the group.principal.mapping capability. 

Usecases and configuration


Explicit Mappings with Logical OR's and AND's

We want to define a Virtual Group for datalake-admin.
Specific user/s would be mapped to the datalake-admin virtual group.
We also want to map all users that are both members of the admin and datalake LDAP groups to the datalake-admin Virtual Group.

    <param>
        <name>virtual.group.mapping</name>
        <value>user:lmccay,pzampino=datalake-admin||group:admin&&group:datalake=datalake-admin</value>
    </param>

In the above configuration:

1. Users lmccay and pzampino are explicitly added to the Virtual Group regardless of their LDAP groups
2. All users that are members of both the admin and datalake LDAP groups will be added to the Virtual Group

This will require that we split the statements within the value on the '||' as logical OR's.
We will then need to process any of the '&&' as logical AND's.
We should be able to have arbitrary but not necessarily nested combinations of these.

Select built-in Variable Support

The following are just different ideas that overlap in various ways so the same thing count be implemented in different ways.

Syntax is also up for discussion as some of the parsing here may be unnecessarily difficult.

USERNAME

We want to be able to distinguish a dynamic group based on a given variable. For instance, any user that is a member of the group of the same name as their username should be granted the environment-group. This leverages the knowledge that any user that should have access to the given environment should have a local account with a group of the same name as their username.

    <param>
        <name>virtual.group.mapping</name>
        <value>group:{$USERNAME}=environment-group</value>
    </param>

The above configuration, looks for a GroupPrincipal with the same name as the authenticated principal or username. This requires that certain variables be populated by the identity assertion provider or maybe even at a higher level within the gateway servlet so that the variables can but set as request parameters and flow through the provide pipeline and into API services as appropriate. This would allow these variables to infuence actions anywhere within the pipeline.

NOTE: username is subject to mapping itself within the identity assertion provider and we would need to consider how to handle this change within variable evaluation. It seems reasonable to just allow it to be changed within the variable post identity assertion mapping and any references after that will be relative to the new identity/username.

AT_LEAST_ONE or ANY

This variable represents more of a calculation that is stored in the variable than a specific attribute from the security context. Here we are making the assignment of the environment-group contingent on being a member of AT_LEAST_ONE LDAP group. There are many ways that we could determine this same sort of condition to satisfy access to an environment. We should try to determine the best performing way and avoid duplication especially where there is an expensive determination per request. We may also want to consider caching of these variables if there is expense associated with it at the request level.

    <param>-
        <name>virtual.group.mapping</name>
        <value>group:{$AT_LEAST_ONE}=environment-group</value>
    </param>

REQUEST PARAMS

This variable is represents a query param that is compared to a value perhaps regex and to assign the virtual group based on the conditional.

    <param>-
        <name>virtual.group.mapping</name>
        <value>request:{$PARAM("originalURL", "^http://localhost:8443/gateway/home/")}=environment-group</value>
    </param>

REQUEST HEADERS

This variable is represents a request header that is compared to a value perhaps regex and to assign the virtual group based on the conditional.

    <param>-
        <name>virtual.group.mapping</name>
        <value>request:{$HEADER("name", "value")}=environment-group</value>
    </param>

REQUEST METHOD

This variable is represents a HttpServletRequest method call that is compared to a value perhaps regex and to assign the virtual group based on the conditional.

    <param>-
        <name>virtual.group.mapping</name>
        <value>request:{$METHOD("getRemoteUser", "lmccay")}=environment-group</value>
    </param>

SESSION ATTRIBUTES

This variable is represents a session attribute that is compared to a value perhaps regex and to assign the virtual group based on the conditional.

    <param>-
        <name>virtual.group.mapping</name>
        <value>session:{$ATTR("name", "value")}=environment-group</value>
    </param>



  • No labels