Restringe el acceso a la base de datos a la aplicación

PostgreSQLBeginner
Practicar Ahora

Introducción

La base de pedidos acepta conexiones de toda la VPC de la aplicación, y la aplicación usa una identidad administradora de la base. Reducirás el acceso de red y crearás un usuario dedicado que pueda leer y añadir pedidos, pero no eliminarlos.

Completa primero los laboratorios de conexión y SQL. Este entorno independiente proporciona un PostgreSQL primario, tres pedidos de ejemplo y una aplicación. Probarás ambos límites de acceso y eliminarás la base de práctica al final.

Relación con certificaciones

Este laboratorio ofrece práctica introductoria para los siguientes temas de examen.

Restringe el origen de red de PostgreSQL

En este paso sustituirás el acceso amplio desde la VPC por acceso desde el grupo de seguridad preparado para la aplicación.

Un grupo de seguridad controla qué conexiones de red llegan a la base. No decide qué operaciones SQL puede ejecutar un usuario autenticado. Abordarás ese límite diferente en el siguiente paso.

Carga la configuración preparada:

cd /home/labex/project
source database.env

Inspecciona el grupo de la base y sus dos documentos de reglas:

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

La regla actual permite el puerto TCP 5432 desde 10.70.0.0/16, por lo que otros clientes de esa VPC pueden intentar conectarse. La sustituta usa UserIdGroupPairs para referenciar el grupo de la aplicación. Una referencia permite tráfico desde recursos asociados al grupo de origen; no copia las reglas de ese grupo.

Elimina la regla amplia y añade la de la aplicación:

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

Prueba una conexión nueva desde el origen de la aplicación:

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

Debes obtener 3. Después prueba el cliente suministrado que está fuera del grupo de la aplicación:

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

El cliente externo debe fallar al conectar. Su contraseña es válida, pero su origen de red no está permitido. Los nombres de conexión preparados seleccionan estos dos orígenes. Las reglas del experimento no cambian tu conexión de administración a Terminal o AWS View.

AWS View debe mostrar el grupo de la aplicación como origen PostgreSQL de la base, en lugar del CIDR amplio de la VPC.

Crea un usuario de base de datos para la aplicación

En este paso permitirás leer e insertar pedidos sin conceder privilegios administrativos ni de eliminación.

Un rol de PostgreSQL puede tener privilegios. Un rol con LOGIN puede autenticarse como usuario de base de datos. Los roles de base son independientes de las identidades AWS IAM: IAM administra el recurso RDS, mientras estos permisos SQL controlan operaciones dentro de PostgreSQL.

Acceso de red, inicio de sesión y permisos SQL son límites distintos

Diagrama conceptual: Acceso de red, inicio de sesión y permisos SQL son límites distintos.

Crea orders_app con el archivo privado de contraseña suministrado. --set define una variable psql; :'app_password' cita su valor de forma segura como cadena 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 conexiones a la base. USAGE permite acceder mediante el esquema, un espacio de nombres que contiene tablas. SELECT e INSERT permiten solo las operaciones de pedidos necesarias. No has concedido DELETE, UPDATE, CREATEDB, CREATEROLE ni privilegios de superusuario.

Prueba el rol pasando el valor privado de la contraseña a psql:

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

Debes obtener el usuario orders_app y 3 pedidos.

Intenta eliminar un ID de pedido que no existe. La sentencia no puede borrar un pedido real aunque los privilegios fueran demasiado amplios por error:

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

Debes obtener permission denied for table orders. Este fallo sucede después de conectar y autenticar correctamente en la base, por lo que demuestra un límite distinto del fallo de conexión del cliente externo.

Usa la identidad limitada en la aplicación

En este paso configurarás el rol en la aplicación y comprobarás que las operaciones normales siguen funcionando.

Cambia su identidad de base y referencia al archivo de contraseña, conservando ambos 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

Lee la lista actual de pedidos:

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

Debes obtener los tres pedidos originales y user: orders_app.

Añade un pedido mediante el endpoint HTTP de la aplicación. Content-Type indica que el cuerpo de la petición es 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

Debes obtener saved: true y el ID 104. Lee la lista otra vez:

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

Debes obtener cuatro pedidos, incluido el de Kai por 5.00. AWS View debe mostrar los mismos datos almacenados y la identidad limitada de la aplicación. Los permisos reducidos mantienen el comportamiento necesario. La aplicación lee los pedidos originales y el nuevo con el usuario limitado orders_app.

Elimina la base de práctica

En este paso eliminarás la base del laboratorio, incluidos sus pedidos de ejemplo y usuarios 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'

Debes obtener []. El motor y sus roles han desaparecido; el endpoint antiguo de la aplicación ya no conecta. Conserva la red y el grupo de base restringido. No hay motivo para reabrir el acceso durante la limpieza.

Resumen

Restringiste las conexiones PostgreSQL al origen de la aplicación y le diste un rol propio limitado. El cliente externo no pudo conectar y el rol no pudo eliminar pedidos, mientras las lecturas e inserciones normales siguieron funcionando. Después eliminaste la base de práctica y conservaste las reglas de red restringidas.

El siguiente laboratorio recupera pedidos perdidos restaurando un snapshot manual de RDS en una base nueva.