educación, informática y demás

GNU/Linux bash, Shell scripts

Usando ficheros de configuración: Variables de entorno

En ocasiones nos puede interesar contar con un fichero externo donde tengamos parte de la configuración nuestros programas o scripts. De esta forma, por ejemplo, podemos mantener la configuración básica de la funcionalidadde nuestro script separada del código fuente.

Esto nos puede dar varias ventajas, entre ellas la posibilidad de que los usuarios puedan acceder al fichero de configuración de laaplicación y adaptar la configuración a sus necesidades sin tener porqué ver el código fuente de la aplicación o sin tener que modificar el fichero que contiene el código.

Otra ventaja puede ser la de permitir que los usuarios cuenten con ficheros propios de configuración dentro de su directorio personal de forma que cada usuario pueda personalizar el funcionamiento del script a sus necesidades.

Sea como fuere, en esta entrada vamos a aprender cómo podemos cargar una configuración basada en asignación de datos avariables desde un fichero externo. En una primera aproximación lo haremos desde un fichero de configuración que estará en el directorio de trabajo, para después proponer que el fichero de configuración esté dentro de un directorio proio en el directorio /etc.

Fichero de configuración

Vamos a crear un fichero de configuración que contenga un par de variables que utilizaremos en nuestro script. En este caso, el fichero de configuración tan solo tendrá estos datos.

Este fichero contiene la declaración de dos variables. Si nos fijamos, estas variables contienen un par de rutas, que además hacen uso de la variable de entorno $HOME, que contiene la ruta del directorio personal del usuario actual.

Por último, fíjate en el . que hay delante de educatica. Este punto, hace que el directorio .educatica esté oculto. Aunque esto es un detalle que no tiene que ver con el uso de variables en fichero de configuración.

En nuestro script podemos cargar este fichero haciendo uso de source.

El comando source permite ejecutar las ordenes o comandos del fichero cuya ruta se pasa por parámetro. En nuestro caso, el fichero tan solo tendrá declaraciones de variables. Ojo, esto puede acarrear un pequeño problema de seguridad. Más adelante lo veremos.

Vamos a crear un pequeño script que lea la configuración del fichero de configuración.

Vamos a ejecutar el script

En esta aproximación el fichero de configuración está en el directorio de trabajo.

Fichero de configuración en el directorio personal del usuario

Para configurar el script para que obtenga el fichero de configuración desde el directorio personal del usuario sería tan sencillo como cambiar la ruta del fichero haciendo uso de la variable $HOME.

Ahora, podemos ejecutar el script desde cualquier directorio de trabajo y leerá el fichero de configuración desde el directorio personal del usuario actual.

Fichero de configuración en /etc

Exactamente igual que en el caso anterior, tan solo tenemos que cambiar la ruta del fichero de configuración para que lea la configuración desde el directorio de configuración de la aplicación en /etc, por ejemplo en /etc/educatica.

Con esto hemos cambiado tan solo la ruta del fichero. Ahora tendremos que crear el directorio /etc/educatica y dejar entro el fichero de configuración variables.cfg para que esté accesible.

Ahora el fichero de configuración del script está dentro del directorio /etc, y solo lo podrá editar root. Esto sería lo más normal si se trata de una herramienta de administración que solo ejecutará root. De esta forma evitamos posibles problemas de seguridad.

Vamos a hacer un pequeño cambio en la configuración

Si ejecutamos el script, ahora leera los datos de /etc/educatica/variables.cfg

Control de errores: valores por defecto

El uso de este tipo de ficheros nos puede venir bien para separar por un lado la configuración de nuestra aplicación o script en un fichero y mantener en otro fichero la funcionalidad de la aplicación. De esta forma, si tan solo queremos cambiar el valor de alguna de estas variables podemos hacerlo sin tener que tocar el fichero que contiene la funcionalidad de la aplicación.

No obstante, esto nos añade un nuevo foco de problemas. ¿Qué sucede si no encontramos el fichero de configuración o no está establecido algún valor o el valor no es correcto?. Deberíamos controlar estos posibles errores.

En el caso de que el fichero no esté disponible o que alguna variable no esté establecida tenemos dos posibles soluciones: mostrar un mensaje de error y terminar la ejecución del script o establecer valores por defecto a estas variables en el código.

En el primer caso, que es el más restrictivo, si no encontramos el fichero de configuración mostramos un mensaje de error y terminamos con la ejecución del script.

Vamos a probarlo.

Funciona correctamente, se carga la configuración y se ejecuta el código. Para que falle, vamos a cambiar el nombre del fichero de configuración.

La segunda opción que tenemos es cargar valores por defecto para las variables en caso de que no exista el fichero de configuración o que alguna de las variables no esté establecida. En este caso estaremos duplicando la asignación de variables, pero evitamos el problema de que el fichero o las variables no estén establecidas.

De esta forma asignamos primero los valores por defecto y después cargamos los datos del fichero. Podemos mostrar un mensaje de advertencia, si queremos,en caso de que no encontremos el fichero para que el usuario sea consciente de que tiene la posibilidad de utilizar este fichero para configurar la funcionalidad de nuestro programa.

Veamos qué pasa si no encuentra el fichero de configuración en este caso

Por último, vamos a ver qué pasa si se puede cargar el fichero de configuración.

Problema de seguridad

Hasta aquí hemos visto como podemos utilizar ficheros de configuración dónde el usuario o el administrador puede asignar valores a variables que serán utilizadas en nuestros programas o scripts para agilizar la funcionalidad de estos.

Pero, el uso del comando source nos añade un problema de seguridad. Igual que estamos ejecutando declaraciones de variables, un usuario podría escribir un comando o varios en el fichero de configuración. Estos comandos serían ejecutados por el script al utilizar el comando source.

Supongamos que el fichero de configuración de uno de nuestros scripts tiene permiso de escritura para cualquier usuario.

Ahora si nuestro script es ejecutado por root, podríamos tener un problema de seguridad.

Si el script lo ejecuta un usuario normal, no pasa nada…

El usuario marinapg no pertenece al grupo sudo ni tiene en su directorio personal el fichero de contraseñas del sistema. No obstante, si este script lo ejecuta root.

¿Cómo solucionamos este problema? Sencillo si un script utiliza source para cargar fichero de configuración y el script debe ser ejecutado por root, no proporcionar permiso de escritura a los usuarios, tan solo podrá escribir root.

Esto es lo que sucede con cualquier servicio o herramienta de administración, que los usuarios de a pie no pueden configurarla.

Modificamos el fichero de configuración

¿Qué pasa si queremos ficheros de configuración para cada usuario?

Si tenemos ficheros de configuración para cada usuario, cada usuario podrá leer y escribir su fichero de configuración, pero claro el script será ejecutado por el propio usuario, no por root.

Vamos a probar si esto funciona o no. Para ello, lo primero que vamos a hacer es dejar el script en /bin y le vamos a quitar el .sh

Ahora vamos a iniciar sesión con alfredoff y ejecutaremos el script.

Nos cambiamos a alfredoff

Alfredo, que es un lince, se da cuenta de que tiene la posibilidad de crear un fichero de configuración. Consulta el manual de la aplicación y crea su propio fichero de configuración.

Entre nosotros, lo ideal sería que para este tipo de ficheros de configuración personalizados, el propio script detectara que no existe el fichero de configuración y creara el directorio y un fichero de configuración con valores por defecto…

Si vuelve a ejecutar el script…

Si alfredoff se pasa de listo e intenta hacer una escalada de privilegios tocando el fichero, no tendrá efecto, puesto que los comandos se ejecutarán con el nivel de permisos que tenga alfredoff

El Warning se ejecuta porque el comando source devuelve como código de retorno el código de salida del último comando ejecutado, que en nuestro caso es un cp que no se puede ejecutar porque no tiene permiso de lectura.

Se podría «camuflar» el warning ejecutando un comando que funcione bien, por ejemplo un echo.

Lo importante es que al final aunque el usuario escriba comandos, estos comandos se ejecutarán con los permisos del usuario sin poder hacer nada que no pudiera.

Dejar una respuesta