[Rtir] Scripted Action: Variable substitution in RTIR Templates?

Gorazd Bozic gorazd.bozic at arnes.si
Thu Mar 25 08:43:54 EST 2004


Well, here I go again... :-)

Gorazd Bozic wrote:

> Another solution (easier to implement) would be to add a Scripted Action
> with attachment. The attachment name supplied in RTIR would include
> either _ADDR_ or _IP_. This would get replaced before the file is
> attached...

I have modified ScriptedAction.html now to accomodate SI-CERT needs. The
diffs are attached. I have done some testing and I believe that it works
as planned. Here is a list of modifications that I did:

1. The HTML form part used to supply a list of email addresses/IPs
   always included the person's signature (default behaviour of RT's
   MessageBox); adding IncludeSignature => 0 when calling MessageBox
   corrected this.

2. One major bug that I found was that the content of the template was
   not properly processed for substitutions of _ADDR_ and/or _IP_
   placeholders. Also, if the Subject contained _ADDR_ or _IP_, they
   were replaced only the first time, since the replacement was done
   directly to $ARGS{'Subject'}. Because of that I have added a copy
   of %ARGS named %TARGS, which is declared inside the loop of
   emails/IPs processed, so you don't have to worry about modifying
   "global" %ARGS.

3. If a template was supplied but no manually typed message at the
   bottom of the form existed, the mail that was sent out contained an
   empty text/plain part and only then the text of the template.
   Modified ScriptedAction.html now checks for existance of this message
   and inserts it as the first text/plain part, otherwise the template
   text becomes the first part of the MIME message.

4. The form now has another field, labeled "Attach files:". In this
   field you enter the location of file(s) on the host running your
   copy of RTIR. The filename can include _IP_ and _ADDR_ strings
   (which is the whole point of it). Before the file is attached to
   the transaction, those strings are replaced and only then the
   relevant file is attached. This enables you to attach files with
   logs/netflow data that pertains to a particular host/net only. If
   you wish to report (=open investigations) to contacts of
   10.1.2.0 and 10.2.3.0, you can copy files log-10.1.2.0.txt and
   log-10.2.3.0.txt to the RTIR (let's say to /tmp) and supply the
   filename pattern /tmp/log-_IP_.txt in this field.

5. This version includes the earlier modification allowing you to
   explicitly name the incident number you want all these investigations
   linked to (as opposed to each investigation also having a unique
   parent incident).

I hope someone else will find this useful. I have tested it, but you (of
course) use it at your own risk.

Gorazd

-- 
Gorazd Bozic <gorazd.bozic at arnes.si>
ARNES SI-CERT, Jamova 39 p.p. 7, SI-1001 Ljubljana, Slovenia
tel: +386 1 479 88 22, fax: +386 1 479 88 99
-------------- next part --------------
--- share/html/RTIR/Tools/ScriptedAction.html	Mon Mar 15 09:14:50 2004
+++ local/html/RTIR/Tools/ScriptedAction.html	Thu Mar 25 13:16:10 2004
@@ -90,9 +90,9 @@
     </TD>
     <TD COLSPAN=5>
 % if (exists $ARGS{IPs}) {
-      <& /Elements/MessageBox, Name=>"IPs", Width => 30, Default=>$ARGS{IPs}, %ARGS&>
+      <& /Elements/MessageBox, Name=>"IPs", Width => 30, IncludeSignature => 0, Default=>$ARGS{IPs}, %ARGS&>
 % } else {
-      <& /Elements/MessageBox, Name=> 'IPs', Width => 30 &>
+      <& /Elements/MessageBox, Name=> 'IPs', Width => 30, IncludeSignature => 0 &>
 % }
     </TD>
   </TR>
@@ -103,15 +103,35 @@
     </TD>
     <TD COLSPAN=5>
 % if (exists $ARGS{Addresses}) {
-      <& /Elements/MessageBox, Name=>"Addresses", Width => 30, Default=>$ARGS{Addresses}, %ARGS&>
+      <& /Elements/MessageBox, Name=>"Addresses", Width => 30, IncludeSignature => 0, Default=>$ARGS{Addresses}, %ARGS&>
 % } else {
-      <& /Elements/MessageBox, Name=> 'Addresses', Width => 30 &>
+      <& /Elements/MessageBox, Name=> 'Addresses', Width => 30, IncludeSignature => 0 &>
 % }
     </TD>
   </TR>
 % }
 <TR>
   <TD class=label>
+    <&|/l&>Link to incident</&>:
+  </TD>
+  <TD>
+    <INPUT Name="incident_no" SIZE=6 Value="<% $ARGS{'incident_no'} %>">
+  </TD>
+</TR>
+<TR>
+  <TD class=label>
+    <&|/l&>Attach files</&>:
+  </TD>
+  <TD>
+    <INPUT Name="attach_tmpl" SIZE=30 Value="<% $ARGS{'attach_tmpl'} %>"><br>
+    <span class="label">Specify file pattern to attach to each message. Can
+    include _IP_ or _ADDR_ in filename which will be replaced by an appropriate
+    walue before being attached. Files must exist on the system running RTIR.
+    </span>
+  </TD>
+</TR>
+<TR>
+  <TD class=label>
     <&|/l&>Template</&>:
   </TD>
   <TD>
@@ -260,14 +280,17 @@
 } else {
 
 foreach my $key (keys %$addrhash) {
+  # For each recipient, create a copy of %ARGS hash, otherwise we have
+  # problems with replacements of _ADDR_ and _IP_.
+  my %TARGS = %ARGS;
   my $addr = $addrhash->{$key}->{'Address'};
   my $ip = $addrhash->{$key}->{'IP'};
-  if ((!exists $ARGS{'AddMoreAttach'}) && 
-      ($ARGS{'id'} eq 'new')) { # new ticket?
+  if ((!exists $TARGS{'AddMoreAttach'}) && 
+      ($TARGS{'id'} eq 'new')) { # new ticket?
     # {{{ Create a new ticket
     
   # {{{ deal with deleting uploaded attachments
-  foreach my $key (keys %ARGS) {
+  foreach my $key (keys %TARGS) {
     if ($key =~ m/^DeleteAttach-(.+)$/) {
 	delete $session{'Attachments'}{$1};
     }
@@ -275,25 +298,24 @@
   }
 
   # {{{ store the uploaded attachment in session
-  if ($ARGS{'Attach'}) {			# attachment?
+  if ($TARGS{'Attach'}) {			# attachment?
     $session{'Attachments'} = {} unless defined $session{'Attachments'};
 
     # strip leading directories
-    $ARGS{'Attach'} =~ s#^.*[\\/]##;
-
+    $TARGS{'Attach'} =~ s#^.*[\\/]##;
 
     my $attachment = MakeMIMEEntity(
-        Subject             => "$ARGS{'Attach'}",
+        Subject             => "$TARGS{'Attach'}",
         Body                => "",
         AttachmentFieldName => 'Attach'
     );
     $session{'Attachments'} = { %{$session{'Attachments'} || {}},
-				$ARGS{'Attach'} => $attachment };
+				$TARGS{'Attach'} => $attachment };
   }
 # }}}
 
   # delete temporary storage entry to make WebUI clean
-  unless (keys %{$session{'Attachments'}} and $ARGS{'id'} eq 'new') {
+  unless (keys %{$session{'Attachments'}} and $TARGS{'id'} eq 'new') {
     delete $session{'Attachments'};
   }
 
@@ -302,20 +324,34 @@
 
   # if the subject contains _ADDR_ or _IP_
   # substitute appropriately
-  $ARGS{'Subject'} =~ s/_ADDR_/$addr/g;
-  $ARGS{'Subject'} =~ s/_IP_/$ip/g;
+  $TARGS{'Subject'} =~ s/_ADDR_/$addr/g;
+  $TARGS{'Subject'} =~ s/_IP_/$ip/g;
 
   if ($addr ne loc("ADDRESS_UNKNOWN")) {
-    # create the Incident
-    unless ($incidentq->CurrentUserHasRight('CreateTicket')) {
-	Abort('You have no permission to create tickets in that queue.');
-    }
-    $ARGS{'Queue'} = $incidentq->Id;
 
-    ($Incident, @IncidentActions) =
-       CreateTicket(Attachments => $session{'Attachments'}, %ARGS);
-    unless ($Incident->CurrentUserHasRight('ShowTicket')) {
-      Abort("No permission to view newly created ticket #".$Incident->id.".");
+    $TARGS{'Queue'} = $incidentq->Id;
+
+    if ($TARGS{'incident_no'}) {
+        # Ticket number of Incident supplied, try to load
+        $Incident = new RT::Ticket($session{'CurrentUser'});
+	my $ticket_no = $Incident->Load($TARGS{'incident_no'});
+        unless ($ticket_no) {
+            Abort('Ticket '.$TARGS{'incident_no'}.' does not exist.');
+        }
+        unless ($Incident->QueueObj->Id == $incidentq->Id) {
+            Abort('Ticket '.$TARGS{'incident_no'}.' is not an Incident');
+        }
+    } else {
+        # create the Incident
+        unless ($incidentq->CurrentUserHasRight('CreateTicket')) {
+	    Abort('You have no permission to create tickets in that queue.');
+        }
+
+        ($Incident, @IncidentActions) =
+           CreateTicket(Attachments => $session{'Attachments'}, %TARGS);
+        unless ($Incident->CurrentUserHasRight('ShowTicket')) {
+          Abort("No permission to view newly created ticket #".$Incident->id.".");
+        }
     }
     # }}}
 
@@ -323,21 +359,22 @@
     unless ($investigationq->CurrentUserHasRight('CreateTicket')) {
 	Abort('You have no permission to create tickets in that queue.');
     }
-    $ARGS{'new-MemberOf'} = $Incident->Id;
-    $ARGS{'Queue'} = $investigationq->Id;
+    $TARGS{'new-MemberOf'} = $Incident->Id;
+    $TARGS{'Queue'} = $investigationq->Id;
+
     # Create the investigation without attachments, and send them later
     ($Ticket, @ChildActions) =
-       CreateTicket(%ARGS);
+       CreateTicket(%TARGS);
     unless ($Ticket->CurrentUserHasRight('ShowTicket')) {
       Abort("No permission to view newly created ticket #".$Ticket->id.".");
     }
-    $ARGS{'new-MemberOf'} = undef;
-    $ARGS{'Queue'} = undef;
+    $TARGS{'new-MemberOf'} = undef;
+    $TARGS{'Queue'} = undef;
 
     # add the address as a Requestor and update the watchers
-    $ARGS{"WatcherAddressEmail1"} = $addr;
-    push @watchresults, ProcessTicketWatchers(TicketObj => $Ticket, ARGSRef => \%ARGS);    
-    $ARGS{"WatcherAddressEmail1"} = undef;
+    $TARGS{"WatcherAddressEmail1"} = $addr;
+    push @watchresults, ProcessTicketWatchers(TicketObj => $Ticket, ARGSRef => \%TARGS);    
+    $TARGS{"WatcherAddressEmail1"} = undef;
 
     # find the Create transaction, so we can pass it to the template
     my $transaction;
@@ -347,28 +384,59 @@
 
     # if the template's argument contains _ADDR_ or _IP_
     # substitute appropriately
-    my $arg = $ARGS{'TemplateArg'};
+    my $arg = $TARGS{'TemplateArg'};
     $arg =~ s/_ADDR_/$addr/g;
     $arg =~ s/_IP_/$ip/g;
 
     # load the selected template
     my $TemplateObj = new RT::Template($session{'CurrentUser'});
-    $TemplateObj->Load($ARGS{'Template'});
+    $TemplateObj->Load($TARGS{'Template'});
     my ( $result, $message ) = $TemplateObj->Parse(
                                          Argument       => $arg,
                                          TicketObj      => $Ticket,
 					 TransactionObj => $transaction,
     );
 
+    my $message_body;
+
+    if ($TARGS{'Content'}) {
+      # Content is given, so we will use that as the first text/plain MIME
+      # part, followed by the attached template
+      # add the template's MIMEObj to the Attachments list
+      $session{'Attachments'} = { _Body => $TemplateObj->MIMEObj,
+                                 %{$session{'Attachments'} || {}} };
+      $message_body = $TARGS{'Content'};
+    } else {
+      $message_body = join('', @{$TemplateObj->MIMEObj->body});
+    }
 
-    # add the template's MIMEObj to the Attachments list
-    $session{'Attachments'} = { _Body => $TemplateObj->MIMEObj,
-				%{$session{'Attachments'} || {}} };
+    my $attach_extra = undef;
+
+    if ($TARGS{'attach_tmpl'}) {
+      # Attachment filename pattern is supplied
+      my $attach_filename = $TARGS{'attach_tmpl'};
+      $attach_filename =~ s/_ADDR_/$addr/g;
+      $attach_filename =~ s/_IP_/$ip/g;
+      if (-r $attach_filename) {
+        open(ATT, $attach_filename);
+        my $body = join("", <ATT>);
+        close(ATT);
+        my $attach_extra = MakeMIMEEntity(
+           Subject             => "$attach_filename",
+           Body                => $body,
+           AttachmentFieldName => 'Attach'
+        );
+        $session{'Attachments'} = { %{$session{'Attachments'} || {}},
+	  			    $TARGS{'Attach'} => $attach_extra };
+      }
+    }
 
     # the content will be part of the template, if desired
-    $ARGS{'UpdateContent'} = " ";
-    $ARGS{UpdateAttachments} = $session{'Attachments'};
-    ProcessUpdateMessage(ARGSRef=>\%ARGS, 
+    $message_body =~ s/_ADDR_/$addr/gs;
+    $message_body =~ s/_IP_/$ip/gs;
+    $TARGS{'UpdateContent'} = $message_body;
+    $TARGS{UpdateAttachments} = $session{'Attachments'};
+    ProcessUpdateMessage(ARGSRef=>\%TARGS, 
 			 Actions=>\@updateresults, 
 			 TicketObj=>$Ticket);
   } else {
@@ -377,14 +445,14 @@
     unless ($reportq->CurrentUserHasRight('CreateTicket')) {
 	Abort('You have no permission to create tickets in that queue.');
     }
-    $ARGS{'Queue'} = $reportq->Id;
+    $TARGS{'Queue'} = $reportq->Id;
     # Create the investigation without attachments, and send them later
     ($Ticket, @ChildActions) =
-       CreateTicket(%ARGS);
+       CreateTicket(%TARGS);
     unless ($Ticket->CurrentUserHasRight('ShowTicket')) {
       Abort("No permission to view newly created ticket #".$Ticket->id.".");
     }
-    $ARGS{'Queue'} = undef;
+    $TARGS{'Queue'} = undef;
   }
 
   # say what ticket these refer to


More information about the Rtir mailing list