pg_hba.conf

Introdução

O arquivo pg_hba.conf (PostgreSQL Host-Based Authentication) é uma peça fundamental na configuração de segurança de qualquer instância PostgreSQL. Ele define as regras de autenticação e acesso ao banco de dados, determinando quem pode se conectar, de onde e como essas conexões são autenticadas. Neste artigo, exploraremos as diversas opções de configuração disponíveis no pg_hba.conf, desde os métodos de autenticação até a especificação de IPs, usuários e grupos. Também abordaremos os modelos de autenticação mais comuns, como TRUST, password, md5 e scram-sha-256, além de métodos específicos como ident e peer. Ao final, você será capaz de configurar esse arquivo para garantir um ambiente seguro e eficiente para suas aplicações.

Roteiro:

  • Modelo de autenticação
    • TYPE (tipos de conexão)
      • local
      • host
      • hostssl
    • DATABASE (banco de dados)
    • USER (usuários ou grupos de usuários)
    • ADDRESS (endereços)
    • METHOD (método)
    • OPTIONS (opções)
    • Exemplos
    • Considerações importantes
  • Ident file

Modelo de autenticação

O modelo de autenticação define como a autenticação será realizada e gerenciada, verificando a identidade dos usuários do banco de dados de diferentes formas. No PostgreSQL, o principal modelo é baseado no arquivo pg_hba.conf. Ele pode estar localizado em diferentes locais, dependendo do seu ambiente:

  • /var/lib/pgsql/<versão>/data/ nos ambientes Linux Red Hat e derivados (como CentOS);
  • /etc/postgresql/<versão>/<cluster>/pg_hba.conf nos ambientes Linux Debian e derivados (como Ubuntu);
  • C:\Program Files\PostgreSQL\<versão>\data\pg_hba.conf em Windows;
  • Se você criou o seu cluster de dados em um diretório específico e não está utilizando o Linux Debian, o pg_hba.conf deverá estar nesse diretório, que chamamos de $PGDATA (que é a variável de ambiente que contém essa localização).

O pg_hba.conf tem como características regras específicas que suportam vários métodos de autenticação, que podem ainda ser aplicados de forma seletiva.

A estrutura básica do pg_hba.conf é (em cada linha):

Arquivo pg_hba.conf: estrutura padrão
TYPE  DATABASE  USER  ADDRESS  METHOD [OPTIONS]

Sendo que  TYPE se refere ao tipo de conexão, DATABASE, ao banco de dados  ao qual a regra se aplica, USER, a usuário ou grupo de usuários, ADDRESS, ao endereço IP ou intervalo (range) de IPs, METHOD  ao método de autenticação, e OPTIONS a algumas opções que podem existir de acordo com o método escolhido, respectivamente.
Além disso, no pg_hba.conf, as linhas de regras são divididas por seções, sendo uma para conexões locais, outra para IPv4, outra para IPv6 e mais uma para replicações.
Apenas para lembrar, é tradição no universo Linux/Unix (de onde o PostgreSQL surgiu) usar o caractere ‘#‘ para marcar comentários no início da linha.

Confira um exemplo de conteúdo do pg_hba.conf:

Arquivo pg_hba.conf: exemplo de conteúdo
# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            scram-sha-256
host    replication     all             ::1/128                 scram-sha-256

TYPE (tipos de conexão)

O PostgreSQL suporta diversos tipos de conexão, cada um com suas próprias características e casos de uso, que determinam como os clientes podem se conectar ao servidor de banco de dados. Entre os principais e mais utilizados, estão:

  • local: conexões feitas através de Unix sockets no mesmo sistema onde o servidor PostgreSQL está rodando, ou seja, conexões locais, portanto, não sendo necessário passar a informação da coluna ADDRESS;
  • host: conexões TCP/IP tanto locais quanto remotas não criptografadas, ou seja, sem criptografia SSL;
  • hostssl: para conexões TCP/IP seguras, ou seja, criptografadas via SSL. É o que recomendamos utilizar e teremos um artigo especial dedicado a ele.

Existem ainda as opções mais incomuns: hostnossl (sem SSL), hostgssenc (com criptografia GSSAPI) e hostnogssenc (sem criptografia GSSAPI).

DATABASE (banco de dados)

Para isolar as regras de autenticação, deve-se especificar a qual banco a linha com as instruções se refere, sendo possível utilizar all para aplicação em todos os bancos. Além disso, há a opção samerole, que é particularmente útil em ambientes com multitenancy, onde diferentes usuários ou grupos precisam acessar seus próprios bancos de dados sem interferir em outros. Com samerole, o Postgres permite que um usuário se conecte apenas a bancos de dados cujo nome coincide com uma role (grupo) da qual ele é membro. Assim, é possível definir que cada usuário tenha acesso apenas aos bancos relacionados ao seu papel, reforçando a segurança e o isolamento entre bancos de dados de diferentes usuários.

USER (usuários ou grupos de usuários)

É possível especificar usuários individuais do PostgreSQL no pg_hba.conf pelo campo USER ou, ainda, usar all para corresponder a todos os usuários, assim como para os bancos de dados.
Podemos também indicar grupos de usuários com o prefixo +, por exemplo, +admins, o que torna fácil o processo de gerenciar permissões de vários usuários simultaneamente. É importante lembrar que não são grupos do sistema operacional, mas, sim, roles definidas no PostgreSQL.
No contexto do PostgreSQL, um “grupo de usuários” é, na verdade, uma role à qual outras roles (usuários) recebem grants (privilégios). Isso permite agrupar vários usuários sob uma mesma role, facilitando o gerenciamento de permissões e acessos em ambientes mais complexos.
Além disso, também podemos informar nomes de usuário como expressões regulares, indicando com o prefixo /, e também é possível gerenciar os usuários, com nome ou expressões regulares, em um arquivo separado, que deve ser mencionado com o prefixo @. Há ainda o caso de replicação, que trata-se de uma conexão usada para sincronizar dados entre servidores, e que deve ser indicada nessa coluna com a palavra-chave replication.

ADDRESS (endereços)

O campo ADDRESS no pg_hba.conf permite especificar quais endereços podem se conectar:

  • Subnet: permite conexões de uma faixa de IPs, por exemplo:
    • 192.168.1.1/32 ou fe80::7a31:c1ff:fa34:9eb3/128 – permite apenas um IP específico;
    • 127.0.0.1 ou ::1/128 - (ipv6) – permite apenas conexões locais;
    • 192.168.1.0/24 – permite todos os IPs classe C, de 192.168.1.0 a 192.168.1.255;
    • 192.168.0.0/16 – permite todos os IPs classe B, de 192.168.0.0 a 192.168.255.255;
    • 192.0.0.0/8 – permite todos os IPs classe A, de 192.0.0.0 a 192.255.255.255;
    • 0.0.0.0/0 ou ::0/0 (ipv6) – permite qualquer IP (não recomendamos usar esta configuração em ambiente de produção).
  • IP-mask: permite a definição de uma faixa de IPs, semelhante a anterior, mas em vez de usar a subnet, colocamos o IP e a máscara de IPs:
    • 192.168.1.0 ou 255.255.255.0 – permite todos os IPs classe C, de 192.168.1.0 a 192.168.1.255;
    • 192.168.0.0 ou 255.255.0.0 – permite todos os IPs classe B, de 192.168.0.0 a 192.168.255.255.
  • Hostname: além de endereços IP, podemos utilizar um hostname, no qual o PostgreSQL realiza várias verificações para garantir a correspondência entre o hostname especificado e o cliente. Lembrando que qualquer lentidão na resolução de nomes pelo DNS irá provocar uma lentidão no processo de conexão em si.
    • Hostname específico: é só colocá-lo, como exemplo.com;
    • Subdomínios: necessário colocar o prefixo “.” antes do hostname, e assim qualquer endereço com esse subdomínio será autorizado, como em .exemplo.com permitiria conexão de sub.exemplo.com, app.exemplo.com etc. (mas não o próprio exemplo.com).
  • Também podemos utilizar all para permitir a conexão de qualquer IP, samehost para permitir qualquer IP do próprio servidor e samenet para permitir qualquer IP em qualquer sub-rede à qual o servidor esteja conectado.

METHOD (método)

Os métodos de autenticação no PostgreSQL são as diferentes maneiras que o banco de dados usa para verificar e realizar a autenticação, indo desde a exigência de senhas até a confiança total e permissão absoluta. Os principais são:

  • trust: permite conexões sem nenhuma autenticação, ou seja, se o seu IP for contemplado na lista de endereços autorizados, não será necessário fornecer senhas, por isso é adequado apenas para ambiente de testes e desenvolvimento local ou com redes totalmente isoladas e confiáveis endereçando apenas um IP local ou um IP único confiável;
  • password / md5 / scram-sha-256: é exigida uma senha no momento da conexão, que varia entre essas três opções com diferentes níveis de segurança:
    • password: senha em texto simples, sem criptografia durante a transmissão pela rede;
    • md5: usa hash MD5 para criptografar a senha durante a transmissão, o que torna o processo um pouco mais seguro, mas seu uso está sendo descontinuado em favor do próximo método considerado mais seguro;
    • scram-sha-256: usa o método SCRAM (Salted Challenge Response Authentication Mechanism) como hash SHA-256, o que o torna a opção baseada em senha mais segura, já que seu protocolo de autenticação não transmite a senha real, e sua criptografia é considerada muito forte.

É importante saber que o tipo de encriptação padrão da senha (md5 ou scram-sha-256) é definido pelo parâmetro password_encryption, que significa que todos os seus usuários criados com senha, ou com a senha alterada, vão tê-la com a criptografia apontada por esse parâmetro. O nosso padrão é scram-sha-256, porém fizemos alterações para exemplificar diferentes cenários;

  • ident: usa o serviço de identificação do sistema operacional (Ident ou identd) para autenticar, confiando na informação que o SO passa, por isso requer que o cliente esteja em um servidor ident (mais comum em ambientes Linux, em que o serviço Ident já vem ativado por padrão); 
  • peer: confia nas informações de usuários do SO local, ou seja, diferente do ident, não precisa de um serviço externo para isso e só funciona para redes locais. É esse o método de autenticação que costumamos usar para acessar o psql com usuário postgres (estando conectado ao usuário postgres do SO);
  • Além desses, o PostgreSQL suporta vários outros métodos, incluindo:
    • reject: rejeita todas as conexões, podendo ser usado para filtrar e impedir grupos; 
    • sspi: autenticação nativa do Windows;
    • ldap: para autenticação via servidores LDAP;
    • radius: para autenticação via servidores RADIUS;
    • cert: usa certificados SSL do cliente para autenticação.

OPTIONS (opções)

Além de todas as configurações que vimos, é possível ainda inserir mais opções para o método de autenticação, que devem ter o formato de nome=valor, e servem para especificar opções adicionais para o método escolhido. Algumas delas são:

  • clientcert: além das opções específicas de cada método de autenticação, existe essa opção geral, que pode ser usada em qualquer entrada do tipo hostssl. Essa opção tem dois valores possíveis: verify-ca e verify-full, sendo que o primeiro exige que o cliente apresente um certificado SSL válido e confiável, e o segundo, além de exigir um certificado válido, também verifica se o Common Name (CN) no certificado do cliente corresponde ao nome de usuário ou a um mapeamento aplicável. Isso fornece um nível extra de segurança;
  • clientname: quando você está usando autenticação com certificado de cliente (usando o método cert ou a opção clientcert), você pode usar essa opção para especificar qual parte das credenciais do certificado do cliente deve ser comparada com o nome de usuário, sendo as subopções clientname=CN, em que o nome de usuário será comparado com o Common Name (CN) do certificado, e clientname=DN, em que o nome de usuário será comparado com o Distinguished Name (DN) completo do certificado, conforme o formato RFC 2253;
  • include, include_if_exists e include_dir: essas opções permitem definir suas regras de autenticação em um arquivo separado, sendo necessário passar o local do arquivo entre aspas simples. A diferença entre essas opções é que a primeira apenas checa o local do arquivo informado e tenta substituir as regras, a segunda faz isso apenas se o arquivo existir, caso contrário será exibida uma mensagem indicando que o arquivo não foi lido, e a última reconhece todos os arquivos de um diretório.

Exemplos

Conexão local de todos os usuários com peer

Arquivo pg_hba.conf: exemplo de configuração de conexão
local		all		all		peer

Este é o caso que possibilita o acesso ao psql pelo usuário postgres do SO, pulando a etapa de fornecimento de senha (acessamos o banco também chamado postgres):

Debian shell: exemplo de acesso ao psql sem inserção de senha
postgresdebian:~$ psql -U postgres -d postgres
psql (16.2 (Debian 16.2-1.pgdg120+2))
Type "help" for help.

postgres=#

Além desse usuário, poderíamos repetir esse tipo de acesso com qualquer outro usuário que existisse tanto no banco de dados quanto no SO, claro, com o mesmo nome nos dois lugares:

Debian shell: acessando o psql sem inserção de senha
ludmila@debian:~$ psql -U ludmila -d postgres
psql (16.2 (Debian 16.2-1.pgdg120+2))
Type "help" for help.

postgres=>

Além disso, conforme explicado, podemos aplicar as regras por banco de dados, então, se fosse especificado o método de conexão peer apenas para o banco postgres, não seria possível acessar sem senha em outros bancos.

Conexão host com IP específico e senha sem criptografia

Arquivo pg_hba.conf: exemplo de configuração de conexão
host		all		all		192.168.1.10/32		password

Como você pode notar, foi solicitada a senha para acessar o banco de outro IP:

Debian shell: acessando o psql com senha
fabio@debian-2:~$ psql -h 64.23.248.23 -p 5432 -U fabio -d postgres
Password for user fabio:
psql (16.4 (Debian 16.4-1.pgdg120+1), server 16.2 (Debian 16.2-1.pgdg120+2))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=>

Mas, se a tentativa de acessar fosse feita da rede local com o mesmo usuário fabio, considerando que temos no mesmo arquivo a linha de regras exemplificadas anteriormente, este seria o resultado:

Debian shell: acessando o psql sem inserção de senha (com peer)_
fabio@debian:~$ psql -U fabio -d postgres
psql (16.2 (Debian 16.2-1.pgdg120+2))
Type "help" for help.

postgres=>

Conexão host para grupo de usuários com IP específico e trust

Arquivo pg_hba.conf: exemplo de configuração de conexão
host	    all	 +groupname	      192.168.1.20/32	trust

Esse cenário permite que os usuários pertencentes ao grupo editors se conectem de um IP específico sem a necessidade de informar senha. No nosso caso, o usuário ana está neste grupo:

Debian shell: acessando o psql sem inserção de senha
ana@debian-2:~$ psql -h 64.23.248.23 -p 5432 -U ana -d postgres
psql (16.4 (Debian 16.4-1.pgdg120+1), server 16.2 (Debian 16.2-1.pgdg120+2))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=>

Conexão host para bancos de dados com o mesmo proprietário (samerole)

Arquivo pg_hba.conf: exemplo de configuração de conexão
host    samerole    all     192.168.1.0/24    md5

Com essa configuração, se o usuário user1 tentar acessar o banco de dados que ele mesmo possui, a senha será solicitada, porém, se ele tentar acessar um banco que pertence a outro usuário, como user2, ele não conseguirá, pois a regra só se aplica aos bancos que possuem o mesmo proprietário.

Considerações importantes

  • As regras são aplicadas na ordem em que aparecem no arquivo;
  • As primeiras regras têm prioridade, então coloque as mais restritivas no início;
  • Após modificar o pg_hba.conf, recarregue as configurações com o comando systemctl reload postgresql;
  • Se não funcionar, deve-se checar os logs do banco ou então consultar a tabela pg_hba_file_rule do catálogo para entender onde está o erro dentro do pg_hba.conf ;
Debian shell: logs do banco de dados exibindo erro no pg_hba.conf
$ tail postgresql-16-main.log
2024-11-13 17:29:31.029 UTC [141035] LOG:  received SIGHUP, reloading configuration files
2024-11-13 17:29:31.037 UTC [141035] LOG:  invalid connection type "hoost"
2024-11-13 17:29:31.037 UTC [141035] CONTEXT:  line 126 of configuration file "/etc/postgresql/16/main/pg_hba.conf"
2024-11-13 17:29:31.037 UTC [141035] LOG:  /etc/postgresql/16/main/pg_hba.conf was not reloaded
Debian shell: consulta na tabela pg_hba_file_rules com registro de erro
postgres=# select * from pg_hba_file_rules ;
 rule_number |              file_name              | line_number | type  |   database    | user_name  |  address  |                 netmask                 |  auth_method  | options |              error
-------------+-------------------------------------+-------------+-------+---------------+------------+-----------+-----------------------------------------+---------------+---------+---------------------------------
           1 | /etc/postgresql/16/main/pg_hba.conf |         118 | local | {all}         | {postgres} |           |                                         | peer          |         |
           2 | /etc/postgresql/16/main/pg_hba.conf |         125 | local | {all}         | {all}      |           |                                         | trust         |         |
             | /etc/postgresql/16/main/pg_hba.conf |         126 |       |               |            |           |                                         |               |         | invalid connection type "hoost"
           3 | /etc/postgresql/16/main/pg_hba.conf |         128 | host  | {all}         | {all}      | ::1       | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 |         |
           4 | /etc/postgresql/16/main/pg_hba.conf |         131 | local | {replication} | {all}      |           |                                         | peer          |         |
           5 | /etc/postgresql/16/main/pg_hba.conf |         132 | host  | {replication} | {all}      | 127.0.0.1 | 255.255.255.255                         | scram-sha-256 |         |
           6 | /etc/postgresql/16/main/pg_hba.conf |         133 | host  | {replication} | {all}      | ::1       | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 |         |
(7 rows)
  • Teste as configurações em um ambiente de desenvolvimento antes de aplicá-las em produção.

Ident file

O ident file é um arquivo utilizado pelo PostgreSQL para mapear nomes de usuários do sistema operacional para nomes de usuários do banco de dados. Ele é útil quando você usa o método de autenticação ident, que verifica a identidade do usuário que está tentando se conectar ao banco de dados com base no nome de usuário do sistema operacional.

Para fazer essa autenticação baseada nos usuários do SO, o PostgreSQL consulta o ident file para mapear o nome de usuário do SO para o nome de usuário do banco de dados.

Esse arquivo geralmente é chamado pg_ident.conf e está localizado no mesmo diretório que o arquivo pg_hba.conf (/etc/postgresql/<versão>/<cluster>/pg_hba.conf para sistemas de base Linux). 

Seu conteúdo é simples, com cada linha contendo três colunas:

  1. Mapa de identidade: nome de um grupo de mapeamento definido;
  2. Nome de usuário do SO: nome do usuário no sistema operacional;
  3. Nome de usuário do banco: nome do usuário no banco de dados que corresponde ao usuário do SO. 

Após feita a configuração do arquivo pg_ident.conf, para utilizá-lo basta selecionar como método de autenticação no pg_hba.conf o ident e, então, como última opção da linha de regra, informar o nome do mapa definido no ident file. Exemplo:

Arquivo pg_ident.conf: exemplo de conteúdo
mymap   seu_usuario_os   seu_usuario_db

Nesse caso, mymap é o nome do seu mapeamento, seu_usuario_os é o nome do usuário no sistema operacional, e seu_usuario_db é o nome do usuário no banco de dados.

Para aplicar isso no pg_hba.conf, poderíamos incluir essa linha nas regras do arquivo:

Arquivo pg_hba.con:f: exemplo de configuração com ident file
host   all	all   192.168.1.10/32   ident   mymap

Sendo que ident é o método escolhido, e a opção extra mymap refere-se ao mapeamento que queremos utilizar (considerando que podemos mapear vários usuários no ident file).

Conclusão

O pg_hba.conf é uma peça fundamental na definição de políticas de acesso ao banco de dados. Ele é relativamente simples de configurar e tem uma sintaxe bastante intuitiva se compararmos com outros bancos de dados por aí. No entanto, conhecer as opções disponíveis é uma condição indispensável para administrar um ambiente de produção de forma minimamente segura. 

Por padrão, as instalações do PostgreSQL vêm apenas habilitadas para permitir conexões locais, o que gera uma certa frustração em novatos. Algumas pessoas, na pressa de colocar o banco de dados no ar, acabam utilizando o método TRUST ou colocando faixas de IPs abertas para o mundo todo com 0.0.0.0/0, o que deixa o servidor completamente vulnerável a ataques. Na mesma linha, você deve utilizar o ALL para usuários, e nomes de bancos de dados devem ser utilizados com moderação. Aqui vale a regra do “menor privilégio possível”. Você deve sempre colocar as regras mais restritas possíveis para permitir que as aplicações e os usuários acessem o banco de dados com segurança. 

Outra tendência forte é utilizar conexões com criptografia SSL para todas as conexões que não forem locais, evitando possíveis ataques de pessoas que ficam escutando o tráfego da sua rede. Isso é tão importante hoje que escrevemos um artigo só sobre isso, que você poderá conferir mais adiante. Portanto, seja cuidadoso e crie regras com prudência. Lembre-se, você pode alterá-las e adicionar quantas linhas forem necessárias depois; e recarregar o arquivo pg_hba.conf sem precisar reiniciar o serviço do PostgreSQL, apenas dando um RELOAD.

Compartilhe

Você pode gostar

Tuning de SO (no Linux)

Introdução Tuning refere-se ao processo de ajustar e otimizar o desempenho de um sistema, software ou aplicação. A otimização do sistema operacional é uma etapa

Tipos de cargas dos bancos de dados

Introdução Cargas de dados referem-se aos diferentes tipos de operações e transações que um banco de dados deve processar. Essas cargas variam conforme o tipo

plugins premium WordPress