Práctica 1.8

Despliegue de Aplicaciones Web

José Juan Sánchez Hernández

Curso 2023/2024

1 Arquitectura de una aplicación web LAMP en dos niveles

En esta práctica deberá automatizar la instalación y configuración de una aplicación web LAMP en dos máquinas virtuales EC2 de Amazon Web Services (AWS), con la última versión de Ubuntu Server. En una de las máquinas deberá instalar Apache HTTP Server y los módulos necesarios de PHP y en la otra máquina deberá instalar MySQL Server.

Ahora vamos a tener la pila LAMP repartida en dos máquinas virtuales, una se encargará de gestionar las peticiones web y la otra de gestionar la base de datos.

Una vez que hayas comprobado que todos los servicios de la pila LAMP están funcionando correctamente en las dos máquinas, instala y configura WordPress en ellas.

Ten en cuenta que tendrás que modificar la configuración de MySQL Server para que permita conexiones remotas y también tendrás que revisar los privilegios del usuario que se conecta a la base de datos de la aplicación.

La arquitectura estará formada por:

1.1 Arquitectura de dos niveles

1.2 Configuración de MySQL

Edita el siguiente archivo de configuración:

/etc/mysql/mysql.conf.d/mysqld.cnf

Busca la directiva de configuración bind-address dentro del bloque de [mysqld]:

[mysqld]
bind-address = 127.0.0.1

En la configuración por defecto, MySQL sólo permite conexiones desde localhost (127.0.0.1). Habrá que modificar este valor por la dirección IP de la máquina donde se está ejecutando el servicio de MySQL.

[mysqld]
bind-address = IP_SERVIDOR_MYSQL

El valor de IP_SERVIDOR_MYSQL indica desde que interfaz de red del servidor de MySQL se van a permitir conexiones. En nuestro caso, los valores que podemos poner aquí son:

Si nuestra máquina dispone más de una interfaz de red podemos poner la dirección IP 0.0.0.0 para permitir que se puedan conectar a MySQL desde cualquiera de las interfaces de red disponibles.

[mysqld]
bind-address = 0.0.0.0

Una vez hecho esto tenemos que reiniciar el servicio de MySQL:

sudo systemctl restart mysql

1.3 Asignando privilegios a los usuarios de MySQL con GRANT

Si queremos mejorar la seguridad de nuestro servidor de MySQL, podemos configurar que el usuario de MySQL sólo pueda conectarse desde una determinada dirección IP.

Paso 1. Eliminar si existe algún usuario previo con el mismo nombre

Antes de crear un usuario, debemos comprobar si existe y eliminarlo en caso de que exista. Para ello, ejecutamos la siguiente sentencia SQL:

DROP USER IF EXISTS '$DB_USER'@'$IP_MAQUINA_CLIENTE';

Donde $DB_USER es el nombre del usuario de MySQL y $IP_MAQUINA_CLIENTE es la dirección IP desde la que el usuario puede conectarse al servidor de MySQL.

Paso 2. Creación de un usuario

La sintaxis para crear un usuario de MySQL es la siguiente:

CREATE USER '$DB_USER'@'$IP_MAQUINA_CLIENTE' IDENTIFIED BY '$DB_PASS';

Donde $DB_USER es el nombre del usuario de MySQL, $DB_PASS es la contraseña y $IP_MAQUINA_CLIENTE es la dirección IP desde la que el usuario podrá conectarse al servidor de MySQL.

Los valores que podemos utilizar para $IP_MAQUINA_CLIENTE son los siguientes:

Tenga en cuenta que tendrá que reemplazar los valores de las variables $DB_USER, $DB_PASS y $IP_MAQUINA_CLIENTE por los valores que necesite.

Paso 3. Asignación de privilegios

Una vez que hemos creado el usuario le asignamos los privilegios que sean necesarios sobre la base de datos de la aplicación. Para asignar privilegios utilizaremos la sentencia GRANT de SQL. La sintaxis es la siguiente:

GRANT [permiso] ON [nombre_base_de_datos].[nombre_tabla] TO '$DB_USER'@'$IP_MAQUINA_CLIENTE';

Por ejemplo:

GRANT ALL PRIVILEGES ON *.* TO 'nombre_usuario'@'localhost';

En este comando, los asteriscos indican que estamos aplicando el permiso ALL PRIVILEGES al usuario nombre_usuario para que pueda acceder a todas las tablas de cada una de las bases de datos. En el ejemplo anterior, el usuario sólo puede conectarse al servidor de MySQL dede localhost.

En esta práctica tenemos que asignar todos los privilegios con ALL PRIVILEGES al usuario de MySQL que vamos a utilizar para conectarnos desde la máquina donde está corriendo el servicio de Apache HTTP.

GRANT ALL PRIVILEGES ON '$DB_NAME'.* TO '$DB_USER'@'$IP_MAQUINA_CLIENTE';

Tenga en cuenta que tendrá que reemplazar los valores de las variables $DB_NAME, $DB_USER y $IP_MAQUINA_CLIENTE por los valores que necesite.

Los diferentes tipos de permisos que podemos aplicar son los siguientes:

Paso 4. Actualizamos las tablas de privilegios

Para que los cambios que hemos realizado sobre los privilegios de los usuarios se apliquen de forma inmediata, tendremos que ejecutar el siguiente comando.

FLUSH PRIVILEGES;

Ejemplo

En el script de bash de la práctica que va a realizar debería tener el siguiente bloque de instrucciones SQL para crear el usuario de MySQL y asignarle los privilegios necesarios sobre la base de datos de la aplicación web:

DROP USER IF EXISTS '$DB_USER'@'$IP_MAQUINA_CLIENTE';
CREATE USER '$DB_USER'@'$IP_MAQUINA_CLIENTE' IDENTIFIED BY '$DB_PASS';
GRANT ALL PRIVILEGES ON '$DB_NAME'.* TO '$DB_USER'@'$IP_MAQUINA_CLIENTE';

Las variables estarán definidas en un archivo .env:

1.4 Comprobamos la lista de usuarios de MySQL

Los usuarios de MySQL se almacenan en la tabla mysql.user. La clave primaria de esta tabla está formada por los valores user y host, de modo que cada fila vendrá identificada por un nombre de usuario y el host desde el que puede conectarse.

La siguiente consulta nos devuelve el listado de usuarios que tenemos en MySQL y desde qué host pueden conectarse:

SELECT user,host FROM mysql.user;

En nuestra caso la consulta anterior devuelve el siguiente resultado:

+------------------+--------------+
| user             | host         |
+------------------+--------------+
| root             | %            |
| root             | localhost    |
| lamp_user        | %            |
| lamp_user        | localhost    |
| debian-sys-maint | localhost    |
| phpmyadmin       | localhost    |
| mysql.session    | localhost    |
| mysql.sys        | localhost    |
+------------------+--------------+

El siguiente diagrama muestra un ejemplo de dos usuarios que se están conectando a una máquina con MySQL Server. El usuario root@localhost es un usuario que sólo puede conectarse desde la máquina local y el usuario root@'%' es un usuario que se puede conectar desde una máquina remota.

También podemos consultar qué permisos específicos tiene un determinado usuario. La siguiente consulta nos devuelve los permisos que tiene el usuario root:

SHOW GRANTS FOR root;
+------------------------------------------------+
| Grants for root@%                              |
+------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'      |
+------------------------------------------------+

1.5 Comprobamos que podemos conectarnos a MySQL

Ahora vamos a comprobar que podemos conectarnos con MySQL desde la máquina donde está corriendo el servicio de Apache HTTP. Podemos comprobarlo conectando con el shell de mysql:

mysql -u USERNAME -p -h IP-SERVIDOR-MYSQL

O haciendo un telnet al puerto donde está corriendo el servicio de MySQL:

telnet IP-SERVIDOR-MYSQL 3306

Si no podemos conectarnos a MySQL revisaremos que el servicio está activo y que no tenemos ningún firewall que nos esté filtrando el puerto del servicio donde se ejecuta MySQL.

1.6 Configuración de la aplicación web para conectar a MySQL

Una vez que has realizado los pasos anteriores debes instalar y configurar WordPress para que pueda conectar a MySQL.

Recuerda que tendrás que modificar el archivo de configuración de WordPress wp-config.php y configurar las constantes relacionadas con la base de datos.

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

En esta práctica la constante DB_HOST tendrá que tener el valor de la dirección IP privada de la máquina donde se está ejecutando el servicio de MySQL.

1.7 ¿Qué puedo hacer si desde la máquina de front-end (Apache HTTP Server) no puedo conectar a la máquina de back-end (MySQL)?

A continuación se describe una secuencia de pasos que se pueden realizar para detectar posibles errores cuando desde la máquina de front-end (Apache HTTP Server) no puedo conectar con la máquina de back-end (MySQL).

1.8 Entregables

En esta práctica habrá que entregar un documento técnico con la descripción de los pasos que se han llevado a cabo.

El documento debe incluir como mínimo los siguientes contenidos:

1.9 Entregables

Deberá crear un repositorio en GitHub con el nombre de la práctica y añadir al profesor como colaborador.

El repositorio debe tener el siguiente contenido:

Además del contenido anterior puede ser necesario crear otros archivos de configuración. A continuación se muestra un ejemplo de cómo puede ser la estructura del repositorio:

.
├── README.md
├── conf
│   └── 000-default.conf
└── scripts
    ├── .env
    ├── install_lamp_frontend.sh
    ├── install_lamp_backend.sh
    ├── setup_letsencrypt_https.sh    
    ├── deploy_frontend.sh
    └── deploy_backend.sh

1.9.1 Documento técnico

El documento técnico README.md tiene que estar escrito en Markdown y debe incluir como mínimo los siguientes contenidos:

1.9.2 Scripts de Bash

El directorio scripts debe incluir los siguientes archivos:

2 Referencias

3 Licencia

Licencia de Creative Commons
Esta página forma parte del curso Implantación de Aplicaciones Web de José Juan Sánchez Hernández y su contenido se distribuye bajo una licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0 Internacional.