Restrinja o acesso ao banco de dados à aplicação

PostgreSQLBeginner
Pratique Agora

Introdução

O banco de pedidos aceita conexões de toda a VPC da aplicação, que usa uma identidade administradora do banco. Você reduzirá o acesso de rede e criará um usuário dedicado que pode ler e adicionar pedidos, mas não excluí-los.

Conclua primeiro os laboratórios de conexão e SQL. Este ambiente independente fornece um PostgreSQL primário, três pedidos de exemplo e uma aplicação. Você testará os dois limites de acesso e removerá o banco de exercício ao final.

Relação com certificações

Este laboratório oferece prática introdutória para os seguintes tópicos de exames.

Restrinja a origem de rede do PostgreSQL

Nesta etapa, você substituirá o acesso amplo da VPC pelo acesso do grupo de segurança preparado para a aplicação.

Um grupo de segurança controla quais conexões de rede chegam ao banco. Ele não decide quais operações SQL um usuário autenticado pode executar. Você tratará esse outro limite na próxima etapa.

Carregue as configurações preparadas:

cd /home/labex/project
source database.env

Inspecione o grupo do banco e seus dois documentos de regras fornecidos:

aws ec2 \
  describe-security-groups \
  --group-ids "$DB_SECURITY_GROUP_ID" \
  --query 'SecurityGroups[].{Group:GroupName,Ingress:IpPermissions}'
cat broad-rule.json
cat application-rule.json

A regra atual permite a porta TCP 5432 a partir de 10.70.0.0/16, então outros clientes dessa VPC podem tentar conectar-se. A substituta usa UserIdGroupPairs para referenciar o grupo da aplicação. Uma referência permite tráfego de recursos associados ao grupo de origem; ela não copia suas regras.

Remova a regra ampla e adicione a regra da aplicação:

aws ec2 \
  revoke-security-group-ingress \
  --group-id "$DB_SECURITY_GROUP_ID" \
  --ip-permissions file://broad-rule.json
aws ec2 \
  authorize-security-group-ingress \
  --group-id "$DB_SECURITY_GROUP_ID" \
  --ip-permissions file://application-rule.json

Teste uma nova conexão da origem da aplicação:

psql \
  "service=orders-db" \
  --command 'SELECT count(*) FROM orders;'

Espere encontrar 3. Depois teste o cliente fornecido fora do grupo da aplicação:

psql \
  "service=orders-db-external" \
  --command 'SELECT count(*) FROM orders;'

A conexão do cliente externo deve falhar. Sua senha do banco é válida, mas sua origem de rede não está permitida. Os nomes de conexão preparados selecionam essas duas origens. As regras do exercício não alteram sua conexão de gerenciamento ao Terminal ou AWS View.

O AWS View deve mostrar o grupo da aplicação como origem PostgreSQL do banco, em vez do CIDR amplo da VPC.

Crie um usuário de banco para a aplicação

Nesta etapa, você permitirá ler e inserir pedidos sem conceder privilégios administrativos ou de exclusão.

Um papel do PostgreSQL pode ter privilégios. Um papel com LOGIN pode autenticar-se como usuário de banco. Papéis de banco são separados de identidades AWS IAM: IAM gerencia o recurso RDS, enquanto essas concessões SQL controlam operações dentro do PostgreSQL.

Acesso de rede, login e permissões SQL são limites distintos

Diagrama conceitual: Acesso de rede, login e permissões SQL são limites distintos.

Crie orders_app com o arquivo privado de senha fornecido. --set define uma variável psql; :'app_password' coloca seu valor entre aspas com segurança como uma string SQL:

psql \
  "service=orders-db" \
  --set=ON_ERROR_STOP=1 \
  --set=app_password="$(cat app-password.txt)" <<'SQL'
CREATE ROLE orders_app LOGIN PASSWORD :'app_password';
GRANT CONNECT ON DATABASE orders TO orders_app;
GRANT USAGE ON SCHEMA public TO orders_app;
GRANT SELECT, INSERT ON orders TO orders_app;
SQL

CONNECT permite conexões ao banco. USAGE permite acesso pelo esquema, um espaço de nomes que contém tabelas. SELECT e INSERT permitem apenas as operações necessárias. Você não concedeu DELETE, UPDATE, CREATEDB, CREATEROLE nem privilégios de superusuário.

Teste o papel passando o valor privado da senha ao psql:

PGPASSWORD="$(cat app-password.txt)" psql \
  "service=orders-db-app" \
  --command 'SELECT current_user, count(*) FROM orders;'

Espere encontrar o usuário orders_app e 3 pedidos.

Tente excluir um ID de pedido inexistente. A instrução não pode remover um pedido real mesmo se os privilégios forem excessivos por engano:

PGPASSWORD="$(cat app-password.txt)" psql \
  "service=orders-db-app" \
  --command 'DELETE FROM orders WHERE order_id = -1;'

Espere encontrar permission denied for table orders. Essa falha ocorre depois do sucesso da conexão de rede e da autenticação no banco, comprovando um limite diferente da falha de conexão do cliente externo.

Use a identidade limitada na aplicação

Nesta etapa, você configurará o papel na aplicação e comprovará que as operações normais de pedidos continuam funcionando.

Altere a identidade do banco e a referência ao arquivo de senha, mantendo os dois campos de endpoint:

jq \
  '.user = "orders_app" | .password_file = "app-password.txt"' \
  app-config.json > app-config.new
mv app-config.new app-config.json

Leia a lista atual de pedidos:

curl \
  --silent \
  --show-error \
  --fail \
  http://127.0.0.1:8080/application/orders | jq

Espere encontrar os três pedidos originais e user: orders_app.

Adicione um pedido pelo endpoint HTTP da aplicação. Content-Type informa que o corpo da solicitação é JSON:

curl \
  --silent \
  --show-error \
  --fail \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"order_id":104,"customer":"Kai","total":"5.00"}' \
  http://127.0.0.1:8080/application/orders

Espere encontrar saved: true e o ID 104. Leia a lista novamente:

curl \
  --silent \
  --show-error \
  --fail \
  http://127.0.0.1:8080/application/orders | jq

Espere encontrar quatro pedidos, incluindo o pedido de Kai de 5.00. O AWS View deve mostrar os mesmos dados armazenados e a identidade limitada da aplicação. Os privilégios reduzidos preservam o comportamento necessário. A aplicação lê os pedidos originais e o novo com o usuário limitado orders_app.

Remova o banco de exercício

Nesta etapa, você removerá o banco do laboratório, incluindo os pedidos de exemplo e os usuários SQL.

aws rds \
  delete-db-instance \
  --db-instance-identifier orders-db \
  --skip-final-snapshot \
  --query 'DBInstance.DBInstanceIdentifier'
aws rds \
  wait db-instance-deleted \
  --db-instance-identifier orders-db
aws rds \
  describe-db-instances \
  --query 'DBInstances[].DBInstanceIdentifier'

Espere encontrar []. O mecanismo e seus papéis foram removidos; o endpoint antigo da aplicação não conecta mais. Preserve a rede fornecida e seu grupo de banco restrito. Não há motivo para reabrir o acesso durante a limpeza.

Resumo

Você restringiu as conexões PostgreSQL à origem da aplicação e deu a ela seu próprio papel limitado. O cliente externo não conseguiu conectar e o papel não pôde excluir pedidos, enquanto leituras e inserções normais funcionaram. Depois, removeu o banco de exercício e preservou as regras de rede restritas.

O próximo laboratório recupera pedidos perdidos restaurando um snapshot manual do RDS em um novo banco.