-2

I am using [rt] and would like to create an action to parse a series of firewall rules and pick up the IP addresses in them as a comma-separated value to be applied to a field. My firewall rules look like this:

access-list ACL-outside-1net extended permit tcp host 172.16.0.7 host 10.0.1.55 eq www
access-list ACL-outside-1net extended permit tcp host 172.16.0.9 host 10.0.1.56 eq www

And it would be great if I could have a regex that will snarf whatever occurs after "host" and return them as a comma-separated string without picking up everything until the end of the line, which is my current point of failure.

i.e. my ideal output from the regex would be:

172.16.0.7,10.0.1.55,172.16.0.9,10.0.1.56

The rules I'm interested in will always end in eq $service or $port and the IP address will be preceded by host, but the IP address can be ipv4 or ipv6 and [rt] will be smart about parsing the address, so I would rather pick up "after host up to host" and "after host up to eq", but I'm having a hard time getting a regex to match, let alone replace into a comma-separated string.

lil' help?

edit 201305080832

I've been asked (and appropriately downvoted) to share my work, so here is my template that I'm working in for [rt].

IPs|Body|host(.*)||

My custom field is named IPs and I'm doing a Body search for "host" and then have been doing a greedy match that isn't an acceptable IP address for the Multi-value IP address field in [rt]. The suggestions below may be workable if I change from using a template and ExtractCustomFieldValue to writing a scrip action specific for this use case.


[rt] Request Tracker

Community
  • 1
  • 1
incumbent
  • 355
  • 2
  • 7
  • 1
    for reference, you should attempt to do the code yourself and post what you have. Otherwise, most people will not want to answer your questions. – Steve P. May 08 '13 at 03:04

2 Answers2

0
use strict;
use warnings;

my $s="access-list ACL-outside-1net extended permit tcp host 172.16.0.7 host 10.0.1.55 eq www";

if ($s =~ /host(.*) host(.*) eq.*/)
{
    print "$1\n$2\n";
}

Use parenthesis for grouping with extraction. The elements from the first group go into $1 and the elements from the second group go into `$2'. .* will get all characters except for newline. Good luck.

Edit: To be more precise, you could use this:

if ($s =~ /host((?:[0-9]|.)+) host((?:[0-9]|.)+) eq.*/)
    {
        print "$1\n$2\n";
    }

(?:..) says to group, but not to extract. [0-9]|. says that you demand that all characters be 0-9 or .

To print out everything on one line, simply write a loop to go through all the lines and use commas instead of \n to separate them.

Steve P.
  • 14,489
  • 8
  • 42
  • 72
  • Demanding a numeric value like that will mean ipv6 addresses don't get picked up, but I think your first example is getting me closer and I'll continue to beat on it. – incumbent May 08 '13 at 15:05
0

Perhaps the following will be helpful:

use strict;
use warnings;
use Regexp::Common qw/net/;

my ( @IPs, @ips );
while (<DATA>) {
    push @IPs, @ips if @ips = /($RE{net}{IPv4})/g;
}

print join ',', @IPs;

__DATA__
access-list ACL-outside-1net extended permit tcp host 172.16.0.7 host 10.0.1.55 eq www
access-list ACL-outside-1net extended permit tcp host 172.16.0.9 host 10.0.1.56 eq www

Output:

172.16.0.7,10.0.1.55,172.16.0.9,10.0.1.56

This uses the module Regexp::Common to capture IPs on each line, and those are pushed onto @IPs and are later printed after being joined with a ','.

Kenosis
  • 6,196
  • 1
  • 16
  • 16