Bisher erhielten Sie eine Admin-Sitzung oder einen Resource Resolver in AEM mithilfe der Sling-Methoden SlingRepository.loginAdministrative()
und ResourceResolverFactory.getAdministrativeResourceResolver()
.
Allerdings waren diese beiden Methoden um das sogenannte Principle of Least Privilege (Prinzip der geringsten Berechtigung) aufgebaut und sie machen es Entwicklern zu einfach, anfangs eine angemessene Struktur und entsprechende Zugriffssteuerungsebenen für die Inhalte zu ignorieren. Wenn in einem solche Dienst eine Sicherheitslücke vorhanden ist, führt dies oft zu Berechtigungseskalationen an den admin
, auch wenn der Code selbst keine Administratorrechte benötigt, um zu funktionieren.
Es kann vorkommen, dass die Adminsitzung nicht verwendet wird oder die Funktion vollständig deaktiviert ist. Ist dies mit Ihrer Implementierung der Fall, entfernen Sie die Funktion vollständig oder bauen Sie Nulloperations-Code darin ein.
Refaktorieren Sie das Feature wann immer möglich, damit die gegebene, authentifizierte Anfragesitzung für das Lesen und Schreiben von Inhalten verwendet werden kann. Wenn dies nicht machbar ist, erreichen Sie dieses Ziel, indem Sie die Prioritäten anwenden, die nach den folgenden aufgeführt werden.
Viele Probleme lassen sich durch die Umstrukturierung des Inhalts lösen. Berücksichtigen Sie bei der Umstrukturierung die folgenden einfachen Regeln:
Zugriffssteuerung ändern
Inhaltsstruktur verfeinern
Code zum korrekten Dienst refaktorieren
Achten Sie außerdem darauf, dass alle neu entwickelten Funktionen diesen Richtlinien entsprechen:
Sicherheitsanforderungen müssen Inhaltsstruktur unterstützen
Knotentypen nutzen
Datenschutzeinstellungen respektieren
/profile
-Knoten zu finden sind, nicht anzuzeigen.Unabhängig davon, ob Sie Zugriffssteuerung bei der Umstrukturierung von Inhalten oder auf neue Dienstbenutzende anwenden, müssen Sie die strengsten möglichen Zugriffssteuerungsebenen anwenden. Nutzen Sie alle verfügbaren Funktionen für die Zugriffssteuerung:
Wenden Sie beispielsweise jcr:read
nicht auf /apps
, sondern nur auf /apps/*/components/*/analytics
an.
Verwenden Sie Einschränkungen.
Wenden Sie Zugriffssteuerungsebenen für alle Knotentypen an.
Schränken Sie Berechtigungen ein.
jcr:write
, sondern die Berechtigung jcr:modifyProperties
.Falls das oben Genannte fehlschlägt, bietet Sling 7 einen Dienst für die Zuordnung von Dienstbenutzenden, der die Konfiguration einer Bundle-zu-Benutzenden-Zuordnung und zweier entsprechender API-Methoden ermöglicht: [SlingRepository.loginService()](https://sling.apache.org/apidocs/sling7/org/apache/sling/jcr/api/SlingRepository.html#loginService-java.lang.String-java.lang.String-)
und [ResourceResolverFactory.getServiceResourceResolver()](https://sling.apache.org/apidocs/sling7/org/apache/sling/api/resource/ResourceResolverFactory.html#getServiceResourceResolver-java.util.Map-)
, die eine Sitzung bzw. einen Resource Resolver mit ausschließlich den Berechtigungen einer konfigurierten Benutzerin oder eines konfigurierten Benutzers zurückgeben. Diese Methoden verfügen über die folgenden Merkmale:
Sie ermöglichen die Zuordnung von Diensten zu Benutzenden.
Sie ermöglichen die Definition von Unterdienstbenutzenden.
Der zentrale Konfigurationspunkt ist: org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl
.
service-id
= service-name
[ ":" subservice-name ]
service-id
wird einem Resource Resolver und/oder einer JCR-Repository-Benutzer-ID zur Authentifizierung zugewiesen.
service-name
ist der symbolische Name des Bundles, das den Service zur Verfügung stellt.
Dienstbenutzer sind JCR-Benutzer ohne festgelegtes Kennwort und mit einem minimalen Satz von Berechtigungen, die zur Durchführung einer bestimmten Aufgabe erforderlich sind. Da kein Kennwort festgelegt ist, kann man sich nicht als Dienstbenutzer anmelden.
Adminsitzungen können verringert werden, indem sie durch Dienstbenutzersitzungen ersetzt werden. Sie können bei Bedarf auch durch mehrere Unterdienstbenutzer ersetzt werden.
Ersetzen Sie eine Adminsitzung wie folgt durch einen Dienstbenutzer:
Identifizieren Sie die erforderlichen Berechtigungen für den Dienst. Berücksichtigen Sie dabei das Prinzip der geringsten Berechtigung.
Überprüfen Sie, ob bereits ein Benutzer mit denselben Berechtigungen, die Sie benötigen, vorhanden ist. Erstellen Sie einen neuen Systemdienstbenutzer, falls kein vorhandener Benutzer Ihren Anforderungen entspricht. RTC ist erforderlich, um einen neuen Dienstbenutzer zu erstellen. Manchmal ist es sinnvoll, mehrere Unterdienstbenutzer zu erstellen (beispielsweise einen zum Schreiben und einen zum Lesen), um den Zugriff noch weiter aufzuteilen.
Richten Sie für Ihren Benutzer ACEs ein und testen Sie sie.
Fügen Sie eine service-user
-Zuordnung für Ihren Dienst und für user/sub-users
hinzu.
Stellen Sie das Dienstbenutzer-Sling-Feature Ihrem Bundle zur Verfügung: Aktualisieren Sie auf die neueste Version von org.apache.sling.api
.
Ersetzen Sie die admin-session
in Ihrem Code durch den loginService
oder getServiceResourceResolver
-APIs.
Nachdem Sie überprüft haben, dass kein Benutzer in der Liste der AEM-Dienstbenutzer Ihrem Anwendungsfall entspricht und die jeweiligen RTC-Ausgaben genehmigt wurden, können Sie den neuen Benutzer zum Standardinhalt hinzufügen.
Es wird empfohlen, einen Dienstbenutzer zu erstellen, um den Repository-Explorer unter https://<Server>:<Port>/crx/explorer/index.jsp zu verwenden.
Das Ziel ist, eine gültige Eigenschaft jcr:uuid
zu erhalten, die erforderlich ist, um die Benutzerin oder den Benutzer anhand einer Inhaltspaketinstallation zu erstellen.
Dienstbenutzende erstellen Sie wie folgt:
Verwenden Sie den Repository-Explorer unter https://<Server>:<Port>/crx/explorer/index.jsp..
Melden Sie sich als Administrator an, indem Sie oben links auf dem Bildschirm auf Anmelden klicken.
Als Nächstes erstellen und benennen Sie Ihren Systembenutzer. Um Benutzende als Systembenutzende zu erstellen, legen Sie für den intermediate-Pfad system
fest und fügen Sie je nach Bedarf optionale Unterordner hinzu:
Überprüfen Sie, ob Ihr Systembenutzerknoten wie folgt aussieht:
Dienstbenutzenden werden keine Mixin-Typen zugeordnet. Das heißt, dass es für Systembenutzende keine Zugriffssteuerungsrichtlinien gibt.
Vergewissern Sie sich beim Hinzufügen der entsprechenden „.content.xml“ zum Inhalt des Bundles, dass Sie die rep:authorizableId
festgelegt haben und der primäre Typ rep:SystemUser
ist. Dies sollte wie folgt aussehen:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="https://www.jcp.org/jcr/1.0" xmlns:rep="internal"
jcr:primaryType="rep:SystemUser"
jcr:uuid="4917dd68-a0c1-3021-b5b7-435d0044b0dd"
rep:principalName="authentication-service"
rep:authorizableId="authentication-service"/>
Um eine Zuordnung vom Dienst zu den entsprechenden Systembenutzenden hinzuzufügen, müssen Sie eine Werkskonfiguration für den Dienst [ServiceUserMapper](https://sling.apache.org/apidocs/sling7/org/apache/sling/serviceusermapping/ServiceUserMapper.html)
erstellen. Um die Modularität zu gewährleisten, können derartige Konfigurationen mithilfe des Sling-Änderungsmechanismus bereitgestellt werden. Zum Installieren solcher Konfigurationen mit Ihrem Bundle wird Sling Initial Content Loading empfohlen:
Erstellen Sie unterhalb des Ordners „src/main/resources“ des Bundles einen Unterordner „SLING-INF/content“.
Erstellen Sie in diesem Ordner eine Datei namens „org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-<eindeutiger Name für Ihre Werkskonfiguration>.xml“ mit dem Inhalt Ihrer Werkskonfiguration (einschließlich aller Unterdienstbenutzerzuordnungen). Beispiel:
Erstellen Sie unterhalb des Ordners SLING-INF/content
des Bundles einen Ordner src/main/resources
.
Erstellen Sie in diesem Ordner eine Datei namens named org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-<a unique name for your factory configuration>.xml
mit dem Inhalt Ihrer Werkskonfiguration (einschließlich aller Unterdienstbenutzerzuordnungen).
Wählen Sie zu Illustrationszwecken die Datei org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-com.adobe.granite.auth.saml.xml
aus:
<?xml version="1.0" encoding="UTF-8"?>
<node>
<primaryNodeType>sling:OsgiConfig</primaryNodeType>
<property>
<name>user.default</name>
<value></value>
</property>
<property>
<name>user.mapping</name>
<values>
<value>com.adobe.granite.auth.saml=authentication-service</value>
</values>
</property>
</node>
Verweisen Sie auf den anfänglichen Sling-Inhalt in der Konfiguration des maven-bundle-plugin
in der Datei pom.xml
Ihres Bundles. Beispiel:
<Sling-Initial-Content>
SLING-INF/content;path:=/libs/system/config;overwrite:=true;
</Sling-Initial-Content>
Installieren Sie das Bundle und prüfen Sie, ob die Werkskonfiguration installiert wurde. Gehen Sie dazu wie folgt vor:
loginAdministrative()
-Aufrufe treten häufig zusammen mit freigegebenen Sitzungen auf. Diese Sitzungen werden bei Aktivierung des Diensts abgerufen und erst abgemeldet, wenn der Dienst gestoppt wird. Dies ist eine gängige Vorgehensweise führt aber zu zwei Problemen:
Die offensichtlichste Lösung für das Sicherheitsrisiko besteht darin, den Aufruf loginAdministrative()
durch einen Aufruf loginService()
an eine Benutzerin oder einen Benutzer mit eingeschränkten Berechtigungen zu ersetzen. Dies hat jedoch keine Auswirkungen auf potenzielle Leistungsbeeinträchtigungen. Eine Chance, dies zu verringern, besteht darin, alle erforderlichen Informationen in einem Objekt zu verpacken, das keine Verbindung zur Sitzung aufweist. Erstellen (oder zerstören) Sie die Sitzung dann bei Bedarf.
Die empfohlene Vorgehensweise besteht darin, die API des Dienstes zu refaktorieren, um der aufrufenden Person die Kontrolle über die Erstellung bzw. Zerstörung der Sitzung zu gewähren.
JSPs können loginService()
nicht verwenden, weil kein zugehöriger Dienst vorhanden ist. Allerdings sind Adminsitzungen in JSPs für gewöhnlich ein Zeichen einer Verletzung des MVC-Paradigmas.
Dies kann auf zwei Arten behoben werden:
Die erste Methode wird bevorzugt.
Bei der Verarbeitung von Ereignissen oder Aufträgen und in manchen Fällen Workflows geht die Sitzung, die das Ereignis ausgelöst hat, irgendwann verloren. Dies führt dazu, dass Ereignis-Handler und Auftragsprozesse oft Adminsitzungen zur Verrichtung ihrer Arbeit nutzen. Zu diesem Problem gibt es verschiedene denkbare Lösungsansätze, die alle jeweils verschiedene Vorteile und Nachteile aufweisen:
user-id
an die Ereignis-Payload weitergeben und Personifikation nutzen
Vorteile: Benutzerfreundlich.
Nachteile: Verwendet dennoch loginAdministrative()
. Authentifiziert eine Anfrage erneut, die bereits authentifiziert wurde.
Erstellen oder erneutes Verwenden eines Dienstbenutzers, der Zugriff auf die Daten hat
Vorteile: Entspricht aktuellem Design. Erfordert minimale Änderung.
Nachteile: Erfordert sehr leistungsstarke Dienstbenutzende, um flexibel zu sein, was schnell zu Berechtigungseskalationen führen kann. Umgeht das Sicherheitsmodell.
Übergeben Sie eine Serialisierung des Subject
in der Ereignis-Payload und erstellen Sie einen ResourceResolver
auf Grundlage dieses Betreffs. Ein Beispiel ist die Verwendung des JAAS doAsPrivileged
in der ResourceResolverFactory
.
Vorteile: Saubere Implementierung von einem Sicherheitsstandpunkt aus. Diese Methode vermeidet die erneute Authentifizierung und nutzt die ursprünglichen Berechtigungen. Sicherheitsrelevanter Code ist für den Verbraucher des Ereignisses nicht sichtbar.
Nachteile: Muss umstrukturiert werden. Die Tatsache, dass sicherheitsrelevanter Code für den Verbraucher nicht sichtbar ist, kann auch zu Problemen führen.
Der dritte Ansatz ist derzeit die bevorzugte Verarbeitungsweise.
Innerhalb von Workflow-Prozessimplementierungen geht die entsprechende Benutzersitzung, die den Workflow ausgelöst hat, für gewöhnlich verloren. Dies führt dazu, dass Workflowprozesse oft Adminsitzungen zur Verrichtung ihrer Arbeit nutzen.
Zur Behebung dieser Probleme sollten ebenfalls die Ansätze im Abschnitt Verarbeiten von Ereignissen, Replikationsvorprozessen und Aufträgen verwendet werden.
In Sling-POST-Prozessimplementierungen werden mehrere Adminsitzungen verwendet. In der Regel werden Adminsitzungen verwendet, um auf Knoten zuzugreifen, die im verarbeiteten POST zur Löschung markiert sind. Daher sind sie nicht mehr über die Anfragesitzung verfügbar. Auf zur Löschung markierte Knoten kann zugegriffen werden, um Metadaten anzuzeigen, die ansonsten nicht sichtbar sein sollten.