Prezado leitor,

O intuito do post de hoje é que você aprenda como integrar o GeoServer a um servidor LDAP, autenticar usuários, transformar grupos LDAP em roles e preparar essas roles para utilização nas regras de segurança do GeoServer. O laboratório utiliza GeoServer 3, OpenLDAP e Docker Compose.

Em instalações simples do GeoServer é comum administrar usuários diretamente pela interface da aplicação. Esse modelo funciona bem em laboratórios, treinamentos e ambientes pequenos. Em ambientes corporativos, porém, normalmente a organização já possui uma infraestrutura centralizada de identidade. É nesse cenário que entra o LDAP (Lightweight Directory Access Protocol).

Em vez de manter usuários e senhas dentro do próprio GeoServer, podemos integrá-lo a um diretório LDAP e utilizar os usuários e grupos existentes na organização. A arquitetura passa a ser semelhante a esta:

Uma forma simples de entender essa integração é: O LDAP autentica. O GeoServer autoriza.

O GeoServer possui suporte nativo à autenticação LDAP através de LDAP Bind. Também pode transformar os grupos encontrados no LDAP em roles utilizadas posteriormente nas regras de segurança do GeoServer. A ideia é criar três usuários com diferentes níveis de acesso e, posteriormente, utilizar os grupos LDAP para controlar o acesso dentro do GeoServer.

A versão 3.0.1 do GeoServer também trouxe a melhoria da GEOS-12095 relacionada à conversão entre o nome do membro do grupo LDAP e o nome utilizado na pesquisa de usuários.

1. Estrutura do Laboratório

Neste artigo vou utilizar o GeoServer 3.0.1, que no momento da publicação deste texto é a versão estável recomendada para produção. A versão 3.0.1 também trouxe uma melhoria específica relacionada à conversão de usuários LDAP (GEOS-12095 relacionada à conversão entre o nome do membro do grupo LDAP e o nome utilizado na pesquisa de usuários), além de correções de segurança importantes.

2. Criando o Docker Compose

Neste artigo, eu vou considerar que você já instalou o Docker no seu ambiente, então vamos criar agora o arquivo docker-compose.yml com o seguinte conteúdo:

services:
  geoserver:
    image: docker.osgeo.org/geoserver:3.0.1
    container_name: geoserver
    ports:
      - "8080:8080"
    environment:
      PROXY_BASE_URL: http://localhost:8080/geoserver
      GEOSERVER_ADMIN_USER: admin
      GEOSERVER_ADMIN_PASSWORD: geoserver
    volumes:
      - geoserver_data:/opt/geoserver_data
    depends_on:
      openldap:
        condition: service_started

  openldap:
    image: osixia/openldap:1.5.0
    container_name: openldap
    environment:
      LDAP_ORGANISATION: "Geocursos Lab"
      LDAP_DOMAIN: "geocursos.lab"
      LDAP_ADMIN_PASSWORD: "adminldap"
      LDAP_TLS: "false"
    ports:
      - "389:389"
    volumes:
      - ./ldap/10-geoserver-acl.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/10-geoserver-acl.ldif:ro
      - ./ldap/20-geoserver-users.ldif:/container/service/slapd/assets/config/bootstrap/ldif/custom/20-geoserver-users.ldif:ro
    command: ["--copy-service"]

volumes:
  geoserver_data:

A imagem oficial Docker do GeoServer é mantida pelo próprio projeto e publicada no repositório OSGeo. Também estamos expondo a porta 389 apenas para facilitar nossos testes locais. Em produção, não faria sentido necessariamente expor o LDAP dessa forma.

3. Criando nossa estrutura LDAP

Agora precisamos criar os usuários e grupos que serão utilizados. Vamos então criar o arquivo ldap/20-geoserver-users.ldif com o seguinte conteúdo:

dn: ou=people,dc=geocursos,dc=lab
objectClass: organizationalUnit
ou: people


dn: ou=groups,dc=geocursos,dc=lab
objectClass: organizationalUnit
ou: groups


dn: uid=alice,ou=people,dc=geocursos,dc=lab
objectClass: inetOrgPerson
cn: Alice Publico
sn: Publico
uid: alice
mail: alice@geocursos.lab
userPassword: alice123


dn: uid=bob,ou=people,dc=geocursos,dc=lab
objectClass: inetOrgPerson
cn: Bob Restrito
sn: Restrito
uid: bob
mail: bob@geocursos.lab
userPassword: bob123


dn: uid=carol,ou=people,dc=geocursos,dc=lab
objectClass: inetOrgPerson
cn: Carol Admin
sn: Admin
uid: carol
mail: carol@geocursos.lab
userPassword: carol123


dn: cn=geoserver_publico,ou=groups,dc=geocursos,dc=lab
objectClass: groupOfNames
cn: geoserver_publico
member: uid=alice,ou=people,dc=geocursos,dc=lab
member: uid=bob,ou=people,dc=geocursos,dc=lab
member: uid=carol,ou=people,dc=geocursos,dc=lab


dn: cn=geoserver_restrito,ou=groups,dc=geocursos,dc=lab
objectClass: groupOfNames
cn: geoserver_restrito
member: uid=bob,ou=people,dc=geocursos,dc=lab
member: uid=carol,ou=people,dc=geocursos,dc=lab


dn: cn=geoserver_admin,ou=groups,dc=geocursos,dc=lab
objectClass: groupOfNames
cn: geoserver_admin
member: uid=carol,ou=people,dc=geocursos,dc=lab

E agora um segundo arquivo chamado 10-geoserver-acl.ldif com o seguinte conteúdo:

dn: olcDatabase={1}{{ LDAP_BACKEND }},cn=config
changetype: modify
add: olcAccess
olcAccess: {2}to dn.subtree="ou=groups,{{ LDAP_BASE_DN }}" by dn.exact="cn=admin,{{ LDAP_BASE_DN }}" write by users read by * none

Teremos portanto:

Observe que os grupos formam uma espécie de progressão de permissões:

As senhas utilizadas no laboratório são propositalmente simples. Elas não devem ser reutilizadas fora desse ambiente didático.

4. Iniciando os containers

Para subir os containers digite:

docker compose up -d

Depois confira se eles realmente subiram:

docker compose ps

Então acesse: http://localhost:8080/geoserver

Para o laboratório podemos utilizar inicialmente as credenciais padrão.

5. Validando o LDAP antes de envolver o GeoServer

Uma boa prática de troubleshooting é testar primeiro o LDAP isoladamente. Podemos, por exemplo, listar nossos usuários:

docker exec -it openldap \
ldapsearch \
-x \
-H ldap://localhost:389 \
-D "cn=admin,dc=geocursos,dc=lab" \
-w adminldap \
-b "ou=people,dc=geocursos,dc=lab" \
"(objectClass=inetOrgPerson)" \
uid cn

Devemos encontrar as informações dos nossos 3 usuários (alice, bob e carol). Agora pergunte ao LDAP a quais grupos o Bob pertence:

docker exec -it openldap \
ldapsearch \
-x \
-H ldap://localhost:389 \
-D "uid=bob,ou=people,dc=geocursos,dc=lab" \
-w bob123 \
-b "ou=groups,dc=geocursos,dc=lab" \
"(member=uid=bob,ou=people,dc=geocursos,dc=lab)" \
cn

O resultado esperado é: geoserver_publico e geoserver_restrito. Esse teste é importante porque elimina várias dúvidas antes mesmo de configurarmos o GeoServer. Se o LDAP não consegue localizar o usuário ou seus grupos, o problema ainda não está no GeoServer.

6. Configurando a autenticação LDAP no GeoServer

Agora entre no GeoServer como administrador e acesse: Security -> Authentication -> Authentication Providers -> Add new -> LDAP

Nessa mesma tela você configura tanto a autenticação do usuário quanto, opcionalmente, a descoberta dos grupos LDAP usados para gerar roles.

O GeoServer atual permite informar diretamente a URL LDAP, o padrão do DN do usuário e a estratégia utilizada para procurar os grupos desse usuário. Para nosso laboratório utilize:

Name
ldap-geocursos

Server URL
ldap://openldap:389/dc=geocursos,dc=lab

User DN pattern
uid={0},ou=people

Use LDAP groups for authorization:
✓

Bind before group search:
✓

Group search base:
ou=groups

Group search filter:
member={0}

Na própria tela do LDAP Authentication Provider existe a área de teste. Então digite o username bob e a senha bob123, e clique no botão Test Connection, para verificar se a integração entre o LDAP e o GeoServer está funcional.

7. Não esqueça a Authentication Provider Chain

Criar o provider não significa necessariamente que ele esteja participando da autenticação. Volte para Security -> Authentication o localize Provider Chain e adicione ldap-geocursos aos providers selecionados.

Mantenha também o provider loca padrão do GeoServer (GeoServer Local). Essa estratégia mantém, inclusive, uma conta administrativa local para contingência.

Em ambientes corporativos gosto de pensar nela como uma conta break glass: o LDAP pode estar indisponível e ainda precisamos ter uma forma extremamente controlada de administrar o GeoServer.

Após esse passo, faça logout do GeoServer e e tente acessar com o username bob e a senha bob123. O resultado esperado é que você consiga logar com o usuário bob.

8. Do grupo LDAP para a Role do GeoServer

Aqui aparece uma das partes mais interessantes dessa integração.

Quando o GeoServer utiliza grupos LDAP para autorização, ele transforma automaticamente o nome do grupo em uma role: Nome do grupo -> ROLE_ grupo

Esse comportamento é documentado oficialmente pelo GeoServer. Portanto nossos grupos se tornam:

geoserver_publico -> ROLE_GEOSERVER_PUBLICO
geoserver_restrito -> ROLE_GEOSERVER_RESTRITO
geoserver_admin -> ROLE_GEOSERVER_ADMIN

Isso significa que Bob, por exemplo, será autenticado com: ROLE_GEOSERVER_PUBLICO e ROLE_GEOSERVER_RESTRITO.

9. LDAP sozinho não protege nenhuma camada

Esse talvez seja o ponto mais importante deste artigo. Configurar LDAP responde: Quem é o usuário? Mas ainda precisamos responder: O que esse usuário pode acessar?

O GeoServer utiliza roles para controlar acesso às camadas. E existe um detalhe importante: a configuração padrão de Layer Security permite leitura anônima das camadas.

Portanto simplesmente configurar LDAP não torna automaticamente seus dados privados. A arquitetura completa é:

10. LDAP Role Service: quando ele entra? (opcional)

Até aqui utilizamos uma abordagem bastante direta, porém o GeoServer também possui um recurso chamado LDAP Role Service, que é um serviço somente leitura que transforma grupos LDAP em roles. Assim como no provider de autenticação, o nome do grupo é convertido para maiúsculas e recebe o prefixo ROLE_.

Uma configuração para nosso diretório poderia utilizar:

Server URL:
ldap://openldap:389/dc=geocursos,dc=lab

Group search base:
ou=groups

Group user membership search filter:
member=uid={0},ou=people,dc=geocursos,dc=lab

All groups search filter:
cn=*

Authenticate to extract roles:
✓

Username:
cn=admin,dc=geocursos,dc=lab

Password:
adminldap

O caminho na interface é: Security -> Users, Groups, Roles -> Role Services -> Add new -> LDAP

A vantagem desse modelo aparece principalmente quando queremos que as roles LDAP façam parte explicitamente do sistema de roles do GeoServer e estejam disponíveis nas telas de configuração de acesso. O tutorial oficial do GeoServer apresenta exatamente essa segunda etapa.

Para um primeiro laboratório, entretanto, o mapeamento realizado pelo próprio LDAP Authentication Provider já é suficiente para entender o conceito.

Neste laboratório utilizamos o administrador do OpenLDAP apenas para simplificar a demonstração. Em produção, utilize uma conta de serviço somente leitura, com apenas as permissões necessárias para consultar usuários e grupos.

11. O desenho final

Depois de toda a configuração, nosso ambiente fica conceitualmente assim:

Esse é o verdadeiro ganho da integração.

O GeoServer deixa de ser responsável por manter uma base paralela de usuários e passa a trabalhar sobre a estrutura de identidade que já existe na organização.

12. Cuidados para produção

O laboratório utiliza deliberadamente configurações simplificadas. Em produção eu revisaria pelo menos estes pontos:

  • Não utilizar LDAP sem criptografia em redes não confiáveis. O GeoServer suporta tanto ldaps://, normalmente na porta 636, quanto STARTTLS sobre LDAP. Há uma particularidade: a documentação informa que o uso de STARTTLS impede o pooling de conexões LDAP, criando uma nova conexão por autenticação e podendo afetar desempenho.
  • Não utilizar as senhas deste laboratório, nem admin/geoserver. A imagem Docker oficial também recomenda substituir as credenciais padrão.
  • Manter uma conta administrativa local de contingência, fortemente protegida, em vez de tornar a administração completamente dependente da disponibilidade do LDAP.
  • Evitar mapear grupos de negócio acidentalmente para ROLE_ADMINISTRATOR. Essa role possui acesso administrativo completo ao GeoServer.
  • Revisar explicitamente Layer Security, Service Security e REST Security. Integrar LDAP não torna automaticamente as camadas privadas; por padrão, a leitura de layers é aberta e a configuração de Service Security começa sem regras.
  • Em containers, guardar credenciais de bind em Secrets, não diretamente no docker-compose.yml, Deployment ou repositório Git. O usuário usado apenas para pesquisa de grupos deve possuir o mínimo de permissões necessárias.
  • Não expor o LDAP sem necessidade. Se GeoServer e LDAP estiverem em uma mesma infraestrutura privada, apenas a comunicação necessária entre eles deve ser permitida.

13. Conclusão

Integrar GeoServer e LDAP não é apenas substituir uma tela de login. Com a combinação de LDAP + grupos + roles + regras de segurança, é possível integrar o GeoServer a uma infraestrutura corporativa de identidade sem precisar manter manualmente usuários e permissões duplicados dentro da aplicação.

E isso torna a administração especialmente interessante em ambientes com vários usuários, diferentes perfis de acesso e dados que não podem simplesmente ficar disponíveis de forma anônima.

Referências oficiais:

GeoServer — Authentication with LDAP
GeoServer — Authentication Providers / LDAP
GeoServer — Layer Security
GeoServer — Service Security
GeoServer — Docker Container