{"id":3728,"date":"2015-12-07T22:04:04","date_gmt":"2015-12-07T21:04:04","guid":{"rendered":"http:\/\/bitacora.eniac2000.com\/?p=3728"},"modified":"2015-12-07T22:04:04","modified_gmt":"2015-12-07T21:04:04","slug":"automatizacion-de-despliegue-y-gestion-de-cortafuegos-con-ansible","status":"publish","type":"post","link":"https:\/\/bitacora.eniac2000.com\/?p=3728","title":{"rendered":"Automatizaci\u00f3n de despliegue y gesti\u00f3n de cortafuegos con Ansible"},"content":{"rendered":"<p>Estas \u00faltimas jornadas he estado trabajando en un sistema de automatizaci\u00f3n de despliegue de cortafuegos en Softlayer. Llevo un tiempo trabajando con cortafuegos Vyatta, que si bien son bastante pr\u00e1cticos para desplegarlos tanto sobre entornos virtuales como sobre m\u00e1quinas f\u00edsicas, adolecen de un grave problema: carecen de un sistema de gesti\u00f3n centralizado. Y cuando manejas del orden de medio centenar de cortafuegos, esto se hace especialmente necesario, no s\u00f3lo para mantener un sistema homog\u00e9neo y manejable, sino tambi\u00e9n para evitar, en la medida de lo posible, fallos humanos.<\/p>\n<p>\u00bfY cu\u00e1l ha sido el sistema elegido para automatizar ciertas tareas de despliegue y gesti\u00f3n? Pues como no pod\u00eda ser menos, ha sido <a href=\"http:\/\/www.ansible.com\" target=\"_blank\">Ansible<\/a>. Hasta este momento he sido capaz de:<\/p>\n<ul>\n<li>Hacer un despliegue automatizado de la configuraci\u00f3n inicial de cortafuegos vyatta en cl\u00faster a partir de cortafuegos individuales.<\/li>\n<li>Automatizar el desploegue y borrado de m\u00faltiples reglas en diferentes cortafuegos<\/li>\n<\/ul>\n<p>Para ello, lo primero ha sido preparar un entorno de demo, que ha tenido casi m\u00e1s chicha que la propia configuracion con Ansible:<\/p>\n<p><figure id=\"attachment_3729\" aria-describedby=\"caption-attachment-3729\" style=\"width: 400px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2015\/12\/pic26060.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2015\/12\/pic26060-400x249.gif\" alt=\"Diagrama del entorno de despliegue\" title=\"Diagrama del entorno de despliegue\" width=\"400\" height=\"249\" class=\"size-medium wp-image-3729\" \/><\/a><figcaption id=\"caption-attachment-3729\" class=\"wp-caption-text\">Diagrama del entorno de despliegue<\/figcaption><\/figure><br \/>\n&#8230;que se compone de los siguientes elementos:<\/p>\n<ul>\n<li><strong>Port\u00e1til:<\/strong> Mi propio port\u00e1til de trabajo. Act\u00faa como entorno de virtualizaci\u00f3n basado en KVM. Su funci\u00f3n como entorno de virtualizaci\u00f3n no es relevante en s\u00ed como elemento de testeo, pero sin \u00e9l no ser\u00eda posible realizar el despliegue del entorno. S\u00ed es relevante su funci\u00f3n como cliente de los servicios desplegados por el servidor CirrOS. Se le ha configurado una ruta est\u00e1tica para enrutar el tr\u00e1fico a trav\u00e9s de la IP .254 de la subred externa, que ser\u00e1 la IP flotante del cl\u00faster de cortafuegos.<\/li>\n<li><strong>Servidor CirrOS:<\/strong> Servidor extremadamente ligero (en torno a 32 MB de RAM y un procesador) que levanta servicios SSH y HTTP, este \u00faltimo mediante una simulaci\u00f3n con NetCat, lo que tambi\u00e9n tiene su miga. En cuanto al servidor CirrOS, a los conocedores de entornos cloud como Openstack les sonar\u00e1 bastante, pero he conseguido hacer un despliegue en un entorno KVM convencional.<\/li>\n<li><strong>Cl\u00faster de cortafuegos Vyatta:<\/strong> El cl\u00faster de cortafuegos Vyatta (bueno, en realidad VyOS, el fork software libre surgido cuando Brocade compr\u00f3 el proyecto original) act\u00faa como cortafuegos entre las subredes interna y externa. En la fase inicial consiste en dos cortafuegos independientes, como una configuraci\u00f3n b\u00e1sica de sus interfaces de red y poco m\u00e1s, con direcci\u00f3namiento .252 y .253. En esta fase, por lo tanto, el port\u00e1til no es capaz de conectar con el servidor CirrOS. El equipo <strong>vyatta1<\/strong> actuar\u00e1 como maestro en la configuraci\u00f3n VRRP, y el equipo <strong>vyatta2<\/strong> actuar\u00e1 como esclavo.<\/li>\n<li><strong>Ansible:<\/strong> Este servidor act\u00faa como servidor de Ansible, como su propio nombre indica. Conecta con los dispositivos vyatta haciendo uso de clave SSH, por lo que -y esto es de lo mejor de Ansible- no necesita de ning\u00fan tipo de agente o plugin para realizar los despliegues de configuraci\u00f3n o recogida de informaci\u00f3n desde los dispositivos.<\/li>\n<\/ul>\n<p>Ansible -y esto no pretente ser una descripci\u00f3n exhaustiva de sus caracter\u00edsticas, por lo que ruego se me perdone cualquier incorrecci\u00f3n que pueda perpetrar- puede actuar bien enviando comandos \u00fanicos a los equipos administrados, bien haciendo uso de recetas (playbooks). Estas recetas consisten en un grupo de <strong>tareas<\/strong>, <strong>plantillas <\/strong>y <strong>par\u00e1metros <\/strong>que se combinan para realizar las labores de automatizaci\u00f3n de configuraci\u00f3n y labores de gesti\u00f3n en los <strong>dispositivos<\/strong>:<\/p>\n<ul>\n<li><strong>Tareas (task):<\/strong> Comando o grupo de comandos que realizan alguna acci\u00f3n en el dispositivo. \u00c9stas pueden ser creadas en base a m\u00f3dulos predefinidos para simplificar su proceso de creaci\u00f3n<\/li>\n<li><strong>Plantillas (templates):<\/strong> Las tareas pueden hacer uso de plantillas para simplificar el proceso de configuraci\u00f3n o gesti\u00f3n de los dispositivos. Estas plantillas, cuyas variables se completan haciendo uso de los valores asignados a los par\u00e1metros, se usan para crear al vuelo los scripts (o cualquier comando) que se quieran aplicar al dispositivo. Lo m\u00e1s interesante del asunto es que estas plantillas se pueden crear de manera bastante sencilla en base a scripts convencionales que ya se estuvieran utilizando para gestionar el dispositivo, simplemente reemplazando las variables del scripts por las variables propias de j2, que posteriormente, en tiempo de ejecuci\u00f3n, ser\u00e1n sustituidas por los par\u00e1metros definidos en Ansible.<\/li>\n<li><strong>Par\u00e1metros:<\/strong> Valores concretos de la configuraci\u00f3n de los dispositivos a gestionar con Ansible, como por ejemplo el nombre del cortafuegos, la IP de una interfaz, o los valores de la VPN. Estos par\u00e1metros pueden ser definidos de m\u00faltiples maneras: usando un fichero de configuraci\u00f3n global de par\u00e1metros, usando ficheros espec\u00edficos para cada dispositivo (algo especialmente interesante para este caso), almacenando valores en tiempo de ejecuci\u00f3n de los propios dispositivos gestionados o del entorno, o una combinaci\u00f3n de estos m\u00e9todos. Posteriormente, estos par\u00e1metros se usan para configurar los dispositivos, bien mediante tareas individuales o mediante plantillas.<\/li>\n<li><strong>Dispositivos (hosts):<\/strong> Conjunto de servidores que queremos administrar. Pueden ser etiquetados para aplicarle s\u00f3lo ciertas tareas (por ejemplo, los dispositivos individuales de las parejas de vyattas pueden ser etiquetados como <em>maestro <\/em>y <em>esclavo <\/em>para s\u00f3lo aplicar a cada uno de ellos la configuraci\u00f3n que corresponda) que sean de aplicaci\u00f3n para el tipo de disposito gestionado.<\/li>\n<\/ul>\n<p>Una vez configurado el entorno, el recetario, las plantillas y par\u00e1metros, la configuraci\u00f3n qued\u00f3 lista para ser aplicada a los dispositivos. Las tareas de un recetario pueden ser ejecutadas de manera secuencial o en una sucesi\u00f3n espec\u00edfica, usando para ello las oportunas etiquetas. En mi entorno, y hasta el momento, he definido tres tipos de tareas:<\/p>\n<ul>\n<li><strong>Despliegue inicial:<\/strong> Realiza el despligue inicial de la configuraci\u00f3n a la pareja de vyattas para convertirlos en un cl\u00faster y realizar las configuraciones b\u00e1sicas de seguridad y gesti\u00f3n requeridas. En el entorno de demo, una vez realizada esta tarea, queda configurada la interfaz flotante en ambas subredes, realizado NAT y el enmascaramiento del tr\u00e1fico de la interfaz interna a la externa, y permitido el tr\u00e1fico ICMP entrante de la interfaz externa a la interna. Todo ello permite que el port\u00e1til haga ping al servidor, pero no pueda acceder a los servicios.<\/li>\n<li><strong>A\u00f1adir reglas:<\/strong> Esta tarea realiza un despliegue de pol\u00edtica a los cortafuegos. En concreto, permite el tr\u00e1fico por los puertos 22 y 80 TCP al servidor CirrOS.<\/li>\n<li><strong>Borrado de reglas:<\/strong> Permite eliminar las reglas anteriormente definidas<\/li>\n<\/ul>\n<p>Un ejemplo de ejecuci\u00f3n de Ansible para este entorno ser\u00eda el siguiente:<\/p>\n<p><code>i82hisaj@debian:~\/ansible\/vyos# ansible-playbook main.yml -t initial<\/p>\n<p>PLAY [all] ******************************************************************** <\/p>\n<p>GATHERING FACTS ***************************************************************<br \/>\nok: [192.168.122.252]<br \/>\nok: [192.168.122.253]<\/p>\n<p>TASK: [initial-config | upload script for configuring description] ************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [initial-config | run script for configuring description] ***************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [initial-config | debug var=desc_value.stdout_lines] ********************<br \/>\nok: [192.168.122.253] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<br \/>\nok: [192.168.122.252] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<\/p>\n<p>PLAY RECAP ********************************************************************<br \/>\n192.168.122.252            : ok=4    changed=2    unreachable=0    failed=0<br \/>\n192.168.122.253            : ok=4    changed=2    unreachable=0    failed=0   <\/p>\n<p>i82hisaj@debian:~\/ansible\/vyos# ansible-playbook main.yml -t add<\/p>\n<p>PLAY [all] ******************************************************************** <\/p>\n<p>GATHERING FACTS ***************************************************************<br \/>\nok: [192.168.122.253]<br \/>\nok: [192.168.122.252]<\/p>\n<p>TASK: [rules | retrieve Description for a firewall] ***************************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [rules | upload script for configuring description] *********************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [rules | run script for configuring description] ************************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [rules | debug var=desc_value.stdout_lines] *****************************<br \/>\nok: [192.168.122.252] => {<br \/>\n    \"desc_value.stdout_lines\": [<br \/>\n        \"Outside In\"<br \/>\n    ],<br \/>\n    \"item\": \"\"<br \/>\n}<br \/>\nok: [192.168.122.253] => {<br \/>\n    \"desc_value.stdout_lines\": [<br \/>\n        \"Outside In\"<br \/>\n    ],<br \/>\n    \"item\": \"\"<br \/>\n}<\/p>\n<p>PLAY RECAP ********************************************************************<br \/>\n192.168.122.252            : ok=5    changed=3    unreachable=0    failed=0<br \/>\n192.168.122.253            : ok=5    changed=3    unreachable=0    failed=0   <\/p>\n<p>i82hisaj@debian:~\/ansible\/vyos# ansible-playbook main.yml -t delete<\/p>\n<p>PLAY [all] ******************************************************************** <\/p>\n<p>GATHERING FACTS ***************************************************************<br \/>\nok: [192.168.122.252]<br \/>\nok: [192.168.122.253]<\/p>\n<p>TASK: [initial-config | debug var=desc_value.stdout_lines] ********************<br \/>\nok: [192.168.122.252] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<br \/>\nok: [192.168.122.253] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<\/p>\n<p>TASK: [rules | upload script for deleting rule] *******************************<br \/>\nchanged: [192.168.122.252]<br \/>\nchanged: [192.168.122.253]<\/p>\n<p>TASK: [rules | run script for configuring description] ************************<br \/>\nchanged: [192.168.122.253]<br \/>\nchanged: [192.168.122.252]<\/p>\n<p>TASK: [rules | debug var=desc_value.stdout_lines] *****************************<br \/>\nok: [192.168.122.253] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<br \/>\nok: [192.168.122.252] => {<br \/>\n    \"desc_value.stdout_lines\": \"{{ desc_value.stdout_lines }}\",<br \/>\n    \"item\": \"\"<br \/>\n}<\/p>\n<p>PLAY RECAP ********************************************************************<br \/>\n192.168.122.252            : ok=5    changed=2    unreachable=0    failed=0<br \/>\n192.168.122.253            : ok=5    changed=2    unreachable=0    failed=0<br \/>\n<\/code><\/p>\n<p>Algunas ideas hasta el momento:<\/p>\n<ul>\n<li>Desafortunadamente no existe ning\u00fan m\u00f3dulo oficial que permita hacer la administraci\u00f3n simplificada de cortafuegos vyatta, lo que significa que todo el trabajo de definir la automatizaci\u00f3n de tareas ha de realizarse desde cero, en base a scripts y configuraciones b\u00e1sicas de Ansible.<\/li>\n<li>Afortunadamente, el sistema de interacci\u00f3n de Ansible es lo suficientemente flexible para permitir la conversi\u00f3n sencilla de scripts previamente existentes a plantillas J2, lo que permite -en mi caso- aprovechar bastante trabajo previo ya existente.<\/li>\n<li>Existen interesantes posibilidades de conectar Ansible con sistemas de gesti\u00f3n v\u00eda web, como es el caso del proyecto <a href=\"http:\/\/code-complete.com\/code\/?p=40\" target=\"_blank\">Semaphore<\/a>.<\/li>\n<\/ul>\n<p>En resumen, si bien Ansible este caso requiere de bastante trabajo para poder realizar de manera efectiva la automatizaci\u00f3n del despliegue y gesti\u00f3n de cortafuegos (vyatta, en este caso), las ventajas que proporciona y el trabajo final que ahorra hacen que valga la pena. Como dir\u00eda nuestro amigo Barney, en este caso nos encontramos claramente por encima de la diagonal Vicky Mendoza:<\/p>\n<p><a href=\"http:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2015\/12\/vlcsnap-00012.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2015\/12\/vlcsnap-00012.jpg\" alt=\"\" title=\"Escala Hot-Crazy\" width=\"330\" height=\"283\" class=\"aligncenter size-full wp-image-3730\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Estas \u00faltimas jornadas he estado trabajando en un sistema de<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[13],"tags":[110,421,910,1767,1768],"series":[],"class_list":["post-3728","post","type-post","status-publish","format-standard","hentry","category-informatica","tag-ansible","tag-cirros","tag-kvm","tag-vyatta","tag-vyos"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/3728","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3728"}],"version-history":[{"count":0,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/3728\/revisions"}],"wp:attachment":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3728"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3728"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3728"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=3728"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}