Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

File(s): conf/intercept/impersonate-intercept-config.xml (V4.0), conf/idp.properties (V4.1+), views/intercept/impersonate.vm, conf/access-control.xml
Format: Native Spring, Properties (V4.1+), Velocity

Table of Contents

Overview

The "impersonate" interceptor flow is an example of how to use an interceptor to implement a testing capability that allows a user to represent themselves as a different user to a downstream service, subject to appropriate authorization. It does not affect the user's overall session and has no persistent effect on access to other services within the same session; it is a per-request feature that changes the set of attributes resolved by re-running the attribute resolver as though the user had a different identity.

...

The primary configuration involved with this flow is to define AccessControl policies to control who can impersonate whom. And of course, one can customize the view template displayed.

Localtabgroup
Localtab live
titleV4.0

The beans named shibboleth.impersonate.GeneralPolicy and shibboleth.impersonate.SpecificPolicy in conf/intercept/impersonate-intercept-config.xml must be defined by you with the named AccessControl policies you want to apply.

Localtab live
activetrue
titleV4.1+

The properties named idp.impersonate.generalPolicy and idp.impersonate.specificPolicy control the named AccessControl policies you want to apply. They default to "GeneralImpersonationPolicy" and "SpecificImpersonationPolicy" respectively.

If the legacy file conf/intercept/impersonate-intercept-config.xml remains present, the beans in that file supersede the property definition(s) but you may remove the file if the default values or properties are used instead.

...

If the policy allows access, the flow will:

  • log an informational message

  • destroy any existing attributes resolved for the user

  • move the original username into an "impersonatingPrincipalName" property in the attached SubjectContext

  • populate the impersonated principal name into the attached SubjectContext

  • re-run the AttributeResolver with the effective subject name set to the selected value

  • add an audit field ("uu") containing the impersonating account so that it can be recorded in the audit log

Attribute Resolver Considerations

For most configurations, the only user-specific element of the resolution process will be derived from the principalName property of the AttributeResolutionContext provided to the resolver, which will be set by this flow to the impersonated name instead of the original one.

...

To facilitate attaching conditions or adding script logic that can be made dependent on whether impersonation is happening, a new property has been added to the AttributeResolutionContext, the resolutionLabel, and it will be set to "intercept/impersonate" (the flow ID) when this flow is doing the resolution (it will be empty in the traditional case).

As a general matter, unless all of your attributes come from a persistent store you can re-query, this feature is not likely to work, or be safe to use.

Reference

Localtabgroup
Localtab live
titleBeans (V4.0)

The following beans are defined in conf/intercept/impersonate-intercept-config.xml:

Bean ID

Type

Description

shibboleth.impersonate.GeneralPolicy

String

Named AccessControl policy to run to determine whether to run this flow 

shibboleth.impersonate.SpecificPolicy

String

Named AccessControl policy to run to determine whether to allow the requested impersonation

Localtab live
activetrue
titleProperties (V4.1+)

The following properties in conf/idp.properties may be used to override the default policy names used:

Name

Default

Description

idp.impersonate.generalPolicy

GeneralImpersonationPolicy

Named AccessControl policy to run to determine whether to run this flow 

idp.impersonate.specificPolicy

SpecificImpersonationPolicy

Named AccessControl policy to run to determine whether to allow the requested impersonation

Example

Aside from the UI, all of the flow's configuration is actually just defining policies, either in conf/access-control.xml or an included file. In practice, a "real world" implementation of such policies would likely rely on some kind of directory or database of rules controlling which users can impersonate which users to which services, perhaps through group memberships resolved during initial attribute resolution.

...

The "general" policy is a simple test of an entitlement attribute for a specific value that is intended to mean "allow this logged-in user to at least attempt impersonation", and uses the SimpleAttributePredicate Java class. This class is often used to implement authorization rules in the context-check interceptor.

The "specific" policy could be implemented by a somewhat-involved script, but the example below relies on an advanced Java class that checks the values of a resolved IdPAttribute against a dynamically computed candidate value (or values) produced by functions, which can themselves be scripts or expressions. This DynamicAttributePredicate class relies on an injected map of attribute names to functions, instead of attribute names to strings. The mapped function objects return the data values that have to be found in the named attribute at runtime to be a valid match. It's indirect instead of static/direct.

...

Once you understand the idea, it's not a lot of configuration to maintain and supports a plausible real-world approach to authorizing the impersonation feature.

xmlcollapsetrue
Code Block
language
Expand
titleconf/access-control.xml
Code Block
language
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
                           
       default-init-method="initialize"
       default-destroy-method="destroy">

    <util:map id="shibboleth.AccessControlPolicies">
    
		<!-- Limits who can impersonate based on entitlement. -->
        <entry key="GeneralImpersonationPolicy">
            <bean parent="shibboleth.PredicateAccessControl">
                <constructor-arg>
                    <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate">
                        <property name="attributeValueMap">
                            <map>
                                <entry key="eduPersonEntitlement">
                                    <list>
                                        <value>https://example.org/entitlement/impersonation</value>
                                    </list>
                                </entry>
                            </map>
                        </property>
                    </bean>
                </constructor-arg>
            </bean>
        </entry>

		<!-- Controls the impersonation scenarios to allow. -->
        <entry key="SpecificImpersonationPolicy">
            <bean parent="shibboleth.PredicateAccessControl">
                <constructor-arg>
                    <bean parent="shibboleth.Conditions.AND">
                        <constructor-arg>
                            <bean class="net.shibboleth.idp.profile.logic.DynamicAttributePredicate">
                                <property name="attributeFunctionMap">
                                    <map>
                                        <entry key="impersonatableUsernames">
                                            <list>
                                                <bean parent="shibboleth.ContextFunctions.Expression"
                                                    c:expression="#input.getSubcontext(T(org.opensaml.profile.context.AccessControlContext)).getResource()" />
                                            </list>
                                        </entry>
                                    </map>
                                </property>
                            </bean>
                        </constructor-arg>
                        <constructor-arg>
                            <bean class="net.shibboleth.idp.profile.logic.DynamicAttributePredicate">
                                <property name="attributeFunctionMap">
                                    <map>
                                        <entry key="impersonatableServices">
                                            <list>
                                                <bean parent="shibboleth.RelyingPartyIdLookup.Simple" />
                                            </list>
                                        </entry>
                                    </map>
                                </property>
                            </bean>
                        </constructor-arg>
                    </bean>
                </constructor-arg>
            </bean>
        </entry>

    </util:map>

</beans>