Request Tracker es una muy buena herramienta que se puede adaptar a nuestras necesidades, pero su configuración básica (como viene con la instalación) requiere bastante trabajo para adaptarlo a cada realidad y la documentación disponible no es muy buena y es en muchos casos para versiones antiguas. En este tutorial voy a partir con la instalación y luego continuaré realizando varias personalizaciones para lograr una integración con la herramienta de monitoreo Prometheus (prometheus.io) a modo de ejemplo.
La versión 4.4 aún no es liberada en su versión estable, por lo que este tutorial está hecho con la versión RC2.
https://www.bestpractical.com/docs/rt/4.4/README.html
Los siguientes pasos fueron probados en Ubuntu 14.04
Instalación
Requisitos
Instalar los siguientes paquetes:
apt-get install -y perl mariadb-server apache2 libapache2-mod-fastcgi liblwp-protocol-https-perl libcrypt-ssleay-perl libxml-rss-perl libperlio-eol-perl libfile-which-perl libgnupg-interface-perl libconvert-color-perl libfcgi-procmanager-perl libfcgi-perl libmime-types-perl libcss-squish-perl libnet-cidr-perl libmodule-refresh-perl libdata-guid-perl libjson-perl libemail-address-list-perl libplack-perl libencode-perl libdata-ical-perl libdevel-globaldestruction-perl libtext-password-pronounceable-perl libhtml-formattext-withlinks-perl libtext-wrapper-perl libregexp-ipv6-perl libcrypt-x509-perl libstring-shellquote-perl libdatetime-format-natural-perl libcrypt-eksblowfish-perl libdate-manip-perl liblocale-maketext-fuzzy-perl libhtml-formattext-withlinks-andtables-perl libtext-template-perl libhtml-scrubber-perl libencode-perl libdbix-searchbuilder-perl liblocale-maketext-lexicon-perl libtext-wikiformat-perl liblog-dispatch-perl libapache-session-perl libtree-simple-perl librole-basic-perl libipc-run3-perl libcgi-psgi-perl libhtml-mason-perl libhtml-quoted-perl libuniversal-require-perl libregexp-common-net-cidr-perl libhtml-mason-psgihandler-perl libregexp-common-perl libmodule-versions-report-perl libhtml-quoted-perl libdate-extract-perl libsymbol-global-name-perl libtext-quoted-perl libgd-graph-perl libgd-text-perl libnet-ldap-perl libnet-ldap-server-perl graphviz libgraphviz-perl libscope-upper-perl libipc-run-perl libdata-pageset-perl libjavascript-minifier-xs-perl libencode-perl libhtml-rewriteattributes-perl libcss-minifier-xs-perl sendmail
Espacio mínimo en disco:
200MB en /opt
Instalación
Por ahora está disponible el Release Candidate 2:
wget https://download.bestpractical.com/pub/rt/devel/rt-4.4.0rc2.tar.gz
tar -zxvf rt-4.4.0rc2.tar.gz
cd rt-4.4.0rc2/
./configure --enable-graphviz --enable-gd
/usr/bin/perl -MCPAN -e shell
make fixdeps
make install
Configuración inicial
/opt/rt4/sbin/rt-server --port 8080
Navegar a la página y seguir instrucciones. Asumiendo que nuestro servidor de instalación se llama rt.example.com, navegamos a http://rt.example.com:8080
Al finalizar la configuración, damos ctrl-C al comando para terminar el servidor. Ahora lo vamos a configurar para subir con apache.
Configurar apache
Creamos un archivo con la configuración del sitio:
> cat /etc/apache2/sites-available/001-rt4.conf
# Tell FastCGI to put its temporary files somewhere sane; this may
# be necessary if your distribution doesn't already set it
#FastCgiIpcDir /tmp
FastCgiServer /opt/rt4/sbin/rt-server.fcgi -processes 5 -idle-timeout 300
<VirtualHost rt.lagos.cl>
### Optional apache logs for RT
# Ensure that your log rotation scripts know about these files
ErrorLog /opt/rt4/var/log/apache2.error
TransferLog /opt/rt4/var/log/apache2.access
LogLevel debug
AddDefaultCharset UTF-8
ScriptAlias / /opt/rt4/sbin/rt-server.fcgi/
DocumentRoot "/opt/rt4/share/html"
<Location />
Require all granted
Options +ExecCGI
AddHandler fastcgi-script fcgi
</Location>
</VirtualHost>
Ahora reemplazamos el sitio por defecto que viene con la instalación de apache por RT4:
cd /etc/apache2/sites-enabled
rm 000-default.conf
ln -s ../sites-available/001-rt4.conf
service apache2 restart
Configurar correo
Para configurar sendmail, editar en archivo /etc/mail/sendmail.mc las líneas:
DAEMON_OPTIONS(`Family=inet, Name=MTA-v4, Port=smtp')dnl
define(`confCONNECTION_RATE_THROTTLE', `-1')dnl
y eliminar línea:
define(`confCONNECTION_RATE_WINDOW_SIZE',`10m')dnl
Luego ejecutar:
m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
En archivo /etc/aliases agregar:
<casilla correspondencia>: "|/opt/rt4/bin/rt-mailgate --queue <cola> --action correspond --url <ubicación de rt>"
<casilla comentarios>: "|/opt/rt4/bin/rt-mailgate --queue <cola> --action comment --url <ubicación de rt>"
Por ejemplo:
rt: "|/opt/rt4/bin/rt-mailgate --queue 'Reportes de Incidente' --action correspond --url http://rt.example.com/"
rt-comment: "|/opt/rt4/bin/rt-mailgate --queue 'Reportes de Incidente' --action comment --url http://rt.example.com/"
rtinc: "|/opt/rt4/bin/rt-mailgate --queue 'Incidentes' --action correspond --url http://rt.example.com/"
rtinc-com: "|/opt/rt4/bin/rt-mailgate --queue 'Incidentes' --action comment --url http://rt.example.com/"
Y reiniciar sendmail:
service sendmail restart
En el ejemplo anterior, los usuarios se comunican con rt a la casilla rt@rt.example.com y los comentarios privados del personal se envían a rt-comment@rt.example.com
Extensiones
Instalar la siguiente extensión siguiendo sus instrucciones de instalación:
- RT::Extension::ExtractCustomFieldValues
En CPAN hay muchas extensiones para Request Tracker. Estas son algunas de las que encuentro más interesantes, pero no es necesario instalar para este tutorial:
- Nagios (usar como referencia):
- RT-Extension-ActivityReports:
- https://metacpan.org/pod/RT::Extension::ActivityReports
- (Ojo, prerequisito: Time::Duration. Instalar: > cpan Time::Duration)
- RT-Extension-Announce
- RT::Extension::PreviewInSearch
- RT::Extension::PriorityAsString
- RT::Extension::QuickUpdate
- RT::Extension::RepeatTicket
- RT::Extension::ResetPassword
Configuración
Usuarios
Para efectos de este tutorial, crear los siguientes usuarios (Admin -> Users -> Create) y a todos ,menos a "user", activarles la casilla "Let this user be granted rights (Privileged)". Todos deben tener activada la casilla "Let this user access RT".
- agent: Service Desk Analyst
- resolutor: First/second/third line analyst
- manager: Service Desk Manager (no necesario crear de inmediato)
- user: Usuario de los servicios TI
- mon: usuario creado para que el monitoreo gestione sus tickets
Grupos
Crear los siguientes grupos y asignarles los usuarios correspondientes:
- ServiceDeskManager (no necesario crear de inmediato)
- manager
- ServiceDeskAnalyst
- agent
- IncidentAnalyst
- resolutor
- mon
Escenario 2
Usando como base el post anterior, los pasos para configurar Request Tracker para que cumpla con el escenario 2 son:
- Renombrar cola General a “Reportes de Incidente”
- Crear cola “Incidentes”
- Otorgar los siguientes permisos al grupo Everyone en cola “Reporte de Incidente”:
- Comment on Ticket
- Create Tickets
- Reply to Tickets
- View Queue
- Otorgar el siguiente permiso al grupo Requestor:
- View Ticket Summaries
- Otorgar los siguientes permisos al grupo ServiceDeskAnalyst en colas Incidentes y Reportes de Incidente y a IncidentAnalyst en cola Incidentes:
- Comment on Ticket
- Create Tickets
- Reply to Tickets
- View Queue
- View Ticket Summaries
- View Ticket Private Commentary
- View custom field values
- Sign up as a ticket Requestor or ticket or queue Cc
- Sign up as a ticket or queue AdminCc
- Own Tickets
- Modify Tickets
- Crear los siguientes campos custom en cola Incidentes (adaptar según preferencias):
- Descripción (Fill in one text area)
- Categoría (Select one value)
- Monitoreo
- Backups
- Servidor
- Red
- Storage
- Base de Datos
- Servicio de Directorio
- Microinformática
- Middleware
- Internet
- Data Center
- Urgencia (Select one value)
- Alta
- Media
- Baja
- Impacto (Select one value)
- Alto
- Medio
- Bajo
- Reportado por (Enter one value)
- Método de notificación (Select one value)
- Teléfono
- Autoatención
- Automático
- Agregar permisos para ver y modificar los campos custom al grupo ServiceDeskAnalyst y al rol Owner
- Asignar scrip “On Resolve, Resolve Children” a cola Incidentes (ver detalle de scrip en sección correspondiente más abajo).
Ahora "resolutor" ve el ticket en la cola Incidente, por lo que puede trabajar en su solución y cerrarlo. Al resolver el Incidente, entra en acción el scrip asignado cerrando todos los tickets de la cola "Reportes de Incidente" y notificando a los usuarios de su cierre.
Escenario 4
Me saltaré el escenario 3, pasando directamente al escenario 4. Para efectos del tutorial, usaré Prometheus como sistema de monitoreo, pero evitaré extenderme en la explicación del uso de Prometheus, ya que queda fuera del alcance de este tutorial.
En la sección de configuración del correo, se definieron 4 alias: rt, rt-comment, rtinc y rtinc-com.
La primera casilla es para ser usada por los usuarios: ellos envían correos a esa casilla para abrir y hacer seguimiento de tickets (cuando responden a un correo con el subject del correo recibido de confirmación de creación de ticket, el correo se suma al ticket como comentario). La segunda y cuarta casillas son para comentarios internos del staff del Service Desk. Lo que llegue por esa casilla quedará registrado en Request Tracker, pero no será visible por el usuario final. La tercera casilla, es para recibir los correos del monitoreo, los que gatillarán automáticamente la generación de un ticket en la cola "Incidentes", saltándose el paso de crear un ticket en "Reportes de Incidente".
Tomando como base lo que ya hicimos para el escenario 2:
- Modificar en RT la configuración de la cola Incidentes para que las direcciones “Reply Address” y “Comment Address” apunten a rtinc@rt.example.com y rtinc-com@rt.example.com)
- Se debe configurar un scrip en la cola Incidentes que cierre los tickets al recibir un ok desde Pometheus. Ver Scrip “Update Prometheus Tickets” (este scrip adicionalmente une los tickets duplicados).
Por el lado de Prometheus:
- En este ejemplo se usó la siguiente configuración en prometheus, donde se aprovechó la integración con consul para service discovery:
- Para las reglas en prometheus:
ALERT LowDiskSpace
SUMMARY "Service Alert: {{$labels.instance}}/Filesystem {{$labels.mountpoint}} is WARNING"
DESCRIPTION "Descripción: El filesystem {{$labels.mountpoint}} del nodo {{$labels.instance}} se esta quedando sin espacio (espacio libre: {{$value}}%)&Categoría: Servidor&Urgencia: Baja&Impacto: Bajo&Reportado por: monitoreo&Método de notificación: Automático"
- Usar la siguiente configuración para alertmanager (esto es para versión v0.0.4 que al parecer será deprecada pronto):
> cat alertmanager.conf
notification_config {
name: "node_notification"
email_config {
email: "rtinc@rt.example.com"
send_resolved: true
}
}
aggregation_rule {
repeat_rate_seconds: 3600
notification_config_name: "node_notification"
}
- Yo tengo el Alert Manager corriendo en un container docker:
- run -d -p 9093:9093 --name prom_alert2 -v /docker/prometheus/config/alertmanager.conf:/alertmanager.conf prom/alertmanager -config.file=/alertmanager.conf -notification.smtp.smarthost=mail.example.com:25 -alerts.min-refresh-period=0m30s -notification.smtp.sender=mon@example.com
Con esta configuración, si un nodo monitoreado por Prometheus gatilla una alarma de espacio en disco, se generará automáticamente un ticket en la cola "Incidentes". Si un usuario reporta un incidente relacionado al llenado de ese disco, el agente asociará el ticket de la cola Incidente creado por Prometheus como padre del ticket de Reporte de Incidente. El resolutor verá el ticket creado por Prometheus y trabajará en su solución. Una vez que se limpie la alarma, Prometheus enviará un correo indicando que la alerta está resuelta. Esto provocará en Request Tracker que se creé un nuevo ticket y se gatille el scrip "Update Prometheus Tickets". Este scrip buscará todos los tickets asociados a esa alerta y los unirá para posteriormente cerrar el ticket. Al resolver el ticket, se resolverán también todos los tickets hijos (Reportes de Incidente).
Escenario 5
Para no seguir alargando el tutorial, solo haré una parte del escenario 5: extraer datos para la generación del ticket desde el contenido del correo de alerta de Prometheus. Para ello usaré la extensión RT::Extension::ExtractCustomFieldValues.
- Crear el siguiente template:
Name: PrometheusFieldScanner
Description: Busca Custom Fields en los correos de Prometheus
Type: Perl
Content:
Descripción|Body|Descripción:\s+([^&]+)
Categoría|Body|Categoría:\s+([^&]+)
Urgencia|Body|Urgencia:\s+([^&]+)
Impacto|Body|Impacto:\s+([^&]+)
Reportado por|Body|Reportado por:\s+([^&]+)
Método de notificación|Body|Método de notificación:\s+([^\n]+)
- Crear el siguiente scrip en cola Incidente (o donde lleguen los correos de Prometheus):
Description: Prometheus Field Scanner
Condition: On Create
Action: Extract Custom Field Values With Code in Template
Template: PrometheusFieldScanner
Y eso es todo. Ahora Request Tracker llenará automáticamente los campos custom con la información que extraiga del correo recibido desde Prometheus.
Scrips
Name: On Resolve, Resolve Children
Condition: On Resolve
Action: User Defined
Template: blank
Custom Condition: “”
Custom action preparation code:
return 1;
Custom action commit code:
my $ticket = $self->TicketObj;
my $id = $ticket->Id;
my $members = RT::Tickets->new( $ticket->CurrentUser );
$members->LimitQueue(VALUE => 'Reportes de Incidente');
$members->LimitToActiveStatus();
$members->LimitLinkedTo(TYPE => 'MemberOf', TARGET => $ticket->id);
while ( my $member = $members->Next ) {
my $set_to = "resolved";
next if $member->Status eq $set_to;
my ($res, $msg) = $member->SetStatus( $set_to );
RT->Logger->info( "Couldn't resolve ticket: $msg" ) unless $res;
}
return 1;
Name: Update Prometheus Tickets
Condition: On Create
Action: User Defined
Template: blank
Custom Condition: “”
Custom action preparation code:
return 1;
Custom action commit code:
$RT::Logger->info("Update Prometheus Tickets: Inicio scrip");
my $attachment = $self->TransactionObj->Attachments->First;
return 1 unless $attachment;
my $new_ticket = $self->TicketObj;
my $new_ticket_id = $new_ticket->id;
my $subject = $attachment->GetHeader('Subject');
return unless $subject;
if ( my ( $type, $category, $host, $port, $problem_type, $problem_severity ) =
$subject =~ m{\[(ALERT|RESOLVED)\]
\s+ ([^:]+):
\s+Service\s+Alert:
\s+([^/:]+):(\d+)/?(.*)
\s+ is \s+(\w+)}ix
)
{
$RT::Logger->info(
"Extracted type, category, host, problem_type and problem_severity from
subject with values $type, $category, $host, $problem_type and $problem_severity"
);
my $tickets = RT::Tickets->new( $self->CurrentUser );
$tickets->LimitQueue( VALUE => $new_ticket->Queue );
my $subject = "$category: Service Alert: $host:$port/$problem_type";
$tickets->LimitSubject(
VALUE => $subject,
OPERATOR => 'LIKE',
);
my @active = RT::Queue->ActiveStatusArray();
for my $active (@active) {
$tickets->LimitStatus(
VALUE => $active,
OPERATOR => '=',
);
}
my $resolved = 'resolved';
my $merge_type = -1;
my $merged_ticket;
$tickets->OrderBy(
FIELD => 'Created',
ORDER => $merge_type > 0 ? 'DESC' : 'ASC',
);
$merged_ticket = $tickets->Next;
while ( my $ticket = $tickets->Next ) {
$RT::Logger->info("Update Prometheus Tickets: Voy a unir los tickets " . $ticket->id . " y " . $merged_ticket->id);
my ( $ret, $msg ) = $ticket->MergeInto( $merged_ticket->id );
if ( !$ret ) {
$RT::Logger->error( 'failed to merge ticket '
. $ticket->id
. " into "
. $merged_ticket->id
. ": $msg" );
}
}
if ( uc $type eq 'RESOLVED' ) {
if ( not $merged_ticket or not $merged_ticket->id ) {
$RT::Logger->error( 'Recovery ticket with no initial ticket: $subject' );
$merged_ticket = $new_ticket;
}
$RT::Logger->info("Update Prometheus Tickets: Voy a cerrar el ticket " . $merged_ticket->id);
my ( $ret, $msg ) = $merged_ticket->SetStatus($resolved);
if ( !$ret ) {
$RT::Logger->error( 'failed to resolve ticket '
. $merged_ticket->id
. ":$msg" );
}
}
}
return 1;
PD
Maldito Blogger. No logro dar buen formato a los posts