Puedes ver el procedimiento de despliegue de la aplicación en este tutorial en Youtube:
API REST de ejemplo para simular un sencillo servicio de banca online. El objetivo es utilizar una aplicación de muestra para su despliegue en un servidor web (con AWS Beanstalk) o de manera serverless (con AWS Lambda). Por sencillez se deja sin implementar todo el tema de autenticación.
Se podrán realizar las siguientes operaciones:
- Ver la lista de cuentas disponibles
- Abrir una cuenta
- Cerrar una cuenta
- Ver los detalles de una cuenta (titular, autorizado)
- Ver la lista de movimientos de una cuenta
- Hacer un ingreso en una cuenta
- Hacer un reintegro en una cuenta
- Hacer una transferencia entre cuentas
Se desarrollará también un cliente de una sola página (SPA) para interactuar con la API. Dicho cliente está disponible en https://github.com/pedroprieto/cliente-bank-app
La aplicación está estructurada en tres grandes bloques:
- Web API
- Proporciona la lógica de la aplicación y el punto de acceso para interactuar con ella. La API puede dar servicio a clientes web, aplicaciones móviles o a plataformas de terceros que deseen interactuar con ella.
- Cliente web SPA
- Se trata de un cliente de una sola página (SPA). En la primera carga se descargan todos los archivos necesarios para su funcionamiento (HTML, CSS, JavaScript) y a continuación se realizan llamadas a la API para obtener los datos correspondientes. El envío de datos entre cliente y API se realiza utilizando la tecnología AJAX.
- Base de datos
- Almacena la lógica de negocio
El esquema de la solución desplegada en un servidor web con AWS Beanstalk sería el siguiente:
El esquema de la solución desplegada de manera serverless con AWS Lambda sería el siguiente:
Método | URL | Acción | Parámetros |
---|---|---|---|
GET | /accounts | Ver la lista de cuentas disponibles | |
POST | /accounts | Crear una cuenta | titular, autorizado, alias |
GET | /accounts/{idAccount} | Ver los detalles de una cuenta | |
PUT | /accounts/{idAccount} | Editar los detalles de una cuenta | titular, autorizado |
DELETE | /accounts/{idAccount} | Cerrar una cuenta | |
GET | /accounts/{idAccount}/movements | Ver la lista de movimientos de una cuenta | |
POST | /accounts/{idAccount}/deposit | Realizar un ingreso en una cuenta | cantidad, descripción |
POST | /accounts/{idAccount}/withdrawal | Realizar un reintegro de una cuenta | cantidad, descripción |
POST | /accounts/{idAccount}/transfer | Realizar una transferencia entre cuentas | cantidad, descripción, cuenta_destino |
Se utilizará el formato JSON para el intercambio de datos entre la API y el cliente.
- Account
{
"id": "id de la cuenta",
"alias": "alias de la cuenta",
"titular": "nombre del titular",
"autorizado": "nombre del autorizado"
}
- Movements
[
{
"id": "id del movimiento",
"cantidad": 100,
"descripcion":, "descripción del movimiento"
}
]
- Sesiones en el servidor
- Problemas para mantener la sesión entre distintas instancias de ejecución (caso de uso de Lambda o instancias escaladas). No hay garantía de que las peticiones vayan a ser atendidas por el mismo “servidor”: por tanto, el estado de la sesión no puede almacenarse en memoria. Alternativas:
- Almacenamiento del estado de la sesión en la base de datos
- Uso de servicios de caché externos (Redis, AWS ElastiCache,…) para el almacenamiento del estado de la sesión
- Uso de JWT para evitar tener que almacenar el estado de la sesión en el servidor
La aplicación está realizada con ASP.NET Core 3.0.
- SDK de .NET Core
- Servidor MySQL para prueba local
- Herramienta Entity Framework para .NET CLI. Podemos instalarla ejecutando:
dotnet tool install -g dotnet-ef
- Extensiones de AWS para .NET CLI. En concreto, necesitaremos instalar las extensiones para
Lambda
y paraElasticaBeanstalk
:dotnet tool install -g Amazon.ElasticBeanstalk.Tools
dotnet tool install -g Amazon.Lambda.Tools
- Clonar repositorio
- Acceder a la carpeta del repositorio
cd api-bank-app
- Instalar dependencias de .NET
dotnet restore
- Instalar base de datos MySQL en el sistema. Anotar los parámetros de conexión
- Acceder al directorio del proyecto
cd api-bank-app
- Actualizar los datos de conexión a la base de datos local en archivo
api-bank-app/appsettings.json
"ConnectionStrings": { "BankDatabase": "server=localhost;port=3306;user=root;password=;database=bank" },
- Actualizar base de datos a través de Entity Framework
dotnet ef database update
- Lanzar aplicación
dotnet run
- Acceder a la API en
http://localhost:5000/api/clients
- Crear un usuario en AWS IAM para que permita el acceso mediante CLI. Para desplegar en BeanStalk será necesario concederle los siguientes permisos:
AdministratorAccess-AWSElasticBeanstalk
IAMFullAccess
- Configurar en el equipo local las credenciales de acceso a AWS con los datos del usuario creado
- Instalar proyecto y dependencias de .NET
- Crear una nueva aplicación en ElasticBeanstalk en la consola de AWS
- Crear un entorno .NET dentro de la aplicación de ElasticBeanstalk. Elegir una máquina
t2.micro
- Crear una base de datos en AWS RDS de tipo MySQL. Para la práctica es recomendable utilizar MariaDB y seleccionar una instancia
t2.micro
. - Anotar los datos de conexión a la base de datos de RDS
- Configurar el grupo de seguridad de la base de datos para que permita el acceso desde cualquier IP de la VPC para que la aplicación Beanstalk tenga acceso. Abrir el puerto de entrada 3306.
- Crear archivo
api-bank-app/.ebextensions/db.config
a partir del que se proporciona como ejemplo enapi-bank-app/.ebextensions/db.config.example
utilizando los datos de conexión de la base de datos de RDS - Publicar la aplicación en AWS Beanstalk indicando el nombre de la aplicación y el nombre del entorno de AWS BeanStalk creados.
dotnet eb deploy-environment
- Actualizar base de datos en RDS. (Nota: este punto se puede mejorar para que se pueda realizar de manera automática mediante las migraciones de .NET. Así, cada vez que se suba una nueva versión de la aplicación se actualizará la base de datos automáticamente)
- Conceder acceso público a la base de datos de RDS
- Crear en el sistema operativo local una variable de entorno con los datos de conexión de la base de datos de RDS
# Para Windows setx ConnectionStrings__BankDatabase "server=HOST_BASEDEDATOS_RDS;port=PUERTO_BASEDATOS_RDS;user=USUARIO_BASEDATOS_RDS;password=PASSWORD_BASEDATOS_RDS;database=NOMBRE_BASEDATOS_RDS" /M # Para Linux export ConnectionStrings__BankDatabase="server=HOST_BASEDEDATOS_RDS;port=PUERTO_BASEDATOS_RDS;user=USUARIO_BASEDATOS_RDS;password=PASSWORD_BASEDATOS_RDS;database=NOMBRE_BASEDATOS_RDS"
De esta manera también se puede testear la aplicación local con la base de datos remota
- Actualizar la base de datos desde Visual Studio o mediante el comando
dotnet ef database update
. Al existir la variable de entorno se actualizará la base de datos remota.
Se supone que en este punto ya se dispone del usuario de IAM, se ha clonado el repositorio y se han instalado las dependencias de .NET. También se supone creada la base de datos en AWS RDS y que dispone de acceso público.
- Conceder al usuario de IAM creado los siguientes permisos en la consola de AWS:
AWSLambda_FullAccess
AmazonAPIGatewayAdministrator
- Crear un bucket en AWS S3 y anotar su nombre
- Crear archivo
api-bank-app/serverless.template
a partir del que se proporciona como ejemplo enapi-bank-app/serverless.template.example
. Modificar la línea correspondiente a la variable de entornoConnectionStrings__BankDatabase
con los datos de acceso a la base de datos de RDS."ConnectionStrings__BankDatabase": "server=HOST_BASEDEDATOS_RDS;port=PUERTO_BASEDATOS_RDS;user=USUARIO_BASEDATOS_RDS;password=PASSWORD_BASEDATOS_RDS;database=NOMBRE_BASEDATOS_RDS"
- Publicar la aplicación en AWS Lambda indicando el bucket de S3 creado anteriormente.
dotnet lambda deploy-serverless
Al finalizar la práctica hay que recordar borrar todos los recursos creados en AWS. Esto incluye:
- Base de datos en la consola de RDS
- Snapshots de la base de datos en la consola de RDS (una vez eliminada la base de datos)
- Aplicación y entorno en la consola de Elastic BeanStalk
- Recursos creados para la función Lambda en la consola de CloudFormation. Si se hace desde ahí se eliminará la función Lambda y los recursos creados en API Gateway.
- Buckets en S3:
- Bucket creado para la función Lambda
- Bucket creado por BeanStalk (está protegido contra borrado; para eliminarlo hay que eliminar la política del bucket en: Permisos / Política del Bucket / Eliminar política del Bucket)
- Bucket creado para el cliente
- Autenticación
- Uso de servicios Cloud (Amazon Cognito,…)
- Autenticación mediante Single Sign On (Servicios de Google/Twitter/Facebook)
- Autenticación clásica usuario-password
- Uso de Hypermedia como medio de intercambio de datos entre cliente y servidor para desacoplar las dependencias entre ambos