Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende ÜberarbeitungLetzte ÜberarbeitungBeide Seiten der Revision |
de:shibidp3testzugang_fuer_externe_admins [2017/08/29 09:13] – Raoul Gunnar Borenius | de:shibidp:config-testzugang [2022/11/28 15:41] – Wolfgang Pempe |
---|
====== Testzugang für externe bzw. SP Admins ====== | ====== Zugriff einzelner User auf bestimmte SPs beschränken ====== |
**Das Szenario:**\\ | |
Ein neuer SP soll an den IdP angebunden werden. Der SP wird von einem externen Partner administriert, der kein Angehöriger der Hochschule ist. Dieser Admin möchte jetzt den Zugang zum SP via Shibboleth testen. Dazu braucht er einen Gastaccount auf dem IdP. | |
| |
Das Problem: Die gleichen Attribute, die für das Login zu dem neuen SP nötig sind, gewähren möglicherweise auch Zugang zu anderen SPs, auf die der externe Admin keinen Zugriff haben soll. | **Anwendungsfälle:** |
| * Ein neuer Service-Provider soll an den Identity-Provider einer Hochschule angebunden werden. Der SP wird von einem externen Partner administriert, dessen Mitarbeitende keine Angehörigen der Hochschule sind. Eine dieser Personen muss jedoch den Zugang zum SP via Shibboleth testen. Dazu benötigt sie einen Gastaccount bei der Hochschule um sich an deren IdP authentisieren zu können. |
| * Für den Zugang zu einem lokalen SP wird ein Funktionsaccount eingerichtet. |
| * |
| **Das Problem:** Der Login über einen solchen Gast- oder Funktionsaccount darf keinen Zugriff auf andere Service-Provider ermöglichen. |
| |
Lösung: Der IdP wird so konfiguriert, daß beim Anmelden mit dem Gastaccount die Attributwerte nur dann erzeugt werden, wenn eine Verbindung zu dem neuen SP aufgebaut wird. Falls der Gastaccount versucht, auf einen anderen SP zuzugreifen, werden keine Attribute weitergegeben, so daß dieser andere SP den Zugang verweigert. | **Die Lösung:** Der Shibboleth-IdP (ab Version 4.1.x) wird so konfiguriert, dass beim Login über einen [[https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631716/ContextCheckInterceptConfiguration|Context Check Interceptor]] die Entity ID des anfragenden Service-Providers und die Nutzerkennung des aktuellen Users gegen eine entsprechende Regel abgeglichen werden. Handelt es sich um einen Gast-/Funktionsaccount, der auf einen "verbotenen" SP zugreifen will, wird der Anmeldevorgang abgebrochen. |
| |
Dazu ergänzt man im AttributeResolver die Definition der Daten-Konnektoren um eine Aktivierungsbedingung. | Hierzu muss zunächst das Modul ''idp.intercept.ContextCheck'' aktiviert werden: |
| |
| <code> |
| (Windows) |
| C:\opt\shibboleth-idp> bin\module.bat -t idp.intercept.ContextCheck || bin\module.bat -e idp.intercept.ContextCheck |
| |
Zuerst legt man eine neue Datei an, in der das Bean mit der Bedingung definiert wird: | (Other) |
<file xml /opt/shibboleth-idp/conf/shibgast_resolver_condition.xml> | $ bin/module.sh -t idp.intercept.ContextCheck || bin/module.sh -e idp.intercept.ContextCheck |
<?xml version="1.0" encoding="UTF-8"?> | </code> |
| |
| Anschließend wird die entsprechende Bedingung formuliert: |
| |
| <file xml /opt/shibboleth-idp/conf/intercept/context-check-intercept-config.xml> |
<beans xmlns="http://www.springframework.org/schema/beans" | <beans xmlns="http://www.springframework.org/schema/beans" |
xmlns:util="http://www.springframework.org/schema/util" | xmlns:context="http://www.springframework.org/schema/context" |
xmlns:p="http://www.springframework.org/schema/p" | xmlns:util="http://www.springframework.org/schema/util" |
xmlns:c="http://www.springframework.org/schema/c" | xmlns:p="http://www.springframework.org/schema/p" |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | xmlns:c="http://www.springframework.org/schema/c" |
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd | xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd |
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.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" |
<bean id="shibgast_resolver_condition" parent="shibboleth.Conditions.OR"> | |
| default-init-method="initialize" |
| default-destroy-method="destroy"> |
| |
| <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.OR"> |
<constructor-arg> | <constructor-arg> |
<list> | <list> |
<bean parent="shibboleth.Conditions.NOT"> | <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{{'https://sp.example.org/shibboleth'}}" /> |
<constructor-arg> | <bean parent="shibboleth.Conditions.NOT"> |
<bean parent="shibboleth.Conditions.Expression"> | <constructor-arg> |
<constructor-arg> | <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" |
<value> | p:useUnfilteredAttributes="true"> |
#profileContext.getSubcontext(T(net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext)).principal.equals("shibgast") | <property name="attributeValueMap"> |
</value> | <map> |
</constructor-arg> | <entry key="uid"> |
</bean> | <list> |
</constructor-arg> | <value>shibgast</value> |
</bean> | </list> |
<bean parent="shibboleth.Conditions.RelyingPartyId" c:_0="https://neuer_sp.example.org/shibboleth"/> | </entry> |
</list> | </map> |
| </property> |
| </bean> |
| </constructor-arg> |
| </bean> |
| </list> |
</constructor-arg> | </constructor-arg> |
</bean> | </bean> |
| |
| <!-- ... --> |
</beans> | </beans> |
| |
</file> | </file> |
Dabei ist ''shibgast'' die uid des Gastaccounts, und ''%%https://neuer_sp.example.org/shibboleth%%'' die entityId des neuen Service Providers. Diese Werte bitte entsprechend anpassen.\\ | |
Die Bedingung ist erfüllt, wenn der Benutzer sich nicht mit "shibgast" angemeldet hat oder der Benutzer sich mit dem neuen SP verbindet. Anders ausgedrückt: Wenn "shibgast" sich mit einem anderen SP verbindet, ist die Bedingung nicht erfüllt und der Konnektor wird nicht aktiviert. | |
| |
| Dabei ist ''shibgast'' die User Id des Gast-/Funktionsaccounts, und ''%%https://sp.example.org/shibboleth%%'' die Entity Id des Service Providers, auf den diese Person(en) Zugriff erhalten soll(en). Passen Sie diese Werte sowie den Namen des Quell-Attributs (hier ''uid'') bitte entsprechend an. Die Bedingung ist erfüllt, wenn |
| * eine Person sich //nicht// mit ''shibgas'' angemeldet hat oder |
| * eine Person auf den fraglichen SP zugreift. |
| Anders ausgedrückt: Wenn ''shibgast'' sich mit einem anderen SP verbindet, ist die Bedingung nicht erfüllt und der Context Check - und somit auch die Anmeldung - schlagen fehl. |
| |
Diese Datei muß in ''services.xml'' referenziert werden: | Der Context Ceck muss dann noch zu den Post-Authentication-Flows in ''relying-party.xml'' hinzugefügt werden: |
<file xml /opt/shibboleth-idp/conf/services.xml> | |
<!-- ... --> | |
<util:list id ="shibboleth.AttributeResolverResources"> | |
<value>%{idp.home}/conf/attribute-resolver.xml</value> | |
<value>%{idp.home}/conf/shibgast_resolver_condition.xml</value> | |
</util:list> | |
<!-- ... --> | |
</file> | |
| |
Schließlich ergänzt man die Definition der Daten-Konnektoren um das Attribut ''activationConditionRef'': | <file xml /opt/shibboleth-idp/conf/relying-party.xml> |
<file xml /opt/shibboleth-idp/conf/attribute-resolver.xml> | |
<!-- ... --> | <!-- ... --> |
<resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory" | <bean parent="SAML2.SSO" p:postAuthenticationFlows="#{ {'terms-of-use', 'context-check', 'attribute-release'} }" /> |
activationConditionRef="shibgast_resolver_condition" | |
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}" | |
<!-- ... --> | <!-- ... --> |
</file> | </file> |
Dieses Attribut muß bei allen Daten-Konnektoren eingefügt werden, auch bei dem für die statischen Attribute. | |
| |
==== Alternative Activation Condition ==== | |
| |
Alternativ sollte auch diese Activation-Condition auf Java-Script-Basis funktionieren: | |
| |
<file xml> | |
<?xml version="1.0" encoding="UTF-8"?> | |
<beans | |
xmlns="http://www.springframework.org/schema/beans" | |
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"> | |
| |
<bean | |
id="activation-condition-ExternalAdmin" | |
parent="shibboleth.Conditions.Scripted" | |
factory-method="inlineScript"> | |
<constructor-arg> | |
<value> | |
<![CDATA[ | |
var adminsAndServices = { | |
//Wertepaare können hier kommasepariert eingetragen werden | |
//"admin1" : "service1", | |
//"admin2" : "service2" | |
}; | |
| |
value = true; | |
for(admin in adminsAndServices){ | |
value = value && canAccess(admin, adminsAndServices[admin]); | |
} | |
| |
value; | |
| |
function canAccess(user, service){ | |
return isAdministratedService(service) || !isServiceAdministrator(user); | |
} | |
| |
function isAdministratedService(service){ | |
rpCtx = profileContext.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext"); | |
return rpCtx != null && rpCtx.getRelyingPartyId().equals(service); | |
} | |
| |
function isServiceAdministrator(user){ | |
arCtx = profileContext.getSubcontext("net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext"); | |
return arCtx != null && arCtx.principal.equals(user); | |
} | |
]]> | |
</value> | |
</constructor-arg> | |
| |
</bean> | |
</beans> | |
</file> | |
| |
Herzlichen Dank an Ramon Pfeiffer aus Tübingen für diese Variante! | |
| |
| Anschließend den IdP neu starten. |