Autenticación de geonode a través de LDAP

Este paquete proporciona utilidades para usar LDAP como backend de autenticación y autorización para geonode.

El paquete django_auth_ldap es una forma muy capaz de agregar integración LDAP con proyectos de Django.Proporciona mucha flexibilidad a la hora de asignar usuarios LDAP a usuarios de geonode y es capaz de gestionar la autenticación de usuarios.

Sin embargo, para brindar soporte completo para mapear grupos LDAP con geonode y aplicar permisos de grupo en los recursos, se requiere un backend de autenticación de geonode personalizado.Este paquete de contribución proporciona dicho backend, basado en django_auth_ldap.

Instalación

Instalar este paquete contrib es cuestión de:

  1. Instalación de geonode

  2. Instalación de bibliotecas LDAP del sistema (se necesitan paquetes de desarrollo)

  3. Clonando este repositorio localmente

  4. Cambie al directorio ldap e instale este paquete contrib

# 1. install geonode (not shown here for brevity)
# 2. install systemwide LDAP libraries
sudo apt install \
    libldap2-dev \
    libsasl2-dev

# 3. get geonode/contribs code
git clone https://github.com/GeoNode/geonode-contribs.git

# 4. install geonode ldap contrib package
cd geonode-contribs/ldap
pip install .

Configuración

  1. Agregue geonode_ldap.backend.GeonodeLdapBackend como backend de autenticación adicional.

    # e.g. by updating your settings.py or local_settings.py
    AUTHENTICATION_BACKENDS += (
        "geonode_ldap.backend.GeonodeLdapBackend",
    )
    

    Puede utilizar backends de autenticación adicionales, el marco de autenticación de Django los prueba todos según el orden que figura en la configuración.Esto significa que el geonode se puede configurar de tal manera que permita a los usuarios internos de la organización iniciar sesión con sus credenciales LDAP y, al mismo tiempo, permitir que los usuarios ocasionales utilicen su inicio de sesión de Facebook (siempre que habilite el proveedor de autenticación social de Facebook).

    Nota

    También se debe utilizar django.contrib.auth.backends.ModelBackend de django para proporcionar una integración completa del geonode con LDAP.Sin embargo, esto está incluido de forma predeterminada en la configuración de GeoNode.

    # The GeoNode default settings are the following
    AUTHENTICATION_BACKENDS = (
        'oauth2_provider.backends.OAuth2Backend',
        'django.contrib.auth.backends.ModelBackend',
        'guardian.backends.ObjectPermissionBackend',
        'allauth.account.auth_backends.AuthenticationBackend',
    )
    
  2. Establezca algunos valores de configuración adicionales.Algunas de estas variables tienen el prefijo AUTH_LDAP (las usa directamente django_auth_ldap), mientras que otras tienen el prefijo GEONODE_LDAP (las usa geonode_ldap).Las variables personalizadas del geonode son:

    • GEONODE_LDAP_GROUP_PROFILE_FILTERSTR: este es un fragmento de búsqueda LDAP con el filtro que permite consultar grupos existentes.Ver ejemplo a continuación

    • GEONODE_LDAP_GROUP_NAME_ATTRIBUTE: este es el nombre del atributo LDAP que se utilizará para derivar el nombre del grupo de geonode.Si no se especifica, el valor predeterminado será «cn», lo que significa que el «nombre común» del objeto LDAP se utilizará para generar el nombre del grupo de geonode.

    • GEONODE_LDAP_GROUP_PROFILE_MEMBER_ATTR: este es el nombre del atributo LDAP que se utilizará para derivar la membresía del geonode.Si no se especifica, el valor predeterminado será «miembro»

Configuración de ejemplo:

# add these import lines to the top of your geonode settings file
from django_auth_ldap import config as ldap_config
from geonode_ldap.config import GeonodeNestedGroupOfNamesType
import ldap

# enable logging
import logging
logger = logging.getLogger('django_auth_ldap')
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)

# add both standard ModelBackend auth and geonode.contrib.ldap auth
AUTHENTICATION_BACKENDS += (
    'geonode_ldap.backend.GeonodeLdapBackend',
)

# django_auth_ldap configuration
AUTH_LDAP_SERVER_URI = os.getenv("LDAP_SERVER_URL")
AUTH_LDAP_BIND_DN = os.getenv("LDAP_BIND_DN")
AUTH_LDAP_BIND_PASSWORD = os.getenv("LDAP_BIND_PASSWORD")
AUTH_LDAP_USER_SEARCH = ldap_config.LDAPSearch(
    os.getenv("LDAP_USER_SEARCH_DN"),
    ldap.SCOPE_SUBTREE,
    os.getenv("LDAP_USER_SEARCH_FILTERSTR")
)
# should LDAP groups be used to spawn groups in GeoNode?
AUTH_LDAP_MIRROR_GROUPS = strtobool(os.getenv("LDAP_MIRROR_GROUPS", 'True'))
AUTH_LDAP_GROUP_SEARCH = ldap_config.LDAPSearch(
    os.getenv("LDAP_GROUP_SEARCH_DN"),
    ldap.SCOPE_SUBTREE,
    os.getenv("LDAP_GROUP_SEARCH_FILTERSTR")
)
AUTH_LDAP_GROUP_TYPE = GeonodeNestedGroupOfNamesType()
AUTH_LDAP_USER_ATTR_MAP = {
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mailPrimaryAddress"
}
AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_MIRROR_GROUPS_EXCEPT = [
    "test_group"
]

# these are not needed by django_auth_ldap - we use them to find and match
# GroupProfiles and GroupCategories
GEONODE_LDAP_GROUP_NAME_ATTRIBUTE = os.getenv("LDAP_GROUP_NAME_ATTRIBUTE", default="cn")
GEONODE_LDAP_GROUP_PROFILE_FILTERSTR = os.getenv("LDAP_GROUP_SEARCH_FILTERSTR", default='(ou=research group)')
GEONODE_LDAP_GROUP_PROFILE_MEMBER_ATTR = os.getenv("LDAP_GROUP_PROFILE_MEMBER_ATTR", default='member')

Variables de entorno de ejemplo:

LDAP_SERVER_URL=ldap://<the_ldap_server>
LDAP_BIND_DN=uid=ldapinfo,cn=users,dc=ad,dc=example,dc=org
LDAP_BIND_PASSWORD=<something_secret>
LDAP_USER_SEARCH_DN=dc=ad,dc=example,dc=org
LDAP_USER_SEARCH_FILTERSTR=(&(uid=%(user)s)(objectClass=person))
LDAP_MIRROR_GROUPS=True
LDAP_GROUP_SEARCH_DN=cn=groups,dc=ad,dc=example,dc=org
LDAP_GROUP_SEARCH_FILTERSTR=(|(cn=abt1)(cn=abt2)(cn=abt3)(cn=abt4)(cn=abt5)(cn=abt6))
LDAP_GROUP_PROFILE_MEMBER_ATTR=uniqueMember

La configuración que se ve en el ejemplo anterior permitirá a los usuarios de LDAP iniciar sesión en el geonode con sus credenciales LDAP.

En el primer inicio de sesión, se crea un usuario de geonode a partir del usuario LDAP y sus atributos LDAP cn y sn se utilizan para completar los campos de perfil first_name y last_name del usuario del geonode.

Cualquier grupo del que el usuario sea miembro en LDAP (bajo la base de búsqueda cn=groups,dc=ad,dc=example,dc=org y que pertenezca a uno de los grupos (|(cn=abt1)(cn=abt2)(cn=abt3)(cn=abt4)(cn=abt5)(cn=abt6))) se asignará a los grupos de geonode correspondientes, incluso creando estos grupos. En geonode en caso de que aún no existan.El usuario del geonode también se convierte en miembro de estos grupos de geonode.

Cada vez que inicia sesión, las membresías del grupo de geonode del usuario se reevalúan de acuerdo con la información extraída de LDAP.La configuración AUTH_LDAP_MIRROR_GROUPS_EXCEPT se puede utilizar para especificar grupos cuyas membresías no serán reevaluadas.

Si no se reflejan grupos LDAP, LDAP_MIRROR_GROUPS y LDAP_MIRROR_GROUPS_EXCEPT deben establecerse en False.

Nota

Los usuarios asignados desde LDAP se marcarán con una etiqueta ldap.Esto se utilizará para mantenerlos sincronizados.

Advertencia

Si elimina la etiqueta ldap, los usuarios serán amenazados como usuarios puramente internos de GeoNode.

También puede generar manualmente los grupos de geonode por adelantado, antes de que los usuarios inicien sesión.En este caso, cuando un usuario inicia sesión y el grupo LDAP asignado ya existe, el usuario simplemente se agrega al grupo de geonode.

Asegúrese de consultar django_auth_ldap para obtener más información sobre las distintas opciones de configuración.

Mantenga sincronizados a los usuarios y grupos

Para mantener constantemente los usuarios y grupos LDAP remotos sincronizados con GeoNode, deberá ejecutar periódicamente algunos comandos de administración específicos.

*/10 * * * * /opt/geonode/my-geonode/manage.sh updateldapgroups  >> /var/log/cron.log 2>&1
*/10 * * * * /opt/geonode/my-geonode/manage.sh updateldapusers   >> /var/log/cron.log 2>&1

Donde manage.sh es un script bash similar al siguiente:

administrar.sh

export $(grep -v '^#' /opt/geonode/my-geonode/.env | xargs -d '\n'); /home/<my_user>/.virtualenvs/geonode/bin/python /opt/geonode/my-geonode/manage.py $@

y el /opt/geonode/my-geonode/.env es algo similar al siguiente:

/opt/geonode/mi-geonode/.env

DEBUG=False
DJANGO_ALLOWED_HOSTS=<geonode_public_host>,localhost,127.0.0.1
DJANGO_DATABASE_URL=postgis://my_geonode:**********@localhost:5432/my_geonode_db
DEFAULT_BACKEND_UPLOADER=geonode.importer
DEFAULT_FROM_EMAIL=geonode@example.org
DJANGO_EMAIL_HOST=smtp.example.org
DJANGO_EMAIL_HOST_PASSWORD=**********
DJANGO_EMAIL_HOST_USER=geonode
DJANGO_EMAIL_PORT=465
DJANGO_EMAIL_USE_SSL=True
DJANGO_SETTINGS_MODULE=my_geonode.settings
DJANGO_SECRET_KEY=**********
OAUTH2_API_KEY=**********
PROXY_URL=/proxy/?url=
EXIF_ENABLED=True
EMAIL_ENABLE=True
TIME_ENABLED=True
ACCOUNT_OPEN_SIGNUP=True
ACCOUNT_APPROVAL_REQUIRED=True
ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_EMAIL_VERIFICATION=optional
AVATAR_GRAVATAR_SSL=True
GEONODE_DB_URL=postgis://my_geonode:**********@localhost:5432/my_geonode_data
GEOSERVER_ADMIN_PASSWORD=**********
GEOSERVER_LOCATION=https://<geonode_public_host>/geoserver/
GEOSERVER_PUBLIC_HOST=<geonode_public_host>
GEOSERVER_PUBLIC_LOCATION=https://<geonode_public_host>/geoserver/
GEOSERVER_WEB_UI_LOCATION=https://<geonode_public_host>/geoserver/
LDAP_SERVER_URL=ldap://<the_ldap_server>
LDAP_BIND_DN=uid=ldapinfo,cn=users,dc=ad,dc=example,dc=org
LDAP_BIND_PASSWORD=<something_secret>
LDAP_USER_SEARCH_DN=dc=ad,dc=example,dc=org
LDAP_USER_SEARCH_FILTERSTR=(&(uid=%(user)s)(objectClass=person))
LDAP_MIRROR_GROUPS=True
LDAP_GROUP_SEARCH_DN=cn=groups,dc=ad,dc=example,dc=org
LDAP_GROUP_SEARCH_FILTERSTR=(|(cn=abt1)(cn=abt2)(cn=abt3)(cn=abt4)(cn=abt5)(cn=abt6))
LDAP_GROUP_PROFILE_MEMBER_ATTR=uniqueMember
OGC_REQUEST_MAX_RETRIES=3
OGC_REQUEST_POOL_CONNECTIONS=100
OGC_REQUEST_POOL_MAXSIZE=100
OGC_REQUEST_TIMEOUT=60
SITEURL=https://<geonode_public_host>/
SITE_HOST_NAME=<geonode_public_host>
FREETEXT_KEYWORDS_READONLY=False
# Advanced Workflow Settings
ADMIN_MODERATE_UPLOADS=False
GROUP_MANDATORY_RESOURCES=False
GROUP_PRIVATE_RESOURCES=False
RESOURCE_PUBLISHING=False

Nota

Es posible que también quieras usar el mismo /opt/geonode/my-geonode/.env para tu configuración UWSGI:

[uwsgi]
socket = 0.0.0.0:8000
uid = <my_user>
gid = www-data

plugins = python3
virtualenv = /home/<my_user>/.virtualenvs/geonode

# set environment variables from .env file
env LANG=en_US.utf8
env LC_ALL=en_US.UTF-8
env LC_LANG=en_US.UTF-8

for-readline = /opt/geonode/my-geonode/.env
    env = %(_)
endfor =

chdir = /opt/geonode/my-geonode
module = my_geonode.wsgi:application

processes = 12
threads = 2
enable-threads = true
master = true

# logging
# path to where uwsgi logs will be saved
logto = /storage/my_geonode/logs/geonode.log
daemonize = /storage/my_geonode/logs/geonode.log
touch-reload = /opt/geonode/my-geonode/my_geonode/wsgi.py
buffer-size = 32768
max-requests = 500
harakiri = 300 # respawn processes taking more than 5 minutes (300 seconds)
# limit-as = 1024 # avoid Errno 12 cannot allocate memory
harakiri-verbose = true
vacuum = true
thunder-lock = true