JBoss CLi desde Ansible

JBoss CLi desde Ansible

Ejecutar comandos en JBoss Cli para modificar la configuración, agregar nueva funcionalidad, cambiar prioridades de los logs para encontrar problemas, o configurar un JBoss para una nueva aplicacion es una tarea muy facil, pero cuando se tienen varios cluster de servidores JBoss, varias instancias en un mismo servidor virtual, o crear containers de docker que se configure automaticamente para desplegar una aplicacion, la tarea con JBoss cli se vuelve un muy dificil.

Con la aparacicion de sistemas como chef y puppet esta tarea se vuelve un poco mas facil, pero ejecutar en estos entornos comandos JBoss-Cli es un poco complicado. Con la llegada de Ansible esto se volvio mas facil, el inconveniente es que hasta el momento no existe un modulo para conectarse a JBoss Cli y ejecutar comandos.
Cuando vi la necesidad de ejecutar comandos de JBoss Cli desde Ansible me di cuenta que los playbook y los comandos se volvian muy grandes y podian fallar y que era necesario crear un modulo, con esto en mente desarrolle un Modulo el cual pongo a su dispocicion para ejecutar comandos de JBoss Cli en ansible

El código lo pueden obtener desde mi repo en GitHub: https://github.com/Wolfant/ansible-jbossCli

El uso es muy facil primero debes clonar el repo, y copiar el archivo jbosscli.py en la carpeta de modulos de ansible comunmente en:

/usr/lib/python2.7/site-packages/ansible/modules/web_infrastructure

Con esto ya se puede empezar a usar el modulo desde PlayBooks o comandos simples

Ejemplo:

Para cambiar el intervalo del Deployement scaner:

- jboss:
    command: /subsystem=deployment-scanner/scanner=default:write-attribute(name=scan-interval,value=6000)
    cli_path: /home/user/wildfly-10.1.0.Final/bin

Si se tiene una clave generica para la autenticacion de JBoss CLi recomiendo configurar directamente en el codigo:


module = AnsibleModule(
argument_spec=dict(
src=dict(),
user=dict(default='USUARIO'),
password=dict(default='CONTRASEÑA'),
command=dict(),
cli_path=dict(default='/usr/share/wildfly/bin'),
server=dict(default='localhost:9990'),
verbose=dict(default="False"),
),
mutually_exclusive=[['command', 'src']],
)

Hardening RHEL – Tips

En todos los años de experiencia que tengo revisando servidores
RHEL/CentOs/Debian/Ubuntu muy pocas veces he visto que se tome el tiempo de asegurar los servidores,muchos administradores novatos se limitan a configurar el firewall e instalar el famoso y peligroso Webmin. ( una vez vi que alguien lo instalo y 3 horas después le toco formatear el servidor por culpa Black Hats chinos).

He recolectado las mejores practicas de Hardenin de Linux,
La mayoría son para RHEL/CentOs 6, muy pocos tiene RHEL/CentOs 7 así que lo voy a dejar de lado “for a while”

Voy a dividir este post en varios para no hacerlos tan largos.

Algo que muy pocos conocen, es el servicios Audit, audit es un sistema que
registra todo lo que haces y se hacen en el sistema operativo, es manejado por medio de reglas, por defecto el sistema no configura ninguna clase de regla.
Aquí expongo un set reglas, algunas son necesarias en el contexto del standar OpenSCAP [1]

Las siguientes reglas deben ir en: /etc/audit/audit.rules, son válidas para RHEL 6 de 64Bits

# Reglas Antonio Insuasti 2015 <antonio[at]insuasti.ec>
# Reglas basadas en SCAP

# audit_rules_exec
-w /etc/passwd -p wa -k passwd_changes
-w /etc/selinux/ -p wa -k selinux_changes
-w /usr/local/sbin -p x -k eject_commands
-w /usr/local/bin -p x -k eject_commands
-w /bin -p x -k eject_commands
-w /sbin -p x -k eject_commands
-w /usr/sbin -p x -k eject_commands
-w /usr/bin -p x -k eject_commands

# audit_rules_modules
-w /usr/sbin/insmod -p x -k modules
-w /usr/sbin/rmmod -p x -k modules
-w /usr/sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules
# audit_rules_time
-a always,exit -F arch=b64 -S adjtimex -k audit_time_rules
-a always,exit -F arch=b64 -S settimeofday -k audit_time_rules
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -S clock_settime -k audit_time_rules
-a always,exit -F arch=b64 -S clock_settime -k audit_time_rules
-w /etc/localtime -p wa -k audit_time_rules

# audit_rules_usergroup_modification
-w /etc/group -p wa -k audit_rules_usergroup_modification
-w /etc/passwd -p wa -k audit_rules_usergroup_modification
-w /etc/gshadow -p wa -k audit_rules_usergroup_modification
-w /etc/shadow -p wa -k audit_rules_usergroup_modification
-w /etc/security/opasswd -p wa -k audit_rules_usergroup_modification

# audit_rules_networkconfig_modification
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k audit_rules_networkconfig_modification
-w /etc/issue -p wa -k audit_rules_networkconfig_modification
-w /etc/issue.net -p wa -k audit_rules_networkconfig_modification
-w /etc/hosts -p wa -k audit_rules_networkconfig_modification
-w /etc/sysconfig/network -p wa -k audit_rules_networkconfig_modification
# audit_rules_access_control – RHEL 6
-a always,exit -F arch=b64 -F auid=0 -S unlink -S unlinkat -S rename -S renameat -k root_delete
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -k user_delete
-a always,exit -F arch=b64 -S chmod -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -k change_perms
-a always,exit -F arch=b64 -S chown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchmod -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchmodat -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fchownat -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S fsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lremovexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S lsetxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S removexattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S setxattr -F auid>=500 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 -F auid!=4294967295 -k access
-a always,exit -F arch=b64 -S creat -S open -S openat -S open_by_handle_at -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 -F auid!=4294967295 -k access
-a always,exit -F arch=b64 -S mount -F auid>=500 -F auid!=4294967295 -k export
-a always,exit -F arch=b64 -S rmdir -S unlink -S unlinkat -S rename -S renameat -F auid>=500 -F auid!=4294967295 -k delete
-w /etc/sudoers -p wa -k actions

# Audit para programas Jboss
# SETUID_PROG_PATH
#-a always,exit -F path=/home/jboss/jboss6/bin/ -F perm=x -F auid>=500 -F auid!=4294967295 -k eject_commands
##

Luego se debe reiniciar el servicio de auditd

$ service auditd restart

Para revisar que las reglas estén creadas podemos usar el comando:

$ auditctl -l

Ahora cada paso que se de en el sistema será registrado, uno de los problemas es que el archivo audit.log incrementa su tamaño muy rápido, y para eso hay dos configuraciones que debemos tomar en cuenta en el archivo /etc/audit/auditd.conf existen tres parámetros importantes:

num_logs = 5
max_log_file = 6
max_log_file_action = ROTATE

La primera es la cantidad de archivos de logs que se va a almacenar
la segunda es el tamaño máximo del archivo de log en megas
y la ultima es la acción que se va a tomar cuando llegue al máximo de tamaño.

Cuando estamos analizando logs importan 3 cosas:

  • Cantidad de archivos de log
  • Peso en MB de los archivos de log
  • Dispersión de datos

Más cantidad de archivos con menos espacio generan una mayor dispersión, esto hace que en contexto de audit buscar una fecha sea mucho mas complicado.
Dependiendo del nivel de historia que se requiera. Sugiero como mínimo almacenar 120MB de logs y/o 3 meses

num_logs = 12
max_log_file = 10
max_log_file_action = ROTATE
Comunmente

Comunmente en el Sysctl se deben agregar estas lineas, las cuales son recomendadas en OpenScap
# Antonio Insuasti 2015
# Basado en SCAP
fs.file-max = 4194304
kernel.exec-shield = 1
kernel.randomize_va_space = 2
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 26214400
net.core.somaxconn = 3000
net.core.wmem_max = 12582912
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_rmem = 10240 87380 12582912
net.ipv4.tcp_sack = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_wmem = 10240 87380 12582912

History

Muchas veces se necesita saber la fecha en la que se ingresan los comandos, esto se puede hacer de forma global con un archivo en /etc/profile.d/ , lo llamaremos history.sh ( se tiene que agregar permisos de ejecución) y poner solo esta línea:

export HISTTIMEFORMAT=”%d/%m/%y %T ”

Links:

[1] http://www.open-scap.org/
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sect-Using_SCAP_Workbench.html
https://fedorahosted.org/scap-workbench/

Blogs:
http://foxglovesecurity.com/
http://linux-audit.com/
https://securityblog.redhat.com/
http://www.cyberciti.biz/

Scripts para Zimbra

Recientemente en un cliente me toco migrar un servidor Centos 5 con Zimbra 6 a un Centos 7 Zimbra 8

La verdad el trabajo se realiza de una manera muy fácil con la utilización de Zextras[1]. El problema que tenia es que en el transcurso de 4 años el cliente tiene varias cuentas en estado “Cerrado” y otras que no se han autenticado por mas de un año, lo cual sugiere que se deben cerrar ya que pertenecen a ex empleados que ya no están laborando en la empresa.

Con el comando:

# zmaccts | grep closed | awk {‘print $1’} | cut -d@ -f1

se puede visualizar todos los usuarios que tienen el estado closed. El ultimo cut me da los usuarios pero si quieren ver todo el correo electrónico lo pueden eliminar.

La problemática es que se debía sacar el respaldo de estos usuarios, enviar el respaldo a un NFS, y al final borrar los usuarios para que no sean migrados, ya que el nuevo servidor no los debía tener.

Todos estos pasos los podía desarrollar en un solo script, pero el cliente me solicito que los haga en diferentes.

Por otro lado el cliente tenia un archivo de Microsoft Excel con una lista de 250 usuarios nuevos que debería ser creados después de la migración.

En este punto debo acotar que Zimbra OSE 6 me permite visualizar tan solo 5000 usuarios en la lista de GAL lo cual ya no me permitía ver por la interfaz gráfica los usuarios.

Los escripts desarrollados están publicados en mi cuenta de GitHub

Los nombres de los scripts son los siguientes:

Z6_BackCloseUsers.sh: Obtiene el respaldo de dos usuarios en estado “closed” y los enviá a un path donde se espera que este montado un nfs, o un espacio prudente para almacenamiento. El archivo de respaldo es el común de Zimbra el cual se obtiene al exportar la cuenta. Recibe dos parámetros el uno es el dominio de los usuarios y el segundo es el path

Z6_DeleteCloseUsers.sh: Borra los usuarios con estado “closed”. Recibe un unico parametro que es el dominio de los usuarios.

Zx_CreateUsers.sh: Crea los usuarios en Zimbra a partir de un archivo de texto que se lo pasa como parámetro y tiene el siguiente formato:

Nombre:Apellido:Correo:Constraseña

Dirección de GitHub: https://github.com/Wolfant/ZimbraOSE-Scripts

Instalacion de Jboss 6.2 en RHEL 7/CentOs 7

Con el reciente lanzamiento de  de RHEL 7, los manuales anteriores quedaron en la nada.

Muchas personas dicen que Jboss no se instala solo se descomprime, pero en verdad descomprimir jboss en /opt no es profesional ni es una buena practica para producción. Por lo que voy a escribir la forma correcta de instalarlo en RHEL7.

Antes de empezar voy a decir dos diferencias sustanciales que puede demorarnos en la instalación, primero RHEL 7 viene con firewallD [1]  por lo que iptables no nos va a servir para abrir los puertos necesarios, y para crear el servicio de inicio de Jboss ya no se usa los init scripts de sysV, ahora RHEL es un sistema basado en systemd [2] por lo que se debe usar systemctl y no el clásico comando service

Pues bien empecemos con la instalación:

Recuerde que debe tener instaldo Oracle JDK o el OpenJdk para que jboss funcione.

Primero debemos crear el usuario jboss

# adduser -r jboss
# mkdir /home/jboss
# chown -R jboss:jboss /home/jboss

Con estos comandos creamos un usuario del sistema con nombre jboss y creamos el home que el entrega. Para algunos war me ha dado problema que el usuario jboss no tenga home, un ejemplo de esto es el war de jenkins [3]

ahora debemos descomprimir el jar o el zip de Jboss en la carpeta donde debe ir,  se recomienda que este en /usr/share/jboss

# unzip jboss-eap-6.2.0.zip -d /usr/share/
# mv jboss-eap-6.2 jboss-as
# chown -R jboss:jboss jboss-as

Creamos la carpeta donde va a residir los archivos de configuración, copiamos el archivo de configuración que viene con el zip, damos permisos al usuario.

# mkdir /etc/jboss-as
# cp /usr/share/jboss-as/bin/init.d/jboss-as.conf /etc/jboss-as/
# chown -R jboss:jboss /etc/jboss-as/

El archivo de configuración por defecto viene completamente comentado, quitamos el comentario de las lineas:

JBOSS_USER=jboss
STARTUP_WAIT=30
SHUTDOWN_WAIT=30
JBOSS_CONSOLE_LOG=/var/log/jboss-as/console.log

Notese que el usuario es jboss no jboss-as

Ahora debemos crear el directorio para el pid y para el log

# mkdir -p /var/log/jboss-as/
# chown -R jboss:jboss /var/log/jboss-as/
# mkdir -p /var/run/jboss-as/
# chown -R jboss:jboss /var/run/jboss-as/

Ahora debemos crear el servicio systemd para iniciarlo.  Los servicios en systemd se alojan en dos lugares el principal o de mas precedencia  es: /etc/systemd/system/  Comúnmente los archivos en este directorio son links simbólicos del segundo directorio, el cual es: /lib/systemd/system/

Como es un archivo nuevo lo agrego en /etc/systemd/system/ y lo guardo con el nombre jboss.service

# vim /etc/systemd/system/jboss.service

# Systemd unit file for Jboss
#
# Wolfant Example

[Unit]
Description=Jboss Application Server
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/usr/share/jboss-as/bin/init.d/jboss-as-standalone.sh start
ExecStop=/usr/share/jboss-as/bin/init.d/jboss-as-standalone.sh stop
PIDFile=/var/run/jboss-as/jboss-as-standalone.pid

[Install]
WantedBy=multi-user.target

Después de crear el archivo debemos reiniciar el servicio de systemd

# systemctl daemon-reload

y por ultimo probar iniciar, detener y revisar el estado del nuevo servicio.

# systemctl start jboss.service
# systemctl status jboss.service
# systemctl stop jboss.service

Para que Jboss funcione los puertos que debemos abrir dependiendo de la configuración de nuestro Jboss son:

  • 80/TCP
  • 443/TCP
  • 8080/TCP

Opcional (No recomendado si esta conectado directo al Internet):

  • 9990/TCP
  • 9999/TCP

Estos puertos se abren en firewallD con los siguientes comandos:

# firewall-cmd --permanent --zone=public --add-port=8080/tcp

# firewall-cmd --permanent --zone=public --add-service=https

# firewall-cmd --permanent --zone=public --add-service=http

# firewall-cmd --permanent --zone=public --add-port=9990/tcp

# firewall-cmd --permanent --zone=public --add-port=9999/tcp

# systemctl restart firewalld.service

Si deseamos revisar si restan los puertos abiertos usamos:

firewall-cmd --permanent --zone=public --list-all
Referencias:
[1]https://fedoraproject.org/wiki/FirewallD

[2]http://0pointer.de/blog/projects/systemd-for-admins-3.html

https://fedoraproject.org/wiki/Systemd/es#.C2.BFC.C3.B3mo_personalizar_un_archivo_unidad_o_agregar_uno_personalizado.3F

 [3] http://jenkins-ci.org/

Cluster MySql ( Cluster Circular Master-Master)

Para realizar  se debe configurar el archivo /etc/my.cnf con los siguientes datos.

Servidor A:
/etc/my.cnf
server-id=1
log-bin = mysql-bin
sync_binlog                        = 1
max-binlog-size                  = 500M
expire_logs_days                = 4
innodb_flush_log_at_trx_commit  = 1
relay-log                   = mysqld-relay-bin
max-relay-log-size   = 500M
relay_log_purge       = 1
symbolic-links=0

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
Servidor B:
/etc/my.cnf
server-id=2
 log-bin = mysql-bin
 sync_binlog                        = 1
 max-binlog-size                  = 500M
 expire_logs_days                = 4
 innodb_flush_log_at_trx_commit  = 1
 relay-log                   = mysqld-relay-bin
 max-relay-log-size   = 500M
 relay_log_purge       = 1
 symbolic-links=0
[mysqld_safe]
 log-error=/var/log/mysqld.log
 pid-file=/var/run/mysqld/mysqld.pid

En los dos servidores se debe crear un usuario para la replicación, esto se realiza en el cli de mysql. Se realiza con los siguientes comandos:

# mysql -u root -p
 mysql>
 mysql> grant replication slave, replication client on *.* to 'replication'@'%' identified by 'Master20';
mysql> FLUSH PRIVILEGES;
mysql> show grants for replication@"%";

Se debe saber la direccion del archivo binario y la posición en la que se encuentra el puntero. esto se debe teneren cuenta en los dos servidores

mysql> SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73       | test         | manual,mysql     |
+---------------+----------+--------------+------------------+

En el ejemplo el archivo binario es mysql-bin.003 y esta en la posición 73.

Con la información del archivo binario y la posición del servidor A se ejecuta la edición en el servidor B, se debe parar el sistema de esclavo, la sentencia es la siguiente.

mysql>slave stop;
mysql> CHANGE MASTER TO MASTER_HOST='{IP_SERVIDOR_A}',MASTER_USER='replication', MASTER_PASSWORD='Master20', MASTER_LOG_FILE='{Binary_Log}', MASTER_LOG_POS=  {Binary_Position};
mysql> slave start;

En el caso del ejemplo nos da:

mysql>slave stop;
mysql> CHANGE MASTER TO MASTER_HOST='{IP_SERVIDOR_A}',MASTER_USER='replication', MASTER_PASSWORD='Master20', MASTER_LOG_FILE='mysql-bin.003', MASTER_LOG_POS=  73;
mysql> slave start;

Luego de realizar este cambio se debe revisar los tiempos de sincronización con la sentencia:

mysql> show slave status\G

Creacion de servidor SysLog

Para crear un servidor de logs se utiliza rsyslog. Rsyslog permite tener un servidor de logs multi plataforma escalable y estable.

En RHEL 6.x/ CentOs 6.x viene instalado por defecto para versiones anteriores se debe instalar con el comando:

yum install rsyslog

Para versiones basadas en Debian se puede utilizar:

apt-get install rsyslog

La configuración de rsyslog se la realiza en el archivo /etc/rsyslog

Para configurar como servidor externo se debe descomentar las lineas de uso del módulo TCP y UDP:

#### MODULES ####
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imklog # provides kernel logging support (previously done by rklogd)
#$ModLoad immark # provides --MARK-- message capability
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
#######

Se debe iniciar el servicio con el comando:

# service rsyslog restart

Con esta configuración, el servidor escucha en el puerto 514 tanto en TCP como en UDP.  Para abrir el firewall en este puerto se usa las siguientes lineas en el archivo

/etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 514 -j ACCEPT
-A INPUT -m udp -p udp --dport 514 -j ACCEPT

Estas líneas deben estar antes de las reglas REJECT.