ogdhcp/installer/ogdhcp_installer.sh

689 lines
22 KiB
Bash

#!/bin/bash
#####################################################################
####### Script instalador Ogclient
####### Autor: Luis Gerardo Romero <lguillen@unizar.es>
#####################################################################
function globalSetup() {
local current_dir
current_dir=$(dirname "$0")
PROGRAMDIR=$(readlink -e "$current_dir")
PROGRAMNAME=$(basename "$0")
OPENGNSYS_CLIENT_USER="opengnsys"
current_dir=$(dirname "$0")
PROGRAMDIR=$(readlink -e "$current_dir")
# Ruta del archivo config_ogdhcp.json proporcionado por el usuario
CONFIG_FILE="$PROGRAMDIR/config_ogdhcp.json"
# Comprobar si se ha descargado el paquete comprimido (REMOTE=0) o sólo el instalador (REMOTE=1).
if [ -d "$PROGRAMDIR/../installer" ]; then
echo "REMOTE=0"
REMOTE=0
else
echo "REMOTE=1"
REMOTE=1
fi
BRANCH=${1:-"main"}
GIT_REPO="ssh://git@ognproject.evlt.uma.es:21987/opengnsys/ogdhcp.git"
# Directorios de instalación y destino de OpenGnsys.
WORKDIR=/tmp/ogdhcp_installer
INSTALL_TARGET=$(jq -r '.ogDhcp_Dir' "$CONFIG_FILE")
PATH=$PATH:$INSTALL_TARGET/bin
if command -v service &>/dev/null; then
STARTSERVICE="eval service \$service restart"
STOPSERVICE="eval service \$service stop"
else
STARTSERVICE="eval /etc/init.d/\$service restart"
STOPSERVICE="eval /etc/init.d/\$service stop"
fi
ENABLESERVICE="eval update-rc.d \$service defaults"
DISABLESERVICE="eval update-rc.d \$service disable"
# Variables globales
DEFAULTDEV=""
NGINX_TEMPLATE="$INSTALL_TARGET/etc/nginxServer.conf.tmpl"
NGINX_OUTPUT="/etc/nginx/sites-available/ogdhcp.conf"
NGINX_CONF_PATH="/etc/nginx/nginx.conf"
PHP_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/www.conf"
NEW_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/ogdhcp.conf"
SOCKET_PATH="/run/php/php__PHPVERSION__-fpm-ogdhcp.sock"
# Registro de incidencias.
OGLOGFILE="$INSTALL_TARGET/var/log/${PROGRAMNAME%.sh}.log"
LOG_FILE="/tmp/$(basename "$OGLOGFILE")"
}
function checkDependencies() {
echoAndLog "Checking dependencies..."
# Lista de dependencias
local DEPENDENCIES=(
php
php-cli
php-fpm
php-json
php-pdo
php-mysql
php-zip
php-gd
php-mbstring
php-curl
php-xml
php-pear
php-bcmath
composer
unzip
kea-dhcp4-server
kea-common
kea-ctrl-agent
jq
net-tools
nginx
)
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
# Comprobar cada dependencia
for dep in "${DEPENDENCIES[@]}"; do
if ! dpkg -s "$dep" >/dev/null 2>&1; then
echoAndLog "$dep is not installed. Installing..."
apt-get install -y --no-install-recommends "$dep"
else
echoAndLog "$dep is already installed."
fi
done
sed -i '/ConditionFileNotEmpty=\/etc\/kea\/kea-api-password/d' /usr/lib/systemd/system/kea-ctrl-agent.service
chown -R _kea:_kea /etc/kea
systemctl daemon-reload
systemctl restart kea-ctrl-agent.service
echoAndLog "Dependencies checked."
}
# Obtiene el código fuente del proyecto desde el repositorio de GitHub.
function downloadCode() {
if [ $# -ne 1 ]; then
errorAndLog "${FUNCNAME}(): invalid number of parameters"
exit 1
fi
local url="$1"
echoAndLog "${FUNCNAME}(): downloading code from '$url'..."
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new" git archive --remote="$url" --format zip --output opengnsys.zip --prefix=opengnsys/ "$BRANCH" && unzip opengnsys.zip
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error getting OpenGnsys code from $url"
return 1
fi
rm -f opengnsys.zip
echoAndLog "${FUNCNAME}(): code was downloaded"
return 0
}
# Crea la estructura base de la instalación de opengnsys
function createDirs() {
if [ $# -ne 1 ]; then
errorAndLog "${FUNCNAME}(): invalid number of parameters"
exit 1
fi
local path_opengnsys_base="$1"
# Crear estructura de directorios.
echoAndLog "${FUNCNAME}(): creating directory paths in $path_opengnsys_base"
mkdir -p "$path_opengnsys_base"/{bin,config,docs,public,src,etc/kea/backup,templates,var/{cache,log},vendor}
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error while creating dirs. Do you have write permissions?"
return 1
fi
# Mover el fichero de registro de instalación al directorio de logs.
echoAndLog "${FUNCNAME}(): moving installation log file"
mv "$LOG_FILE" "$path_opengnsys_base/var/log" && LOG_FILE="$OGLOGFILE"
usermod -aG $OPENGNSYS_CLIENT_USER _kea
# Mover el fichero de registro de instalación al directorio de logs.
echoAndLog "${FUNCNAME}(): moving installation log file"
touch "$path_opengnsys_base/var/log/dev.log"
echoAndLog "${FUNCNAME}(): directory paths created"
return 0
# Cambiar permisos de usuario
echoAndLog "Changing user permission"
chown -R "$OPENGNSYS_CLIENT_USER:$OPENGNSYS_CLIENT_USER" "$INSTALL_TARGET"
}
function create_ogdhcp_project {
# Crea el usuario ogdhcp si no existe
echo "Creating ogdhcp user..."
local path_opengnsys_base="$1"
echo $path_opengnsys_base
# Verificar si el usuario OPENGNSYS_CLIENT_USER existe
if id -u "$OPENGNSYS_CLIENT_USER" &>/dev/null; then
# Salida de getent passwd -> opengnsys:x:1001:1001::/opt/opengnsys:/bin/sh
CURRENT_HOME=$(getent passwd "$OPENGNSYS_CLIENT_USER" | cut -d: -f6)
echoAndLog "${FUNCNAME[0]}(): user \"$OPENGNSYS_CLIENT_USER\" already exists with home \"$CURRENT_HOME\""
# Si el home no es correcto, cambiarlo
if [ "$CURRENT_HOME" != "/opt/opengnsys" ]; then
echoAndLog "${FUNCNAME[0]}(): updating home directory for \"$OPENGNSYS_CLIENT_USER\" to \"/opt/opengnsys\""
usermod -d "/opt/opengnsys" -m "$OPENGNSYS_CLIENT_USER"
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME[0]}(): error updating home for \"$OPENGNSYS_CLIENT_USER\""
return 1
fi
fi
else
# Crear usuario si no existe
echoAndLog "${FUNCNAME[0]}(): creating OpenGnsys user \"$OPENGNSYS_CLIENT_USER\""
useradd --create-home -d "/opt/opengnsys" --shell "/bin/bash" "$OPENGNSYS_CLIENT_USER"
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME[0]}(): error creating user \"$OPENGNSYS_CLIENT_USER\""
return 1
fi
fi
# Asegurar que todos los usuarios puedan entrar y leer /opt/opengnsys
echoAndLog "${FUNCNAME[0]}(): setting permissions for /opt/opengnsys"
# sudo chmod 755 /opt/opengnsys
# Crea el directorio path_opengnsys_base con el usuario opengnsys
echoAndLog "${FUNCNAME}(): creating directory $path_opengnsys_base with opengnsys user"
sudo mkdir -p "$path_opengnsys_base"
sudo chown opengnsys:opengnsys $path_opengnsys_base
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error while creating directory $path_opengnsys_base"
return 1
fi
echoAndLog "Directory $path_opengnsys_base created with opengnsys user"
}
function copyServerFiles() {
if [ $# -ne 1 ]; then
errorAndLog "${FUNCNAME}(): invalid number of parameters"
exit 1
fi
local path_opengnsys_base="$1"
# Lista de ficheros y directorios origen y de directorios destino.
local SOURCES=(
config
#public
src
etc
.env
composer.json
composer.lock
phpunit.xml.dist
symfony.lock
)
local TARGETS=(
config
#public
src
etc
.env
composer.json
composer.lock
phpunit.xml.dist
symfony.lock
)
if [ "${#SOURCES[@]}" != "${#TARGETS[@]}" ]; then
errorAndLog "${FUNCNAME}(): inconsistent number of array items"
exit 1
fi
# Copiar ficheros.
echoAndLog "${FUNCNAME}(): copying files to server directories"
pushd "$WORKDIR/ogdhcp" || return
local i
for (( i = 0; i < ${#SOURCES[@]}; i++ )); do
if [ -f "${SOURCES[$i]}" ]; then
echoAndLog "Copying ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}" "$path_opengnsys_base/${TARGETS[$i]}"
elif [ -d "${SOURCES[$i]}" ]; then
echoAndLog "Copying content of ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}"/* "$path_opengnsys_base/${TARGETS[$i]}"
else
warningAndLog "Unable to copy ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
fi
done
echoAndLog "Changing user permission"
chown -R "$OPENGNSYS_CLIENT_USER:$OPENGNSYS_CLIENT_USER" "$INSTALL_TARGET"
popd || return
}
function runComposer() {
echoAndLog "Running composer.phar to install dependencies..."
local path_opengnsys_base="$1"
pushd $path_opengnsys_base
pwd
# Ejecutar composer.phar
sudo -u "$OPENGNSYS_CLIENT_USER" composer --no-interaction install
# Comprobar si la ejecución fue exitosa
if [ $? -ne 0 ]; then
errorAndLog "Failed to run composer.phar"
popd
return 1
fi
echoAndLog "composer.phar ran successfully and dependencies were installed"
return 0
}
get_first_network_interface_with_traffic() {
while read -r line; do
if [[ "$line" == *:* ]]; then
interface=$(echo "$line" | cut -d ':' -f 1 | xargs)
if [[ "$interface" != "lo" ]]; then
received_bytes=$(echo "$line" | awk '{print $2}')
transmitted_bytes=$(echo "$line" | awk '{print $10}')
if (( received_bytes > 0 || transmitted_bytes > 0 )); then
DEFAULTDEV="$interface"
break
fi
fi
fi
done < /proc/net/dev
}
comment_auth_kea() {
KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf"
# Verificar si el bloque de "authentication" ya está comentado
if grep -q '^[^#]*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then
echo "Comentando el bloque de autenticación en $KEA_CTRL_AGENT_CONF..."
# Comentar solo el bloque de authentication desde la apertura hasta la línea con '},'
sed -i '/"authentication": {/,/^[[:space:]]*},/ {
s/^\([[:space:]]*\)\([^#]\)/\1#\2/
}' "$KEA_CTRL_AGENT_CONF"
echo "Bloque de autenticación comentado correctamente."
else
echo "El bloque de autenticación ya está comentado."
fi
# Verificar si el bloque fue comentado correctamente
if grep -q '^#\s*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then
echo "Confirmación: Bloque de autenticación comentado correctamente."
# Reiniciar el servicio de Kea Control Agent para aplicar los cambios
echo "Reiniciando el agente de Kea Control Agent..."
sudo systemctl restart kea-ctrl-agent.service
if systemctl is-active --quiet kea-ctrl-agent.service; then
echo "El agente de Kea Control Agent se ha reiniciado correctamente."
else
echo "Error: No se pudo reiniciar el agente de Kea Control Agent."
fi
else
echo "Error: No se pudo comentar correctamente el bloque de autenticación."
fi
}
# Función para obtener la dirección IP de una interfaz
get_ip_address() {
local interface="$1"
ip -4 addr show "$interface" | grep -oP "(?<=inet\s)\d+(\.\d+){3}"
}
# Función para obtener la versión de PHP instalada
get_php_fpm_version() {
php -v | grep -oP "PHP \K\d+\.\d+"
}
add_write_permission_apparmor() {
APPARMOR_PROFILE="/etc/apparmor.d/usr.sbin.kea-dhcp4"
# Comprobar si las líneas existen
if grep -q "/etc/kea/ r," "$APPARMOR_PROFILE" && grep -q "/etc/kea/** r," "$APPARMOR_PROFILE"; then
echo "Modificando permisos en $APPARMOR_PROFILE..."
# Modificar las líneas /etc/kea/ r, y /etc/kea/** r, añadiendo w
sed -i 's#/etc/kea/ r,#/etc/kea/ rw,#g' "$APPARMOR_PROFILE"
sed -i 's#/etc/kea/\*\* r,#/etc/kea/** rw,#g' "$APPARMOR_PROFILE"
echo "Permisos de escritura añadidos correctamente a $APPARMOR_PROFILE."
else
echo "Las líneas no fueron encontradas o ya están modificadas."
fi
# Recargar el perfil de AppArmor para aplicar los cambios
echo "Recargando el perfil de AppArmor para kea-dhcp4..."
sudo apparmor_parser -r "$APPARMOR_PROFILE"
if [ $? -eq 0 ]; then
echo "El perfil de AppArmor se recargó correctamente."
else
echo "Error al recargar el perfil de AppArmor."
fi
}
# Función para configurar Nginx
setup_nginx() {
local path_opengnsys_base="$1"
local public_dir="$path_opengnsys_base/public"
#ip_address_server=$(get_ip_address "$DEFAULTDEV")
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "Error: El archivo de configuración no se encontró."
exit 1
fi
ip_address_server=$(jq -r '.ogDhcpIP' "$CONFIG_FILE")
if [[ -z "$ip_address_server" ]]; then
echo "Error: No se pudo obtener la dirección IP del servidor desde el archivo de configuración."
exit 1
fi
php_version=$(get_php_fpm_version)
if [[ -z "$php_version" ]]; then
echo "Error: No se pudo obtener la versión de PHP."
exit 1
fi
# Leer y modificar la plantilla de configuración de nginx
if [[ ! -f "$NGINX_TEMPLATE" ]]; then
echo "Error: La plantilla de Nginx no se encontró."
exit 1
fi
nginx_content=$(<"$NGINX_TEMPLATE")
nginx_content="${nginx_content//__SERVERIP__/$ip_address_server}"
nginx_content="${nginx_content//__PHPVERSION__/$php_version}"
nginx_content="${nginx_content//__PUBLICDIR__/$public_dir}"
# Crear el archivo de configuración de Nginx
echo "$nginx_content" > "$NGINX_OUTPUT"
echo "Archivo de configuración de Nginx creado en $NGINX_OUTPUT."
# Crear el enlace simbólico
ln -sf "$NGINX_OUTPUT" /etc/nginx/sites-enabled/ogdhcp.conf
echo "Enlace simbólico creado en /etc/nginx/sites-enabled/ogdhcp.conf."
# Modificar nginx.conf para ejecutar como opengnsys
sed -i 's/user www-data;/user opengnsys;/g' "$NGINX_CONF_PATH"
echo "Nginx configurado para ejecutarse como opengnsys."
# Reiniciar Nginx
systemctl restart nginx.service
echo "Servicio Nginx reiniciado."
}
# Función para modificar el archivo de configuración PHP-FPM
modify_php_fpm_config() {
php_version=$(get_php_fpm_version)
if [[ -z "$php_version" ]]; then
echo "Error: No se pudo obtener la versión de PHP."
exit 1
fi
php_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/www.conf"
new_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/ogdhcp.conf"
socket_path="/run/php/php$php_version-fpm-ogdhcp.sock"
# Verificar si el archivo new_fpm_conf_path ya existe
if [[ -f "$new_fpm_conf_path" ]]; then
echo "El archivo $new_fpm_conf_path ya existe. No se realizarán modificaciones."
return
fi
# Copiar el archivo www.conf a opengnsys.conf
cp "$php_fpm_conf_path" "$new_fpm_conf_path"
# Modificar el archivo ogdhcp.conf
sed -i 's/\[www\]/[ogdhcp]/g' "$new_fpm_conf_path"
sed -i 's/user = www-data/user = opengnsys/g' "$new_fpm_conf_path"
sed -i 's/group = www-data/group = opengnsys/g' "$new_fpm_conf_path"
sed -i "s|listen =.*|listen = $socket_path|g" "$new_fpm_conf_path"
sed -i 's/listen.owner = www-data/listen.owner = opengnsys/g' "$new_fpm_conf_path"
sed -i 's/listen.group = www-data/listen.group = opengnsys/g' "$new_fpm_conf_path"
# Reiniciar PHP-FPM
systemctl restart php"$php_version"-fpm.service
echo "PHP-FPM reiniciado."
# Verificar la creación del socket
if [[ -S "$socket_path" ]]; then
echo "Socket PHP-FPM $socket_path creado correctamente."
else
echo "Error: El socket PHP-FPM $socket_path no se ha creado."
exit 1
fi
}
configure_kea() {
# Verificar si jq está instalado
if ! command -v jq &> /dev/null; then
echo "jq no está instalado. Por favor, instala jq para continuar."
exit 1
fi
# Verificar si el archivo de configuración existe
if [ ! -f "$CONFIG_FILE" ]; then
echo "El archivo $CONFIG_FILE no se encuentra. Asegúrate de que esté disponible antes de la instalación."
exit 1
fi
# Leer los parámetros del archivo JSON usando jq
INTERFACES=$(jq -r '.interfaces[]' "$CONFIG_FILE")
OGBOOT_IP=$(jq -r '.ogbootIP' "$CONFIG_FILE")
# Crear la configuración mínima de Kea DHCP
KEA_CONFIG="/etc/kea/kea-dhcp4.conf"
# Hacer una copia de seguridad del archivo kea-dhcp4.conf si ya existe
if [ -f "$KEA_CONFIG" ]; then
cp "$KEA_CONFIG" "$KEA_CONFIG.backup"
echo "Se ha creado una copia de seguridad del archivo de configuración actual en $KEA_CONFIG.backup"
fi
# Generar la configuración mínima para Kea DHCP
cat > "$KEA_CONFIG" << EOL
{
"Dhcp4": {
"interfaces-config": {
"interfaces": [ $(
for interface in $INTERFACES; do
echo "\"$interface\""
done | paste -sd "," -
) ]
},
"client-classes": [
{
"name": "UEFI-64",
"test": "not substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'",
"boot-file-name": "ipxe.efi",
"next-server": "$OGBOOT_IP"
},
{
"name": "Legacy",
"test": "substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'",
"boot-file-name": "undionly.kpxe",
"next-server": "$OGBOOT_IP"
}
],
"control-socket": {
"socket-name": "/run/kea/kea4-ctrl-socket",
"socket-type": "unix"
}
}
}
EOL
echo "Se ha generado la configuración mínima de Kea DHCP en $KEA_CONFIG"
# Reiniciar el servicio de Kea DHCP y verificar si se reinicia correctamente
echo "Reiniciando el servicio Kea DHCP..."
sudo systemctl restart kea-dhcp4-server.service
# Comprobar el estado del servicio Kea DHCP
if systemctl is-active --quiet kea-dhcp4-server.service; then
echo "Kea DHCP reiniciado correctamente."
else
echo "Error al reiniciar Kea DHCP."
exit 1
fi
}
#####################################################################
####### Algunas funciones útiles de propósito general:
#####################################################################
# Obtiene la fecha y hora actual en el formato especificado
function getDateTime() {
date "+%Y%m%d-%H%M%S"
}
# Escribe un mensaje en el archivo de registro y lo muestra por pantalla
function echoAndLog() {
local DATETIME=$(getDateTime)
echo "$1"
echo "$DATETIME;$SSH_CLIENT;$1" >> "$LOG_FILE"
}
# Escribe un mensaje de error en el archivo de registro y lo muestra por pantalla
function errorAndLog() {
local DATETIME=$(getDateTime)
echo "ERROR: $1"
echo "$DATETIME;$SSH_CLIENT;ERROR: $1" >> "$LOG_FILE"
}
# Escribe un mensaje de advertencia en el archivo de registro y lo muestra por pantalla
function warningAndLog() {
local DATETIME=$(getDateTime)
echo "Warning: $1"
echo "$DATETIME;$SSH_CLIENT;Warning: $1" >> "$LOG_FILE"
}
##########################################################################
################################main######################################
# Sólo ejecutable por usuario root
if [ "$(whoami)" != 'root' ]; then
echo "ERROR: this program must run under root privileges!!"
exit 1
fi
# Verificar si jq está instalado, si no, instalarlo
if ! command -v jq &> /dev/null; then
echo "jq no está instalado. Instalando jq..."
apt-get update -y
apt-get install -y jq
if [ $? -ne 0 ]; then
echo "Error al instalar jq. Por favor, instala jq manualmente y vuelve a intentarlo."
exit 1
fi
echo "jq instalado correctamente."
fi
globalSetup
echoAndLog "OpenGnsys installation begins at $(date)"
mkdir -p $WORKDIR
pushd $WORKDIR
checkDependencies
# Si es necesario, descarga el repositorio de código en directorio temporal
if [ $REMOTE -eq 1 ]; then
downloadCode $GIT_REPO
if [ $? -ne 0 ]; then
errorAndLog "Error while getting code from the repository"
exit 1
fi
else
ln -fs "$(dirname $PROGRAMDIR)" ogdhcp
fi
create_ogdhcp_project ${INSTALL_TARGET}
if [ $? -ne 0 ]; then
errorAndLog "Error while creating skeleton directory!"
exit 1
fi
# Arbol de directorios de OpenGnsys.
createDirs ${INSTALL_TARGET}
if [ $? -ne 0 ]; then
errorAndLog "Error while creating directory paths!"
exit 1
fi
# Copiar ficheros de servicios OpenGnsys Server.
copyServerFiles ${INSTALL_TARGET}
if [ $? -ne 0 ]; then
errorAndLog "Error while copying the server files!"
exit 1
fi
comment_auth_kea
if [ $? -ne 0 ]; then
errorAndLog "Error while commenting auth block!"
exit 1
fi
runComposer ${INSTALL_TARGET}
setup_nginx $INSTALL_TARGET
if [ $? -ne 0 ]; then
errorAndLog "Error configuring Nginx for OpenGnsys Admin"
exit 1
fi
modify_php_fpm_config
if [ $? -ne 0 ]; then
errorAndLog "Error configuring PHP-FPM for OpenGnsys Admin"
exit 1
fi
add_write_permission_apparmor
if [ $? -ne 0 ]; then
errorAndLog "Error adding write permission to AppArmor profile"
exit 1
fi
configure_kea
if [ $? -ne 0 ]; then
errorAndLog "Error configuring Kea DHCP initial configuration"
exit 1
fi
# install_kea
# install_php
# install_composer
# install_symfony
# install_swagger
# Ahora puedes clonar e instalar el componente ogDhcp
# git clone <URL del repositorio de ogDhcp>
# cd <directorio de ogDhcp>
# composer install