lemonldap-ng/doc/sources/admin/applications/alfresco.rst

459 lines
15 KiB
ReStructuredText

Alfresco
========
|image0|
Presentation
------------
`Alfresco <https://www.alfresco.com/>`__ is an ECM/BPM software.
Since 4.0 release, it offers an easy way to configure SSO thanks to
authentication subsystems.
Authentication against LL::NG can be done through:
- HTTP headers (LL::NG Handler)
- SAML 2 (LL::NG as SAML2 IDP)
.. tip::
Alfresco now recommends SAML2 method
HTTP headers
------------
.. _alfresco-1:
Alfresco
~~~~~~~~
.. tip::
The official documentation can be found here:
http://docs.alfresco.com/4.0/tasks/auth-alfrescoexternal-sso.html\
You need to find the following files in your Alfresco installation:
- ``alfresco-global.properties`` (ex:
``tomcat/shared/classes/alfresco-global.properties``)
- ``share-config-custom.xml`` (ex:
``tomcat/shared/classes/alfresco/web-extension/share-config-custom.xml``)
The first will allow one to configure SSO for the alfresco webapp, and
the other for the share webapp.
Edit first ``alfresco-global.properties`` and add the following:
.. code-block:: properties
### SSO ###
authentication.chain=external1:external
external.authentication.enabled=true
external.authentication.defaultAdministratorUserNames=
external.authentication.proxyUserName=
external.authentication.proxyHeader=Auth-User
external.authentication.userIdPattern=
Edit then ``share-config-custom.xml`` and uncomment the last part. In
the ``<endpoint>``, change ``<connector-id>`` value to
``alfrescoHeader`` and change the ``<userHeader>`` value to
``Auth-User``:
.. code-block:: xml
<config evaluator="string-compare" condition="Remote">
<remote>
<keystore>
<path>alfresco/web-extension/alfresco-system.p12</path>
<type>pkcs12</type>
<password>alfresco-system</password>
</keystore>
<connector>
<id>alfrescoCookie</id>
<name>Alfresco Connector</name>
<description>Connects to an Alfresco instance using cookie-based authentication</description>
<class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
</connector>
<connector>
<id>alfrescoHeader</id>
<name>Alfresco Connector</name>
<description>Connects to an Alfresco instance using header and cookie-based authentication</description>
<class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class>
<userHeader>Auth-User</userHeader>
</connector>
<endpoint>
<id>alfresco</id>
<name>Alfresco - user access</name>
<description>Access to Alfresco Repository WebScripts that require user authentication</description>
<connector-id>alfrescoHeader</connector-id>
<endpoint-url>http://localhost:8080/alfresco/s</endpoint-url>
<identity>user</identity>
<external-auth>true</external-auth>
</endpoint>
</remote>
</config>
You need to restart Tomcat to apply changes.
.. danger::
Now you can log in with a simple HTTP header. You need to
restrict access to Alfresco to LL::NG.
LL::NG
~~~~~~
Headers
^^^^^^^
Just set the ``Auth-User`` header with the attribute that carries the
user login, for example ``$uid``.
Rules
^^^^^
Set the default rule to what you need.
Other rules:
- Unprotect access to some resources: ``^/share/res => unprotect``
- Catch logout: ``^/share/page/dologout => logout_app_sso``
SAML2
-----
.. _alfresco-2:
Alfresco
~~~~~~~~
Install SAML Alfresco module package:
::
cp alfresco-saml-repo-1.0.1.amp <ALFRESCO_HOME>/amps
cp alfresco-saml-share-1.0.1.amp <ALFRESCO_HOME>/amps_share
./bin/apply_amp.sh
Generate SAML certificate:
::
keytool -genkeypair -alias my-saml-key -keypass change-me -storepass change-me -keystore my-saml.keystore -storetype JCEKS
Export the keystore:
::
mv my-saml.keystore alf_data/keystore
cat <<EOT > alf_data/keystore/my-saml.keystore-metadata.properties
aliases=my-saml-key
keystore.password=change-me
my-saml-key.password=change-me
EOT
cat <<EOT >> tomcat/shared/classes/alfresco-global.properties
saml.keystore.location=\${dir.keystore}/my-saml.keystore
saml.keystore.keyMetaData.location=\${dir.keystore}/my-saml.keystore-metadata.properties
EOT
Edit then ``share-config-custom.xml``:
.. code-block:: xml
...
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
<!--
If using https make a CSRFPolicy with replace="true" and override the properties section.
Note, localhost is there to allow local checks to succeed.
I.e.
<properties>
<token>Alfresco-CSRFToken</token>
<referer>https://your-domain.com/.*|http://localhost:8080/.*</referer>
<origin>https://your-domain.com|http://localhost:8080</origin>
</properties>
-->
<filter>
<!-- SAML SPECIFIC CONFIG - START -->
<!--
Since we have added the CSRF filter with filter-mapping of "/*" we will catch all public GET to avoid them
having to pass through the remaining rules.
-->
<rule>
<request>
<method>GET</method>
<path>/res/.*</path>
</request>
</rule>
<!-- Incoming posts from IDPs do not require a token -->
<rule>
<request>
<method>POST</method>
<path>/page/saml-authnresponse|/page/saml-logoutresponse|/page/saml-logoutrequest</path>
</request>
</rule>
<!-- SAML SPECIFIC CONFIG - STOP -->
<!-- EVERYTHING BELOW FROM HERE IS COPIED FROM share-security-config.xml -->
<!--
Certain webscripts shall not be allowed to be accessed directly form the browser.
Make sure to throw an error if they are used.
-->
<rule>
<request>
<path>/proxy/alfresco/remoteadm/.*</path>
</request>
<action name="throwError">
<param name="message">It is not allowed to access this url from your browser</param>
</action>
</rule>
<!--
Certain Repo webscripts should be allowed to pass without a token since they have no Share knowledge.
TODO: Refactor the publishing code so that form that is posted to this URL is a Share webscript with the right tokens.
-->
<rule>
<request>
<method>POST</method>
<path>/proxy/alfresco/api/publishing/channels/.+</path>
</request>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!--
Certain Surf POST requests from the WebScript console must be allowed to pass without a token since
the Surf WebScript console code can't be dependent on a Share specific filter.
-->
<rule>
<request>
<method>POST</method>
<path>/page/caches/dependency/clear|/page/index|/page/surfBugStatus|/page/modules/deploy|/page/modules/module|/page/api/javascript/debugger|/page/console</path>
</request>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!-- Certain Share POST requests does NOT require a token -->
<rule>
<request>
<method>POST</method>
<path>/page/dologin(\?.+)?|/page/site/[^/]+/start-workflow|/page/start-workflow|/page/context/[^/]+/start-workflow</path>
</request>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!-- Assert logout is done from a valid domain, if so clear the token when logging out -->
<rule>
<request>
<method>POST</method>
<path>/page/dologout(\?.+)?</path>
</request>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
<action name="clearToken">
<param name="session">{token}</param>
<param name="cookie">{token}</param>
</action>
</rule>
<!-- Make sure the first token is generated -->
<rule>
<request>
<session>
<attribute name="_alf_USER_ID">.+</attribute>
<attribute name="{token}"/>
<!-- empty attribute element indicates null, meaning the token has not yet been set -->
</session>
</request>
<action name="generateToken">
<param name="session">{token}</param>
<param name="cookie">{token}</param>
</action>
</rule>
<!-- Refresh token on new "page" visit when a user is logged in -->
<rule>
<request>
<method>GET</method>
<path>/page/.*</path>
<session>
<attribute name="_alf_USER_ID">.+</attribute>
<attribute name="{token}">.+</attribute>
</session>
</request>
<action name="generateToken">
<param name="session">{token}</param>
<param name="cookie">{token}</param>
</action>
</rule>
<!--
Verify multipart requests from logged in users contain the token as a parameter
and also correct referer & origin header if available
-->
<rule>
<request>
<method>POST</method>
<header name="Content-Type">multipart/.+</header>
<session>
<attribute name="_alf_USER_ID">.+</attribute>
</session>
</request>
<action name="assertToken">
<param name="session">{token}</param>
<param name="parameter">{token}</param>
</action>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!--
Verify that all remaining state changing requests from logged in users' requests contains a token in the
header and correct referer & origin headers if available. We "catch" all content types since just setting it to
"application/json.*" since a webscript that doesn't require a json request body otherwise would be
successfully executed using i.e."text/plain".
-->
<rule>
<request>
<method>POST|PUT|DELETE</method>
<session>
<attribute name="_alf_USER_ID">.+</attribute>
</session>
</request>
<action name="assertToken">
<param name="session">{token}</param>
<param name="header">{token}</param>
</action>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
</filter>
</config>
...
Configure SAML service provider using the Alfresco admin console
(/alfresco/s/enterprise/admin/admin-saml).
Set the following parameters:
- Enable SAML Authentication (SSO): on
- Authentication service URL:
https://auth.example.com/saml/singleSignOn
- Single Logout URL: https://auth.example.com/saml/singleLogout
- Single logout return URL:
https://auth.example.com/saml/singleLogoutReturn
- Entity identification: http://alfresco.myecm.org:8080/share
- User ID mapping: Subject/NameID
To finish with Alfresco configuration, tick the “Enable SAML
authentication (SSO)” box.
.. _llng-1:
LL::NG
~~~~~~
Configure SAML service and set a certificate as signature public key in
metadata.
Export Alfresco SAML Metadata from admin console and import them in
LL::NG.
In the authentication response option, set:
- Default NameID Format: Unspecified
- Force NameID session key: uid
And you can define these exported attributes:
- GivenName
- Surname
- Email
Other resources
---------------
- `DevCon 2012: Unlocking the Secrets of Alfresco Authentication, Mehdi
Belmekki <https://www.youtube.com/watch?v=5tS0XrC_-rw>`__
- `Setting up Alfresco SAML authentication with
LemonLDAP::NG <https://community.alfresco.com/blogs/alfresco-premier-services/2017/08/03/setting-up-alfresco-saml-authentication-lemonldapng>`__
.. |image0| image:: /applications/alfresco_logo.png
:class: align-center